From 1956c6f906c25a07273f5de9d45cbf116a9b602e Mon Sep 17 00:00:00 2001 From: Henrixounez <30901439+Henrixounez@users.noreply.github.com> Date: Wed, 16 Oct 2019 01:50:48 +0200 Subject: [PATCH] repl: readline line editing --- vlib/compiler/repl.v | 24 ++++++++----- vlib/readline/readline_js.v | 66 ++++++++++++++++++++++++++++++++++++ vlib/readline/readline_lin.v | 8 +++-- vlib/readline/readline_mac.v | 5 ++- vlib/readline/readline_win.v | 2 +- 5 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 vlib/readline/readline_js.v diff --git a/vlib/compiler/repl.v b/vlib/compiler/repl.v index 65b613634d..b7c0fb57c1 100644 --- a/vlib/compiler/repl.v +++ b/vlib/compiler/repl.v @@ -4,8 +4,11 @@ module compiler -import os -import term +import ( + os + term + readline +) struct Repl { mut: @@ -81,22 +84,27 @@ pub fn run_repl() []string { os.rm(temp_file.left(temp_file.len - 2)) } mut r := Repl{} + mut readline := readline.Readline{} vexe := os.args[0] + mut prompt := '>>> ' for { if r.indent == 0 { - print('>>> ') + prompt = '>>> ' } else { - print('... ') + prompt = '... ' } - r.line = os.get_raw_line() - if r.line.trim_space() == '' && r.line.ends_with('\n') { + mut line := readline.read_line(prompt) or { + break + } + if line.trim_space() == '' && line.ends_with('\n') { continue } - r.line = r.line.trim_space() - if r.line.len == -1 || r.line == '' || r.line == 'exit' { + line = line.trim_space() + if line.len <= -1 || line == '' || line == 'exit' { break } + r.line = line if r.line == '\n' { continue } diff --git a/vlib/readline/readline_js.v b/vlib/readline/readline_js.v new file mode 100644 index 0000000000..e96014db44 --- /dev/null +++ b/vlib/readline/readline_js.v @@ -0,0 +1,66 @@ +// 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. + +// JS version +// Need to be implemented +// Will serve as more advanced input method +// Based on the work of https://github.com/AmokHuginnsson/replxx + +module readline + +import os + +// Only use standard os.get_line +// Need implementation for readline capabilities +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 << ''.ustring() + r.previous_lines << ''.ustring() + } + else { + r.previous_lines[0] = ''.ustring() + } + + print(r.prompt) + r.current = os.get_raw_line().ustring() + + r.previous_lines[0] = ''.ustring() + r.search_index = 0 + if r.current.s == '' { + return error('empty line') + } + return r.current +} + +// Returns the string from the utf8 ustring +pub fn (r mut Readline) read_line(prompt string) ?string { + s := r.read_line_utf8(prompt) or { + return error(err) + } + return s.s +} + +// Standalone function without persistent functionnalities (eg: history) +// Returns utf8 based ustring +pub fn read_line_utf8(prompt string) ?ustring { + mut r := Readline{} + s := r.read_line_utf8(prompt) or { + return error(err) + } + return s +} + +// Standalone function without persistent functionnalities (eg: history) +// Return string from utf8 ustring +pub fn read_line(prompt string) ?string { + mut r := Readline{} + s := r.read_line(prompt) or { + return error(err) + } + return s +} diff --git a/vlib/readline/readline_lin.v b/vlib/readline/readline_lin.v index 591211e23e..1f13b6be5f 100644 --- a/vlib/readline/readline_lin.v +++ b/vlib/readline/readline_lin.v @@ -149,7 +149,7 @@ pub fn read_line(prompt string) ?string { return s } -fn (r Readline) analyse(c byte) Action { +fn (r Readline) analyse(c int) Action { switch c { case `\0`: return Action.eof case 0x3 : return Action.eof // End of Text @@ -295,7 +295,9 @@ fn (r mut Readline) refresh_line() { fn (r mut Readline) eof() bool { r.previous_lines.insert(1, r.current) r.cursor = r.current.len - r.refresh_line() + if r.is_tty { + r.refresh_line() + } return true } @@ -337,8 +339,8 @@ fn (r mut Readline) commit_line() bool { a := '\n'.ustring() r.current = r.current + a r.cursor = r.current.len - r.refresh_line() if r.is_tty { + r.refresh_line() println('') } return true diff --git a/vlib/readline/readline_mac.v b/vlib/readline/readline_mac.v index f177876132..7fd1a116cb 100644 --- a/vlib/readline/readline_mac.v +++ b/vlib/readline/readline_mac.v @@ -27,8 +27,11 @@ pub fn (r mut Readline) read_line_utf8(prompt string) ?ustring { } print(r.prompt) - r.current = os.get_line().ustring() + line := os.get_raw_line() + if line.len >= 0 { + r.current = line.ustring() + } r.previous_lines[0] = ''.ustring() r.search_index = 0 if r.current.s == '' { diff --git a/vlib/readline/readline_win.v b/vlib/readline/readline_win.v index 9eda679d52..5b7c17457f 100644 --- a/vlib/readline/readline_win.v +++ b/vlib/readline/readline_win.v @@ -27,7 +27,7 @@ pub fn (r mut Readline) read_line_utf8(prompt string) ?ustring { } print(r.prompt) - r.current = os.get_line().ustring() + r.current = os.get_raw_line().ustring() r.previous_lines[0] = ''.ustring() r.search_index = 0