From a9a4032a11f3cf2f97df0322f2482bcec98a7bee Mon Sep 17 00:00:00 2001 From: Henrixounez Date: Fri, 30 Aug 2019 20:57:54 +0200 Subject: [PATCH] readline: basic reading on linux --- vlib/readline/readline_lin.v | 105 +++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 vlib/readline/readline_lin.v diff --git a/vlib/readline/readline_lin.v b/vlib/readline/readline_lin.v new file mode 100644 index 0000000000..47bfd2bd22 --- /dev/null +++ b/vlib/readline/readline_lin.v @@ -0,0 +1,105 @@ +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +// Linux version +// Will serve as more advanced input method +// Based on the work of https://github.com/AmokHuginnsson/replxx + +module readline + +#include + +struct termios { +mut: + c_iflag int + c_oflag int + c_cflag int + c_lflag int + c_cc [12]int //NCCS == 12. Cant use the defined value here +} + +struct Readline { +pub mut: + is_raw bool + orig_termios termios +} + +// Toggle raw mode of the terminal by changing its attributes +pub fn (r mut Readline) enable_raw_mode() { + if ( C.tcgetattr(0, &r.orig_termios) == -1 ) { + panic('No tty') + } + mut raw := r.orig_termios + raw.c_iflag &= ~( C.BRKINT | C.ICRNL | C.INPCK | C.ISTRIP | C.IXON ) + raw.c_cflag |= ( C.CS8 ) + raw.c_lflag &= ~( C.ECHO | C.ICANON | C.IEXTEN | C.ISIG ) + raw.c_cc[C.VMIN] = 1 + raw.c_cc[C.VTIME] = 0 + C.tcsetattr(0, C.TCSADRAIN, &raw) + r.is_raw = true +} + +// Not catching the SIGUSER (CTRL+C) Signal +pub fn (r Readline) enable_raw_mode2() { + if ( C.tcgetattr(0, &r.orig_termios) == -1 ) { + panic('No tty') + } + mut raw := r.orig_termios + raw.c_iflag &= ~( C.BRKINT | C.ICRNL | C.INPCK | C.ISTRIP | C.IXON ) + raw.c_cflag |= ( C.CS8 ) + raw.c_lflag &= ~( C.ECHO | C.ICANON | C.IEXTEN ) + raw.c_cc[C.VMIN] = 1 + raw.c_cc[C.VTIME] = 0 + C.tcsetattr(0, C.TCSADRAIN, &raw) +} + +// Reset back the terminal to its default value +pub fn (r Readline) disable_raw_mode() { + if r.is_raw { + C.tcsetattr(0, C.TCSADRAIN, &r.orig_termios) + } +} + +// Read single char +fn (r Readline) read_char() byte { + return C.getchar() +} + +// Delete character in the string and in the terminal +fn (r Readline) delete_character(s string, cursor int) string { + print('\b \b') + return s.left(cursor - 1) + s.right(cursor) +} + +pub fn (r Readline) read_line() string { + mut s := '' + mut cursor := 0 + + for { + c := r.read_char() + // Check if ending string + if c == `\0` || c == 0x3 || c == 0x4 || c == 255 { + break + } + // Check if backspace + if c == `\b` || c == 127 { + if cursor > 0 { + s = r.delete_character(s, cursor) + cursor-- + } + } else { + // Add new character according to cursor position + s = s.left(cursor) + c.str() + s.right(cursor) + cursor++ + } + // Check if enter + if c == `\n` || c == `\r` { + println('') + break + } else { + print(c.str()) + } + } + return s +} \ No newline at end of file