mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
readline: multiline wrapping for editing and cursor
This commit is contained in:
parent
847b43f6e4
commit
fe3639d547
@ -11,7 +11,9 @@ module readline
|
|||||||
import term
|
import term
|
||||||
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
// Used to change the terminal options
|
||||||
struct termios {
|
struct termios {
|
||||||
mut:
|
mut:
|
||||||
c_iflag int
|
c_iflag int
|
||||||
@ -21,6 +23,14 @@ mut:
|
|||||||
c_cc [12]int //NCCS == 12. Cant use the defined value here
|
c_cc [12]int //NCCS == 12. Cant use the defined value here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to collect the screen informations
|
||||||
|
struct winsize {
|
||||||
|
ws_row u16
|
||||||
|
ws_col u16
|
||||||
|
ws_xpixel u16
|
||||||
|
ws_ypixel u16
|
||||||
|
}
|
||||||
|
|
||||||
struct Readline {
|
struct Readline {
|
||||||
mut:
|
mut:
|
||||||
is_raw bool
|
is_raw bool
|
||||||
@ -28,8 +38,10 @@ mut:
|
|||||||
current string // Line being edited
|
current string // Line being edited
|
||||||
cursor int // Cursor position
|
cursor int // Cursor position
|
||||||
overwrite bool
|
overwrite bool
|
||||||
|
cursor_row_offset int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Defines actions to execute
|
// Defines actions to execute
|
||||||
enum Action {
|
enum Action {
|
||||||
eof
|
eof
|
||||||
@ -171,13 +183,60 @@ fn (r mut Readline) execute(a Action, c byte) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_screen_columns() int {
|
||||||
|
ws := winsize{}
|
||||||
|
cols := if C.ioctl(1, C.TIOCGWINSZ, &ws) == -1 { 80 } else { ws.ws_col }
|
||||||
|
return int(cols)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shift_cursor(xpos int, yoffset int) {
|
||||||
|
if yoffset != 0 {
|
||||||
|
if yoffset > 0 {
|
||||||
|
term.cursor_down(yoffset)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
term.cursor_up(- yoffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Absolute X position
|
||||||
|
print('\x1b[${xpos + 1}G')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_screen_position(x_in int, y_in int, screen_columns int, char_count int, out mut []int) {
|
||||||
|
mut x := x_in
|
||||||
|
mut y := y_in
|
||||||
|
out[0] = x
|
||||||
|
out[1] = y
|
||||||
|
for chars_remaining := char_count; chars_remaining > 0; {
|
||||||
|
chars_this_row := if ( (x + chars_remaining) < screen_columns) { chars_remaining } else { screen_columns - x }
|
||||||
|
out[0] = x + chars_this_row
|
||||||
|
out[1] = y
|
||||||
|
chars_remaining -= chars_this_row
|
||||||
|
x = 0
|
||||||
|
y++
|
||||||
|
}
|
||||||
|
if out[0] == screen_columns {
|
||||||
|
out[0] = 0
|
||||||
|
out[1]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Will redraw the line
|
// Will redraw the line
|
||||||
// TODO: Refreshing on wrapped line
|
fn (r mut Readline) refresh_line() {
|
||||||
fn (r Readline) refresh_line() {
|
mut end_of_input := [0, 0]
|
||||||
term.cursor_back(r.cursor)
|
calculate_screen_position(0, 0, get_screen_columns(), r.current.len, mut end_of_input)
|
||||||
|
end_of_input[1] += r.current.count('\n')
|
||||||
|
mut cursor_pos := [0, 0]
|
||||||
|
calculate_screen_position(0, 0, get_screen_columns(), r.cursor, mut cursor_pos)
|
||||||
|
|
||||||
|
shift_cursor(0, -r.cursor_row_offset)
|
||||||
term.erase_toend()
|
term.erase_toend()
|
||||||
print(r.current)
|
print(r.current)
|
||||||
term.cursor_back(r.current.len - r.cursor)
|
if end_of_input[0] == 0 && end_of_input[1] > 0 {
|
||||||
|
print('\n')
|
||||||
|
}
|
||||||
|
shift_cursor(cursor_pos[0], - (end_of_input[1] - cursor_pos[1]))
|
||||||
|
r.cursor_row_offset = cursor_pos[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (r mut Readline) insert_character(c byte) {
|
fn (r mut Readline) insert_character(c byte) {
|
||||||
@ -194,7 +253,7 @@ fn (r mut Readline) insert_character(c byte) {
|
|||||||
r.cursor++
|
r.cursor++
|
||||||
// Simply print new character if at end of line
|
// Simply print new character if at end of line
|
||||||
// Otherwise refresh the line if cursor != r.current.len
|
// Otherwise refresh the line if cursor != r.current.len
|
||||||
if r.cursor == r.current.len {
|
if r.cursor == r.current.len && r.current.len < get_screen_columns() {
|
||||||
print(c.str())
|
print(c.str())
|
||||||
} else {
|
} else {
|
||||||
r.refresh_line()
|
r.refresh_line()
|
||||||
@ -206,9 +265,9 @@ fn (r mut Readline) delete_character() {
|
|||||||
if r.cursor <= 0 {
|
if r.cursor <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.current = r.current.left(r.cursor - 1) + r.current.right(r.cursor)
|
|
||||||
r.refresh_line()
|
|
||||||
r.cursor--
|
r.cursor--
|
||||||
|
r.current = r.current.left(r.cursor) + r.current.right(r.cursor + 1)
|
||||||
|
r.refresh_line()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a line break then stops the main loop
|
// Add a line break then stops the main loop
|
||||||
@ -217,55 +276,48 @@ fn (r mut Readline) commit_line() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiline wrapping
|
|
||||||
fn (r mut Readline) move_cursor_left() {
|
fn (r mut Readline) move_cursor_left() {
|
||||||
if r.cursor > 0 {
|
if r.cursor > 0 {
|
||||||
term.cursor_back(1)
|
|
||||||
r.cursor--
|
r.cursor--
|
||||||
|
r.refresh_line()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiline wrapping
|
|
||||||
fn (r mut Readline) move_cursor_right() {
|
fn (r mut Readline) move_cursor_right() {
|
||||||
if r.cursor < r.current.len {
|
if r.cursor < r.current.len {
|
||||||
term.cursor_forward(1)
|
|
||||||
r.cursor++
|
r.cursor++
|
||||||
|
r.refresh_line()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiline wrapping
|
|
||||||
fn (r mut Readline) move_cursor_begining() {
|
fn (r mut Readline) move_cursor_begining() {
|
||||||
term.cursor_back(r.cursor)
|
|
||||||
r.cursor = 0
|
r.cursor = 0
|
||||||
|
r.refresh_line()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiline wrapping
|
|
||||||
fn (r mut Readline) move_cursor_end() {
|
fn (r mut Readline) move_cursor_end() {
|
||||||
term.cursor_forward(r.current.len - r.cursor)
|
|
||||||
r.cursor = r.current.len
|
r.cursor = r.current.len
|
||||||
|
r.refresh_line()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 byte) bool {
|
||||||
break_characters := ' \t\v\f\a\b\r\n`~!@#$%^&*()-=+[{]}\\|;:\'",<.>/?'
|
break_characters := ' \t\v\f\a\b\r\n`~!@#$%^&*()-=+[{]}\\|;:\'",<.>/?'
|
||||||
return break_characters.contains(c.str())
|
return break_characters.contains(c.str())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiline wrapping
|
|
||||||
fn (r mut Readline) move_cursor_word_left() {
|
fn (r mut Readline) move_cursor_word_left() {
|
||||||
if r.cursor > 0 {
|
if r.cursor > 0 {
|
||||||
initial := 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[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[r.cursor - 1]); r.cursor-- {}
|
||||||
term.cursor_back(initial - r.cursor)
|
r.refresh_line()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiline wrapping
|
|
||||||
fn (r mut Readline) move_cursor_word_right() {
|
fn (r mut Readline) move_cursor_word_right() {
|
||||||
if r.cursor < r.current.len {
|
if r.cursor < r.current.len {
|
||||||
initial := 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[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[r.cursor]); r.cursor++ {}
|
||||||
term.cursor_forward(r.cursor - initial)
|
r.refresh_line()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user