mirror of https://github.com/boa-dev/boa.git
HalidOdat
4 years ago
committed by
GitHub
2 changed files with 165 additions and 132 deletions
@ -0,0 +1,158 @@ |
|||||||
|
use colored::*; |
||||||
|
use lazy_static::lazy_static; |
||||||
|
use regex::{Captures, Regex}; |
||||||
|
use rustyline::{ |
||||||
|
error::ReadlineError, |
||||||
|
highlight::Highlighter, |
||||||
|
validate::{MatchingBracketValidator, ValidationContext, ValidationResult, Validator}, |
||||||
|
}; |
||||||
|
use rustyline_derive::{Completer, Helper, Hinter}; |
||||||
|
use std::borrow::Cow; |
||||||
|
use std::collections::HashSet; |
||||||
|
|
||||||
|
const STRING_COLOR: Color = Color::Green; |
||||||
|
const KEYWORD_COLOR: Color = Color::Yellow; |
||||||
|
const PROPERTY_COLOR: Color = Color::Magenta; |
||||||
|
const OPERATOR_COLOR: Color = Color::TrueColor { |
||||||
|
r: 214, |
||||||
|
g: 95, |
||||||
|
b: 26, |
||||||
|
}; |
||||||
|
const UNDEFINED_COLOR: Color = Color::TrueColor { |
||||||
|
r: 100, |
||||||
|
g: 100, |
||||||
|
b: 100, |
||||||
|
}; |
||||||
|
|
||||||
|
#[derive(Completer, Helper, Hinter)] |
||||||
|
pub(crate) struct RLHelper { |
||||||
|
highlighter: LineHighlighter, |
||||||
|
validator: MatchingBracketValidator, |
||||||
|
} |
||||||
|
|
||||||
|
impl RLHelper { |
||||||
|
#[inline] |
||||||
|
pub(crate) fn new() -> Self { |
||||||
|
Self { |
||||||
|
highlighter: LineHighlighter, |
||||||
|
validator: MatchingBracketValidator::new(), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Highlighter for RLHelper { |
||||||
|
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { |
||||||
|
hint.into() |
||||||
|
} |
||||||
|
|
||||||
|
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.is_empty() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
lazy_static! { |
||||||
|
static ref KEYWORDS: HashSet<&'static str> = { |
||||||
|
let mut keywords = HashSet::new(); |
||||||
|
keywords.insert("break"); |
||||||
|
keywords.insert("case"); |
||||||
|
keywords.insert("catch"); |
||||||
|
keywords.insert("class"); |
||||||
|
keywords.insert("const"); |
||||||
|
keywords.insert("continue"); |
||||||
|
keywords.insert("default"); |
||||||
|
keywords.insert("delete"); |
||||||
|
keywords.insert("do"); |
||||||
|
keywords.insert("else"); |
||||||
|
keywords.insert("export"); |
||||||
|
keywords.insert("extends"); |
||||||
|
keywords.insert("finally"); |
||||||
|
keywords.insert("for"); |
||||||
|
keywords.insert("function"); |
||||||
|
keywords.insert("if"); |
||||||
|
keywords.insert("import"); |
||||||
|
keywords.insert("instanceof"); |
||||||
|
keywords.insert("new"); |
||||||
|
keywords.insert("return"); |
||||||
|
keywords.insert("super"); |
||||||
|
keywords.insert("switch"); |
||||||
|
keywords.insert("this"); |
||||||
|
keywords.insert("throw"); |
||||||
|
keywords.insert("try"); |
||||||
|
keywords.insert("typeof"); |
||||||
|
keywords.insert("var"); |
||||||
|
keywords.insert("void"); |
||||||
|
keywords.insert("while"); |
||||||
|
keywords.insert("with"); |
||||||
|
keywords.insert("yield"); |
||||||
|
keywords.insert("await"); |
||||||
|
keywords.insert("enum"); |
||||||
|
keywords.insert("let"); |
||||||
|
keywords |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
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#"(?x) |
||||||
|
(?P<identifier>[$A-z_]+[$A-z_0-9]*) | |
||||||
|
(?P<string_double_quote>"([^"\\]|\\.)*") | |
||||||
|
(?P<string_single_quote>'([^'\\]|\\.)*') | |
||||||
|
(?P<op>[+\-/*%~^!&|=<>;:])"#,
|
||||||
|
) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
coloured = reg |
||||||
|
.replace_all(&coloured, |caps: &Captures<'_>| { |
||||||
|
if let Some(cap) = caps.name("identifier") { |
||||||
|
match cap.as_str() { |
||||||
|
"true" | "false" | "null" | "Infinity" | "globalThis" => { |
||||||
|
cap.as_str().color(PROPERTY_COLOR).to_string() |
||||||
|
} |
||||||
|
"undefined" => cap.as_str().color(UNDEFINED_COLOR).to_string(), |
||||||
|
identifier if KEYWORDS.contains(identifier) => { |
||||||
|
cap.as_str().color(KEYWORD_COLOR).bold().to_string() |
||||||
|
} |
||||||
|
_ => cap.as_str().to_string(), |
||||||
|
} |
||||||
|
} else if let Some(cap) = caps.name("string_double_quote") { |
||||||
|
cap.as_str().color(STRING_COLOR).to_string() |
||||||
|
} else if let Some(cap) = caps.name("string_single_quote") { |
||||||
|
cap.as_str().color(STRING_COLOR).to_string() |
||||||
|
} else if let Some(cap) = caps.name("op") { |
||||||
|
cap.as_str().color(OPERATOR_COLOR).to_string() |
||||||
|
} else { |
||||||
|
caps[0].to_string() |
||||||
|
} |
||||||
|
}) |
||||||
|
.to_string(); |
||||||
|
|
||||||
|
coloured.into() |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue