Files
shed/src/expand/alias.rs
2025-03-07 03:36:25 -05:00

66 lines
1.7 KiB
Rust

use crate::{parse::lex::SEPARATORS, prelude::*};
pub fn expand_alias(candidate: Token, shenv: &mut ShEnv) -> Vec<Token> {
let mut tokens = vec![];
let mut work_stack = VecDeque::new();
let logic = shenv.logic().clone();
let mut done = false;
// Start with the candidate token in the work queue
work_stack.bpush(candidate);
// Process until there are no more tokens in the queue
while !done {
done = true;
while let Some(token) = work_stack.fpop() {
if token.rule() == TkRule::Ident {
let cand_str = token.as_raw(shenv);
if let Some(alias) = logic.get_alias(&cand_str) {
done = false;
if !token.span().borrow().expanded {
let mut new_tokens = shenv.expand_input(alias, token.span());
new_tokens.retain(|tk| tk.rule() != TkRule::Whitespace);
for token in &new_tokens {
tokens.push(token.clone());
}
}
} else {
tokens.push(token);
}
} else {
tokens.push(token);
}
}
if !done {
work_stack.extend(tokens.drain(..));
}
}
tokens
}
pub fn expand_aliases(tokens: Vec<Token>, shenv: &mut ShEnv) -> Vec<Token> {
let mut stream = tokens.iter();
let mut processed = vec![];
let mut is_command = true;
while let Some(token) = stream.next() {
match token.rule() {
_ if SEPARATORS.contains(&token.rule()) => {
is_command = true;
processed.push(token.clone());
}
TkRule::Ident if is_command => {
is_command = false;
let mut alias_tokens = expand_alias(token.clone(), shenv);
log!(DEBUG, alias_tokens);
if !alias_tokens.is_empty() {
processed.append(&mut alias_tokens);
} else {
processed.push(token.clone());
}
}
_ => processed.push(token.clone()),
}
}
processed
}