use super::super::command_checker::CheckerEnv;
use super::super::highlight::{ColorSpan, HighlightStyle};
use super::ctx::ScanCtx;
use super::state::ScanMode;
pub(super) fn scan_parameter(
ctx: &mut ScanCtx<'_>,
_env: &CheckerEnv<'_>,
pos: usize,
start: usize,
_braced: bool,
) -> usize {
let mut p = pos;
while p < ctx.input.len() {
if ctx.input[p] == '}' {
ctx.spans.push(ColorSpan {
start,
end: p + 1,
style: HighlightStyle::Variable,
});
ctx.state.pop_mode();
return p + 1;
}
p += 1;
}
p
}
pub(super) fn scan_dollar(ctx: &mut ScanCtx<'_>, _env: &CheckerEnv<'_>, pos: usize) -> usize {
let next = if pos + 1 < ctx.input.len() {
Some(ctx.input[pos + 1])
} else {
None
};
match next {
Some('\'') => {
ctx.state
.push_mode(ScanMode::DollarSingleQuote { start: pos });
ctx.state.word_start = false;
ctx.state.command_position = false;
pos + 2 }
Some('(') => {
if pos + 2 < ctx.input.len() && ctx.input[pos + 2] == '(' {
ctx.state.push_mode(ScanMode::ArithSub { start: pos });
ctx.state.word_start = false;
ctx.state.command_position = false;
pos + 3 } else {
ctx.state.push_mode(ScanMode::CommandSub { start: pos });
ctx.state.push_mode(ScanMode::Normal);
ctx.state.word_start = true;
ctx.state.command_position = true;
pos + 2 }
}
Some('{') => {
ctx.state.push_mode(ScanMode::Parameter {
start: pos,
braced: true,
});
ctx.state.word_start = false;
ctx.state.command_position = false;
pos + 2 }
Some(c) if c.is_ascii_alphabetic() || c == '_' => {
let var_start = pos;
let mut end = pos + 1;
while end < ctx.input.len()
&& (ctx.input[end].is_ascii_alphanumeric() || ctx.input[end] == '_')
{
end += 1;
}
ctx.spans.push(ColorSpan {
start: var_start,
end,
style: HighlightStyle::Variable,
});
ctx.state.word_start = false;
ctx.state.command_position = false;
end
}
Some(c) if c.is_ascii_digit() || matches!(c, '@' | '*' | '#' | '?' | '-' | '$' | '!') => {
ctx.spans.push(ColorSpan {
start: pos,
end: pos + 2,
style: HighlightStyle::Variable,
});
ctx.state.word_start = false;
ctx.state.command_position = false;
pos + 2
}
_ => {
ctx.state.word_start = false;
pos + 1
}
}
}
pub(super) fn scan_arith_sub(
ctx: &mut ScanCtx<'_>,
_env: &CheckerEnv<'_>,
pos: usize,
start: usize,
) -> usize {
let mut p = pos;
while p + 1 < ctx.input.len() {
if ctx.input[p] == ')' && ctx.input[p + 1] == ')' {
ctx.spans.push(ColorSpan {
start,
end: p + 2,
style: HighlightStyle::ArithSub,
});
ctx.state.pop_mode();
return p + 2;
}
p += 1;
}
ctx.input.len()
}