term.ui: render to the alternate buffer (#6832)

pull/6838/head
spaceface777 2020-11-14 20:05:22 +01:00 committed by GitHub
parent b96a0246b5
commit 1ead130eed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 83 deletions

View File

@ -1,10 +1,5 @@
import term.ui as tui import term.ui as tui
struct Point {
x int
y int
}
const ( const (
colors = [ colors = [
tui.Color{33, 150, 243} tui.Color{33, 150, 243}
@ -16,6 +11,11 @@ const (
] ]
) )
struct Point {
x int
y int
}
struct App { struct App {
mut: mut:
tui &tui.Context = 0 tui &tui.Context = 0
@ -33,11 +33,11 @@ fn frame(x voidptr) {
if app.points.len > 0 { if app.points.len > 0 {
app.tui.set_bg_color(app.color) app.tui.set_bg_color(app.color)
mut last := app.points[0] mut last := app.points[0]
for segment in app.points { for point in app.points {
// if the cursor moveds quickly enough, different events are not // if the cursor moves quickly enough, different events are not
// necessarily touching, so we need to draw a line between them // necessarily touching, so we need to draw a line between them
app.tui.draw_line(last.x, last.y, segment.x, segment.y) app.tui.draw_line(last.x, last.y, point.x, point.y)
last = segment last = point
} }
app.tui.reset() app.tui.reset()
@ -62,8 +62,6 @@ fn event(e &tui.Event, x voidptr) {
.key_down { .key_down {
match e.code { match e.code {
.escape { .escape {
app.tui.set_cursor_position(0, 0)
app.tui.flush()
exit(0) exit(0)
} }
.space, .enter { .space, .enter {

View File

@ -32,6 +32,7 @@ app.tui = tui.init(
hide_cursor: true hide_cursor: true
capture_events: true capture_events: true
frame_rate: 60 frame_rate: 60
use_alternate_buffer: false
) )
println('V term.ui event viewer (press `esc` to exit)\n\n') println('V term.ui event viewer (press `esc` to exit)\n\n')

View File

@ -87,19 +87,20 @@ const (
struct App { struct App {
mut: mut:
tui &tui.Context = 0 tui &tui.Context = 0
header_text []string header_text []string
mouse_pos Point mouse_pos Point
msg string msg string
msg_hide_tick int msg_hide_tick int
primary_color tui.Color = colors[1][6] primary_color tui.Color = colors[1][6]
secondary_color tui.Color = colors[1][9] secondary_color tui.Color = colors[1][9]
bg_color tui.Color = tui.Color{0, 0, 0} primary_color_idx int = 25
color_index int secondary_color_idx int = 28
drawing [][]tui.Color = [][]tui.Color{len: h, init: []tui.Color{len: w}} bg_color tui.Color = tui.Color{0, 0, 0}
size int = 1 drawing [][]tui.Color = [][]tui.Color{len: h, init: []tui.Color{len: w}}
should_redraw bool = true size int = 1
is_dragging bool should_redraw bool = true
is_dragging bool
} }
struct Point { struct Point {
@ -169,10 +170,17 @@ fn event(event &tui.Event, x voidptr) {
x: event.x x: event.x
y: event.y y: event.y
} }
if event.direction == .down { d := event.direction == .down
app.inc_size() 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 {
if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 }
}
app.select_color(p, c)
} else { } else {
app.dec_size() if d { app.inc_size() } else { app.dec_size() }
} }
} }
.key_down { .key_down {
@ -217,28 +225,22 @@ fn event(event &tui.Event, x voidptr) {
app.mouse_pos.x += 2 app.mouse_pos.x += 2
} }
.t { .t {
mut c := if event.modifiers & tui.shift != 0 { app.color_index - 19 } else { app.color_index + p := event.modifiers & tui.alt == 0
19 } c := if event.modifiers & tui.shift != 0 {
if c < 0 { if p { app.primary_color_idx - 19 } else { app.secondary_color_idx - 19 }
c = 0 } else {
if p { app.primary_color_idx + 19 } else { app.secondary_color_idx + 19 }
} }
cx := c % 19 app.select_color(p, c)
cy := (c / 19) % 3
color := colors[cy][cx]
app.primary_color = color
app.color_index = c % (19 * 3)
} }
.r { .r {
mut c := if event.modifiers & tui.shift != 0 { app.color_index - 1 } else { app.color_index + p := event.modifiers & tui.alt == 0
1 } c := if event.modifiers & tui.shift != 0 {
if c < 0 { if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }
c = 0 } else {
if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 }
} }
cx := c % 19 app.select_color(p, c)
cy := (c / 19) % 3
color := colors[cy][cx]
app.primary_color = color
app.color_index = c % (19 * 3)
} }
.plus { .plus {
app.inc_size() app.inc_size()
@ -272,6 +274,22 @@ fn (mut app App) render(paint_only bool) {
app.tui.flush() 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) { fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) {
// Term coords start at 1, and adjust for the header // Term coords start at 1, and adjust for the header
x, y := x_ - 1, y_ - 4 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) { 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 x_start, y_start := int(f32((event.x - 1) / 2) - app.size / 2 + 1), event.y - app.size / 2
color := match event.button { color := match event.button {
.left { app.primary_color } .left { app.primary_color }
@ -374,10 +395,6 @@ fn (mut app App) draw_header() {
app.tui.horizontal_separator(3) 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() { fn (mut app App) draw_footer() {
_, wh := app.tui.window_width, app.tui.window_height _, wh := app.tui.window_width, app.tui.window_height
app.tui.horizontal_separator(wh - 4) app.tui.horizontal_separator(wh - 4)
@ -386,8 +403,12 @@ fn (mut app App) draw_footer() {
x := j * 3 + 19 x := j * 3 + 19
y := wh - 3 + i y := wh - 3 + i
app.tui.set_bg_color(color) app.tui.set_bg_color(color)
if app.current_color(j, i) { if app.primary_color_idx == j + (i * 19) {
app.tui.set_color(tui.Color{0, 0, 0}) 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.draw_text(x, y, '><')
app.tui.reset_color() app.tui.reset_color()
} else { } else {
@ -397,9 +418,6 @@ fn (mut app App) draw_footer() {
} }
app.tui.reset_bg_color() app.tui.reset_bg_color()
app.tui.draw_text(3, wh - 3, select_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.bold()
app.tui.draw_text(3, wh - 1, '$select_size $app.size') app.tui.draw_text(3, wh - 1, '$select_size $app.size')
app.tui.reset() app.tui.reset()
@ -414,7 +432,7 @@ fn (mut app App) draw_footer() {
[inline] [inline]
fn (mut app App) inc_size() { fn (mut app App) inc_size() {
if app.size < 20 { if app.size < 30 {
app.size++ app.size++
} }
app.show_msg('inc. size: $app.size', 1) 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 idx := footer_y * 19 - 6 + event.x / 3
if idx < 0 || idx > 56 { return } if idx < 0 || idx > 56 { return }
color := colors[idx / 19][idx % 19] app.select_color(event.button == .left, idx)
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)
} }
else {} else {}
} }

View File

@ -397,7 +397,6 @@ fn (mut a App) init_file() {
a.ed = &Buffer{} a.ed = &Buffer{}
mut init_y := 0 mut init_y := 0
mut init_x := 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 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(':') { if !os.is_file(a.files[a.current_file]) && a.files[a.current_file].contains(':') {
// support the file:line:col: format // support the file:line:col: format
@ -454,8 +453,6 @@ fn event(e &tui.Event, x voidptr) {
if e.typ == .key_down { if e.typ == .key_down {
match e.code { match e.code {
.escape { .escape {
a.tui.set_cursor_position(0, 0)
a.tui.flush()
exit(0) exit(0)
} }
.backspace { .backspace {

View File

@ -167,8 +167,7 @@ mut:
termios C.termios termios C.termios
read_buf []byte read_buf []byte
print_buf []byte print_buf []byte
// init_called bool paused bool
// quit_ordered bool
pub mut: pub mut:
frame_count u64 frame_count u64
window_width int window_width int
@ -190,6 +189,7 @@ pub struct Config {
window_title string window_title string
hide_cursor bool hide_cursor bool
capture_events bool capture_events bool
use_alternate_buffer bool = true
// All kill signals // All kill signals
reset []int = [1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14, 15, 19] reset []int = [1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14, 15, 19]
} }

View File

@ -45,9 +45,10 @@ fn restore_terminal_state() {
termios_reset() termios_reset()
mut c := ctx_ptr mut c := ctx_ptr
if c != 0 { if c != 0 {
c.paused = true
c.load_title() c.load_title()
} }
println('') os.flush()
} }
fn (mut ctx Context) termios_setup() { fn (mut ctx Context) termios_setup() {
@ -79,9 +80,10 @@ fn (mut ctx Context) termios_setup() {
termios.c_cc[C.VMIN] = 0 termios.c_cc[C.VMIN] = 0
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &termios) C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &termios)
print('\x1b[?1003h\x1b[?1006h') print('\x1b[?1003h\x1b[?1006h')
if ctx.cfg.use_alternate_buffer {
print('\x1b[?1049h')
}
ctx.termios = termios ctx.termios = termios
ctx.window_height, ctx.window_width = get_terminal_size() ctx.window_height, ctx.window_width = get_terminal_size()
// Reset console on exit // Reset console on exit
@ -97,6 +99,7 @@ fn (mut ctx Context) termios_setup() {
width: c.window_width width: c.window_width
height: c.window_height height: c.window_height
} }
c.paused = false
c.event(event) c.event(event)
} }
}) })
@ -123,11 +126,17 @@ fn (mut ctx Context) termios_setup() {
c.event(event) c.event(event)
} }
}) })
os.flush()
} }
fn termios_reset() { fn termios_reset() {
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH /* C.TCSANOW ?? */, &termios_at_startup) 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,20 +156,22 @@ fn (mut ctx Context) termios_loop() {
if sleep_len > 0 { if sleep_len > 0 {
time.usleep(sleep_len) time.usleep(sleep_len)
} }
sw.restart() if !ctx.paused {
if ctx.cfg.event_fn != voidptr(0) { sw.restart()
len := C.read(C.STDIN_FILENO, ctx.read_buf.data, ctx.read_buf.cap - ctx.read_buf.len) if ctx.cfg.event_fn != voidptr(0) {
if len > 0 { len := C.read(C.STDIN_FILENO, ctx.read_buf.data, ctx.read_buf.cap - ctx.read_buf.len)
ctx.resize_arr(len) if len > 0 {
ctx.parse_events() ctx.resize_arr(len)
ctx.parse_events()
}
} }
} ctx.frame()
ctx.frame() sw.pause()
sw.pause() e := sw.elapsed().microseconds()
e := sw.elapsed().microseconds() sleep_len = frame_time - int(e)
sleep_len = frame_time - int(e)
ctx.frame_count++ ctx.frame_count++
}
} }
} }