Some highlighter bug fixes
This commit is contained in:
@@ -191,6 +191,7 @@ fn fern_interactive() -> ShResult<()> {
|
|||||||
// Process any available input
|
// Process any available input
|
||||||
match readline.process_input() {
|
match readline.process_input() {
|
||||||
Ok(ReadlineEvent::Line(input)) => {
|
Ok(ReadlineEvent::Line(input)) => {
|
||||||
|
let start = Instant::now();
|
||||||
write_meta(|m| m.start_timer());
|
write_meta(|m| m.start_timer());
|
||||||
if let Err(e) = exec_input(input, None, true) {
|
if let Err(e) = exec_input(input, None, true) {
|
||||||
match e.kind() {
|
match e.kind() {
|
||||||
@@ -201,10 +202,14 @@ fn fern_interactive() -> ShResult<()> {
|
|||||||
_ => eprintln!("{e}"),
|
_ => eprintln!("{e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let command_run_time = start.elapsed();
|
||||||
write_meta(|m| m.stop_timer());
|
write_meta(|m| m.stop_timer());
|
||||||
|
|
||||||
// Reset for next command with fresh prompt
|
// Reset for next command with fresh prompt
|
||||||
readline.reset(get_prompt().ok());
|
readline.reset(get_prompt().ok());
|
||||||
|
let real_end = start.elapsed();
|
||||||
|
log::info!("Command execution time: {:.2?}", command_run_time);
|
||||||
|
log::info!("Total round trip time: {:.2?}", real_end);
|
||||||
}
|
}
|
||||||
Ok(ReadlineEvent::Eof) => {
|
Ok(ReadlineEvent::Eof) => {
|
||||||
// Ctrl+D on empty line
|
// Ctrl+D on empty line
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
pub mod highlight;
|
|
||||||
pub mod readline;
|
pub mod readline;
|
||||||
pub mod statusline;
|
pub mod statusline;
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,16 @@ pub mod markers {
|
|||||||
pub const GLOB: char = '\u{fdde}';
|
pub const GLOB: char = '\u{fdde}';
|
||||||
|
|
||||||
pub const RESET: char = '\u{fde2}';
|
pub const RESET: char = '\u{fde2}';
|
||||||
|
|
||||||
|
pub const END_MARKERS: [char;7] = [
|
||||||
|
VAR_SUB_END,
|
||||||
|
CMD_SUB_END,
|
||||||
|
PROC_SUB_END,
|
||||||
|
STRING_DQ_END,
|
||||||
|
STRING_SQ_END,
|
||||||
|
SUBSH_END,
|
||||||
|
RESET
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Non-blocking readline result
|
/// Non-blocking readline result
|
||||||
@@ -161,6 +171,8 @@ impl FernVi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cmd.should_submit() {
|
if cmd.should_submit() {
|
||||||
|
self.editor.set_hint(None);
|
||||||
|
self.print_line()?;
|
||||||
self.writer.flush_write("\n")?;
|
self.writer.flush_write("\n")?;
|
||||||
let buf = self.editor.take_buf();
|
let buf = self.editor.take_buf();
|
||||||
// Save command to history
|
// Save command to history
|
||||||
@@ -512,6 +524,63 @@ pub fn marker_for(class: &TkRule) -> Option<char> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn annotate_token(input: &mut String, token: Tk) {
|
pub fn annotate_token(input: &mut String, token: Tk) {
|
||||||
|
let sort_insertions = |insertions: &mut Vec<(usize, char)>| {
|
||||||
|
insertions.sort_by(|a, b| {
|
||||||
|
match b.0.cmp(&a.0) {
|
||||||
|
std::cmp::Ordering::Equal => {
|
||||||
|
let priority = |m: char| -> u8 {
|
||||||
|
match m {
|
||||||
|
markers::RESET => 0,
|
||||||
|
markers::VAR_SUB_END |
|
||||||
|
markers::CMD_SUB_END |
|
||||||
|
markers::PROC_SUB_END |
|
||||||
|
markers::STRING_DQ_END |
|
||||||
|
markers::STRING_SQ_END |
|
||||||
|
markers::SUBSH_END => 2,
|
||||||
|
_ => 1,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
priority(a.1).cmp(&priority(b.1))
|
||||||
|
}
|
||||||
|
other => other,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let in_context = |c: char, insertions: &[(usize, char)]| -> bool {
|
||||||
|
let mut stack = insertions.to_vec();
|
||||||
|
stack.sort_by(|a, b| {
|
||||||
|
match b.0.cmp(&a.0) {
|
||||||
|
std::cmp::Ordering::Equal => {
|
||||||
|
let priority = |m: char| -> u8 {
|
||||||
|
match m {
|
||||||
|
markers::RESET => 0,
|
||||||
|
markers::VAR_SUB_END |
|
||||||
|
markers::CMD_SUB_END |
|
||||||
|
markers::PROC_SUB_END |
|
||||||
|
markers::STRING_DQ_END |
|
||||||
|
markers::STRING_SQ_END |
|
||||||
|
markers::SUBSH_END => 2,
|
||||||
|
_ => 1,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
priority(a.1).cmp(&priority(b.1))
|
||||||
|
}
|
||||||
|
other => other,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stack.retain(|(i, m)| *i <= token.span.start && !markers::END_MARKERS.contains(m));
|
||||||
|
|
||||||
|
log::error!("Checking context for token '{}', looking for '{}'", token.span.as_str(), c);
|
||||||
|
let Some(ctx) = stack.last() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
log::error!("Context stack for token '{}': {:?}", token.span.as_str(), stack);
|
||||||
|
log::error!("Found context marker '{}' at position {}", ctx.1, ctx.0);
|
||||||
|
|
||||||
|
ctx.1 == c
|
||||||
|
};
|
||||||
|
|
||||||
if token.class != TkRule::Str
|
if token.class != TkRule::Str
|
||||||
&& let Some(marker) = marker_for(&token.class) {
|
&& let Some(marker) = marker_for(&token.class) {
|
||||||
input.insert(token.span.end, markers::RESET);
|
input.insert(token.span.end, markers::RESET);
|
||||||
@@ -545,6 +614,8 @@ pub fn annotate_token(input: &mut String, token: Tk) {
|
|||||||
insertions.insert(0, (span_start, markers::BUILTIN));
|
insertions.insert(0, (span_start, markers::BUILTIN));
|
||||||
} else if token.flags.contains(TkFlags::IS_CMD) {
|
} else if token.flags.contains(TkFlags::IS_CMD) {
|
||||||
insertions.insert(0, (span_start, markers::COMMAND));
|
insertions.insert(0, (span_start, markers::COMMAND));
|
||||||
|
} else if !token.flags.contains(TkFlags::KEYWORD) && !token.flags.contains(TkFlags::ASSIGN) {
|
||||||
|
insertions.insert(0, (span_start, markers::ARG));
|
||||||
}
|
}
|
||||||
|
|
||||||
if token.flags.contains(TkFlags::KEYWORD) {
|
if token.flags.contains(TkFlags::KEYWORD) {
|
||||||
@@ -590,7 +661,7 @@ pub fn annotate_token(input: &mut String, token: Tk) {
|
|||||||
'{' if cmd_sub_depth == 0 => {
|
'{' if cmd_sub_depth == 0 => {
|
||||||
insertions.push((span_start + dollar_pos, markers::VAR_SUB));
|
insertions.push((span_start + dollar_pos, markers::VAR_SUB));
|
||||||
token_chars.next(); // consume the brace
|
token_chars.next(); // consume the brace
|
||||||
let mut end_pos = dollar_pos + 2; // position after ${
|
let mut end_pos; // position after ${
|
||||||
while let Some((cur_i, br_ch)) = token_chars.peek() {
|
while let Some((cur_i, br_ch)) = token_chars.peek() {
|
||||||
end_pos = *cur_i;
|
end_pos = *cur_i;
|
||||||
// TODO: implement better parameter expansion awareness here
|
// TODO: implement better parameter expansion awareness here
|
||||||
@@ -705,7 +776,10 @@ pub fn annotate_token(input: &mut String, token: Tk) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
'*' | '?' if (!in_dub_qt && !in_sng_qt) => {
|
'*' | '?' if (!in_dub_qt && !in_sng_qt) => {
|
||||||
|
if !in_context(markers::COMMAND, &insertions) {
|
||||||
|
insertions.push((span_start + *i + 1, markers::RESET));
|
||||||
insertions.push((span_start + *i, markers::GLOB));
|
insertions.push((span_start + *i, markers::GLOB));
|
||||||
|
}
|
||||||
token_chars.next(); // consume the glob char
|
token_chars.next(); // consume the glob char
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -719,21 +793,7 @@ pub fn annotate_token(input: &mut String, token: Tk) {
|
|||||||
// - Regular markers middle
|
// - Regular markers middle
|
||||||
// - END markers last (inserted last, ends up leftmost)
|
// - END markers last (inserted last, ends up leftmost)
|
||||||
// Result: [END][TOGGLE][RESET]
|
// Result: [END][TOGGLE][RESET]
|
||||||
insertions.sort_by(|a, b| {
|
sort_insertions(&mut insertions);
|
||||||
match b.0.cmp(&a.0) {
|
|
||||||
std::cmp::Ordering::Equal => {
|
|
||||||
let priority = |m: char| -> u8 {
|
|
||||||
match m {
|
|
||||||
markers::RESET => 0,
|
|
||||||
markers::VAR_SUB_END | markers::CMD_SUB_END => 2,
|
|
||||||
_ => 1,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
priority(a.1).cmp(&priority(b.1))
|
|
||||||
}
|
|
||||||
other => other,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (pos, marker) in insertions {
|
for (pos, marker) in insertions {
|
||||||
let pos = pos.max(0).min(input.len());
|
let pos = pos.max(0).min(input.len());
|
||||||
|
|||||||
Reference in New Issue
Block a user