diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 95 |
1 files changed, 84 insertions, 11 deletions
diff --git a/src/main.rs b/src/main.rs index ffdb690..a8fbcf2 100644 --- a/src/main.rs +++ b/src/main.rs | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | // std | 7 | // std |
| 8 | use std::f64; | 8 | use std::f64; |
| 9 | use std::borrow::Cow::{self, Borrowed, Owned}; | ||
| 9 | 10 | ||
| 10 | // modules | 11 | // modules |
| 11 | mod lex; | 12 | mod lex; |
| @@ -19,14 +20,80 @@ use crate::format::*; | |||
| 19 | 20 | ||
| 20 | // extern crates | 21 | // extern crates |
| 21 | use rustyline::error::ReadlineError; | 22 | use rustyline::error::ReadlineError; |
| 22 | use rustyline::Editor; | 23 | use rustyline::{ Editor, Context, Helper }; |
| 23 | use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType }; | 24 | use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType }; |
| 25 | use rustyline::hint::Hinter; | ||
| 26 | use rustyline::completion::{ FilenameCompleter, Completer, Pair }; | ||
| 24 | use rustyline::highlight::{ Highlighter, MatchingBracketHighlighter }; | 27 | use rustyline::highlight::{ Highlighter, MatchingBracketHighlighter }; |
| 25 | use rustyline::hint::{ Hinter, HistoryHinter }; | 28 | |
| 26 | use clap::{Arg, App}; | 29 | use clap::{Arg, App}; |
| 27 | use lazy_static::lazy_static; | 30 | use lazy_static::lazy_static; |
| 28 | 31 | ||
| 29 | struct LineHelper (MatchingBracketHighlighter, HistoryHinter); | 32 | |
| 33 | struct RLHelper { | ||
| 34 | completer: FilenameCompleter, | ||
| 35 | highlighter: LineHighlighter, | ||
| 36 | hinter: AnswerHinter, | ||
| 37 | } | ||
| 38 | |||
| 39 | struct AnswerHinter { } | ||
| 40 | impl Hinter for AnswerHinter { | ||
| 41 | fn hint(&self, line: &str, _: usize, _: &Context) -> Option<String> { | ||
| 42 | let input = line.trim(); | ||
| 43 | let input = input.replace(" ", ""); | ||
| 44 | if input.len() == 0 { | ||
| 45 | return Some("".into()) | ||
| 46 | } | ||
| 47 | let dry_run = eval_math_expression(&input); | ||
| 48 | match dry_run { | ||
| 49 | Ok(ans) => return Some(format!(" = {}", ans)), | ||
| 50 | Err(_) => return Some(format!("")) | ||
| 51 | }; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | struct LineHighlighter { } | ||
| 56 | impl Highlighter for LineHighlighter { | ||
| 57 | fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { | ||
| 58 | Owned(format!("\x1b[90m{}\x1b[0m", hint)) | ||
| 59 | } | ||
| 60 | fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> { | ||
| 61 | let op = eval_math_expression(line); | ||
| 62 | match op { | ||
| 63 | Ok(_) => Owned(line.into()), | ||
| 64 | Err(_) => Owned(format!("\x1b[31m{}\x1b[0m", line)) | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | impl Highlighter for RLHelper { | ||
| 70 | fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { | ||
| 71 | self.highlighter.highlight_hint(hint) | ||
| 72 | } | ||
| 73 | fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> { | ||
| 74 | self.highlighter.highlight(line, pos) | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | impl Completer for RLHelper { | ||
| 79 | type Candidate = Pair; | ||
| 80 | fn complete( | ||
| 81 | &self, | ||
| 82 | line: &str, | ||
| 83 | pos: usize, | ||
| 84 | ctx: &Context<'_>, | ||
| 85 | ) -> Result<(usize, Vec<Pair>), ReadlineError> { | ||
| 86 | self.completer.complete(line, pos, ctx) | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | impl Hinter for RLHelper { | ||
| 91 | fn hint(&self, line: &str, a: usize, b: &Context) -> Option<String> { | ||
| 92 | self.hinter.hint(line, a, b) | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | impl Helper for RLHelper {} | ||
| 30 | 97 | ||
| 31 | struct Configuration { | 98 | struct Configuration { |
| 32 | radian_mode: bool, | 99 | radian_mode: bool, |
| @@ -57,10 +124,16 @@ fn main() { | |||
| 57 | .completion_type(CompletionType::Circular) | 124 | .completion_type(CompletionType::Circular) |
| 58 | .max_history_size(1000) | 125 | .max_history_size(1000) |
| 59 | .build(); | 126 | .build(); |
| 60 | let mut rl = Editor::<()>::with_config(config); | 127 | let mut rl = Editor::with_config(config); |
| 128 | let h = RLHelper { | ||
| 129 | completer: FilenameCompleter::new(), | ||
| 130 | highlighter: LineHighlighter {}, | ||
| 131 | hinter: AnswerHinter {} | ||
| 132 | }; | ||
| 133 | rl.set_helper(Some(h)); | ||
| 61 | if rl.load_history("history.txt").is_err() { | 134 | if rl.load_history("history.txt").is_err() { |
| 62 | println!("No previous history."); | 135 | println!("No previous history.") |
| 63 | } | 136 | }; |
| 64 | 137 | ||
| 65 | loop { | 138 | loop { |
| 66 | let readline = rl.readline("> "); | 139 | let readline = rl.readline("> "); |
| @@ -127,11 +200,11 @@ fn parse_arguments() -> Configuration { | |||
| 127 | .unwrap_or("10") | 200 | .unwrap_or("10") |
| 128 | .parse() | 201 | .parse() |
| 129 | .unwrap(), | 202 | .unwrap(), |
| 130 | base: config.value_of("base") | 203 | base: config.value_of("base") |
| 131 | .unwrap_or("10") | 204 | .unwrap_or("10") |
| 132 | .parse() | 205 | .parse() |
| 133 | .unwrap(), | 206 | .unwrap(), |
| 134 | input, | 207 | input, |
| 135 | } | 208 | } |
| 136 | } | 209 | } |
| 137 | 210 | ||
