diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs index f390853a159..5fb39f4b965 100644 --- a/clap_complete/src/shells/bash.rs +++ b/clap_complete/src/shells/bash.rs @@ -178,10 +178,23 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String { if let Some(longs) = o.get_long_and_visible_aliases() { opts.extend(longs.iter().map(|long| { - let mut v = vec![ - format!("--{})", long), - format!("COMPREPLY=({})", vals_for(o)), - ]; + let mut v = vec![format!("--{})", long)]; + + if o.get_value_hint() == ValueHint::FilePath { + v.extend([ + "local oldifs".to_string(), + "if [[ -v IFS ]]; then".to_string(), + r#" oldifs="$IFS""#.to_string(), + "fi".to_string(), + r#"IFS=$'\n'"#.to_string(), + format!("COMPREPLY=({})", vals_for(o)), + "if [[ -v oldifs ]]; then".to_string(), + r#" IFS="$oldifs""#.to_string(), + "fi".to_string(), + ]); + } else { + v.push(format!("COMPREPLY=({})", vals_for(o))); + } if let Some(copt) = compopt { v.extend([ @@ -198,10 +211,23 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String { if let Some(shorts) = o.get_short_and_visible_aliases() { opts.extend(shorts.iter().map(|short| { - let mut v = vec![ - format!("-{})", short), - format!("COMPREPLY=({})", vals_for(o)), - ]; + let mut v = vec![format!("-{})", short)]; + + if o.get_value_hint() == ValueHint::FilePath { + v.extend([ + "local oldifs".to_string(), + "if [[ -v IFS ]]; then".to_string(), + r#" oldifs="$IFS""#.to_string(), + "fi".to_string(), + r#"IFS=$'\n'"#.to_string(), + format!("COMPREPLY=({})", vals_for(o)), + "if [[ -v oldifs ]]; then".to_string(), + r#" IFS="$oldifs""#.to_string(), + "fi".to_string(), + ]); + } else { + v.push(format!("COMPREPLY=({})", vals_for(o))); + } if let Some(copt) = compopt { v.extend([ diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc index 2f72ccf40b2..a004f9148fe 100644 --- a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc +++ b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc @@ -556,14 +556,30 @@ _exhaustive() { return 0 ;; --file) + local oldifs + if [[ -v IFS ]]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [[ -v oldifs ]]; then + IFS="$oldifs" + fi if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then compopt -o filenames fi return 0 ;; -f) + local oldifs + if [[ -v IFS ]]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [[ -v oldifs ]]; then + IFS="$oldifs" + fi if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then compopt -o filenames fi diff --git a/clap_complete/tests/snapshots/value_hint.bash b/clap_complete/tests/snapshots/value_hint.bash index 35f6b3d56b1..e2a7f9efd37 100644 --- a/clap_complete/tests/snapshots/value_hint.bash +++ b/clap_complete/tests/snapshots/value_hint.bash @@ -49,14 +49,30 @@ _my-app() { return 0 ;; --file) + local oldifs + if [[ -v IFS ]]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [[ -v oldifs ]]; then + IFS="$oldifs" + fi if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then compopt -o filenames fi return 0 ;; -f) + local oldifs + if [[ -v IFS ]]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [[ -v oldifs ]]; then + IFS="$oldifs" + fi if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then compopt -o filenames fi diff --git a/clap_complete/tests/testsuite/bash.rs b/clap_complete/tests/testsuite/bash.rs index d64d155a521..937f112cfcd 100644 --- a/clap_complete/tests/testsuite/bash.rs +++ b/clap_complete/tests/testsuite/bash.rs @@ -238,7 +238,7 @@ fn complete() { testdir_path.to_string_lossy() ); let expected = r#"% -foo bar.txt baz qux.txt "#; +foo bar.txt baz^Iqux.txt "#; let actual = runtime.complete(input.as_str(), &term).unwrap(); snapbox::assert_eq(expected, actual); }