mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: require calling optfn() ?
/ optfn() or {...}
for fn optfn() ? {}
This commit is contained in:
@@ -9,9 +9,10 @@ import time
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
|
||||
fn C.tcgetattr()
|
||||
|
||||
fn C.tcsetattr()
|
||||
|
||||
fn C.ioctl(fd int, request u64, arg voidptr) int
|
||||
|
||||
struct C.termios {
|
||||
@@ -103,7 +104,6 @@ fn (mut ctx Context) termios_setup() ? {
|
||||
// feature-test rgb (truecolor) support
|
||||
ctx.enable_rgb = supports_truecolor()
|
||||
}
|
||||
|
||||
// Prevent stdin from blocking by making its read time 0
|
||||
termios.c_cc[C.VTIME] = 0
|
||||
termios.c_cc[C.VMIN] = 0
|
||||
@@ -124,7 +124,7 @@ fn (mut ctx Context) termios_setup() ? {
|
||||
os.signal(C.SIGCONT, fn () {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
c.termios_setup()
|
||||
c.termios_setup() or { panic(err) }
|
||||
c.window_height, c.window_width = get_terminal_size()
|
||||
mut event := &Event{
|
||||
typ: .resized
|
||||
@@ -136,7 +136,7 @@ fn (mut ctx Context) termios_setup() ? {
|
||||
}
|
||||
})
|
||||
for code in ctx.cfg.reset {
|
||||
os.signal(code, fn() {
|
||||
os.signal(code, fn () {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
c.cleanup()
|
||||
@@ -145,7 +145,7 @@ fn (mut ctx Context) termios_setup() ? {
|
||||
})
|
||||
}
|
||||
|
||||
os.signal(C.SIGWINCH, fn() {
|
||||
os.signal(C.SIGWINCH, fn () {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
c.window_height, c.window_width = get_terminal_size()
|
||||
@@ -166,10 +166,14 @@ fn get_cursor_position() (int, int) {
|
||||
print('\033[6n')
|
||||
buf := malloc(25)
|
||||
len := C.read(C.STDIN_FILENO, buf, 24)
|
||||
unsafe { buf[len] = 0 }
|
||||
unsafe {
|
||||
buf[len] = 0
|
||||
}
|
||||
s := tos(buf, len)
|
||||
a := s[2..].split(';')
|
||||
if a.len != 2 { return -1, -1 }
|
||||
if a.len != 2 {
|
||||
return -1, -1
|
||||
}
|
||||
return a[0].int(), a[1].int()
|
||||
}
|
||||
|
||||
@@ -184,14 +188,16 @@ fn supports_truecolor() bool {
|
||||
print('\x1bP\$qm\x1b\\')
|
||||
buf := malloc(25)
|
||||
len := C.read(C.STDIN_FILENO, buf, 24)
|
||||
unsafe { buf[len] = 0 }
|
||||
unsafe {
|
||||
buf[len] = 0
|
||||
}
|
||||
s := tos(buf, len)
|
||||
return '1:2:3' in s
|
||||
|
||||
}
|
||||
|
||||
fn termios_reset() {
|
||||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH /* C.TCSANOW ?? */, &termios_at_startup)
|
||||
// C.TCSANOW ??
|
||||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &ui.termios_at_startup)
|
||||
print('\x1b[?1003l\x1b[?1006l\x1b[?25h')
|
||||
c := ctx_ptr
|
||||
if c != 0 && c.cfg.use_alternate_buffer {
|
||||
@@ -201,7 +207,6 @@ fn termios_reset() {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
// TODO: do multiple sleep/read cycles, rather than one big one
|
||||
fn (mut ctx Context) termios_loop() {
|
||||
frame_time := 1_000_000 / ctx.cfg.frame_rate
|
||||
@@ -221,7 +226,8 @@ fn (mut ctx Context) termios_loop() {
|
||||
sw.restart()
|
||||
if ctx.cfg.event_fn != voidptr(0) {
|
||||
unsafe {
|
||||
len := C.read(C.STDIN_FILENO, byteptr(ctx.read_buf.data) + ctx.read_buf.len, ctx.read_buf.cap - ctx.read_buf.len)
|
||||
len := C.read(C.STDIN_FILENO, byteptr(ctx.read_buf.data) + ctx.read_buf.len,
|
||||
ctx.read_buf.cap - ctx.read_buf.len)
|
||||
ctx.resize_arr(ctx.read_buf.len + len)
|
||||
}
|
||||
if ctx.read_buf.len > 0 {
|
||||
@@ -243,7 +249,9 @@ fn (mut ctx Context) parse_events() {
|
||||
mut nr_iters := 0
|
||||
for ctx.read_buf.len > 0 {
|
||||
nr_iters++
|
||||
if nr_iters > 100 { ctx.shift(1) }
|
||||
if nr_iters > 100 {
|
||||
ctx.shift(1)
|
||||
}
|
||||
mut event := &Event(0)
|
||||
if ctx.read_buf[0] == 0x1b {
|
||||
e, len := escape_sequence(ctx.read_buf.bytestr())
|
||||
@@ -272,41 +280,52 @@ fn single_char(buf string) &Event {
|
||||
|
||||
match ch {
|
||||
// special handling for `ctrl + letter`
|
||||
|
||||
// TODO: Fix assoc in V and remove this workaround :/
|
||||
// 1 ... 26 { event = Event{ ...event, code: KeyCode(96 | ch), modifiers: ctrl } }
|
||||
// 65 ... 90 { event = Event{ ...event, code: KeyCode(32 | ch), modifiers: shift } }
|
||||
|
||||
|
||||
// The bit `or`s here are really just `+`'s, just written in this way for a tiny performance improvement
|
||||
// don't treat tab, enter as ctrl+i, ctrl+j
|
||||
1 ... 8, 11 ... 26 { event = &Event{ typ: event.typ, ascii: event.ascii, utf8: event.utf8, code: KeyCode(96 | ch), modifiers: ctrl } }
|
||||
65 ... 90 { event = &Event{ typ: event.typ, ascii: event.ascii, utf8: event.utf8, code: KeyCode(32 | ch), modifiers: shift } }
|
||||
|
||||
1...8, 11...26 { event = &Event{
|
||||
typ: event.typ
|
||||
ascii: event.ascii
|
||||
utf8: event.utf8
|
||||
code: KeyCode(96 | ch)
|
||||
modifiers: ctrl
|
||||
} }
|
||||
65...90 { event = &Event{
|
||||
typ: event.typ
|
||||
ascii: event.ascii
|
||||
utf8: event.utf8
|
||||
code: KeyCode(32 | ch)
|
||||
modifiers: shift
|
||||
} }
|
||||
else {}
|
||||
}
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
[inline]
|
||||
// Gets an entire, independent escape sequence from the buffer
|
||||
// Normally, this just means reading until the first letter, but there are some exceptions...
|
||||
fn escape_end(buf string) int {
|
||||
mut i := 0
|
||||
for {
|
||||
if i + 1 == buf.len { return buf.len }
|
||||
if i + 1 == buf.len {
|
||||
return buf.len
|
||||
}
|
||||
|
||||
if buf[i].is_letter() || buf[i] == `~` {
|
||||
if buf[i] == `O` && i + 2 <= buf.len {
|
||||
n := buf[i+1]
|
||||
n := buf[i + 1]
|
||||
if (n >= `A` && n <= `D`) || (n >= `P` && n <= `S`) || n == `F` || n == `H` {
|
||||
return i + 2
|
||||
}
|
||||
}
|
||||
return i + 1
|
||||
// escape hatch to avoid potential issues/crashes, although ideally this should never eval to true
|
||||
} else if buf[i + 1] == 0x1b { return i + 1 }
|
||||
// escape hatch to avoid potential issues/crashes, although ideally this should never eval to true
|
||||
} else if buf[i + 1] == 0x1b {
|
||||
return i + 1
|
||||
}
|
||||
i++
|
||||
}
|
||||
// this point should be unreachable
|
||||
@@ -339,51 +358,85 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
||||
modifiers: c.modifiers | alt
|
||||
}, 2
|
||||
}
|
||||
|
||||
// ----------------
|
||||
// Mouse events
|
||||
// ----------------
|
||||
|
||||
// Documentation: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
if buf.len > 2 && buf[1] == `<` {
|
||||
split := buf[2..].split(';')
|
||||
if split.len < 3 { return &Event(0), 0 }
|
||||
if split.len < 3 {
|
||||
return &Event(0), 0
|
||||
}
|
||||
|
||||
typ, x, y := split[0].int(), split[1].int(), split[2].int()
|
||||
lo := typ & 0b00011
|
||||
hi := typ & 0b11100
|
||||
|
||||
mut modifiers := u32(0)
|
||||
if hi & 4 != 0 { modifiers |= shift }
|
||||
if hi & 8 != 0 { modifiers |= alt }
|
||||
if hi & 16 != 0 { modifiers |= ctrl }
|
||||
if hi & 4 != 0 {
|
||||
modifiers |= shift
|
||||
}
|
||||
if hi & 8 != 0 {
|
||||
modifiers |= alt
|
||||
}
|
||||
if hi & 16 != 0 {
|
||||
modifiers |= ctrl
|
||||
}
|
||||
|
||||
match typ {
|
||||
0...31 {
|
||||
last := buf[buf.len - 1]
|
||||
button := if lo < 3 { MouseButton(lo + 1) } else { MouseButton.unknown }
|
||||
event := if last == `m` || lo == 3 { EventType.mouse_up } else { EventType.mouse_down }
|
||||
event := if last == `m` || lo == 3 {
|
||||
EventType.mouse_up
|
||||
} else {
|
||||
EventType.mouse_down
|
||||
}
|
||||
|
||||
return &Event{ typ: event, x: x, y: y, button: button, modifiers: modifiers utf8: single }, end
|
||||
return &Event{
|
||||
typ: event
|
||||
x: x
|
||||
y: y
|
||||
button: button
|
||||
modifiers: modifiers
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
32...63 {
|
||||
button, event := if lo < 3 {
|
||||
MouseButton(lo + 1), EventType.mouse_drag
|
||||
} else {
|
||||
MouseButton.unknown, EventType.mouse_move
|
||||
}
|
||||
MouseButton(lo + 1), EventType.mouse_drag
|
||||
} else {
|
||||
MouseButton.unknown, EventType.mouse_move
|
||||
}
|
||||
|
||||
return &Event{ typ: event, x: x, y: y, button: button, modifiers: modifiers, utf8: single }, end
|
||||
return &Event{
|
||||
typ: event
|
||||
x: x
|
||||
y: y
|
||||
button: button
|
||||
modifiers: modifiers
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
64...95 {
|
||||
direction := if typ & 1 == 0 { Direction.down } else { Direction.up }
|
||||
return &Event{ typ: .mouse_scroll, x: x, y: y, direction: direction, modifiers: modifiers, utf8: single }, end
|
||||
} else {
|
||||
return &Event{ typ: .unknown, utf8: single }, end
|
||||
return &Event{
|
||||
typ: .mouse_scroll
|
||||
x: x
|
||||
y: y
|
||||
direction: direction
|
||||
modifiers: modifiers
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
else {
|
||||
return &Event{
|
||||
typ: .unknown
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// Special key combinations
|
||||
// ----------------------------
|
||||
@@ -391,29 +444,29 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
||||
mut code := KeyCode.null
|
||||
mut modifiers := u32(0)
|
||||
match buf {
|
||||
'[A', 'OA' { code = .up }
|
||||
'[B', 'OB' { code = .down }
|
||||
'[C', 'OC' { code = .right }
|
||||
'[D', 'OD' { code = .left }
|
||||
'[5~', '[[5~' { code = .page_up }
|
||||
'[6~', '[[6~' { code = .page_down }
|
||||
'[A', 'OA' { code = .up }
|
||||
'[B', 'OB' { code = .down }
|
||||
'[C', 'OC' { code = .right }
|
||||
'[D', 'OD' { code = .left }
|
||||
'[5~', '[[5~' { code = .page_up }
|
||||
'[6~', '[[6~' { code = .page_down }
|
||||
'[F', 'OF', '[4~', '[[8~' { code = .end }
|
||||
'[H', 'OH', '[1~', '[[7~' { code = .home }
|
||||
'[2~' { code = .insert }
|
||||
'[3~' { code = .delete }
|
||||
'OP', '[11~' { code = .f1 }
|
||||
'OQ', '[12~' { code = .f2 }
|
||||
'OR', '[13~' { code = .f3 }
|
||||
'OS', '[14~' { code = .f4 }
|
||||
'[15~' { code = .f5 }
|
||||
'[17~' { code = .f6 }
|
||||
'[18~' { code = .f7 }
|
||||
'[19~' { code = .f8 }
|
||||
'[20~' { code = .f9 }
|
||||
'[21~' { code = .f10 }
|
||||
'[23~' { code = .f11 }
|
||||
'[24~' { code = .f12 }
|
||||
else {}
|
||||
'[2~' { code = .insert }
|
||||
'[3~' { code = .delete }
|
||||
'OP', '[11~' { code = .f1 }
|
||||
'OQ', '[12~' { code = .f2 }
|
||||
'OR', '[13~' { code = .f3 }
|
||||
'OS', '[14~' { code = .f4 }
|
||||
'[15~' { code = .f5 }
|
||||
'[17~' { code = .f6 }
|
||||
'[18~' { code = .f7 }
|
||||
'[19~' { code = .f8 }
|
||||
'[20~' { code = .f9 }
|
||||
'[21~' { code = .f10 }
|
||||
'[23~' { code = .f11 }
|
||||
'[24~' { code = .f12 }
|
||||
else {}
|
||||
}
|
||||
|
||||
if buf == '[Z' {
|
||||
@@ -455,5 +508,10 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
||||
}
|
||||
}
|
||||
|
||||
return &Event{ typ: .key_down, code: code, utf8: single, modifiers: modifiers }, end
|
||||
return &Event{
|
||||
typ: .key_down
|
||||
code: code
|
||||
utf8: single
|
||||
modifiers: modifiers
|
||||
}, end
|
||||
}
|
||||
|
Reference in New Issue
Block a user