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)
==================================
diff --git a/src/complete.rs b/src/complete.rs
index cc3ecab07d61..345babfb6902 100644
--- a/src/complete.rs
+++ b/src/complete.rs
@@ -908,26 +908,17 @@ 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 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 {
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 {
@@ -2229,8 +2220,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 +2243,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;
}
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