readline: utf8 compatibility

pull/2083/head
Henrixounez 2019-09-23 12:43:24 +02:00 committed by Alexander Medvednikov
parent 23c84516e2
commit db44004d51
1 changed files with 33 additions and 31 deletions

View File

@ -35,12 +35,12 @@ struct Readline {
mut:
is_raw bool
orig_termios termios
current string // Line being edited
current ustring // Line being edited
cursor int // Cursor position
overwrite bool
cursor_row_offset int
prompt string
previous_lines []string
previous_lines []ustring
search_index int
is_tty bool
}
@ -109,25 +109,24 @@ pub fn (r Readline) disable_raw_mode() {
}
// Read single char
// TODO: Maybe handle UNICODE
fn (r Readline) read_char() byte {
return C.getchar()
fn (r Readline) read_char() int {
return utf8_getchar()
}
// Main function of the readline module
// Will loop and ingest characters until EOF or Enter
// Returns the completed line
pub fn (r mut Readline) read_line(prompt string) string {
r.current = ''
pub fn (r mut Readline) read_line_utf8(prompt string) ustring {
r.current = ''.ustring()
r.cursor = 0
r.prompt = prompt
r.search_index = 0
if r.previous_lines.len <= 1 {
r.previous_lines << ''
r.previous_lines << ''
r.previous_lines << ''.ustring()
r.previous_lines << ''.ustring()
}
else {
r.previous_lines[0] = ''
r.previous_lines[0] = ''.ustring()
}
print(r.prompt)
@ -138,11 +137,15 @@ pub fn (r mut Readline) read_line(prompt string) string {
break
}
}
r.previous_lines[0] = ''
r.previous_lines[0] = ''.ustring()
r.search_index = 0
return r.current
}
pub fn (r mut Readline) read_line(prompt string) string {
return r.read_line_utf8(prompt).s
}
fn (r Readline) analyse(c byte) Action {
switch c {
case `\0`: return Action.eof
@ -206,7 +209,7 @@ fn (r Readline) analyse_extended_control_no_eat(last_c byte) Action {
return Action.nothing
}
fn (r mut Readline) execute(a Action, c byte) bool {
fn (r mut Readline) execute(a Action, c int) bool {
switch a {
case Action.eof: return r.eof()
case Action.insert_character: r.insert_character(c)
@ -267,11 +270,10 @@ fn calculate_screen_position(x_in int, y_in int, screen_columns int, char_count
}
// Will redraw the line
// TODO: Fix if prompt is longer than terminal columns
fn (r mut Readline) refresh_line() {
mut end_of_input := [0, 0]
calculate_screen_position(r.prompt.len, 0, get_screen_columns(), r.current.len, mut end_of_input)
end_of_input[1] += r.current.count('\n')
end_of_input[1] += r.current.count('\n'.ustring())
mut cursor_pos := [0, 0]
calculate_screen_position(r.prompt.len, 0, get_screen_columns(), r.cursor, mut cursor_pos)
@ -289,19 +291,16 @@ fn (r mut Readline) refresh_line() {
// End the line without a newline
fn (r mut Readline) eof() bool {
r.previous_lines.insert(1, r.current)
r.cursor = r.current.len
r.refresh_line()
return true
}
fn (r mut Readline) insert_character(c byte) {
// Small ASCII, to expand
if c >= 127 {
return
}
// TODO: Add character if overwrite at end
fn (r mut Readline) insert_character(c int) {
if !r.overwrite || r.cursor == r.current.len {
r.current = r.current.left(r.cursor) + c.str() + r.current.right(r.cursor)
r.current = r.current.left(r.cursor).ustring() + utf32_to_str(u32(c)).ustring() + r.current.right(r.cursor).ustring()
} else {
r.current = r.current.left(r.cursor) + c.str() + r.current.right(r.cursor + 1)
r.current = r.current.left(r.cursor).ustring() + utf32_to_str(u32(c)).ustring() + r.current.right(r.cursor + 1).ustring()
}
r.cursor++
// Refresh the line to add the new character
@ -316,7 +315,7 @@ fn (r mut Readline) delete_character() {
return
}
r.cursor--
r.current = r.current.left(r.cursor) + r.current.right(r.cursor + 1)
r.current = r.current.left(r.cursor).ustring() + r.current.right(r.cursor + 1).ustring()
r.refresh_line()
}
@ -325,14 +324,17 @@ fn (r mut Readline) suppr_character() {
if r.cursor > r.current.len {
return
}
r.current = r.current.left(r.cursor) + r.current.right(r.cursor + 1)
r.current = r.current.left(r.cursor).ustring() + r.current.right(r.cursor + 1).ustring()
r.refresh_line()
}
// Add a line break then stops the main loop
fn (r mut Readline) commit_line() bool {
r.previous_lines.insert(1, r.current)
r.current = r.current + '\n'
a := '\n'.ustring()
r.current = r.current + a
r.cursor = r.current.len
r.refresh_line()
if r.is_tty {
println('')
}
@ -364,23 +366,23 @@ fn (r mut Readline) move_cursor_end() {
}
// Check if the character is considered as a word-breaking character
fn (r Readline) is_break_character(c byte) bool {
fn (r Readline) is_break_character(c string) bool {
break_characters := ' \t\v\f\a\b\r\n`~!@#$%^&*()-=+[{]}\\|;:\'",<.>/?'
return break_characters.contains(c.str())
return break_characters.contains(c)
}
fn (r mut Readline) move_cursor_word_left() {
if r.cursor > 0 {
for ; r.cursor > 0 && r.is_break_character(r.current[r.cursor - 1]); r.cursor-- {}
for ; r.cursor > 0 && !r.is_break_character(r.current[r.cursor - 1]); r.cursor-- {}
for ; r.cursor > 0 && r.is_break_character(r.current.at(r.cursor - 1)); r.cursor-- {}
for ; r.cursor > 0 && !r.is_break_character(r.current.at(r.cursor - 1)); r.cursor-- {}
r.refresh_line()
}
}
fn (r mut Readline) move_cursor_word_right() {
if r.cursor < r.current.len {
for ; r.cursor < r.current.len && r.is_break_character(r.current[r.cursor]); r.cursor++ {}
for ; r.cursor < r.current.len && !r.is_break_character(r.current[r.cursor]); r.cursor++ {}
for ; r.cursor < r.current.len && r.is_break_character(r.current.at(r.cursor)); r.cursor++ {}
for ; r.cursor < r.current.len && !r.is_break_character(r.current.at(r.cursor)); r.cursor++ {}
r.refresh_line()
}
}