use super::declaration::{Flag, Style, Verb, WrappedCommand};
use super::parse::{Call, Item};
pub(crate) struct Rendered {
pub(crate) argv: Vec<String>,
pub(crate) item_argv_index: Vec<usize>,
}
pub(crate) fn render(declaration: &WrappedCommand, verb: &Verb, call: &Call) -> Rendered {
let mut argv: Vec<String> = Vec::new();
argv.extend(declaration.lead.iter().cloned());
if !verb.omit_name
&& let Some(name) = &verb.name
{
argv.push(name.clone());
}
argv.extend(verb.lead.iter().cloned());
let mut item_argv_index = Vec::with_capacity(call.items.len());
for item in &call.items {
item_argv_index.push(argv.len());
match item {
Item::Positional { value, .. } => argv.push(value.clone()),
Item::Flag(use_index) => {
if let Some(use_) = call.flags.get(*use_index)
&& let Some(flag) = verb.flags.get(use_.flag_index)
{
render_flag(flag, use_.value.as_deref(), &mut argv);
}
}
Item::DashDash => argv.push("--".to_string()),
Item::Undeclared(word) => argv.push(word.clone()),
}
}
Rendered {
argv,
item_argv_index,
}
}
fn render_flag(flag: &Flag, value: Option<&str>, argv: &mut Vec<String>) {
let name = flag.written_name();
match value {
None => argv.push(name),
Some(value) => match flag.effective_style() {
Style::Equals => argv.push(format!("{name}={value}")),
Style::Separate => {
argv.push(name);
argv.push(value.to_string());
}
},
}
}