Commit Graph

996 Commits

Author SHA1 Message Date
Daniel Rainer
397969ddcc Add message localization tests
These tests require building with the `localize-messages` feature.

If certain translations are updated, this test might fail, either
because a message was changed in the source, or because a translation of
a message was changed, or because a translation was added in a language
which previously did not have a translation for a particular message,
and we rely on that in the test. If any of these happen, the tests need
to be updated accordingly.

Closes #11726
2025-09-20 13:56:23 +02:00
Johannes Altmanninger
f69c2a4d4a fish_config: silence error when compiled without embed-data 2025-09-13 15:14:13 +02:00
Johannes Altmanninger
89883b791d checks/po-files-up-to-date.fish: mention how to update translations
As pointed out in
https://github.com/fish-shell/fish-shell/issues/11610#issuecomment-3240489072
2025-09-13 15:10:24 +02:00
Johannes Altmanninger
4ba070645d Merge pull request #11763 2025-08-29 22:23:53 +02:00
Isaac Oscar Gariano
6149ac4e40 Added a -C/--center option to string pad.
The --center option does exactly what you'd expect. When a
perfectly centred result is not possible, this adds extra padding to
the left. If the --right option is also given, the extra padding is
added to the right.
2025-08-30 02:57:01 +10:00
Isaac Oscar Gariano
944cfd181e Added a -v/--validate option to fish_opt
This new flag causes fish_opt to generrate an option spec with !
(e.g. "fish_opt -s s -rv some code" will output "s=!some code").

Such validation scripts are not particular useful (they are highly limited as
they cannot access the values for other options, and must be quoted
appropriately so they can be passed to argparse). I merely added the option to
fish_opt so that it can now generate any valid option spec.
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
007edac145 Make argparse reject supplying a validator for boolean flags
Specifically, this commit simply makes argparse issue an error if you use the !
syntax to define a validation script on an option that does not take any
arguments. For example, "argparse foo!exit -- --foo" is now an error. This was
previously accepted, despite that fact that the code after ! would never be
executed (the ! code is only executed when an option is given a value).

Alternatively, ! validation scripts could be made to execute even when no value
was provided, but this break existing code that uses them with flags that take
optional values.
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
c403822fac Modified argparse to support one character long only options.
This fixes an issue noticed in the previous commit (the made the -s/--short
option optional to fish_opt): it was impossible to define a single character
long flag, unless you also provided a single-character short flag equivalent.

This commit works by allowing an option spec to start with a '/', treating the
subsequent alpha-numeric characters as a long flag name.

In detail, consider the following:
- s defines a -s short flag
- ss defines an --ss long flag
- /ss (new) also defines a --ss long flag
- s/s defines a -s short flag and an --s long flag
- s-s defines a --s long flag (if there's already an -s short flag, you'd have
    to change the first s, e.g. S-s)
- /s (new) defines a --s long flag
- s/ is an error (a long flag name must follow the /)

Note that without using --strict-longopts, a long flag --s can always be
abbreviated as -s, provided that -s isn't defined as a separate short flag.

This 'issue' fixed by this commit is relatively trivial, however it does allow
simplifying the documentation for fish_opt (since it no longer needs to mention
the restriction). In particular, this commit makes the --long-only flag to
fish_opt completely unnecessary (but it is kept for backwards compatibility).
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
663430a925 Added support to fish_opt for defining a long flag with no short flag.
Specifically, this now makes the -s/--short option to fish_opt optional when the
-l/--long option is given. This commit does not modify argparse, as it already
supports defining long flags without a corresponding short flag, however
fish_opt would never take advantage of this feature.

Note that due to a limitation in argparse, fish_opt will give an error if you
try to define a one-character --long flag without also providing a --short
option.

For backwards compatibility, the --long-only flag is still included with
fish_opt, and when used with -s/--short, will behave as before (the short flag
is still defined, but argparse will fail if it is actually used by the parsed
arguments, moreover the _flag_ option variables will not be defined). This can
however be used to define a one character long flag.
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
4db61ee117 Added argparse support for arguments with multiple optional values.
This commit fixes #8432 by adding put =* in an option spec to indicate that the
option takes an optional value, where subsequent uses of the option accumulate
the value (so the parsing behaviour is like =?, but the _flag_ variables are
appended to like =+). If the option didn't have a value, it appends an empty
string. As an example,. long=* -- --long=1 --long will execute
set -l _flag_long 1 '' (i.e. count $_flag_long is 2), whereas with =? instead,
you'd get set -l _flag_long (i.e. count $_flag_long is 0).

As a use case, I'm aware of git clone which has a
--recurse-submodules=[<pathspec>]: if you use it without a value, it operates on
all submodules, with a value, it operates on the given submodule.

The fish_opt function will generate an =* option spec when given both the
--optional-val and --multiple-vals options (previously, doing so was an error).
fish_opt now also accepts -m as an abbreviation for --multiple-vals, to go with
the pre-existing -o and -r abbreviations for --optional-val and --required-val.
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
9d56cdbcbc Added a -U/--unknown-arguments option to argparse
The new -U/--unknown-arguments option takes either 'optional', 'required', or
'none', indicating how many arguments unknown options are assumed to take.
The default is optional, the same behaviour as before this commit, despite
most options in practice taking not taking any arguments. Using
--unknown-arguments=required and --unknown-arguments=none (but not
--unknown-arguments=optional) can give you parse errors if, respectively,
an unknown option has no argument (because it the option is at the end of the
argument list), or is given an argument (with the `--flag=<value> syntax).
See doc_src/cmds/argparse.rst for more details (specifically, the descritpion
of the --unknown-arguments flag and the example at the end
of the examples section).

As a convenience, -U/--unknown-arguments implies -u/--move-unknown.
However you can use it the deprecated -i/--ignore-unknown if you really want to.
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
24eeed65a2 Added an -S/--strict-longopts option to argparse.
This flag disables a very surprising and confusing feature I found in the code
of wgetopt.rs: the ability to abbreviate the names of long options and the
ability to parse long options with a single "-". This commit addresses #7341,
but unlike pull request #11220, it does so in a backwards compatible way: one
must use the new -S/--strict-longotps flag to disable the old legacy behaviour.

Unlike pull request #11220 however, this flag only applies to ``argparse``,
and not to any builtins used by fish.

Note that forcing the flag -S/--strict-longotps on (i.e. in  src/wgetopt.rs,
replacing both uses of `self.strict_long_opts` with `true`), does not cause any
of the current test cases to fail. However, third-party fish scripts may be
depending on the current behaviour.
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
70dca1e136 Give a more helpful error when a boolean option has an argument.
This fixes an issue very similar to #6483,
For example, fish --login=root used to print this:
    fish: --login=root: unknown option
But `--login` is a valid option to fish.
So the above now prints:
    fish: --login=root: option does not take an argument

This is done by modifying WGetOpter so that it returns a ';' if it encountered
an option with an argument, but the option was not declared as taking an option
(this is only possible with the --long=value or legacy -long=value syntax).
All uses of WGetOpter (except echo, fish_indent, and some tests) are modified to
then print an appropriate error message when ';' is returned.
echo doesn't have any long options, so it will panic if gets a ';'.
fish_indent doesn't print any error messages for invalid options anyway, and I
wasn't sure if this was intentional or not.

Moreover, WGetOpter now always returns a ':' for options that are missing an
argument. And you can no longer prefix a your option spec with a ':' to enable
this (since every use of WGetOpter was doing this anyway, except
wgetopt::test_exchange and tests::wgetopt::test_wgetopt).
2025-08-30 01:55:56 +10:00
Isaac Oscar Gariano
51d16f017d Added a -u/--move-unknown option to argparse.
--move-unknown is like --ignore-unknown, but unknown options are instead moved
from $argv to $argv_opts, just like known ones. This allows unambiguously
parsing non-option arguments to other commands. For example if $argv contains
`--opt -- --file`, and we execute `argparse --move-unknown -- $argv`, we can
then call `cmd $argv_opts -- --another-file $argv`, which will correctly
interpret `--opt` as an option, but `--file` and `--some-file` as an argument.
This makes `--move-unknown` a better alternative to `--ignore-unknown`, so the
latter has been marked as deprecated, but kept for backwards compatibility.
2025-08-29 23:10:02 +10:00
Isaac Oscar Gariano
5a7e5dc743 Make argparse separate known and unknown options that occur in a group together.
For example, argparse --ignore-unknown h -- -ho will now set set $argv to -o and
$argv_opts to -h (i.e. -ho is split into -h and -o). Previously, it would set
$argv to -ho, and $argv_opts to empty. With this change, the "Limitations"
section of argparse's man page has been removed, and the examples merged into
the description of the -i/--ignore-unknown option. (Note: there was another
'limitation' mentioned in the 'limitations' section: that everything occuring
after an unknown option in a group was considered an argument to an option; the
documentation has been reworded to make it clear that this is intended
behaviour, as unknown options are always treated as taking optional arguments,
and modifying that behaviour would be a breaking change and not a bug fix).
2025-08-29 23:10:02 +10:00
Isaac Oscar Gariano
f780b01ac9 Added way to tell argparse to delete an option from $argv_opts.
The intention is that if you want to parse some of your options verbatim to
another command, but you want to modfy other options (e.g. change their value,
convert them to other options, or delete them entirely), you mark the options
you want to modify with an &, and argparse will not add them to argv_opts. You
can then call the other command with argv_opts together with any new/modified
options, ensuring that the other command doesn't set the pre-modified options.
As with other known options, & options will be removed from $argv, and have
their $_flag_ variables set.

The `&` goes at the end of the option spec, or if the option spec contains a
validation script, immediately before the `!`. There is also now a -d/--delete
flag to fish_opt that will generate such an option spec.

See the changes in doc_src/cmds/argparse.rst for more details and an example use
case.
2025-08-29 23:10:02 +10:00
Isaac Oscar Gariano
e62abc460d Make argparse save parsed options in $argv_opts. (Fixes #6466)
Specifically, every argument (other than the first --, if any) that argparse
doesn't add to $argv is now added to a new local variable $argv_opts. This
allows you to make wrapper commands that modify non-option arguments, and then
forwards all arguments to another command. See the new example at the end of
doc_src/cmds/argparse.rst for a use case for this new variable.
2025-08-29 23:10:02 +10:00
Isaac Oscar Gariano
e6b4f0a696 Stopped argparse tests from leaking local variables.
By wrapping the various argparse tests in begin ... end blocs, it makes it much
easier to debug test failures and add new tests. In particular, each block is
independent, and shouldn't affect any subsequent tests. There's also now a check
at the end of the test file to ensure that the tests are no longer leaking local
variables.
2025-08-29 23:10:02 +10:00
Bryce Berger
9273f352a0 allow psub --fifo --suffix ... 2025-08-15 15:02:44 -04:00
Saeed M Rad
45bb8f535b funced: pretend copied functions are defined interactively
After #9542, the format for `functions -Dv` was changed for copied
functions.

```diff
-stdin
-n/a
+[path to copy location]
+[path to original definition]
 [and a few more lines]
```

Some components were (and perhaps are) still expecting the old format,
however. After a search, it looks like `funced` and `fish_config` are
the only two functions using `functions -D` and `functions -Dv` in this
repo (none are using `type -p`).

As noted in issue #11614, `funced` currently edits the file which
copies the given copied function. Another option was to make `funced`
edit the file which originally defined the function. Since the copied
function would not have been updated either way, I modified `funced` so
it would pretend that the copied function was defined interactively,
like it was before.

I did not modify `fish_config`, since it was only used for preset
prompts in the web config, none of which used `functions --copy`.
(Moreover, I believe it would have behaved correctly, since the preset
would not have had to define the function, only copy it.)

Fixes issue #11614
2025-08-07 10:19:42 +00:00
Daniel Müller
5b39efc96d Support incrementing/decrementing the number below the cursor
Vim supports incrementing & decrementing the number below the cursor (or
after it) via Ctrl-a and Ctrl-x, respectively. Given fish's Vi mode
support, it makes sense to provide similar functionality when working on
the command line, to provide a more natural environment for Vim users.
With this change we add the necessary functionality.

Closes: #8320
Closes #11570
2025-07-03 14:38:42 +02:00
Daniel Müller
32c36aa5f8 builtins commandline/complete: allow handling commandline before reader initialization
Commands like "commandline foo" silently fail, and "complete -C" fails with
a weird "option requires an argument" error.

I think at least the first one can be useful in edge cases, e.g. to test
code that does not separate the `commandline` input and output (#11570),
and to set fish's initial commandline, see the next commit.

I don't think there are super strong reasons to allow these, but if the
existing state is merely due to "no one has ever thought of doing this",
then we should try changing it.

For consistency, also allow "complete -C". I guess an argument for that is
that it's weird to make a command behave differently in non-interactive shells.

For now, keep the historical behavior of disabling access to the command
line in non-interactive shells. If we find a good reason for allowing that
(which seems unlikely), we can.

Ref: https://github.com/fish-shell/fish-shell/pull/11570#discussion_r2144544053

Co-authored-by: Johannes Altmanninger <aclopte@gmail.com>
2025-07-03 14:16:18 +02:00
Dezhi Wu
144725e947 fix(echo): handle overflow in octal/hex escape parsing
Use wrapping arithmetic when parsing octal and hex escapes in echo to
prevent panics on overflow and ensure consistent behavior with other
shells. This change allows echo to process escape sequences like \5555
without crashing, keeping the same behavior as 3.7.1.

```
$ ./fish --version
fish, version 3.7.1
$ ./fish -c 'echo -e "\5555"'
m5
```
2025-06-28 11:15:42 +08:00
Johannes Altmanninger
096f225579 alias: fix indentation
Fixes #11602
2025-06-23 13:53:43 +02:00
Johannes Altmanninger
60881f1195 __fish_complete_list: only unescape "$(commandline -t)"
Commit cd3da62d24 (fix(completion): unescape strings for __fish_complete_list,
2024-09-17) bravely addressed an issue that exists in a lot of completions.
It did so only for __fish_complete_list. Fair enough.

Unfortunately it unescaped more than just "$(commandline -t)".

This causes the problem described at
https://github.com/fish-shell/fish-shell/issues/11508#issuecomment-2889088934
where completion descriptions containing a backslash followed by "n" are
interpreted as newlines, breaking the completion parser.  Fix that.
2025-06-21 18:53:50 +02:00
Johannes Altmanninger
320ebb6859 __fish_complete_list: strip "--foo=" prefix from replacing completions
Given a command line like

	foo --foo=bar=baz=qux\=argument

(the behavior is the same if '=' is substituted with ':').

fish completes arguments starting from the last unescaped separator, i.e.

	foo --foo=bar=baz=qux\=argument
			 ^
__fish_complete_list provides completions like

	printf %s\n (commandline -t)(printf %s\n choice1 choice2 ...)

This means that completions include the "--foo=bar=baz=" prefix.

This is wrong. This wasn't a problem until commit f9febba (Fix replacing
completions with a -foo prefix, 2024-12-14), because prior to that, replacing
completions would replace the entire token.
This made it too hard to writ ecompletions like

	complete -c foo -s s -l long -xa "hello-world goodbye-friend"

that would work with "foo --long fri" as well as "foo --long=frie".
Replacing the entire token would only work if the completion included that
prefix, but the above command is supposed to just work.
So f9febba made us replace only the part after the separator.

Unfortunately that caused the earlier problem.  Work around this.  The change
is not pretty, but it's a compromise until we have a better way of telling
which character fish considers to be the separator.

Fixes #11508
2025-06-21 18:53:50 +02:00
Johannes Altmanninger
06578bd03d Merge pull request #11565 2025-06-16 12:25:08 +02:00
Johannes Altmanninger
6491518b97 Merge pull request #11571 2025-06-16 12:23:39 +02:00
Daniel Rainer
80131acff2 Add PO file update check to tests
The PO file updates can now run in a normal test, eliminating the need for
special handling.

Rename the `check-translations.fish` script, to clarify which part of the checks
happens in it.
2025-06-15 23:43:31 +02:00
Daniel Rainer
03e3d0aa3f Split up sphinx HTML and MAN file generation
This test is the one with the longest runtime. Splitting the two targets into
separate tests allows them to run in parallel, which can speed up the tests.
2025-06-15 18:44:58 +02:00
Peter Ammon
e10a12c0f2 Rationalize certain edge cases for function execution
This concerns edge cases when executing a function. Historically, when we parse
fish script, we identify early whether or not it's a function; but only record
the function's name and not its properties (i.e. not its source).

This means that the function can change between parsing and execution. Example:

    function foo; echo alpha; end
    foo (function foo; echo beta; end)

This has historically output "beta" because the function is replaced as part of
its own arguments.

Worse is if the function is deleted:

    function foo; echo alpha; end
    foo (functions --erase foo)

This outputs an error but in an awkward place; that's OK since it's very rare.

Let's codify this behavior since someone might be depending on it.
2025-06-14 10:34:10 -07:00
Johannes Altmanninger
535a09a5b3 Silence error in check-all-fish-files
Our docker/docker_run_tests.sh script runs tests in a container with the fish
source tree mounted as read-only.  We have a hack to speed up repeated runs
of the check-all-fish-files test that assumes the source tree is writable.
Paper over this by silencing the error for now.

  There were no remaining checks left to match stderr:1:
    touch: cannot touch '/fish-source/tests/.last-check-all-files': Read-only file system
2025-06-13 14:56:02 +02:00
Johannes Altmanninger
5346d3d491 check-all-fish-files: don't glob the entire worktree
Commit 22c0054c1e (Add check to test all fish files with -n, 2020-02-17)
added a test that runs "fish --no-execute" on all fish files in share/**.fish

Commit 329cd7d429 (Make functions, completions and tests resilient to
running on an embed-data fish, 2025-03-25) change this to run it on **.fish.

Evidently "the tests are exempt because they contain syntax errors" is no
longer true - this is because we have since changed those files to recursively
run 'fish -c "syntax-error"', which makes it easier to test for multiple
syntax-errors in a single test file. Remove the comment.

Globbing everything seems a bit crass, and there's no explicit
motivation.

	$ time find -name '*.fish' >/dev/null
	Executed in  431.93 millis
	$ time find * -name '*.fish' >/dev/null
	Executed in   39.98 millis

Let's go back to testing only directories where we currently have Git-tracked
fish files.  This makes uncached "check-all-fish-files.fish" go from 26
seconds to 5 seconds.
2025-06-09 10:28:49 +02:00
Johannes Altmanninger
138c6c4c40 check-all-fish-files: remove unneeded fallback
According to commit 8a07db8e8f (Revert "Revert "Speed up check-all-fish-files
when executed locally"", 2021-03-06), we can assume "find -newer" is supported.
2025-06-09 10:28:49 +02:00
Johannes Altmanninger
f8751a4f97 check-all-fish-files: fix caching logic
check-all-fish-files takes a long time (>20 seconds here); which is why we
have a (hacky) optimization to avoid checking files we already checked.
This optimization hasn't worked since commit e96b6e157c (Remove TMPDIR
dependency from tests/, 2021-07-30) which started each test invocation in
a private tmpdir. Fix that.

The optimization is useful because this test is, by far, the bottleneck
for parallel test execution (#11561):

	$ cargo b && time tests/test_driver.py target/debug
	...
	checks/tmux-complete.fish                      PASSED    8465 ms
	checks/check-completions.fish                  PASSED   10948 ms
	checks/check-sphinx.fish                       PASSED   12949 ms
	checks/check-all-fish-files.fish               PASSED   29828 ms
	200 / 200 passed (0 skipped)
	________________________________________________________
	Executed in   31.00 secs    fish           external
	   usr time   81.02 secs  462.00 micros   81.02 secs
	   sys time   26.41 secs  272.00 micros   26.41 secs

A cache miss for check-all-fish-files.fish takes 24 seconds (though the
grandchild commit will speed this up), a cache hit 0.5 seconds.
2025-06-09 10:28:49 +02:00
Dennis Huang
7fe92be405 Add --all option to path
- Add --all option to path
- Add tests
- Add doc
2025-06-05 14:10:47 +02:00
Johannes Altmanninger
3951a858dd reader: do not send queries if stdout is not a terminal
Interactive fish with output redirected ("fish >/dev/null")
is not a common use case but it is valid.

Perhaps surprisingly, "fish >some-file" *does* print terminal escape codes
(colors, cursor movement etc.) even if terminal output is not a TTY.
This is typically harmless, and potentially useful for debugging.

We also send blocking terminal queries but those are not harmless in this case.
Since no terminal will receive the queries, we hang; indefinitely as of today,
but we should give up after a timeout and print an error.  Either way that
seems needlessly surprising. Suppress queries in this case.

In future, we should probably do something similar if stdin is not a terminal;
though in that case we're even less likely to be interactive (only "-i"
I think).
2025-05-29 17:57:38 +02:00
Johannes Altmanninger
5657f093e7 Test case for autoload + erase + autoload
Commit 5918bca1eb (Make "complete -e" prevent completion autoloading,
2024-08-24) has a weird "!removed" check; it was added because "complete
-e" only needs to create the tombstone if we removed nothing.  Otherwise the
autoloader will usually take care of not loading the removed completions again.
We should probably get rid of "!removed"..  for now add a test to demonstrate
this behavior.
2025-05-29 17:57:38 +02:00
Johannes Altmanninger
a7c04890c9 Fix "set fish_complete_path" accidentally disabling autoloading
Commit 5918bca1eb (Make "complete -e" prevent completion autoloading,
2024-08-24) makes "complete -e foo" add a tombstone for "foo", meaning we
will never again load completions for "foo".

Due to an oversight, the same tombstone is added when we clear cached
completions after changing "fish_complete_path", preventing completions from
being loaded in that case.  Fix this by restoring the old behavior unless
the user actually used "complete -e".
2025-05-29 17:57:38 +02:00
Johannes Altmanninger
6737872fb7 embed-data: naturalize generated_completions-hack to prevent repeated autoloading
As reported in https://github.com/fish-shell/fish-shell/issues/11535#issuecomment-2915440295,
a command like "complete -C'git '" gets progressively slower every time.

A diff of "fish_trace=1" output shows that each completion invocation added
more stuff to the global "__fish_git_aliases", resulting in output like:

	--> for s db
	...
	--> for s db s db
	...
	--> for s db s db s db

Reproducer:

	$ touch ~/.local/share/fish/generated_completions/foo.fish
	$ cargo install --path . --debug
	$ ~/.cargo/bin/fish -d autoload -c 'function foo; end; for i in 1 2; complete -C"foo "; end'

We redundantly autoload the embedded file, which, by definition doesn't change.
This happens when
1. the "embed-data" feature is enabled (default for "cargo install")
2. there is a completion file in generated_completions

which triggers a hack to give precedence to "embedded:completions/git.fish"
over "generated_completions/git.fish".

Since we always load all file-based files first, we clobber the autoload cache
("self.autoloaded_files") with the mtime of the generated completion file, even
if we're never gonna return it.  This makes the embed-data logic think that
the asset has changed (which is impossible! But of course it is possible that
"fish_complete_path" changes and causes a need to load "embedded:git.fish").

Fix that by treating embedded files more like normal files.  This is closer
to historical behavior where $__fish_data_dir/{functions,completions}
are normal directories. Seems like this should fix a false negative in
"has_attempted_autoload" which feels useful.

Add a dead test, I guess. It's not run with feature="embed-data" yet. In
future we should test this in CI.
2025-05-29 17:38:42 +02:00
Johannes Altmanninger
093b468ac1 Merge pull request #11502 2025-05-29 16:06:24 +02:00
Daniel Rainer
c2e2237e7c Add a test which fails on sphinx warning/failure 2025-05-28 15:32:13 +02:00
Johannes Altmanninger
e26b585ce5 builtin status: remove spurious newline from current-command (Rust port regression)
WHen "status current-command" is called outside a function it always returns
"fish". An extra newline crept in, fix that.

Fixes 77aeb6a2a8 (Port execution, 2023-10-08).
Fixes #11503
2025-05-20 12:32:22 +02:00
Johannes Altmanninger
107e4d11de Fix Vi mode glitch when replacing at last character
Another regression from d51f669647 (Vi mode: avoid placing cursor beyond last
character, 2024-02-14) "Unfortunately Vi mode sometimes needs to temporarily
select past end". So do the replace_one mode bindings which were forgotten.

Fix this.

This surfaces a tricky problem: when we use something like

	bind '' self-insert some-command

When key event "x" matches this generic binding, we insert both "self-insert"
and "some-command" at the front of the queue, and do *not* consume "x",
since the binding is empty.

Since there is a command (that might call "exit"), we insert a check-exit
event too, after "self-insert some-command" but _before_ "x".

The check-exit event makes "self-insert" do nothing. I don't think there's a
good reason for this; self-insert can only be triggered by a key event that
maps to self-insert; so there must always be a real key available for it to
consume. A "commandline -f self-insert" is a nop. Skip check-exit here.

Fixes #11484
2025-05-13 00:01:11 +02:00
Johannes Altmanninger
50500ec5b9 Fix typo causing wrong cursor position after Vi mode paste
Regressed in d51f669647 (Vi mode: avoid placing cursor beyond last character,
2024-02-14).
2025-05-12 22:57:20 +02:00
Johannes Altmanninger
41dfb5147f Fix typo in set_color test 2025-05-11 22:55:48 +02:00
Johannes Altmanninger
156fa8081c Underline styles for double/dotted/dashed
My phone uses dotted underline to indicate errors; that seems nice, a bit
less aggressive than curly.  Unfortunately dotted underlines are not as well
supported in terminal emulators; sometimes they are barely visible.  So it's
unlikely that we want to use --underline=dotted for an important theme.
Add double and dashed too I guess, even though I don't have a concrete
use case..
2025-05-11 22:18:06 +02:00
Johannes Altmanninger
80e30ac756 Always treat brace at command start as compound statement
For backwards compatibility, fish does not treat "{echo,hello}" as a compound
statement but as brace expansion (effectively "echo hello").  We interpret
"{X...}" as compound statement only if X is whitespace or ';' (which is an
interesting solution).

A brace expansion at the very start of a command 
is usually pointless (space separation is shorter).
The exception are cases where the command name and the first few arguments
share a suffix.

	$ {,1,2,3,4}echo
	1echo 2echo 3echo 4echo

Not sure if anyone uses anything like that.  Perhaps we want to trade
compatibility for simplicity. I don't have a strong opinion on this.

Always parse the opening brace as first character of a command token as
compound statement.
Brace expansion can still be used with a trick like: «''{echo,foo}»

Closes #11477
2025-05-11 22:00:43 +02:00
Johannes Altmanninger
83f74f9332 builtin commandline: fix "-x" spuriously including redirection targets
completions frequently use

	argparse ... -- (commandline -xpc)

The "commandline -xpc" output
contains only string tokens.

A syntactically-valid process ("-p") consistes of only string tokens
and redirection tokens.  We skip all non-string tokens, but we do include
redirection targets, which are always strings.  This is weird, and confuses
completion scripts such as the one above.  Leave out redirection targets too.

Part of #11084
2025-05-11 12:46:08 +02:00
Johannes Altmanninger
111922b60f Fix export test on macOS GHA runner
This system sets something like
$MANPATH: originally inherited as |/Applications/Xcode_15.4.app/...|
2025-05-04 18:19:42 +02:00