Early implementation of scripting elements
This commit is contained in:
@@ -1,75 +1,62 @@
|
||||
use crate::{parse::lex::SEPARATORS, prelude::*};
|
||||
|
||||
pub fn expand_aliases(input: &str, shenv: &mut ShEnv) -> Option<String> {
|
||||
let mut result = input.to_string();
|
||||
let mut expanded_aliases = Vec::new();
|
||||
let mut found_in_iteration = true;
|
||||
pub fn expand_alias(candidate: Token, shenv: &mut ShEnv) -> Vec<Token> {
|
||||
let mut tokens = vec![];
|
||||
let mut work_stack = VecDeque::new();
|
||||
let mut expanded_aliases = vec![];
|
||||
let logic = shenv.logic().clone();
|
||||
|
||||
// Loop until no new alias expansion happens.
|
||||
while found_in_iteration {
|
||||
found_in_iteration = false;
|
||||
let mut new_result = String::new();
|
||||
let mut chars = result.chars().peekable();
|
||||
let mut alias_cand = String::new();
|
||||
let mut is_cmd = true;
|
||||
// Start with the candidate token in the work queue
|
||||
work_stack.bpush(candidate);
|
||||
|
||||
while let Some(ch) = chars.next() {
|
||||
match ch {
|
||||
';' | '\n' => {
|
||||
new_result.push(ch);
|
||||
is_cmd = true;
|
||||
// Consume any extra whitespace or delimiters.
|
||||
while let Some(&next_ch) = chars.peek() {
|
||||
if matches!(next_ch, ' ' | '\t' | ';' | '\n') {
|
||||
new_result.push(next_ch);
|
||||
chars.next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
// Process until there are no more tokens in the queue
|
||||
while let Some(token) = work_stack.fpop() {
|
||||
if token.rule() == TkRule::Ident {
|
||||
let candidate_str = token.as_raw(shenv);
|
||||
if let Some(alias) = logic.get_alias(&candidate_str) {
|
||||
// Expand the alias only if it hasn't been expanded yet
|
||||
if !expanded_aliases.contains(&candidate_str) {
|
||||
expanded_aliases.push(candidate_str);
|
||||
let mut new_tokens = shenv.expand_input(alias, token.span());
|
||||
for token in new_tokens.iter_mut() {
|
||||
work_stack.bpush(token.clone());
|
||||
}
|
||||
} else {
|
||||
// If already expanded, just add the token to the output
|
||||
tokens.push(token);
|
||||
}
|
||||
' ' | '\t' => {
|
||||
is_cmd = false;
|
||||
new_result.push(ch);
|
||||
}
|
||||
_ if is_cmd => {
|
||||
// Accumulate token characters.
|
||||
alias_cand.push(ch);
|
||||
while let Some(&next_ch) = chars.peek() {
|
||||
if matches!(next_ch, ' ' | '\t' | ';' | '\n') {
|
||||
break;
|
||||
} else {
|
||||
alias_cand.push(next_ch);
|
||||
chars.next();
|
||||
}
|
||||
}
|
||||
// Check for an alias expansion.
|
||||
if let Some(alias) = shenv.logic().get_alias(&alias_cand) {
|
||||
// Only expand if we haven't already done so.
|
||||
if !expanded_aliases.contains(&alias_cand) {
|
||||
new_result.push_str(alias);
|
||||
expanded_aliases.push(alias_cand.clone());
|
||||
found_in_iteration = true;
|
||||
} else {
|
||||
new_result.push_str(&alias_cand);
|
||||
}
|
||||
} else {
|
||||
new_result.push_str(&alias_cand);
|
||||
}
|
||||
alias_cand.clear();
|
||||
}
|
||||
_ => {
|
||||
new_result.push(ch);
|
||||
} else {
|
||||
tokens.push(token);
|
||||
}
|
||||
} else {
|
||||
tokens.push(token);
|
||||
}
|
||||
}
|
||||
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()),
|
||||
}
|
||||
result = new_result;
|
||||
log!(DEBUG, result);
|
||||
}
|
||||
|
||||
if expanded_aliases.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(result)
|
||||
}
|
||||
processed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user