1
0
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:
Delyan Angelov
2021-01-26 16:43:10 +02:00
parent 97103f680a
commit e5a84719ca
90 changed files with 1994 additions and 1832 deletions

View File

@@ -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
}