Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,38 @@ fish ?.?.? (released ???)

Notable improvements and fixes
------------------------------
- Translatable messages defined in Rust source code may now be localized using `Fluent <https://projectfluent.org/>`__ instead of GNU gettext.
- Translatable messages defined in Rust source code can and should now be translated using `Fluent <https://projectfluent.org/>`__ instead of GNU gettext.
To make Fluent easy to work with, we have added tooling based on the new `fluent-ftl-tools <https://codeberg.org/danielrainer/fluent-ftl-tools>`__ library.
See :ref:`Contributing Translations <localization>` (:issue:`11928`).

Deprecations and removed features
---------------------------------
- The ``--command`` and ``--path`` options in :doc:`complete <cmds/complete>` no longer unescape their argument.
- Builtin :doc:`complete's <cmds/complete>` ``--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 <cmds/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 <cmds/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
-------------------------------
Expand All @@ -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 <cmds/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)
==================================
Expand Down
20 changes: 6 additions & 14 deletions src/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<usize> {
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;
Expand All @@ -2250,7 +2243,6 @@ fn param_match2(e: &CompleteEntryOpt, optstr: &wstr) -> Option<usize> {

// 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;
}
Expand Down
9 changes: 5 additions & 4 deletions tests/checks/complete.fish
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading