diff options
Diffstat (limited to 'src/shells/bash.rs')
-rw-r--r-- | src/shells/bash.rs | 72 |
1 files changed, 50 insertions, 22 deletions
diff --git a/src/shells/bash.rs b/src/shells/bash.rs index 2a97e1d..f390853 100644 --- a/src/shells/bash.rs +++ b/src/shells/bash.rs @@ -18,6 +18,8 @@ impl Generator for Bash { .get_bin_name() .expect("crate::generate should have set the bin_name"); + let fn_name = bin_name.replace('-', "__"); + w!( buf, format!( @@ -58,13 +60,17 @@ impl Generator for Bash { esac }} -complete -F _{name} -o nosort -o bashdefault -o default {name} +if [[ \"${{BASH_VERSINFO[0]}}\" -eq 4 && \"${{BASH_VERSINFO[1]}}\" -ge 4 || \"${{BASH_VERSINFO[0]}}\" -gt 4 ]]; then + complete -F _{name} -o nosort -o bashdefault -o default {name} +else + complete -F _{name} -o bashdefault -o default {name} +fi ", name = bin_name, - cmd = bin_name.replace('-', "__"), + cmd = fn_name, name_opts = all_options_for_path(cmd, bin_name), name_opts_details = option_details_for_path(cmd, bin_name), - subcmds = all_subcommands(cmd), + subcmds = all_subcommands(cmd, &fn_name), subcmd_details = subcommand_details(cmd) ) .as_bytes() @@ -72,7 +78,7 @@ complete -F _{name} -o nosort -o bashdefault -o default {name} } } -fn all_subcommands(cmd: &Command) -> String { +fn all_subcommands(cmd: &Command, parent_fn_name: &str) -> String { debug!("all_subcommands"); fn add_command( @@ -102,9 +108,8 @@ fn all_subcommands(cmd: &Command) -> String { } } let mut subcmds = vec![]; - let fn_name = cmd.get_name().replace('-', "__"); for subcmd in cmd.get_subcommands() { - add_command(&fn_name, subcmd, &mut subcmds); + add_command(parent_fn_name, subcmd, &mut subcmds); } subcmds.sort(); @@ -164,29 +169,50 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String { let mut opts = vec![String::new()]; for o in p.get_opts() { + let compopt = match o.get_value_hint() { + ValueHint::FilePath => Some("compopt -o filenames"), + ValueHint::DirPath => Some("compopt -o plusdirs"), + ValueHint::Other => Some("compopt -o nospace"), + _ => None, + }; + if let Some(longs) = o.get_long_and_visible_aliases() { opts.extend(longs.iter().map(|long| { - format!( - "--{}) - COMPREPLY=({}) - return 0 - ;;", - long, - vals_for(o) - ) + let mut v = vec![ + format!("--{})", long), + format!("COMPREPLY=({})", vals_for(o)), + ]; + + if let Some(copt) = compopt { + v.extend([ + r#"if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then"#.to_string(), + format!(" {}", copt), + "fi".to_string(), + ]); + } + + v.extend(["return 0", ";;"].iter().map(|s| s.to_string())); + v.join("\n ") })); } if let Some(shorts) = o.get_short_and_visible_aliases() { opts.extend(shorts.iter().map(|short| { - format!( - "-{}) - COMPREPLY=({}) - return 0 - ;;", - short, - vals_for(o) - ) + let mut v = vec![ + format!("-{})", short), + format!("COMPREPLY=({})", vals_for(o)), + ]; + + if let Some(copt) = compopt { + v.extend([ + r#"if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then"#.to_string(), + format!(" {}", copt), + "fi".to_string(), + ]); + } + + v.extend(["return 0", ";;"].iter().map(|s| s.to_string())); + v.join("\n ") })); } } @@ -206,6 +232,8 @@ fn vals_for(o: &Arg) -> String { .collect::<Vec<_>>() .join(" ") ) + } else if o.get_value_hint() == ValueHint::DirPath { + String::from("") // should be empty to avoid duplicate candidates } else if o.get_value_hint() == ValueHint::Other { String::from("\"${cur}\"") } else { |