use nu_ansi_term::Style;
use nu_color_config::get_shape_color;
use nu_parser::{flatten_block, parse};
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
use std::sync::Arc;
pub struct HighlightedContent {
pub lines: Vec<String>,
}
pub fn highlight_nushell_content(
engine_state: &Arc<EngineState>,
stack: &Arc<Stack>,
content: &str,
) -> HighlightedContent {
if content.is_empty() {
return HighlightedContent {
lines: vec![String::new()],
};
}
let config = stack.get_config(engine_state);
let mut working_set = StateWorkingSet::new(engine_state);
let block = parse(&mut working_set, None, content.as_bytes(), false);
let shapes = flatten_block(&working_set, &block);
let global_span_offset = engine_state.next_span_start();
let mut result = String::new();
let mut last_seen_span_end = global_span_offset;
for (raw_span, flat_shape) in &shapes {
let span = if let nu_parser::FlatShape::External(alias_span) = flat_shape {
alias_span
} else {
raw_span
};
if span.end <= last_seen_span_end
|| last_seen_span_end < global_span_offset
|| span.start < global_span_offset
{
continue;
}
if span.start > last_seen_span_end {
let gap = &content
[(last_seen_span_end - global_span_offset)..(span.start - global_span_offset)];
result.push_str(gap);
}
let token = &content[(span.start - global_span_offset)..(span.end - global_span_offset)];
let style = get_shape_color(flat_shape.as_str(), &config);
result.push_str(&style.paint(token).to_string());
last_seen_span_end = span.end;
}
let remainder = &content[(last_seen_span_end - global_span_offset)..];
if !remainder.is_empty() {
result.push_str(&Style::new().paint(remainder).to_string());
}
let lines: Vec<String> = result.lines().map(|s| s.to_string()).collect();
let final_lines = if lines.is_empty() {
vec![String::new()]
} else {
lines
};
HighlightedContent { lines: final_lines }
}