term.ui #

term.ui

A V module for designing terminal UI apps

Quickstart

import term.ui as tui

struct App {
mut:
    tui &tui.Context = 0
}

fn event(e &tui.Event, x voidptr) {
    mut app := &App(x)
    println(e)
    if e.typ == .key_down && e.code == .escape {
        exit(0)
    }
}

fn frame(x voidptr) {
    mut app := &App(x)

    app.tui.clear()
    app.tui.set_bg_color(r: 63, g: 81, b: 181)
    app.tui.draw_rect(20, 6, 41, 10)
    app.tui.draw_text(24, 8, 'Hello from V!')
    app.tui.set_cursor_position(0, 0)

    app.tui.reset()
    app.tui.flush()
}

mut app := &App{}
app.tui = tui.init(
    user_data: app
    event_fn: event
    frame_fn: frame
    hide_cursor: true
)
app.tui.run() ?

See the /examples/term.ui/ folder for more usage examples.

Configuration

  • user_data voidptr - a pointer to any user_data, it will be passed as the last argument to each callback. Used for accessing your app context from the different callbacks.
  • init_fn fn(voidptr) - a callback that will be called after initialization and before the first event / frame. Useful for initializing any user data.
  • frame_fn fn(voidptr) - a callback that will be fired on each frame, at a rate of frame_rate frames per second. event_fn fn(&Event, voidptr) - a callback that will be fired for every event received.
  • cleanup_fn fn(voidptr) - a callback that will be fired once, before the application exits.
  • fail_fn fn(string) - a callback that will be fired if a fatal error occurs during app initialization.
  • buffer_size int = 256 - the internal size of the read buffer. Increasing it may help in case you're missing events, but you probably shouldn't lower this value unless you make sure you're still receiving all events. In general, higher frame rates work better with lower buffer sizes, and vice versa.
  • frame_rate int = 30 - the number of times per second that the frame callback will be fired. 30fps is a nice balance between smoothness and performance, but you can increase or lower it as you wish.
  • hide_cursor bool - whether to hide the mouse cursor. Useful if you want to use your own.
  • capture_events bool - sets the terminal into raw mode, which makes it intercept some escape codes such as ctrl + c and ctrl + z. Useful if you want to use those key combinations in your app.
  • window_title string - sets the title of the terminal window. This may be changed later, by calling the set_window_title() method.
  • reset []int = [1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14, 15, 19] - a list of reset signals, to setup handlers to cleanup the terminal state when they're received. You should not need to change this, unless you know what you're doing.

All of these fields may be omitted, in which case, the default value will be used. In the case of the various callbacks, they will not be fired if a handler has not been specified.

FAQ

Q: My terminal (doesn't receive events / doesn't print anything / prints gibberish characters), what's up with that? A: Please check if your terminal. The module has been tested with xterm-based terminals on Linux (like gnome-terminal and konsole), and Terminal.app and iterm2 on macOS. If your terminal does not work, open an issue with the output of echo $TERM.

Q: There are screen tearing issues when doing large prints A: This is an issue with how terminals render frames, as they may decide to do so in the middle of receiving a frame, and cannot be fully fixed unless your console implements the synchronized updates spec. It can be reduced drastically, though, by using the rendering methods built in to the module, and by only painting frames when your app's content has actually changed.

Q: Why does the module only emit keydown events, and not keyup like sokol/gg? A: It's because of the way terminals emit events. Every key event is received as a keypress, and there isn't a way of telling terminals to send keyboard events differently, nor a reliable way of converting these into keydown / keyup events.

fn init #

fn init(cfg Config) &Context

enum Direction #

enum Direction {
	unknown
	up
	down
	left
	right
}

enum EventType #

enum EventType {
	unknown
	mouse_down
	mouse_up
	mouse_move
	mouse_drag
	mouse_scroll
	key_down
	resized
}

enum KeyCode #

enum KeyCode {
	null = 0
	tab = 9
	enter = 10
	escape = 27
	space = 32
	backspace = 127
	exclamation = 33
	double_quote = 34
	hashtag = 35
	dollar = 36
	percent = 37
	ampersand = 38
	single_quote = 39
	left_paren = 40
	right_paren = 41
	asterisk = 42
	plus = 43
	comma = 44
	minus = 45
	period = 46
	slash = 47
	_0 = 48
	_1 = 49
	_2 = 50
	_3 = 51
	_4 = 52
	_5 = 53
	_6 = 54
	_7 = 55
	_8 = 56
	_9 = 57
	colon = 58
	semicolon = 59
	less_than = 60
	equal = 61
	greater_than = 62
	question_mark = 63
	at = 64
	a = 97
	b = 98
	c = 99
	d = 100
	e = 101
	f = 102
	g = 103
	h = 104
	i = 105
	j = 106
	k = 107
	l = 108
	m = 109
	n = 110
	o = 111
	p = 112
	q = 113
	r = 114
	s = 115
	t = 116
	u = 117
	v = 118
	w = 119
	x = 120
	y = 121
	z = 122
	left_square_bracket = 91
	backslash = 92
	right_square_bracket = 93
	caret = 94
	underscore = 95
	backtick = 96
	left_curly_bracket = 123
	vertical_bar = 124
	right_curly_bracket = 125
	tilde = 126
	insert = 260
	delete = 261
	up = 262
	down = 263
	right = 264
	left = 265
	page_up = 266
	page_down = 267
	home = 268
	end = 269
	f1 = 290
	f2 = 291
	f3 = 292
	f4 = 293
	f5 = 294
	f6 = 295
	f7 = 296
	f8 = 297
	f9 = 298
	f10 = 299
	f11 = 300
	f12 = 301
	f13 = 302
	f14 = 303
	f15 = 304
	f16 = 305
	f17 = 306
	f18 = 307
	f19 = 308
	f20 = 309
	f21 = 310
	f22 = 311
	f23 = 312
	f24 = 313
}

enum Modifiers #

enum Modifiers {
	ctrl
	shift
	alt
}

enum MouseButton #

enum MouseButton {
	unknown
	left
	middle
	right
}

struct Color #

struct Color {
pub:
	r byte
	g byte
	b byte
}

fn (Color) hex #

fn (c Color) hex() string

struct Config #

struct Config {
	user_data  voidptr
	init_fn    fn (voidptr)
	frame_fn   fn (voidptr)
	cleanup_fn fn (voidptr)
	event_fn   fn (&Event, voidptr)
	fail_fn    fn (string)

	buffer_size int = 256
	frame_rate  int = 30
	use_x11     bool

	window_title         string
	hide_cursor          bool
	capture_events       bool
	use_alternate_buffer bool = true
	skip_init_checks     bool

	reset []os.Signal = [.hup, .int, .quit, .ill, .abrt, .bus, .fpe, .kill, .segv, .pipe, .alrm, .term,
	.stop,
]
}

struct Context #

struct Context {
	ExtraContext
pub:
	cfg Config
mut:
	print_buf  []byte
	paused     bool
	enable_su  bool
	enable_rgb bool
pub mut:
	frame_count   u64
	window_width  int
	window_height int
}

fn (Context) bold #

fn (mut ctx Context) bold()

bold sets the character state to bold.

fn (Context) clear #

fn (mut ctx Context) clear()

fn (Context) draw_dashed_line #

fn (mut ctx Context) draw_dashed_line(x int, y int, x2 int, y2 int)

draw_dashed_line draws a dashed line segment, starting at point x,y, and ending at point x2,y2.

fn (Context) draw_empty_dashed_rect #

fn (mut ctx Context) draw_empty_dashed_rect(x int, y int, x2 int, y2 int)

draw_empty_dashed_rect draws a rectangle with dashed lines, starting at top left x,y, and ending at bottom right x2,y2.

fn (Context) draw_empty_rect #

fn (mut ctx Context) draw_empty_rect(x int, y int, x2 int, y2 int)

draw_empty_rect draws a rectangle with no fill, starting at top left x,y, and ending at bottom right x2,y2.

fn (Context) draw_line #

fn (mut ctx Context) draw_line(x int, y int, x2 int, y2 int)

draw_line draws a line segment, starting at point x,y, and ending at point x2,y2.

fn (Context) draw_point #

fn (mut ctx Context) draw_point(x int, y int)

draw_point draws a point at position x,y.

fn (Context) draw_rect #

fn (mut ctx Context) draw_rect(x int, y int, x2 int, y2 int)

draw_rect draws a rectangle, starting at top left x,y, and ending at bottom right x2,y2.

fn (Context) draw_text #

fn (mut ctx Context) draw_text(x int, y int, s string)

draw_text draws the string s, starting from position x,y.

fn (Context) flush #

fn (mut ctx Context) flush()

flush displays the accumulated print buffer to the screen.

fn (Context) hide_cursor #

fn (mut ctx Context) hide_cursor()

hide_cursor will make the cursor invisible

fn (Context) horizontal_separator #

fn (mut ctx Context) horizontal_separator(y int)

horizontal_separator draws a horizontal separator, spanning the width of the screen.

fn (Context) reset #

fn (mut ctx Context) reset()

reset restores the state of all colors and text formats back to their default values.

fn (Context) reset_bg_color #

fn (mut ctx Context) reset_bg_color()

reset_bg_color sets the current background color back to it's default value.

fn (Context) reset_color #

fn (mut ctx Context) reset_color()

reset_color sets the current foreground color back to it's default value.

fn (Context) run #

fn (mut ctx Context) run() ?

fn (Context) set_bg_color #

fn (mut ctx Context) set_bg_color(c Color)

set_color sets the current background color used by any succeeding draw_* calls.

fn (Context) set_color #

fn (mut ctx Context) set_color(c Color)

set_color sets the current foreground color used by any succeeding draw_* calls.

fn (Context) set_cursor_position #

fn (mut ctx Context) set_cursor_position(x int, y int)

set_cursor_position positions the cusor at the given coordinates x,y.

fn (Context) set_window_title #

fn (mut ctx Context) set_window_title(s string)

set_window_title sets the string s as the window title.

fn (Context) show_cursor #

fn (mut ctx Context) show_cursor()

show_cursor will make the cursor appear if it is not already visible

fn (Context) write #

fn (mut ctx Context) write(s string)

write puts the string s into the print buffer.

struct Event #

struct Event {
pub:
	typ EventType

	x         int
	y         int
	button    MouseButton
	direction Direction

	code      KeyCode
	modifiers Modifiers
	ascii     byte
	utf8      string

	width  int
	height int
}