mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-02-07 20:19:18 +01:00
Implemented simple syntax highlighting and symbol-completion.
This commit is contained in:
parent
f6b7dce791
commit
c1facbe6f1
59
kalk_cli/Cargo.lock
generated
59
kalk_cli/Cargo.lock
generated
@ -1,5 +1,14 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
@ -86,22 +95,21 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "2.0.2"
|
||||
name = "dirs-next"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||
checksum = "1cbcf9241d9e8d106295bd496bbe2e9cffd5fa098f2a8c9e2bbcbf09773c11a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.4"
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||
checksum = "9c60f7b8a8953926148223260454befb50c751d3c50e1c178c4fd1ace4083c9a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
@ -143,6 +151,8 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"kalk",
|
||||
"phf",
|
||||
"regex",
|
||||
"rustyline",
|
||||
]
|
||||
|
||||
@ -328,6 +338,24 @@ dependencies = [
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
|
||||
|
||||
[[package]]
|
||||
name = "rug"
|
||||
version = "1.9.0"
|
||||
@ -353,12 +381,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustyline"
|
||||
version = "6.1.2"
|
||||
version = "6.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd20b28d972040c627e209eb29f19c24a71a19d661cc5a220089176e20ee202"
|
||||
checksum = "3358c21cbbc1a751892528db4e1de4b7a2b6a73f001e215aaba97d712cfa9777"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs",
|
||||
"dirs-next",
|
||||
"libc",
|
||||
"log",
|
||||
"memchr",
|
||||
@ -405,6 +433,15 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.6.0"
|
||||
|
@ -11,3 +11,5 @@ panic = "abort"
|
||||
kalk = { path = "../kalk" }
|
||||
rustyline = "6.1.2"
|
||||
ansi_term = "0.12"
|
||||
regex = "1"
|
||||
phf = { version = "0.8", features = ["macros"] }
|
||||
|
@ -1,12 +1,29 @@
|
||||
use crate::output;
|
||||
use ansi_term::Colour::Cyan;
|
||||
use ansi_term::Colour::{self, Cyan};
|
||||
use kalk::parser;
|
||||
use regex::Captures;
|
||||
use regex::Regex;
|
||||
use rustyline::completion::Completer;
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::Editor;
|
||||
use rustyline::highlight::Highlighter;
|
||||
use rustyline::hint::Hinter;
|
||||
use rustyline::hint::HistoryHinter;
|
||||
use rustyline::validate::MatchingBracketValidator;
|
||||
use rustyline::validate::ValidationContext;
|
||||
use rustyline::validate::ValidationResult;
|
||||
use rustyline::validate::Validator;
|
||||
use rustyline::{Editor, Helper};
|
||||
use std::borrow::Cow;
|
||||
use std::borrow::Cow::Owned;
|
||||
use std::process;
|
||||
|
||||
pub fn start(mut parser: &mut parser::Context) {
|
||||
let mut editor = Editor::<()>::new();
|
||||
let mut editor = Editor::<RLHelper>::new();
|
||||
editor.set_helper(Some(RLHelper {
|
||||
highlighter: LineHighlighter {},
|
||||
hinter: HistoryHinter {},
|
||||
validator: MatchingBracketValidator::new(),
|
||||
}));
|
||||
|
||||
loop {
|
||||
let readline = editor.readline(&Cyan.paint(">> ").to_string());
|
||||
@ -30,3 +47,106 @@ fn eval_repl(parser: &mut parser::Context, input: &str) {
|
||||
_ => output::eval(parser, input),
|
||||
}
|
||||
}
|
||||
|
||||
struct LineHighlighter {}
|
||||
|
||||
impl Highlighter for LineHighlighter {
|
||||
fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> {
|
||||
let mut coloured = line.to_string();
|
||||
|
||||
let reg = Regex::new(r"([A-z]+|[\+-/\*\^!])").unwrap();
|
||||
let unit = Regex::new(r"(deg|rad)").unwrap();
|
||||
let identifier = Regex::new(r"[^0-9\.,\(\)=\+-/\*\^!]+").unwrap();
|
||||
let op = Regex::new(r"[\+-/\*\^!]+").unwrap();
|
||||
|
||||
coloured = reg
|
||||
.replace_all(&coloured, |caps: &Captures| {
|
||||
let cap = &caps[0];
|
||||
|
||||
if unit.is_match(cap) {
|
||||
Colour::Yellow.paint(cap).to_string()
|
||||
} else if identifier.is_match(cap) {
|
||||
Colour::Blue.paint(cap).to_string()
|
||||
} else if op.is_match(cap) {
|
||||
Colour::Fixed(172).paint(cap).to_string()
|
||||
} else {
|
||||
cap.to_string()
|
||||
}
|
||||
})
|
||||
.to_string();
|
||||
|
||||
Owned(coloured)
|
||||
}
|
||||
}
|
||||
|
||||
struct RLHelper {
|
||||
highlighter: LineHighlighter,
|
||||
hinter: HistoryHinter,
|
||||
validator: MatchingBracketValidator,
|
||||
}
|
||||
|
||||
impl Helper for RLHelper {}
|
||||
|
||||
const COMPLETION_FUNCS: phf::Map<&'static str, &'static str> = phf::phf_map! {
|
||||
"sqrt" => "√",
|
||||
"deg" => "°",
|
||||
};
|
||||
|
||||
impl Completer for RLHelper {
|
||||
type Candidate = String;
|
||||
fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
pos: usize,
|
||||
_ctx: &rustyline::Context<'_>,
|
||||
) -> Result<(usize, Vec<Self::Candidate>), ReadlineError> {
|
||||
for key in COMPLETION_FUNCS.keys() {
|
||||
if line[..pos].ends_with(key) {
|
||||
return Ok((
|
||||
pos - key.len(),
|
||||
vec![String::from(*COMPLETION_FUNCS.get(key).unwrap())],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok((0, vec![line.to_string()]))
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn highlight_candidate<'c>(
|
||||
&self,
|
||||
candidate: &'c str,
|
||||
_completion: rustyline::CompletionType,
|
||||
) -> Cow<'c, str> {
|
||||
self.highlighter.highlight(candidate, 0)
|
||||
}
|
||||
|
||||
fn highlight_char(&self, line: &str, _: usize) -> bool {
|
||||
line.len() > 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Hinter for RLHelper {
|
||||
fn hint(&self, line: &str, a: usize, b: &rustyline::Context) -> Option<String> {
|
||||
self.hinter.hint(line, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl Validator for RLHelper {
|
||||
fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult, ReadlineError> {
|
||||
self.validator.validate(ctx)
|
||||
}
|
||||
|
||||
fn validate_while_typing(&self) -> bool {
|
||||
self.validator.validate_while_typing()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user