From cb3e69df8b17ffc0cab721e2dcc285731a1c5bc9 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Sun, 26 Dec 2021 14:09:27 +0100 Subject: Add functions to highlighting list --- src/readline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/readline.rs') diff --git a/src/readline.rs b/src/readline.rs index d689f95..2939ee1 100644 --- a/src/readline.rs +++ b/src/readline.rs @@ -55,7 +55,7 @@ impl Highlighter for LineHighlighter { let functions = [ "sin", "cos", "tan", "csc", "sec", "cot", "sinh", "cosh", "tanh", "ln", "log", "sqrt", "ceil", "floor", "rad", "deg", "abs", "asin", "acos", "atan", "acsc", - "asec", "acot", + "asec", "acot", "exp2", "exp" ]; let ops = Regex::new(r"(?P[\+-/\*%\^!])").unwrap(); let mut coloured: String = ops.replace_all(line, "\x1b[35m$o\x1b[0m").into(); -- cgit v1.2.3 From 4fd3ec330a89e4177099c21277d3c12e97ca0c21 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Sun, 26 Dec 2021 15:22:57 +0100 Subject: Update rustyline to v9 Also refresh line always. This isn't a big deal for the small expressions we have here and also fixes a few annoying issues I had with the highlighter. --- src/readline.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/readline.rs') diff --git a/src/readline.rs b/src/readline.rs index 2939ee1..f59cd22 100644 --- a/src/readline.rs +++ b/src/readline.rs @@ -7,6 +7,7 @@ use rustyline::error::ReadlineError; use rustyline::highlight::Highlighter; use rustyline::hint::{Hinter, HistoryHinter}; use rustyline::{Context, Editor, Helper}; +use rustyline::validate::Validator; use directories::ProjectDirs; @@ -75,6 +76,7 @@ impl Highlighter for LineHighlighter { } impl Highlighter for RLHelper { + fn highlight_char(&self, _: &str, _: usize) -> bool { true } fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { self.highlighter.highlight_hint(hint) } @@ -96,11 +98,14 @@ impl Completer for RLHelper { } impl Hinter for RLHelper { - fn hint(&self, line: &str, a: usize, b: &Context) -> Option { + type Hint = String; + fn hint(&self, line: &str, a: usize, b: &Context) -> Option { self.hinter.hint(line, a, b) } } +impl Validator for RLHelper {} + impl Helper for RLHelper {} pub fn create_readline() -> Editor { -- cgit v1.2.3 From acf947b608db99ff2e46a8020b6e70466c233088 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Sun, 26 Dec 2021 15:27:41 +0100 Subject: Fix highlighting of `e` vs `exp` --- src/readline.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/readline.rs') diff --git a/src/readline.rs b/src/readline.rs index f59cd22..9912af6 100644 --- a/src/readline.rs +++ b/src/readline.rs @@ -62,10 +62,12 @@ impl Highlighter for LineHighlighter { let mut coloured: String = ops.replace_all(line, "\x1b[35m$o\x1b[0m").into(); for c in &constants { - coloured = coloured.replace(c, &format!("\x1b[33m{}\x1b[0m", c)); + let re = Regex::new(format!("(?P{})(?P(\x1b\\[35m)?([\\+-/\\*%\\^! ]|$))", c).as_str()).unwrap(); + coloured = re.replace_all(&coloured, "\x1b[33m$o\x1b[0m$r").into(); } for f in &functions { - coloured = coloured.replace(f, &format!("\x1b[34m{}\x1b[0m", f)); + let re = Regex::new(format!("(?P{})(?P(\\(|$))", f).as_str()).unwrap(); + coloured = re.replace_all(&coloured, "\x1b[34m$o\x1b[0m$r").into(); } Owned(coloured) } -- cgit v1.2.3 From 7d1db014ebc6bf0a8fd3e5a25abdc81aa2270a1d Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Sun, 26 Dec 2021 15:31:13 +0100 Subject: Deduplicate references to functions & constants --- src/readline.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/readline.rs') diff --git a/src/readline.rs b/src/readline.rs index 9912af6..6734674 100644 --- a/src/readline.rs +++ b/src/readline.rs @@ -15,6 +15,7 @@ use regex::Regex; use crate::error::CalcError; use crate::eval_math_expression; +use crate::lex::{CONSTANTS, FUNCTIONS}; pub struct RLHelper { completer: FilenameCompleter, @@ -52,20 +53,16 @@ impl Highlighter for LineHighlighter { let op = eval_math_expression(line, prev_ans); match op { Ok(_) => { - let constants = ["e", "pi"]; - let functions = [ - "sin", "cos", "tan", "csc", "sec", "cot", "sinh", "cosh", "tanh", "ln", "log", - "sqrt", "ceil", "floor", "rad", "deg", "abs", "asin", "acos", "atan", "acsc", - "asec", "acot", "exp2", "exp" - ]; + let constants = CONSTANTS.keys(); + let functions = FUNCTIONS.keys(); let ops = Regex::new(r"(?P[\+-/\*%\^!])").unwrap(); let mut coloured: String = ops.replace_all(line, "\x1b[35m$o\x1b[0m").into(); - for c in &constants { + for c in constants { let re = Regex::new(format!("(?P{})(?P(\x1b\\[35m)?([\\+-/\\*%\\^! ]|$))", c).as_str()).unwrap(); coloured = re.replace_all(&coloured, "\x1b[33m$o\x1b[0m$r").into(); } - for f in &functions { + for f in functions { let re = Regex::new(format!("(?P{})(?P(\\(|$))", f).as_str()).unwrap(); coloured = re.replace_all(&coloured, "\x1b[34m$o\x1b[0m$r").into(); } -- cgit v1.2.3 From 3f0f8d9f0f910b4c9477297049d4a508eacc3734 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Tue, 4 Jan 2022 17:46:33 +0100 Subject: readline: explain constant highlighting regex --- src/readline.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/readline.rs') diff --git a/src/readline.rs b/src/readline.rs index 6734674..8906a4f 100644 --- a/src/readline.rs +++ b/src/readline.rs @@ -59,6 +59,22 @@ impl Highlighter for LineHighlighter { let mut coloured: String = ops.replace_all(line, "\x1b[35m$o\x1b[0m").into(); for c in constants { + // This regex consists of the following pieces: + // * the constant (`o`) to highlight (to be substituted as `{}` via `format!`), + // e.g. `e` or `pi`. + // * (optionally) an ANSI escape-code (`\x1b\[35m`) that is used to highlight + // a binary operator (e.g. `+`/`-`/...). With this one it is ensured that + // binary operators are always correctly detected after a constant + // (see the next bullet-point for why that's needed). + // * the following operator (e.g. `+`/`-`/...), a space or the end + // of the expression (to highlight e.g. `1+e` correctly). This is + // required to distinguish a constant in an expression from a function-call, + // e.g. `e+1` from `exp(1)`, without this matching logic, the `e` from + // `exp` would be improperly interpreted as constant. + // + // To make sure none of existing highlighting (i.e. highlighting + // of binary operators that happens before) breaks, the escape-codes & operator + // (called `r`) are appended after the highlighted constant. let re = Regex::new(format!("(?P{})(?P(\x1b\\[35m)?([\\+-/\\*%\\^! ]|$))", c).as_str()).unwrap(); coloured = re.replace_all(&coloured, "\x1b[33m$o\x1b[0m$r").into(); } -- cgit v1.2.3