119625d8cSopenharmony_ciuse std::io::Write; 219625d8cSopenharmony_ci 319625d8cSopenharmony_ciuse clap::builder::StyledStr; 419625d8cSopenharmony_ciuse clap::*; 519625d8cSopenharmony_ci 619625d8cSopenharmony_ciuse crate::generator::{utils, Generator}; 719625d8cSopenharmony_ciuse crate::INTERNAL_ERROR_MSG; 819625d8cSopenharmony_ci 919625d8cSopenharmony_ci/// Generate elvish completion file 1019625d8cSopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq, Debug)] 1119625d8cSopenharmony_cipub struct Elvish; 1219625d8cSopenharmony_ci 1319625d8cSopenharmony_ciimpl Generator for Elvish { 1419625d8cSopenharmony_ci fn file_name(&self, name: &str) -> String { 1519625d8cSopenharmony_ci format!("{name}.elv") 1619625d8cSopenharmony_ci } 1719625d8cSopenharmony_ci 1819625d8cSopenharmony_ci fn generate(&self, cmd: &Command, buf: &mut dyn Write) { 1919625d8cSopenharmony_ci let bin_name = cmd 2019625d8cSopenharmony_ci .get_bin_name() 2119625d8cSopenharmony_ci .expect("crate::generate should have set the bin_name"); 2219625d8cSopenharmony_ci 2319625d8cSopenharmony_ci let subcommands_cases = generate_inner(cmd, ""); 2419625d8cSopenharmony_ci 2519625d8cSopenharmony_ci let result = format!( 2619625d8cSopenharmony_ci r#" 2719625d8cSopenharmony_ciuse builtin; 2819625d8cSopenharmony_ciuse str; 2919625d8cSopenharmony_ci 3019625d8cSopenharmony_ciset edit:completion:arg-completer[{bin_name}] = {{|@words| 3119625d8cSopenharmony_ci fn spaces {{|n| 3219625d8cSopenharmony_ci builtin:repeat $n ' ' | str:join '' 3319625d8cSopenharmony_ci }} 3419625d8cSopenharmony_ci fn cand {{|text desc| 3519625d8cSopenharmony_ci edit:complex-candidate $text &display=$text' '(spaces (- 14 (wcswidth $text)))$desc 3619625d8cSopenharmony_ci }} 3719625d8cSopenharmony_ci var command = '{bin_name}' 3819625d8cSopenharmony_ci for word $words[1..-1] {{ 3919625d8cSopenharmony_ci if (str:has-prefix $word '-') {{ 4019625d8cSopenharmony_ci break 4119625d8cSopenharmony_ci }} 4219625d8cSopenharmony_ci set command = $command';'$word 4319625d8cSopenharmony_ci }} 4419625d8cSopenharmony_ci var completions = [{subcommands_cases} 4519625d8cSopenharmony_ci ] 4619625d8cSopenharmony_ci $completions[$command] 4719625d8cSopenharmony_ci}} 4819625d8cSopenharmony_ci"#, 4919625d8cSopenharmony_ci ); 5019625d8cSopenharmony_ci 5119625d8cSopenharmony_ci w!(buf, result.as_bytes()); 5219625d8cSopenharmony_ci } 5319625d8cSopenharmony_ci} 5419625d8cSopenharmony_ci 5519625d8cSopenharmony_ci// Escape string inside single quotes 5619625d8cSopenharmony_cifn escape_string(string: &str) -> String { 5719625d8cSopenharmony_ci string.replace('\'', "''") 5819625d8cSopenharmony_ci} 5919625d8cSopenharmony_ci 6019625d8cSopenharmony_cifn get_tooltip<T: ToString>(help: Option<&StyledStr>, data: T) -> String { 6119625d8cSopenharmony_ci match help { 6219625d8cSopenharmony_ci Some(help) => escape_string(&help.to_string()), 6319625d8cSopenharmony_ci _ => data.to_string(), 6419625d8cSopenharmony_ci } 6519625d8cSopenharmony_ci} 6619625d8cSopenharmony_ci 6719625d8cSopenharmony_cifn generate_inner(p: &Command, previous_command_name: &str) -> String { 6819625d8cSopenharmony_ci debug!("generate_inner"); 6919625d8cSopenharmony_ci 7019625d8cSopenharmony_ci let command_name = if previous_command_name.is_empty() { 7119625d8cSopenharmony_ci p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string() 7219625d8cSopenharmony_ci } else { 7319625d8cSopenharmony_ci format!("{};{}", previous_command_name, &p.get_name()) 7419625d8cSopenharmony_ci }; 7519625d8cSopenharmony_ci 7619625d8cSopenharmony_ci let mut completions = String::new(); 7719625d8cSopenharmony_ci let preamble = String::from("\n cand "); 7819625d8cSopenharmony_ci 7919625d8cSopenharmony_ci for option in p.get_opts() { 8019625d8cSopenharmony_ci if let Some(shorts) = option.get_short_and_visible_aliases() { 8119625d8cSopenharmony_ci let tooltip = get_tooltip(option.get_help(), shorts[0]); 8219625d8cSopenharmony_ci for short in shorts { 8319625d8cSopenharmony_ci completions.push_str(&preamble); 8419625d8cSopenharmony_ci completions.push_str(format!("-{short} '{tooltip}'").as_str()); 8519625d8cSopenharmony_ci } 8619625d8cSopenharmony_ci } 8719625d8cSopenharmony_ci 8819625d8cSopenharmony_ci if let Some(longs) = option.get_long_and_visible_aliases() { 8919625d8cSopenharmony_ci let tooltip = get_tooltip(option.get_help(), longs[0]); 9019625d8cSopenharmony_ci for long in longs { 9119625d8cSopenharmony_ci completions.push_str(&preamble); 9219625d8cSopenharmony_ci completions.push_str(format!("--{long} '{tooltip}'").as_str()); 9319625d8cSopenharmony_ci } 9419625d8cSopenharmony_ci } 9519625d8cSopenharmony_ci } 9619625d8cSopenharmony_ci 9719625d8cSopenharmony_ci for flag in utils::flags(p) { 9819625d8cSopenharmony_ci if let Some(shorts) = flag.get_short_and_visible_aliases() { 9919625d8cSopenharmony_ci let tooltip = get_tooltip(flag.get_help(), shorts[0]); 10019625d8cSopenharmony_ci for short in shorts { 10119625d8cSopenharmony_ci completions.push_str(&preamble); 10219625d8cSopenharmony_ci completions.push_str(format!("-{short} '{tooltip}'").as_str()); 10319625d8cSopenharmony_ci } 10419625d8cSopenharmony_ci } 10519625d8cSopenharmony_ci 10619625d8cSopenharmony_ci if let Some(longs) = flag.get_long_and_visible_aliases() { 10719625d8cSopenharmony_ci let tooltip = get_tooltip(flag.get_help(), longs[0]); 10819625d8cSopenharmony_ci for long in longs { 10919625d8cSopenharmony_ci completions.push_str(&preamble); 11019625d8cSopenharmony_ci completions.push_str(format!("--{long} '{tooltip}'").as_str()); 11119625d8cSopenharmony_ci } 11219625d8cSopenharmony_ci } 11319625d8cSopenharmony_ci } 11419625d8cSopenharmony_ci 11519625d8cSopenharmony_ci for subcommand in p.get_subcommands() { 11619625d8cSopenharmony_ci let data = &subcommand.get_name(); 11719625d8cSopenharmony_ci let tooltip = get_tooltip(subcommand.get_about(), data); 11819625d8cSopenharmony_ci 11919625d8cSopenharmony_ci completions.push_str(&preamble); 12019625d8cSopenharmony_ci completions.push_str(format!("{data} '{tooltip}'").as_str()); 12119625d8cSopenharmony_ci } 12219625d8cSopenharmony_ci 12319625d8cSopenharmony_ci let mut subcommands_cases = format!( 12419625d8cSopenharmony_ci r" 12519625d8cSopenharmony_ci &'{}'= {{{} 12619625d8cSopenharmony_ci }}", 12719625d8cSopenharmony_ci &command_name, completions 12819625d8cSopenharmony_ci ); 12919625d8cSopenharmony_ci 13019625d8cSopenharmony_ci for subcommand in p.get_subcommands() { 13119625d8cSopenharmony_ci let subcommand_subcommands_cases = generate_inner(subcommand, &command_name); 13219625d8cSopenharmony_ci subcommands_cases.push_str(&subcommand_subcommands_cases); 13319625d8cSopenharmony_ci } 13419625d8cSopenharmony_ci 13519625d8cSopenharmony_ci subcommands_cases 13619625d8cSopenharmony_ci} 137