aboutsummaryrefslogtreecommitdiff
path: root/src/readline/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/readline/mod.rs')
-rw-r--r--src/readline/mod.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/readline/mod.rs b/src/readline/mod.rs
new file mode 100644
index 0000000..1f9fe98
--- /dev/null
+++ b/src/readline/mod.rs
@@ -0,0 +1,93 @@
1use std::borrow::Cow::{self,Owned};
2
3use rustyline::error::ReadlineError;
4use rustyline::{ Editor, Context, Helper };
5use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType };
6use rustyline::hint::Hinter;
7use rustyline::completion::{ FilenameCompleter, Completer, Pair };
8use rustyline::highlight::Highlighter;
9
10use crate::eval_math_expression;
11
12pub struct RLHelper {
13 completer: FilenameCompleter,
14 highlighter: LineHighlighter,
15 hinter: AnswerHinter,
16}
17
18struct AnswerHinter { }
19impl Hinter for AnswerHinter {
20 fn hint(&self, line: &str, _: usize, _: &Context) -> Option<String> {
21 let input = line.trim();
22 let input = input.replace(" ", "");
23 if input.len() == 0 {
24 return Some("".into())
25 }
26 let dry_run = eval_math_expression(&input);
27 match dry_run {
28 Ok(ans) => return Some(format!(" = {}", ans)),
29 Err(_) => return Some(format!(""))
30 };
31 }
32}
33
34struct LineHighlighter { }
35impl Highlighter for LineHighlighter {
36 fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
37 Owned(format!("\x1b[90m{}\x1b[0m", hint))
38 }
39 fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> {
40 let op = eval_math_expression(line);
41 match op {
42 Ok(_) => Owned(line.into()),
43 Err(_) => Owned(format!("\x1b[31m{}\x1b[0m", line))
44 }
45 }
46}
47
48impl Highlighter for RLHelper {
49 fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
50 self.highlighter.highlight_hint(hint)
51 }
52 fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
53 self.highlighter.highlight(line, pos)
54 }
55}
56
57impl Completer for RLHelper {
58 type Candidate = Pair;
59 fn complete(
60 &self,
61 line: &str,
62 pos: usize,
63 ctx: &Context<'_>,
64 ) -> Result<(usize, Vec<Pair>), ReadlineError> {
65 self.completer.complete(line, pos, ctx)
66 }
67}
68
69impl Hinter for RLHelper {
70 fn hint(&self, line: &str, a: usize, b: &Context) -> Option<String> {
71 self.hinter.hint(line, a, b)
72 }
73}
74
75impl Helper for RLHelper {}
76
77pub fn create_readline() -> Editor<RLHelper> {
78 let config_builder = Builder::new();
79 let config = config_builder.color_mode(ColorMode::Enabled)
80 .edit_mode(EditMode::Emacs)
81 .history_ignore_space(true)
82 .completion_type(CompletionType::Circular)
83 .max_history_size(1000)
84 .build();
85 let mut rl = Editor::with_config(config);
86 let h = RLHelper {
87 completer: FilenameCompleter::new(),
88 highlighter: LineHighlighter {},
89 hinter: AnswerHinter {}
90 };
91 rl.set_helper(Some(h));
92 return rl;
93}