Try to optimize
This commit is contained in:
@@ -16,39 +16,90 @@ pub enum TokenKind {
|
||||
Note,
|
||||
Interval,
|
||||
Variable,
|
||||
Emit,
|
||||
Vary,
|
||||
Generator,
|
||||
Default,
|
||||
}
|
||||
|
||||
impl TokenKind {
|
||||
pub fn style(self) -> Style {
|
||||
match self {
|
||||
TokenKind::Number => Style::default().fg(Color::Rgb(255, 180, 100)),
|
||||
TokenKind::String => Style::default().fg(Color::Rgb(150, 220, 150)),
|
||||
TokenKind::Comment => Style::default().fg(Color::Rgb(100, 100, 100)),
|
||||
TokenKind::Keyword => Style::default().fg(Color::Rgb(220, 120, 220)),
|
||||
TokenKind::StackOp => Style::default().fg(Color::Rgb(120, 180, 220)),
|
||||
TokenKind::Operator => Style::default().fg(Color::Rgb(200, 200, 130)),
|
||||
TokenKind::Sound => Style::default().fg(Color::Rgb(100, 220, 200)),
|
||||
TokenKind::Param => Style::default().fg(Color::Rgb(180, 150, 220)),
|
||||
TokenKind::Context => Style::default().fg(Color::Rgb(220, 180, 120)),
|
||||
TokenKind::Note => Style::default().fg(Color::Rgb(120, 200, 160)),
|
||||
TokenKind::Interval => Style::default().fg(Color::Rgb(160, 200, 120)),
|
||||
TokenKind::Variable => Style::default().fg(Color::Rgb(200, 140, 180)),
|
||||
TokenKind::Default => Style::default().fg(Color::Rgb(200, 200, 200)),
|
||||
TokenKind::Emit => Style::default()
|
||||
.fg(Color::Rgb(255, 255, 255))
|
||||
.bg(Color::Rgb(140, 50, 50))
|
||||
.add_modifier(Modifier::BOLD),
|
||||
TokenKind::Number => Style::default()
|
||||
.fg(Color::Rgb(255, 200, 120))
|
||||
.bg(Color::Rgb(60, 40, 15)),
|
||||
TokenKind::String => Style::default()
|
||||
.fg(Color::Rgb(150, 230, 150))
|
||||
.bg(Color::Rgb(20, 55, 20)),
|
||||
TokenKind::Comment => Style::default()
|
||||
.fg(Color::Rgb(100, 100, 100))
|
||||
.bg(Color::Rgb(18, 18, 18)),
|
||||
TokenKind::Keyword => Style::default()
|
||||
.fg(Color::Rgb(230, 130, 230))
|
||||
.bg(Color::Rgb(55, 25, 55)),
|
||||
TokenKind::StackOp => Style::default()
|
||||
.fg(Color::Rgb(130, 190, 240))
|
||||
.bg(Color::Rgb(20, 40, 70)),
|
||||
TokenKind::Operator => Style::default()
|
||||
.fg(Color::Rgb(220, 220, 140))
|
||||
.bg(Color::Rgb(45, 45, 20)),
|
||||
TokenKind::Sound => Style::default()
|
||||
.fg(Color::Rgb(100, 240, 220))
|
||||
.bg(Color::Rgb(15, 60, 55)),
|
||||
TokenKind::Param => Style::default()
|
||||
.fg(Color::Rgb(190, 160, 240))
|
||||
.bg(Color::Rgb(45, 30, 70)),
|
||||
TokenKind::Context => Style::default()
|
||||
.fg(Color::Rgb(240, 190, 120))
|
||||
.bg(Color::Rgb(60, 45, 20)),
|
||||
TokenKind::Note => Style::default()
|
||||
.fg(Color::Rgb(120, 220, 170))
|
||||
.bg(Color::Rgb(20, 55, 40)),
|
||||
TokenKind::Interval => Style::default()
|
||||
.fg(Color::Rgb(170, 220, 120))
|
||||
.bg(Color::Rgb(35, 55, 20)),
|
||||
TokenKind::Variable => Style::default()
|
||||
.fg(Color::Rgb(220, 150, 190))
|
||||
.bg(Color::Rgb(60, 30, 50)),
|
||||
TokenKind::Vary => Style::default()
|
||||
.fg(Color::Rgb(230, 230, 100))
|
||||
.bg(Color::Rgb(55, 55, 15)),
|
||||
TokenKind::Generator => Style::default()
|
||||
.fg(Color::Rgb(100, 220, 180))
|
||||
.bg(Color::Rgb(15, 55, 45)),
|
||||
TokenKind::Default => Style::default()
|
||||
.fg(Color::Rgb(160, 160, 160))
|
||||
.bg(Color::Rgb(25, 25, 25)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gap_style() -> Style {
|
||||
Style::default().bg(Color::Rgb(25, 25, 25))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Token {
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
pub kind: TokenKind,
|
||||
pub varargs: bool,
|
||||
}
|
||||
|
||||
fn lookup_word_kind(word: &str) -> Option<TokenKind> {
|
||||
fn lookup_word_kind(word: &str) -> Option<(TokenKind, bool)> {
|
||||
if word == "." {
|
||||
return Some((TokenKind::Emit, false));
|
||||
}
|
||||
if word == ".!" {
|
||||
return Some((TokenKind::Emit, true));
|
||||
}
|
||||
|
||||
for w in WORDS {
|
||||
if w.name == word || w.aliases.contains(&word) {
|
||||
return Some(match &w.compile {
|
||||
let kind = match &w.compile {
|
||||
WordCompile::Param => TokenKind::Param,
|
||||
WordCompile::Context(_) => TokenKind::Context,
|
||||
_ => match w.category {
|
||||
@@ -58,9 +109,12 @@ fn lookup_word_kind(word: &str) -> Option<TokenKind> {
|
||||
TokenKind::Operator
|
||||
}
|
||||
"Sound" => TokenKind::Sound,
|
||||
"Randomness" | "Probability" | "Selection" => TokenKind::Vary,
|
||||
"Generator" => TokenKind::Generator,
|
||||
_ => TokenKind::Keyword,
|
||||
},
|
||||
});
|
||||
};
|
||||
return Some((kind, w.varargs));
|
||||
}
|
||||
}
|
||||
None
|
||||
@@ -98,11 +152,11 @@ pub fn tokenize_line(line: &str) -> Vec<Token> {
|
||||
}
|
||||
|
||||
if c == ';' && chars.peek().map(|(_, ch)| *ch) == Some(';') {
|
||||
// ;; starts a comment to end of line
|
||||
tokens.push(Token {
|
||||
start,
|
||||
end: line.len(),
|
||||
kind: TokenKind::Comment,
|
||||
varargs: false,
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -119,6 +173,7 @@ pub fn tokenize_line(line: &str) -> Vec<Token> {
|
||||
start,
|
||||
end,
|
||||
kind: TokenKind::String,
|
||||
varargs: false,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -133,35 +188,35 @@ pub fn tokenize_line(line: &str) -> Vec<Token> {
|
||||
}
|
||||
|
||||
let word = &line[start..end];
|
||||
let kind = classify_word(word);
|
||||
tokens.push(Token { start, end, kind });
|
||||
let (kind, varargs) = classify_word(word);
|
||||
tokens.push(Token { start, end, kind, varargs });
|
||||
}
|
||||
|
||||
tokens
|
||||
}
|
||||
|
||||
fn classify_word(word: &str) -> TokenKind {
|
||||
fn classify_word(word: &str) -> (TokenKind, bool) {
|
||||
if word.parse::<f64>().is_ok() || word.parse::<i64>().is_ok() {
|
||||
return TokenKind::Number;
|
||||
return (TokenKind::Number, false);
|
||||
}
|
||||
|
||||
if let Some(kind) = lookup_word_kind(word) {
|
||||
return kind;
|
||||
if let Some((kind, varargs)) = lookup_word_kind(word) {
|
||||
return (kind, varargs);
|
||||
}
|
||||
|
||||
if INTERVALS.contains(&word) {
|
||||
return TokenKind::Interval;
|
||||
return (TokenKind::Interval, false);
|
||||
}
|
||||
|
||||
if is_note(&word.to_ascii_lowercase()) {
|
||||
return TokenKind::Note;
|
||||
return (TokenKind::Note, false);
|
||||
}
|
||||
|
||||
if word.len() > 1 && (word.starts_with('@') || word.starts_with('!')) {
|
||||
return TokenKind::Variable;
|
||||
return (TokenKind::Variable, false);
|
||||
}
|
||||
|
||||
TokenKind::Default
|
||||
(TokenKind::Default, false)
|
||||
}
|
||||
|
||||
pub fn highlight_line(line: &str) -> Vec<(Style, String)> {
|
||||
@@ -179,13 +234,11 @@ pub fn highlight_line_with_runtime(
|
||||
|
||||
let executed_bg = Color::Rgb(40, 35, 50);
|
||||
let selected_bg = Color::Rgb(80, 60, 20);
|
||||
let gap_style = TokenKind::gap_style();
|
||||
|
||||
for token in tokens {
|
||||
if token.start > last_end {
|
||||
result.push((
|
||||
TokenKind::Default.style(),
|
||||
line[last_end..token.start].to_string(),
|
||||
));
|
||||
result.push((gap_style, line[last_end..token.start].to_string()));
|
||||
}
|
||||
|
||||
let is_selected = selected_spans
|
||||
@@ -196,6 +249,9 @@ pub fn highlight_line_with_runtime(
|
||||
.any(|span| overlaps(token.start, token.end, span.start, span.end));
|
||||
|
||||
let mut style = token.kind.style();
|
||||
if token.varargs {
|
||||
style = style.add_modifier(Modifier::UNDERLINED);
|
||||
}
|
||||
if is_selected {
|
||||
style = style.bg(selected_bg).add_modifier(Modifier::BOLD);
|
||||
} else if is_executed {
|
||||
@@ -207,7 +263,7 @@ pub fn highlight_line_with_runtime(
|
||||
}
|
||||
|
||||
if last_end < line.len() {
|
||||
result.push((TokenKind::Default.style(), line[last_end..].to_string()));
|
||||
result.push((gap_style, line[last_end..].to_string()));
|
||||
}
|
||||
|
||||
result
|
||||
|
||||
Reference in New Issue
Block a user