From fa8a2ee265f40f7f5b2534e746d451d03b911a2a Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Tue, 23 Jun 2026 19:05:31 +0200 Subject: [PATCH] complete short_opt_pos: repeated short options are not invalid complete -C"somecmd -xyz" will not suggest any of the short options that are already present. This is old behavior from 149594f9743 (Initial revision, 2005-09-20) ("if( wcschr( arg, nextopt ) != 0 )"). It's questionable, since repeated options may be valid ("ssh -vvv" etc.), and completions should generally err on the side of false positives; but given that short options are usually easy to type, and discovery is not really relevant if they are already on the command line, this seems fine? Not sure. Recently, fab397e7546 (fix: filter invalid short option completions, 2026-06-18) made two changes: 1. "complete somecmd -s X -n false; complete -C'somecmd -X'" no longer prints completions. This is a bug fix that reduces confusion. 2. complete -C"somecmd -YY" where "Y" no longer completes other short options because we treat repetition as error. But it's not necessarily, and hiding unrelated completions seems wrong. Revert change 2. See https://github.com/fish-shell/fish-shell/pull/12821#issuecomment-4781863199 --- src/complete.rs | 4 ---- tests/checks/complete.fish | 9 +++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/complete.rs b/src/complete.rs index fa581f84d..345babfb6 100644 --- a/src/complete.rs +++ b/src/complete.rs @@ -908,7 +908,6 @@ fn short_option_pos(&mut self, arg: &wstr, options: &[CompleteEntryOpt]) -> Opti return None; } - let mut seen_short_options = HashSet::new(); for (pos, arg_char) in arg.chars().enumerate().skip(1) { let matched = options.iter().find(|o| { o.typ == CompleteOptionType::Short @@ -920,9 +919,6 @@ fn short_option_pos(&mut self, arg: &wstr, options: &[CompleteEntryOpt]) -> Opti if matched.result_mode.requires_param { return Some(pos); } - if !seen_short_options.insert(arg_char) { - return None; - } } else { // The first character after the dash is not a valid option. if pos == 1 { diff --git a/tests/checks/complete.fish b/tests/checks/complete.fish index 21ab96bc2..d0ef6b0f3 100644 --- a/tests/checks/complete.fish +++ b/tests/checks/complete.fish @@ -153,10 +153,11 @@ end complete -c repeated_short_options -f -s h complete -c repeated_short_options -f -s v complete -c repeated_short_options -f -s x -complete -C'repeated_short_options -xx' | count -# CHECK: 0 -complete -C'repeated_short_options -xxh' | count -# CHECK: 0 +complete -C'repeated_short_options -xx' +# CHECK: -xxh +# CHECK: -xxv +complete -C'repeated_short_options -xxh' +# CHECK: -xxhv complete -C'repeated_short_options -x' # CHECK: -xh # CHECK: -xv