2021-07-22 19:50:59 +00:00
|
|
|
use nu_ansi_term::Style;
|
2021-09-02 18:21:37 +00:00
|
|
|
use nu_parser::{flatten_block, parse_source, FlatShape};
|
|
|
|
use nu_protocol::engine::{EngineState, StateWorkingSet};
|
2021-07-22 19:50:59 +00:00
|
|
|
use reedline::{Highlighter, StyledText};
|
2021-07-22 07:48:45 +00:00
|
|
|
use std::{cell::RefCell, rc::Rc};
|
2021-07-17 06:31:34 +00:00
|
|
|
|
2021-07-22 19:50:59 +00:00
|
|
|
pub struct NuHighlighter {
|
2021-09-02 08:25:22 +00:00
|
|
|
pub engine_state: Rc<RefCell<EngineState>>,
|
2021-07-22 07:48:45 +00:00
|
|
|
}
|
2021-07-17 06:31:34 +00:00
|
|
|
|
2021-07-22 19:50:59 +00:00
|
|
|
impl Highlighter for NuHighlighter {
|
|
|
|
fn highlight(&self, line: &str) -> StyledText {
|
|
|
|
let (shapes, global_span_offset) = {
|
2021-09-02 08:25:22 +00:00
|
|
|
let engine_state = self.engine_state.borrow();
|
|
|
|
let mut working_set = StateWorkingSet::new(&*engine_state);
|
2021-09-02 18:21:37 +00:00
|
|
|
let (block, _) = parse_source(&mut working_set, line.as_bytes(), false);
|
2021-07-17 06:31:34 +00:00
|
|
|
|
2021-09-02 18:21:37 +00:00
|
|
|
let shapes = flatten_block(&working_set, &block);
|
2021-09-02 08:25:22 +00:00
|
|
|
(shapes, engine_state.next_span_start())
|
2021-07-22 07:48:45 +00:00
|
|
|
};
|
2021-07-17 06:31:34 +00:00
|
|
|
|
2021-07-22 19:50:59 +00:00
|
|
|
let mut output = StyledText::default();
|
|
|
|
let mut last_seen_span = global_span_offset;
|
2021-07-22 07:48:45 +00:00
|
|
|
|
2021-07-22 19:50:59 +00:00
|
|
|
for shape in &shapes {
|
|
|
|
if shape.0.end <= last_seen_span {
|
|
|
|
// We've already output something for this span
|
|
|
|
// so just skip this one
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if shape.0.start > last_seen_span {
|
|
|
|
let gap = line
|
|
|
|
[(last_seen_span - global_span_offset)..(shape.0.start - global_span_offset)]
|
|
|
|
.to_string();
|
|
|
|
output.push((Style::new(), gap));
|
|
|
|
}
|
2021-07-22 07:48:45 +00:00
|
|
|
|
2021-07-22 19:50:59 +00:00
|
|
|
let next_token = line
|
|
|
|
[(shape.0.start - global_span_offset)..(shape.0.end - global_span_offset)]
|
|
|
|
.to_string();
|
|
|
|
match shape.1 {
|
|
|
|
FlatShape::External => output.push((Style::new().bold(), next_token)),
|
|
|
|
FlatShape::Garbage => output.push((
|
|
|
|
Style::new()
|
|
|
|
.fg(nu_ansi_term::Color::White)
|
|
|
|
.on(nu_ansi_term::Color::Red)
|
|
|
|
.bold(),
|
|
|
|
next_token,
|
|
|
|
)),
|
|
|
|
FlatShape::InternalCall => output.push((
|
|
|
|
Style::new().fg(nu_ansi_term::Color::LightBlue).bold(),
|
|
|
|
next_token,
|
|
|
|
)),
|
|
|
|
FlatShape::Int => {
|
|
|
|
output.push((Style::new().fg(nu_ansi_term::Color::Green), next_token))
|
|
|
|
}
|
2021-08-08 20:21:21 +00:00
|
|
|
FlatShape::Float => {
|
|
|
|
output.push((Style::new().fg(nu_ansi_term::Color::Green), next_token))
|
|
|
|
}
|
2021-07-24 05:57:17 +00:00
|
|
|
FlatShape::Bool => {
|
|
|
|
output.push((Style::new().fg(nu_ansi_term::Color::LightCyan), next_token))
|
|
|
|
}
|
2021-07-22 19:50:59 +00:00
|
|
|
FlatShape::Literal => {
|
|
|
|
output.push((Style::new().fg(nu_ansi_term::Color::Blue), next_token))
|
|
|
|
}
|
|
|
|
FlatShape::Operator => output.push((
|
|
|
|
Style::new().fg(nu_ansi_term::Color::LightPurple).bold(),
|
|
|
|
next_token,
|
|
|
|
)),
|
|
|
|
FlatShape::Signature => output.push((
|
|
|
|
Style::new().fg(nu_ansi_term::Color::Green).bold(),
|
|
|
|
next_token,
|
|
|
|
)),
|
|
|
|
FlatShape::String => output.push((
|
|
|
|
Style::new().fg(nu_ansi_term::Color::Yellow).bold(),
|
|
|
|
next_token,
|
|
|
|
)),
|
|
|
|
FlatShape::Variable => output.push((
|
|
|
|
Style::new().fg(nu_ansi_term::Color::Blue).bold(),
|
|
|
|
next_token,
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
last_seen_span = shape.0.end;
|
|
|
|
}
|
|
|
|
|
|
|
|
let remainder = line[(last_seen_span - global_span_offset)..].to_string();
|
|
|
|
if !remainder.is_empty() {
|
|
|
|
output.push((Style::new(), remainder));
|
|
|
|
}
|
2021-07-17 06:31:34 +00:00
|
|
|
|
2021-07-22 19:50:59 +00:00
|
|
|
output
|
2021-07-22 07:48:45 +00:00
|
|
|
}
|
2021-07-17 06:31:34 +00:00
|
|
|
}
|