From 6fd86a6e9b11e21d2d6cc375492b841984ff866d Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Wed, 24 Jun 2026 07:00:24 +0200 Subject: [PATCH 1/3] complete short_option_pos: use find again instead of raw loop Reverts that part of ab397e7546 (fix: filter invalid short option completions, 2026-06-18). While at it, clean up a comment and assertion from eae1683033c (Completion: complete argument to last of a group of short options, 2019-09-10). --- src/complete.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/complete.rs b/src/complete.rs index cc3ecab07d61..fa581f84d8c5 100644 --- a/src/complete.rs +++ b/src/complete.rs @@ -910,16 +910,11 @@ impl<'ctx, 'parser> Completer<'ctx, 'parser> { let mut seen_short_options = HashSet::new(); for (pos, arg_char) in arg.chars().enumerate().skip(1) { - let mut matched = None; - for o in options { - if o.typ == CompleteOptionType::Short + let matched = options.iter().find(|o| { + o.typ == CompleteOptionType::Short && o.option.char_at(0) == arg_char && self.conditions_test(&o.conditions) - { - matched = Some(o); - break; - } - } + }); if let Some(matched) = matched { if matched.result_mode.requires_param { @@ -2229,8 +2224,10 @@ fn param_match(e: &CompleteEntryOpt, optstr: &wstr) -> bool { } } -/// Test if a string is an option with an argument, like --color=auto or -I/usr/include. +/// Test if a string is an option with an argument, like --color=auto or -std=c++26. +/// Short options are handled by the caller. fn param_match2(e: &CompleteEntryOpt, optstr: &wstr) -> Option { + assert!(e.typ != CompleteOptionType::Short); // We may get a complete_entry_opt_t with no options if it's just arguments. if e.option.is_empty() { return None; @@ -2250,7 +2247,6 @@ fn param_match2(e: &CompleteEntryOpt, optstr: &wstr) -> Option { // Short options are like -DNDEBUG. Long options are like --color=auto. So check for an equal // sign for long options. - assert!(e.typ != CompleteOptionType::Short); if optstr.char_at(cursor) != '=' { return None; } From fa8a2ee265f40f7f5b2534e746d451d03b911a2a Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Tue, 23 Jun 2026 19:05:31 +0200 Subject: [PATCH 2/3] 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 fa581f84d8c5..345babfb6902 100644 --- a/src/complete.rs +++ b/src/complete.rs @@ -908,7 +908,6 @@ impl<'ctx, 'parser> Completer<'ctx, 'parser> { 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 @@ impl<'ctx, 'parser> Completer<'ctx, 'parser> { 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 21ab96bc2840..d0ef6b0f391f 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 From be58b66c8243417e9bd8ea127cf5410883959246 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Tue, 23 Jun 2026 18:44:30 +0200 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.rst | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1557aa228069..d61d19627ef4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,36 +3,38 @@ fish ?.?.? (released ???) Notable improvements and fixes ------------------------------ -- Translatable messages defined in Rust source code may now be localized using `Fluent `__ instead of GNU gettext. +- Translatable messages defined in Rust source code can and should now be translated using `Fluent `__ instead of GNU gettext. To make Fluent easy to work with, we have added tooling based on the new `fluent-ftl-tools `__ library. See :ref:`Contributing Translations ` (:issue:`11928`). Deprecations and removed features --------------------------------- -- The ``--command`` and ``--path`` options in :doc:`complete ` no longer unescape their argument. +- Builtin :doc:`complete's ` ``--command`` and ``--path`` options no longer unescape their argument. Interactive improvements ------------------------ - History search would sometimes forget about commands after those were re-run in concurrent sessions. This has been fixed (:issue:`10300`). -- On the first run after upgrading from an older version, fish will try harder to check if the current theme matches a historical default. If it does match, fish won't create ``~/.config/fish/conf.d/fish_frozen_theme.fish`` when upgrading from fish < 4.3. - Specifically, on systems where fish version 3.x was installed originally, fish 4.8 will avoid creating that file on upgrade (:issue:`12725`). - ``fish_hg_prompt``, ``fish_git_prompt`` and ``fish_fossil_prompt`` now strip control characters from VCS state read off disk, matching ``prompt_pwd``. -- :doc:`bind ` shows the file where bindings were defined (:issue:`12504`). - Abbreviations with ``--position=anywhere`` can now be completed in argument position, not just in command position (:issue:`12630`). - Path component movement (:kbd:`ctrl-w`) skips escaped characters. -- Completions no longer offer repeated short options (:issue:`12821`). -- Fixed an issue where control-C might fail to cancel certain functions (:issue:`12802`). +- Completion of short option groups will now handle ``--condition`` correctly (:issue:`12821`). +- Fixed an issue where :kbd:`ctrl-c` might fail to cancel certain functions (:issue:`12802`). +- On the first run after upgrading from an older version, fish will try harder to check if the current theme matches a historical default. + If it does match, fish won't create ``~/.config/fish/conf.d/fish_frozen_theme.fish`` when upgrading from fish < 4.3. + In particular, on systems where fish version 3.x was installed originally, fish will now avoid creating that file on upgrade (:issue:`12725`). Scripting improvements ---------------------- - ``cd`` supports the ``-L`` and ``-P`` options, like other shells, to allow specifying whether symbolic links (symlinks) are resolved when changing directories (:issue:`7206`). -- ``cd`` with a relative path will now retry using the real current directory, if ``$PWD`` has been moved or deleted (:issue:`12700`). +- ``cd`` with a relative path will now retry using the real current directory, if ``$PWD`` has been moved (:issue:`12700`). - Nested brace expansions now strip unquoted leading and trailing spaces from entries consistently (:issue:`12794`). +- :doc:`bind ` shows the files where bindings were defined (:issue:`12504`). Other improvements ------------------ -- fish no longer creates universal variables by default; specifically, the ``__fish_initialized`` variable is no longer created. +- fish no longer creates the ``__fish_initialized`` universal variable on startup. If you don't expect to need to downgrade to earlier versions, you can remove it with ``set --erase __fish_initialized``. + This means that fish now only creates universal variables if instructed by the user. For distributors and developers ------------------------------- @@ -53,7 +55,7 @@ Regression fixes: - (from 4.4.0) Vi mode ``c,W`` key binding wrongly deleted trailing spaces (:issue:`12790`). - (from 4.4.0) Vi mode ``x`` in :doc:`builtin read ` (:issue:`12724`). - (from 4.3.3) Repeated tab would sometimes insert smartcase completions redundantly. -- (from 4.3.0) Pressing escape during command input would insert garbage text into the command line (:issue:`12379`). +- (from 4.3.0) Pressing escape during command execution could insert garbage text into the command line (:issue:`12379`). fish 4.7.1 (released May 08, 2026) ==================================