term.ui: render to the alternate buffer (#6832)
							parent
							
								
									b96a0246b5
								
							
						
					
					
						commit
						1ead130eed
					
				|  | @ -1,10 +1,5 @@ | |||
| import term.ui as tui | ||||
| 
 | ||||
| struct Point { | ||||
| 	x int | ||||
| 	y int | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	colors = [ | ||||
| 		tui.Color{33, 150, 243} | ||||
|  | @ -16,6 +11,11 @@ const ( | |||
| 	] | ||||
| ) | ||||
| 
 | ||||
| struct Point { | ||||
| 	x int | ||||
| 	y int | ||||
| } | ||||
| 
 | ||||
| struct App { | ||||
| mut: | ||||
| 	tui       &tui.Context = 0 | ||||
|  | @ -33,11 +33,11 @@ fn frame(x voidptr) { | |||
| 	if app.points.len > 0 { | ||||
| 		app.tui.set_bg_color(app.color) | ||||
| 		mut last := app.points[0] | ||||
| 		for segment in app.points { | ||||
| 			// if the cursor moveds quickly enough, different events are not
 | ||||
| 		for point in app.points { | ||||
| 			// if the cursor moves quickly enough, different events are not
 | ||||
| 			// necessarily touching, so we need to draw a line between them
 | ||||
| 			app.tui.draw_line(last.x, last.y, segment.x, segment.y) | ||||
| 			last = segment | ||||
| 			app.tui.draw_line(last.x, last.y, point.x, point.y) | ||||
| 			last = point | ||||
| 		} | ||||
| 		app.tui.reset() | ||||
| 
 | ||||
|  | @ -62,8 +62,6 @@ fn event(e &tui.Event, x voidptr) { | |||
| 		.key_down { | ||||
| 			match e.code { | ||||
| 				.escape { | ||||
| 					app.tui.set_cursor_position(0, 0) | ||||
| 					app.tui.flush() | ||||
| 					exit(0) | ||||
| 				} | ||||
| 				.space, .enter { | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ app.tui = tui.init( | |||
| 	hide_cursor: true | ||||
| 	capture_events: true | ||||
| 	frame_rate: 60 | ||||
| 	use_alternate_buffer: false | ||||
| ) | ||||
| 
 | ||||
| println('V term.ui event viewer (press `esc` to exit)\n\n') | ||||
|  |  | |||
|  | @ -94,8 +94,9 @@ mut: | |||
| 	msg_hide_tick       int | ||||
| 	primary_color       tui.Color = colors[1][6] | ||||
| 	secondary_color     tui.Color = colors[1][9] | ||||
| 	primary_color_idx   int = 25 | ||||
| 	secondary_color_idx int = 28 | ||||
| 	bg_color            tui.Color = tui.Color{0, 0, 0} | ||||
| 	color_index     int | ||||
| 	drawing             [][]tui.Color = [][]tui.Color{len: h, init: []tui.Color{len: w}} | ||||
| 	size                int = 1 | ||||
| 	should_redraw       bool = true | ||||
|  | @ -169,10 +170,17 @@ fn event(event &tui.Event, x voidptr) { | |||
| 				x: event.x | ||||
| 				y: event.y | ||||
| 			} | ||||
| 			if event.direction == .down { | ||||
| 				app.inc_size() | ||||
| 			d := event.direction == .down | ||||
| 			if event.modifiers & tui.ctrl != 0 { | ||||
| 				p := event.modifiers & tui.shift == 0 | ||||
| 				c := if d { | ||||
| 					if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 } | ||||
| 				} else { | ||||
| 				app.dec_size() | ||||
| 					if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 } | ||||
| 				} | ||||
| 				app.select_color(p, c) | ||||
| 			} else { | ||||
| 				if d { app.inc_size() } else { app.dec_size() } | ||||
| 			} | ||||
| 		} | ||||
| 		.key_down { | ||||
|  | @ -217,28 +225,22 @@ fn event(event &tui.Event, x voidptr) { | |||
| 					app.mouse_pos.x += 2 | ||||
| 				} | ||||
| 				.t { | ||||
| 					mut c := if event.modifiers & tui.shift != 0 { app.color_index - 19 } else { app.color_index + | ||||
| 							19 } | ||||
| 					if c < 0 { | ||||
| 						c = 0 | ||||
| 					p := event.modifiers & tui.alt == 0 | ||||
| 					c := if event.modifiers & tui.shift != 0 { | ||||
| 						if p { app.primary_color_idx - 19 } else { app.secondary_color_idx - 19 } | ||||
| 					} else { | ||||
| 						if p { app.primary_color_idx + 19 } else { app.secondary_color_idx + 19 } | ||||
| 					} | ||||
| 					cx := c % 19 | ||||
| 					cy := (c / 19) % 3 | ||||
| 					color := colors[cy][cx] | ||||
| 					app.primary_color = color | ||||
| 					app.color_index = c % (19 * 3) | ||||
| 					app.select_color(p, c) | ||||
| 				} | ||||
| 				.r { | ||||
| 					mut c := if event.modifiers & tui.shift != 0 { app.color_index - 1 } else { app.color_index + | ||||
| 							1 } | ||||
| 					if c < 0 { | ||||
| 						c = 0 | ||||
| 					p := event.modifiers & tui.alt == 0 | ||||
| 					c := if event.modifiers & tui.shift != 0 { | ||||
| 						if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 } | ||||
| 					} else { | ||||
| 						if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 } | ||||
| 					} | ||||
| 					cx := c % 19 | ||||
| 					cy := (c / 19) % 3 | ||||
| 					color := colors[cy][cx] | ||||
| 					app.primary_color = color | ||||
| 					app.color_index = c % (19 * 3) | ||||
| 					app.select_color(p, c) | ||||
| 				} | ||||
| 				.plus { | ||||
| 					app.inc_size() | ||||
|  | @ -272,6 +274,22 @@ fn (mut app App) render(paint_only bool) { | |||
| 	app.tui.flush() | ||||
| } | ||||
| 
 | ||||
| fn (mut app App) select_color(primary bool, idx int) { | ||||
| 	c := (idx + 57) % 57 | ||||
| 	cx := c % 19 | ||||
| 	cy := (c / 19) % 3 | ||||
| 	color := colors[cy][cx] | ||||
| 	if primary { | ||||
| 		app.primary_color_idx = c % (19 * 3) | ||||
| 		app.primary_color = color | ||||
| 	} else { | ||||
| 		app.secondary_color_idx = c % (19 * 3) | ||||
| 		app.secondary_color = color | ||||
| 	} | ||||
| 	c_str := if primary { 'primary' } else { 'secondary' } | ||||
| 	app.show_msg('set $c_str color idx: $idx', 1) | ||||
| } | ||||
| 
 | ||||
| fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) { | ||||
| 	// Term coords start at 1, and adjust for the header
 | ||||
| 	x, y := x_ - 1, y_ - 4 | ||||
|  | @ -285,6 +303,9 @@ fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) { | |||
| } | ||||
| 
 | ||||
| fn (mut app App) paint(event &tui.Event) { | ||||
| 	if event.y < 4 || app.tui.window_height - event.y < 4 { | ||||
| 		return | ||||
| 	} | ||||
| 	x_start, y_start := int(f32((event.x - 1) / 2) - app.size / 2 + 1), event.y - app.size / 2 | ||||
| 	color := match event.button { | ||||
| 		.left { app.primary_color } | ||||
|  | @ -374,10 +395,6 @@ fn (mut app App) draw_header() { | |||
| 	app.tui.horizontal_separator(3) | ||||
| } | ||||
| 
 | ||||
| fn (mut app App) current_color(x int, y int) bool { | ||||
| 	return app.color_index == x + (y * 19) | ||||
| } | ||||
| 
 | ||||
| fn (mut app App) draw_footer() { | ||||
| 	_, wh := app.tui.window_width, app.tui.window_height | ||||
| 	app.tui.horizontal_separator(wh - 4) | ||||
|  | @ -386,8 +403,12 @@ fn (mut app App) draw_footer() { | |||
| 			x := j * 3 + 19 | ||||
| 			y := wh - 3 + i | ||||
| 			app.tui.set_bg_color(color) | ||||
| 			if app.current_color(j, i) { | ||||
| 				app.tui.set_color(tui.Color{0, 0, 0}) | ||||
| 			if app.primary_color_idx == j + (i * 19) { | ||||
| 				app.tui.set_color(r: 0, g: 0, b: 0) | ||||
| 				app.tui.draw_text(x, y, '><') | ||||
| 				app.tui.reset_color() | ||||
| 			} else if app.secondary_color_idx == j + (i * 19) { | ||||
| 				app.tui.set_color(r: 255, g: 255, b: 255) | ||||
| 				app.tui.draw_text(x, y, '><') | ||||
| 				app.tui.reset_color() | ||||
| 			} else { | ||||
|  | @ -397,9 +418,6 @@ fn (mut app App) draw_footer() { | |||
| 	} | ||||
| 	app.tui.reset_bg_color() | ||||
| 	app.tui.draw_text(3, wh - 3, select_color) | ||||
| 	app.tui.set_bg_color(app.primary_color) | ||||
| 	app.tui.draw_text(3 + select_color.len, wh - 3, ' ') | ||||
| 	app.tui.reset_bg_color() | ||||
| 	app.tui.bold() | ||||
| 	app.tui.draw_text(3, wh - 1, '$select_size $app.size') | ||||
| 	app.tui.reset() | ||||
|  | @ -414,7 +432,7 @@ fn (mut app App) draw_footer() { | |||
| 
 | ||||
| [inline] | ||||
| fn (mut app App) inc_size() { | ||||
| 	if app.size < 20 { | ||||
| 	if app.size < 30 { | ||||
| 		app.size++ | ||||
| 	} | ||||
| 	app.show_msg('inc. size: $app.size', 1) | ||||
|  | @ -444,13 +462,7 @@ fn (mut app App) footer_click(event &tui.Event) { | |||
| 			} | ||||
| 			idx := footer_y * 19 - 6 + event.x / 3 | ||||
| 			if idx < 0 || idx > 56 { return } | ||||
| 			color := colors[idx / 19][idx % 19] | ||||
| 			if event.button == .left { | ||||
| 				app.primary_color = color | ||||
| 			} else if event.button == .right { | ||||
| 				app.secondary_color = color | ||||
| 			} | ||||
| 			app.show_msg('set $event.button.str().to_lower() color idx: $idx', 1) | ||||
| 			app.select_color(event.button == .left, idx) | ||||
| 		} | ||||
| 		else {} | ||||
| 	} | ||||
|  |  | |||
|  | @ -397,7 +397,6 @@ fn (mut a App) init_file() { | |||
| 	a.ed = &Buffer{} | ||||
| 	mut init_y := 0 | ||||
| 	mut init_x := 0 | ||||
| 	eprintln('> a.files: $a.files | a.current_file: $a.current_file') | ||||
| 	if a.files.len > 0 && a.current_file < a.files.len && a.files[a.current_file].len > 0 { | ||||
| 		if !os.is_file(a.files[a.current_file]) && a.files[a.current_file].contains(':') { | ||||
| 			// support the file:line:col: format
 | ||||
|  | @ -454,8 +453,6 @@ fn event(e &tui.Event, x voidptr) { | |||
| 	if e.typ == .key_down { | ||||
| 		match e.code { | ||||
| 			.escape { | ||||
| 				a.tui.set_cursor_position(0, 0) | ||||
| 				a.tui.flush() | ||||
| 				exit(0) | ||||
| 			} | ||||
| 			.backspace { | ||||
|  |  | |||
|  | @ -167,8 +167,7 @@ mut: | |||
| 	termios       C.termios | ||||
| 	read_buf      []byte | ||||
| 	print_buf     []byte | ||||
| 	// init_called  bool
 | ||||
| 	// quit_ordered bool
 | ||||
| 	paused        bool | ||||
| pub mut: | ||||
| 	frame_count   u64 | ||||
| 	window_width  int | ||||
|  | @ -190,6 +189,7 @@ pub struct Config { | |||
| 	window_title   string | ||||
| 	hide_cursor    bool | ||||
| 	capture_events bool | ||||
| 	use_alternate_buffer bool = true | ||||
| 	// All kill signals
 | ||||
| 	reset          []int = [1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14, 15, 19] | ||||
| } | ||||
|  |  | |||
|  | @ -45,9 +45,10 @@ fn restore_terminal_state() { | |||
| 	termios_reset() | ||||
| 	mut c := ctx_ptr | ||||
| 	if c != 0 { | ||||
| 		c.paused = true | ||||
| 		c.load_title() | ||||
| 	} | ||||
| 	println('') | ||||
| 	os.flush() | ||||
| } | ||||
| 
 | ||||
| fn (mut ctx Context) termios_setup() { | ||||
|  | @ -79,9 +80,10 @@ fn (mut ctx Context) termios_setup() { | |||
| 	termios.c_cc[C.VMIN] = 0 | ||||
| 	C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &termios) | ||||
| 	print('\x1b[?1003h\x1b[?1006h') | ||||
| 
 | ||||
| 	if ctx.cfg.use_alternate_buffer { | ||||
| 		print('\x1b[?1049h') | ||||
| 	} | ||||
| 	ctx.termios = termios | ||||
| 
 | ||||
| 	ctx.window_height, ctx.window_width = get_terminal_size() | ||||
| 
 | ||||
| 	// Reset console on exit
 | ||||
|  | @ -97,6 +99,7 @@ fn (mut ctx Context) termios_setup() { | |||
| 				width: c.window_width | ||||
| 				height: c.window_height | ||||
| 			} | ||||
| 			c.paused = false | ||||
| 			c.event(event) | ||||
| 		} | ||||
| 	}) | ||||
|  | @ -123,11 +126,17 @@ fn (mut ctx Context) termios_setup() { | |||
| 			c.event(event) | ||||
| 		} | ||||
| 	}) | ||||
| 	os.flush() | ||||
| } | ||||
| 
 | ||||
| fn termios_reset() { | ||||
| 	C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH /* C.TCSANOW ?? */, &termios_at_startup) | ||||
| 	print('\x1b[?1003l\x1b[?1015l\x1b[?1006l\x1b[0J\x1b[?25h') | ||||
| 	print('\x1b[?1003l\x1b[?1006l\x1b[?25h') | ||||
| 	c := ctx_ptr | ||||
| 	if c != 0 && c.cfg.use_alternate_buffer { | ||||
| 		print('\x1b[?1049l') | ||||
| 	} | ||||
| 	os.flush() | ||||
| } | ||||
| 
 | ||||
| ///////////////////////////////////////////
 | ||||
|  | @ -147,6 +156,7 @@ fn (mut ctx Context) termios_loop() { | |||
| 		if sleep_len > 0 { | ||||
| 			time.usleep(sleep_len) | ||||
| 		} | ||||
| 		if !ctx.paused { | ||||
| 			sw.restart() | ||||
| 			if ctx.cfg.event_fn != voidptr(0) { | ||||
| 				len := C.read(C.STDIN_FILENO, ctx.read_buf.data, ctx.read_buf.cap - ctx.read_buf.len) | ||||
|  | @ -163,6 +173,7 @@ fn (mut ctx Context) termios_loop() { | |||
| 			ctx.frame_count++ | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (mut ctx Context) parse_events() { | ||||
| 	// Stop this from getting stuck in rare cases where something isn't parsed correctly
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue