Skip to content

term.ui #

term.ui

A V module for designing terminal UI apps

Quickstart

import term.ui as tui

struct App {
mut:
    tui &tui.Context = unsafe { nil }
}

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

fn frame(x voidptr) {
    mut app := unsafe { &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()
}

fn main() {
    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 toeach callback. Used for accessing your app context from the different callbacks.- init_fn fn(voidptr) - a callback that will be called after initializationand 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 firedif 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 someescape 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.

Constants #

const color_table = init_color_table()

fn init #

fn init(cfg Config) &Context

init initializes the terminal console with Config cfg.

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 #

@[flag]
enum Modifiers {
	ctrl
	shift
	alt
}

enum MouseButton #

enum MouseButton {
	unknown
	left
	middle
	right
}

struct C.winsize #

struct C.winsize {
	ws_row u16
	ws_col u16
}

struct Color #

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

fn (Color) hex #

fn (c Color) hex() string

hex returns c's RGB color in hex format.

struct Config #

struct Config {
pub:
	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
	// All kill signals to set up exit listeners on:
	reset []os.Signal = [.hup, .int, .quit, .ill, .abrt, .bus, .fpe, .kill, .segv, .pipe, .alrm, .term,
	.stop]
}

struct Context #

struct Context {
	ExtraContext // contains fields specific to an implementation
pub:
	cfg Config // the initial configuration, passed to ui.init()
mut:
	print_buf  []u8
	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()

clear erases the entire terminal window and any saved lines.

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() !

run sets up and starts the terminal.

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
	// Mouse event info
	x         int
	y         int
	button    MouseButton
	direction Direction
	// Keyboard event info
	code      KeyCode
	modifiers Modifiers
	ascii     u8
	utf8      string
	// Resized event info
	width  int
	height int
}