1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

vrepl: add support for Home and End keys (#16116)

This commit is contained in:
locriacyber 2022-10-20 17:07:57 +00:00 committed by GitHub
parent f8a28b5a5d
commit a3b050aced
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 60 deletions

View File

@ -57,30 +57,3 @@ pub fn string_from_wide2(_wstr &u16, len int) string {
return '' return ''
} }
} }
// Reads an utf8 character from standard input
pub fn utf8_getchar() int {
c := C.getchar()
len := utf8_len(u8(~c))
if c < 0 {
return 0
} else if len == 0 {
return c
} else if len == 1 {
return -1
} else {
mut uc := c & ((1 << (7 - len)) - 1)
for i := 0; i + 1 < len; i++ {
c2 := C.getchar()
if c2 != -1 && (c2 >> 6) == 2 {
uc <<= 6
uc |= (c2 & 63)
} else if c2 == -1 {
return 0
} else {
return -1
}
}
return uc
}
}

View File

@ -124,29 +124,6 @@ pub fn (_bytes []u8) utf8_to_utf32() ?rune {
return res return res
} }
// Calculate length to read from the first byte
fn utf8_len(c u8) int {
mut b := 0
mut x := c
if (x & 240) != 0 {
// 0xF0
x >>= 4
} else {
b += 4
}
if (x & 12) != 0 {
// 0x0C
x >>= 2
} else {
b += 2
}
if (x & 2) == 0 {
// 0x02
b++
}
return b
}
// Calculate string length for formatting, i.e. number of "characters" // Calculate string length for formatting, i.e. number of "characters"
// This is simplified implementation. if you need specification compliant width, // This is simplified implementation. if you need specification compliant width,
// use utf8.east_asian.display_width. // use utf8.east_asian.display_width.

View File

@ -122,8 +122,8 @@ pub fn (mut r Readline) disable_raw_mode() {
} }
// read_char reads a single character. // read_char reads a single character.
pub fn (r Readline) read_char() int { pub fn (r Readline) read_char() !int {
return utf8_getchar() return int(term.utf8_getchar() or { return err })
} }
// read_line_utf8 blocks execution in a loop and awaits user input // read_line_utf8 blocks execution in a loop and awaits user input
@ -151,7 +151,7 @@ pub fn (mut r Readline) read_line_utf8(prompt string) ?[]rune {
print(r.prompt) print(r.prompt)
for { for {
unsafe { C.fflush(C.stdout) } unsafe { C.fflush(C.stdout) }
c := r.read_char() c := r.read_char() or { return err }
a := r.analyse(c) a := r.analyse(c)
if r.execute(a, c) { if r.execute(a, c) {
break break
@ -239,15 +239,17 @@ fn (r Readline) analyse(c int) Action {
// analyse_control returns an `Action` based on the type of input read by `read_char`. // analyse_control returns an `Action` based on the type of input read by `read_char`.
fn (r Readline) analyse_control() Action { fn (r Readline) analyse_control() Action {
c := r.read_char() c := r.read_char() or { panic('Control sequence incomplete') }
match u8(c) { match u8(c) {
`[` { `[` {
sequence := r.read_char() sequence := r.read_char() or { panic('Control sequence incomplete') }
match u8(sequence) { match u8(sequence) {
`C` { return .move_cursor_right } `C` { return .move_cursor_right }
`D` { return .move_cursor_left } `D` { return .move_cursor_left }
`B` { return .history_next } `B` { return .history_next }
`A` { return .history_previous } `A` { return .history_previous }
`H` { return .move_cursor_begining }
`F` { return .move_cursor_end }
`1` { return r.analyse_extended_control() } `1` { return r.analyse_extended_control() }
`2`, `3` { return r.analyse_extended_control_no_eat(u8(sequence)) } `2`, `3` { return r.analyse_extended_control_no_eat(u8(sequence)) }
else {} else {}
@ -259,7 +261,7 @@ fn (r Readline) analyse_control() Action {
//TODO //TODO
match c { match c {
case `[`: case `[`:
sequence := r.read_char() sequence := r.read_char()?
match sequence { match sequence {
case `C`: return .move_cursor_right case `C`: return .move_cursor_right
case `D`: return .move_cursor_left case `D`: return .move_cursor_left
@ -282,11 +284,11 @@ match c {
// analyse_extended_control returns an `Action` based on the type of input read by `read_char`. // analyse_extended_control returns an `Action` based on the type of input read by `read_char`.
// analyse_extended_control specialises in cursor control. // analyse_extended_control specialises in cursor control.
fn (r Readline) analyse_extended_control() Action { fn (r Readline) analyse_extended_control() Action {
r.read_char() // Removes ; r.read_char() or { panic('Control sequence incomplete') } // Removes ;
c := r.read_char() c := r.read_char() or { panic('Control sequence incomplete') }
match u8(c) { match u8(c) {
`5` { `5` {
direction := r.read_char() direction := r.read_char() or { panic('Control sequence incomplete') }
match u8(direction) { match u8(direction) {
`C` { return .move_cursor_word_right } `C` { return .move_cursor_word_right }
`D` { return .move_cursor_word_left } `D` { return .move_cursor_word_left }
@ -301,7 +303,7 @@ fn (r Readline) analyse_extended_control() Action {
// analyse_extended_control_no_eat returns an `Action` based on the type of input byte given in `c`. // analyse_extended_control_no_eat returns an `Action` based on the type of input byte given in `c`.
// analyse_extended_control_no_eat specialises in detection of delete and insert keys. // analyse_extended_control_no_eat specialises in detection of delete and insert keys.
fn (r Readline) analyse_extended_control_no_eat(last_c u8) Action { fn (r Readline) analyse_extended_control_no_eat(last_c u8) Action {
c := r.read_char() c := r.read_char() or { panic('Control sequence incomplete') }
match u8(c) { match u8(c) {
`~` { `~` {
match last_c { match last_c {

6
vlib/term/utf8.c.v Normal file
View File

@ -0,0 +1,6 @@
module term
[inline]
fn getchar() int {
return C.getchar()
}

54
vlib/term/utf8.v Normal file
View File

@ -0,0 +1,54 @@
module term
// utf8_getchar returns an utf8 rune from standard input
pub fn utf8_getchar() ?rune {
c := getchar()
if c == C.EOF {
return none
}
len := utf8_len(u8(~c))
if c < 0 {
return 0
} else if len == 0 {
return c
} else if len == 1 {
return -1
} else {
mut uc := c & ((1 << (7 - len)) - 1)
for i := 0; i + 1 < len; i++ {
c2 := getchar()
if c2 != -1 && (c2 >> 6) == 2 {
uc <<= 6
uc |= (c2 & 63)
} else if c2 == -1 {
return 0
} else {
return -1
}
}
return uc
}
}
// utf8_len calculates the length of a utf8 rune to read, according to its first byte
pub fn utf8_len(c u8) int {
mut b := 0
mut x := c
if (x & 240) != 0 {
// 0xF0
x >>= 4
} else {
b += 4
}
if (x & 12) != 0 {
// 0x0C
x >>= 2
} else {
b += 2
}
if (x & 2) == 0 {
// 0x02
b++
}
return b
}