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 powershell completion file 1019625d8cSopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq, Debug)] 1119625d8cSopenharmony_cipub struct PowerShell; 1219625d8cSopenharmony_ci 1319625d8cSopenharmony_ciimpl Generator for PowerShell { 1419625d8cSopenharmony_ci fn file_name(&self, name: &str) -> String { 1519625d8cSopenharmony_ci format!("_{name}.ps1") 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_ciusing namespace System.Management.Automation 2819625d8cSopenharmony_ciusing namespace System.Management.Automation.Language 2919625d8cSopenharmony_ci 3019625d8cSopenharmony_ciRegister-ArgumentCompleter -Native -CommandName '{bin_name}' -ScriptBlock {{ 3119625d8cSopenharmony_ci param($wordToComplete, $commandAst, $cursorPosition) 3219625d8cSopenharmony_ci 3319625d8cSopenharmony_ci $commandElements = $commandAst.CommandElements 3419625d8cSopenharmony_ci $command = @( 3519625d8cSopenharmony_ci '{bin_name}' 3619625d8cSopenharmony_ci for ($i = 1; $i -lt $commandElements.Count; $i++) {{ 3719625d8cSopenharmony_ci $element = $commandElements[$i] 3819625d8cSopenharmony_ci if ($element -isnot [StringConstantExpressionAst] -or 3919625d8cSopenharmony_ci $element.StringConstantType -ne [StringConstantType]::BareWord -or 4019625d8cSopenharmony_ci $element.Value.StartsWith('-') -or 4119625d8cSopenharmony_ci $element.Value -eq $wordToComplete) {{ 4219625d8cSopenharmony_ci break 4319625d8cSopenharmony_ci }} 4419625d8cSopenharmony_ci $element.Value 4519625d8cSopenharmony_ci }}) -join ';' 4619625d8cSopenharmony_ci 4719625d8cSopenharmony_ci $completions = @(switch ($command) {{{subcommands_cases} 4819625d8cSopenharmony_ci }}) 4919625d8cSopenharmony_ci 5019625d8cSopenharmony_ci $completions.Where{{ $_.CompletionText -like "$wordToComplete*" }} | 5119625d8cSopenharmony_ci Sort-Object -Property ListItemText 5219625d8cSopenharmony_ci}} 5319625d8cSopenharmony_ci"#, 5419625d8cSopenharmony_ci bin_name = bin_name, 5519625d8cSopenharmony_ci subcommands_cases = subcommands_cases 5619625d8cSopenharmony_ci ); 5719625d8cSopenharmony_ci 5819625d8cSopenharmony_ci w!(buf, result.as_bytes()); 5919625d8cSopenharmony_ci } 6019625d8cSopenharmony_ci} 6119625d8cSopenharmony_ci 6219625d8cSopenharmony_ci// Escape string inside single quotes 6319625d8cSopenharmony_cifn escape_string(string: &str) -> String { 6419625d8cSopenharmony_ci string.replace('\'', "''") 6519625d8cSopenharmony_ci} 6619625d8cSopenharmony_ci 6719625d8cSopenharmony_cifn get_tooltip<T: ToString>(help: Option<&StyledStr>, data: T) -> String { 6819625d8cSopenharmony_ci match help { 6919625d8cSopenharmony_ci Some(help) => escape_string(&help.to_string()), 7019625d8cSopenharmony_ci _ => data.to_string(), 7119625d8cSopenharmony_ci } 7219625d8cSopenharmony_ci} 7319625d8cSopenharmony_ci 7419625d8cSopenharmony_cifn generate_inner(p: &Command, previous_command_name: &str) -> String { 7519625d8cSopenharmony_ci debug!("generate_inner"); 7619625d8cSopenharmony_ci 7719625d8cSopenharmony_ci let command_name = if previous_command_name.is_empty() { 7819625d8cSopenharmony_ci p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string() 7919625d8cSopenharmony_ci } else { 8019625d8cSopenharmony_ci format!("{};{}", previous_command_name, &p.get_name()) 8119625d8cSopenharmony_ci }; 8219625d8cSopenharmony_ci 8319625d8cSopenharmony_ci let mut completions = String::new(); 8419625d8cSopenharmony_ci let preamble = String::from("\n [CompletionResult]::new("); 8519625d8cSopenharmony_ci 8619625d8cSopenharmony_ci for option in p.get_opts() { 8719625d8cSopenharmony_ci if let Some(shorts) = option.get_short_and_visible_aliases() { 8819625d8cSopenharmony_ci let tooltip = get_tooltip(option.get_help(), shorts[0]); 8919625d8cSopenharmony_ci for short in shorts { 9019625d8cSopenharmony_ci completions.push_str(&preamble); 9119625d8cSopenharmony_ci completions.push_str( 9219625d8cSopenharmony_ci format!( 9319625d8cSopenharmony_ci "'-{}', '{}', {}, '{}')", 9419625d8cSopenharmony_ci short, short, "[CompletionResultType]::ParameterName", tooltip 9519625d8cSopenharmony_ci ) 9619625d8cSopenharmony_ci .as_str(), 9719625d8cSopenharmony_ci ); 9819625d8cSopenharmony_ci } 9919625d8cSopenharmony_ci } 10019625d8cSopenharmony_ci 10119625d8cSopenharmony_ci if let Some(longs) = option.get_long_and_visible_aliases() { 10219625d8cSopenharmony_ci let tooltip = get_tooltip(option.get_help(), longs[0]); 10319625d8cSopenharmony_ci for long in longs { 10419625d8cSopenharmony_ci completions.push_str(&preamble); 10519625d8cSopenharmony_ci completions.push_str( 10619625d8cSopenharmony_ci format!( 10719625d8cSopenharmony_ci "'--{}', '{}', {}, '{}')", 10819625d8cSopenharmony_ci long, long, "[CompletionResultType]::ParameterName", tooltip 10919625d8cSopenharmony_ci ) 11019625d8cSopenharmony_ci .as_str(), 11119625d8cSopenharmony_ci ); 11219625d8cSopenharmony_ci } 11319625d8cSopenharmony_ci } 11419625d8cSopenharmony_ci } 11519625d8cSopenharmony_ci 11619625d8cSopenharmony_ci for flag in utils::flags(p) { 11719625d8cSopenharmony_ci if let Some(shorts) = flag.get_short_and_visible_aliases() { 11819625d8cSopenharmony_ci let tooltip = get_tooltip(flag.get_help(), shorts[0]); 11919625d8cSopenharmony_ci for short in shorts { 12019625d8cSopenharmony_ci completions.push_str(&preamble); 12119625d8cSopenharmony_ci completions.push_str( 12219625d8cSopenharmony_ci format!( 12319625d8cSopenharmony_ci "'-{}', '{}', {}, '{}')", 12419625d8cSopenharmony_ci short, short, "[CompletionResultType]::ParameterName", tooltip 12519625d8cSopenharmony_ci ) 12619625d8cSopenharmony_ci .as_str(), 12719625d8cSopenharmony_ci ); 12819625d8cSopenharmony_ci } 12919625d8cSopenharmony_ci } 13019625d8cSopenharmony_ci 13119625d8cSopenharmony_ci if let Some(longs) = flag.get_long_and_visible_aliases() { 13219625d8cSopenharmony_ci let tooltip = get_tooltip(flag.get_help(), longs[0]); 13319625d8cSopenharmony_ci for long in longs { 13419625d8cSopenharmony_ci completions.push_str(&preamble); 13519625d8cSopenharmony_ci completions.push_str( 13619625d8cSopenharmony_ci format!( 13719625d8cSopenharmony_ci "'--{}', '{}', {}, '{}')", 13819625d8cSopenharmony_ci long, long, "[CompletionResultType]::ParameterName", tooltip 13919625d8cSopenharmony_ci ) 14019625d8cSopenharmony_ci .as_str(), 14119625d8cSopenharmony_ci ); 14219625d8cSopenharmony_ci } 14319625d8cSopenharmony_ci } 14419625d8cSopenharmony_ci } 14519625d8cSopenharmony_ci 14619625d8cSopenharmony_ci for subcommand in p.get_subcommands() { 14719625d8cSopenharmony_ci let data = &subcommand.get_name(); 14819625d8cSopenharmony_ci let tooltip = get_tooltip(subcommand.get_about(), data); 14919625d8cSopenharmony_ci 15019625d8cSopenharmony_ci completions.push_str(&preamble); 15119625d8cSopenharmony_ci completions.push_str( 15219625d8cSopenharmony_ci format!( 15319625d8cSopenharmony_ci "'{}', '{}', {}, '{}')", 15419625d8cSopenharmony_ci data, data, "[CompletionResultType]::ParameterValue", tooltip 15519625d8cSopenharmony_ci ) 15619625d8cSopenharmony_ci .as_str(), 15719625d8cSopenharmony_ci ); 15819625d8cSopenharmony_ci } 15919625d8cSopenharmony_ci 16019625d8cSopenharmony_ci let mut subcommands_cases = format!( 16119625d8cSopenharmony_ci r" 16219625d8cSopenharmony_ci '{}' {{{} 16319625d8cSopenharmony_ci break 16419625d8cSopenharmony_ci }}", 16519625d8cSopenharmony_ci &command_name, completions 16619625d8cSopenharmony_ci ); 16719625d8cSopenharmony_ci 16819625d8cSopenharmony_ci for subcommand in p.get_subcommands() { 16919625d8cSopenharmony_ci let subcommand_subcommands_cases = generate_inner(subcommand, &command_name); 17019625d8cSopenharmony_ci subcommands_cases.push_str(&subcommand_subcommands_cases); 17119625d8cSopenharmony_ci } 17219625d8cSopenharmony_ci 17319625d8cSopenharmony_ci subcommands_cases 17419625d8cSopenharmony_ci} 175