use std::collections::BTreeSet;
use crate::parser::ast::{Argument, CommandInvocation};
use crate::spec::registry::CommandRegistry;
use crate::spec::{CommandForm, KwargSpec};
pub fn normalize_command_literals(command: &mut CommandInvocation) {
command.trailing_comment = None;
command
.arguments
.retain(|a| !matches!(a, Argument::InlineComment(_)));
for argument in &mut command.arguments {
match argument {
Argument::Bracket(bracket) => normalize_line_endings(&mut bracket.raw),
Argument::Quoted(value) | Argument::Unquoted(value) => normalize_line_endings(value),
Argument::InlineComment(_) => unreachable!(),
}
}
}
pub fn normalize_keyword_args(command: &mut CommandInvocation, registry: &CommandRegistry) {
let spec = registry.get(&command.name);
let first_arg = command.arguments.iter().find_map(first_arg_text);
let form = spec.form_for(first_arg);
let keyword_set = collect_keywords(form);
for arg in &mut command.arguments {
if let Argument::Unquoted(value) = arg {
let upper = value.to_ascii_uppercase();
if keyword_set.contains(upper.as_str()) {
*value = upper;
}
}
}
}
pub fn normalize_line_endings(value: &mut String) {
if value.contains('\r') {
*value = value.replace("\r\n", "\n");
}
}
fn first_arg_text(argument: &Argument) -> Option<&str> {
match argument {
Argument::Quoted(_) | Argument::Bracket(_) | Argument::InlineComment(_) => None,
Argument::Unquoted(value) => Some(value.as_str()),
}
}
fn collect_keywords(form: &CommandForm) -> BTreeSet<String> {
let mut keywords = BTreeSet::new();
collect_form_keywords(form, &mut keywords);
keywords
}
fn collect_form_keywords(form: &CommandForm, keywords: &mut BTreeSet<String>) {
keywords.extend(form.flags.iter().cloned());
for (name, spec) in &form.kwargs {
keywords.insert(name.clone());
collect_kwarg_keywords(spec, keywords);
}
}
fn collect_kwarg_keywords(spec: &KwargSpec, keywords: &mut BTreeSet<String>) {
keywords.extend(spec.flags.iter().cloned());
for (name, child) in &spec.kwargs {
keywords.insert(name.clone());
collect_kwarg_keywords(child, keywords);
}
}