From 3e67571383b14fddf32383ab90f74b525ab33ad1 Mon Sep 17 00:00:00 2001 From: NerdyPepper Date: Mon, 24 Jun 2019 22:32:29 +0530 Subject: refactor readline code into separate module --- src/readline/mod.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/readline/mod.rs (limited to 'src/readline') 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 @@ +use std::borrow::Cow::{self,Owned}; + +use rustyline::error::ReadlineError; +use rustyline::{ Editor, Context, Helper }; +use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType }; +use rustyline::hint::Hinter; +use rustyline::completion::{ FilenameCompleter, Completer, Pair }; +use rustyline::highlight::Highlighter; + +use crate::eval_math_expression; + +pub struct RLHelper { + completer: FilenameCompleter, + highlighter: LineHighlighter, + hinter: AnswerHinter, +} + +struct AnswerHinter { } +impl Hinter for AnswerHinter { + fn hint(&self, line: &str, _: usize, _: &Context) -> Option { + let input = line.trim(); + let input = input.replace(" ", ""); + if input.len() == 0 { + return Some("".into()) + } + let dry_run = eval_math_expression(&input); + match dry_run { + Ok(ans) => return Some(format!(" = {}", ans)), + Err(_) => return Some(format!("")) + }; + } +} + +struct LineHighlighter { } +impl Highlighter for LineHighlighter { + fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { + Owned(format!("\x1b[90m{}\x1b[0m", hint)) + } + fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> { + let op = eval_math_expression(line); + match op { + Ok(_) => Owned(line.into()), + Err(_) => Owned(format!("\x1b[31m{}\x1b[0m", line)) + } + } +} + +impl Highlighter for RLHelper { + fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { + self.highlighter.highlight_hint(hint) + } + fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> { + self.highlighter.highlight(line, pos) + } +} + +impl Completer for RLHelper { + type Candidate = Pair; + fn complete( + &self, + line: &str, + pos: usize, + ctx: &Context<'_>, + ) -> Result<(usize, Vec), ReadlineError> { + self.completer.complete(line, pos, ctx) + } +} + +impl Hinter for RLHelper { + fn hint(&self, line: &str, a: usize, b: &Context) -> Option { + self.hinter.hint(line, a, b) + } +} + +impl Helper for RLHelper {} + +pub fn create_readline() -> Editor { + let config_builder = Builder::new(); + let config = config_builder.color_mode(ColorMode::Enabled) + .edit_mode(EditMode::Emacs) + .history_ignore_space(true) + .completion_type(CompletionType::Circular) + .max_history_size(1000) + .build(); + let mut rl = Editor::with_config(config); + let h = RLHelper { + completer: FilenameCompleter::new(), + highlighter: LineHighlighter {}, + hinter: AnswerHinter {} + }; + rl.set_helper(Some(h)); + return rl; +} -- cgit v1.2.3