Commit a583fe723 ("commandline -f foo" to skip queue and execute immediately,
2024-04-08) fixed the execution order of some bindings but was partially
backed out in 5ba21cd29 (Send repaint requests through the input queue again,
2024-04-19) because repainting outside toplevel yields surprising results
(wrong $status etc).
Transient prompts wants to first repaint and then execute some more readline
commands, all within a single binding. This was broken by the second commit
because that one defers the repaint until after the binding has finished.
Work around this problem by deferring input events again while a readline
event was queued. This is closest to the historical behavior.
The implementation feels hacky; we might find odd situations.
For example,
commandline -f repaint end-of-line
set token (commandline -t)
sets the wrong token.
Probably not a very important case. We could throw an error or make it work
by letting "commandline -t" drain the input queue.
That seems too complicated, better change repaints to not use the input queue
(and fake $status etc). Let's try to do that in future.
Closes#10492
Prior to this change, signals.py attempted to generate Ctrl-C (SIGINT) by
sending \x03 to stdin. But with the change to use the CSI U sequence, Ctrl-C no
longer generates SIGINT.
Switch to sending SIGINT directly. Also switch up some of the sleep constants so
that a sleep command can't be confused with another one.
Given "abbr foo something", the input sequence
foo<space><ctrl-z><space>
would re-expand the abbreviation on the second space which is surprising
because the cursor is not at or inside the command token. This looks to be
a regression from 00432df42 (Trigger abbreviations after inserting process
separators, 2024-04-13)
Happily, 69583f303 (Allow restricting abbreviations to specific commands
(#10452), 2024-04-24) made some changes that mean the bad commit seems no
longer necessary. Not sure why it works but I'll take it.
On a command with multiline quoted string like
begin
echo "line1
line2"
end
we actually indent line2 which seeems misleading because the indentation
changes the behavior when typed into a script.
This has become more prominent since commits
- a37629f86 (fish_clipboard_copy: indent multiline commands, 2024-04-13)
- 611a0572b (builtins type/functions: indent interactively-defined functions, 2024-04-12)
- 222673f33 (edit_command_buffer: send indented commandline to editor, 2024-04-12)
which add indentation to an exported commandline.
Never indent quoted strings, to make sure the rendering matches the semantics.
Note that we do need to indent the opening quote which is fine because
it's on the same line.
While at it, indent command substitutions recursively. That feature should
also be added to fish_indent's formatting mode (which is the default).
Fortunately the formatting mode already works fine with quoted strings;
it does not indent them. Not sure how that's done and whether indentation
can use the same logic.
vared.fish is installed at
/home/fishuser/fish-build/test/buildroot/usr/local/share/fish/functions/vared.fish
as oppposed to being sourced from share/functions/.
I'm not 100% sure why this happens but it doesn't seem wrong.
These take over two minutes under ASAN (like ~40 seconds without, so
they aren't quick to begin with), and don't really give any additional
insight.
So we skip them to save time
This allows making something like
```fish
abbr --add gc --position anywhere --command git back 'reset --hard
HEAD^'
```
to expand "gc" to "reset --hard HEAD^", but only if the command is
git (including "command git gc" or "and git gc").
Fixes#9411
I have no idea why this matches the string thrice when it is entered
once and suggestions are disabled.
I've seen this fail even on my local system, I expect it works because
of some terminal integration.
This tries to open the given file to use as stdin, and if it fails,
for any reason, it uses /dev/null instead.
This is useful in cases where we would otherwise do either of these:
```fish
test -r /path/to/file
and string match foo < /path/to/file
cat /path/to/file 2>/dev/null | string match foo
```
This both makes it nicer and shorter, *and* helps with TOCTTOU - what if the file is removed/changed after the check?
The reason for reading /dev/null instead of a closed fd is that a closed fd will often cause an error.
In case opening /dev/null fails, it still skips the command.
That's really a last resort for when the operating system
has turned out to be a platypus and not a unix.
Fixes#4865
(cherry picked from commit df8b9b7095)
This introduces a feature flag, "test-require-arg", that removes builtin test's zero and one argument special modes.
That means:
- `test -n` returns false
- `test -z` returns true
- `test -x` with any other option errors out with "missing argument"
- `test foo` errors out as expecting an option
`test -n` returning true is a frequent source of confusion, and so we are breaking with posix in this regard.
As always the flag defaults to off and can be turned on. In future it will default to on and then eventually be made read-only.
There is a new FLOG category "deprecated-test", run `fish -d deprecated-test` and it will show any test call that would change in future.
Another consequence of a583fe723 ("commandline -f foo" to skip queue
and execute immediately, 2024-04-08) is that "commandline -f repaint"
will paint the prompt with the current value of $status which might be
set from a shell command in a the currently executing binding, instead of
waiting for the top-level status. This is wrong, at least historically. It
surfaces in bindings like alt-w which always paint a status value of [1]
when on single-lines commandlines.
Another regression is that a redundant repaint in a signal handler outputs
an extra prompt.
Fix both by making repaint commands go over the input queue again. This way,
they are always run with a good commandline state. There is no need to
repaint immediately because I don't think anyone has a data dependency on it
(we currently don't expose the prompt string), it's only for rendering.
We sometimes leak ^[[I and ^[[O focus reporting events when run from VSCode's
"Run python file" button in the top right corner. To reproduce I installed
the ms-python extension set the VSCode default shell to fish and repeatedly
ran a script that does "time.sleep(1)". I believe VSCode synthesizes keys
and triggers a race condition.
We can probably fix this but I'm not sure when I'll get to it (given how
relatively unimportant this feature is).
So let's go back to the old behavior of only enabling focus reporting in tmux.
I believe that tmux is affected by the same VSCode issue (also on 3.7.1 I
think) but I haven't been able to get tmux to emit focus reporting sequences
yet. Still, keep it to not regress cursor shape (#4788). So far this is
the only motivation for focus reporting and I believe it is only relevant
for terminals that can split windows (though there are a bunch that do).
Closes#10448
Popular operating systems support shift-delete to delete the selected item
in an autocompletion widgets. We already support this in the history pager.
Let's do the same for up-arrow history search.
Related discussion: https://github.com/fish-shell/fish-shell/pull/9515
On
a;
we don't expand the abbreviation because the cursor is right of semicolon,
not on the command token. Fix this by making sure that we call expand-abbr
with the cursor on the semicolon which is the end of the command token.
(Now that our bind command execution order is less surprising, this is doable.)
This means that we need to fix the cursor after successfully expanding
an abbreviation. Do this by setting the position explicitly even when no
--set-position is in effect.
An earlier version of this patch used
bind space self-insert backward-char expand-abbr or forward-char
The problem with that (as a failing test shows) was that given "abbr m
myabbr", after typing "m space ctrl-z", the cursor would be after the "m",
not after the space. The second space removes the space, not changing the
cursor position, which is weird. I initially tried to fix this by adding
a hack to the undo group logic, to always restore the cursor position from
when begin-undo-group was used.
bind space self-insert begin-undo-group backward-char expand-abbr end-undo-group or forward-char
However this made test_torn_escapes.py fail for mysterious reasons.
I believe this is because that test registers and triggers a SIGUSR1 handler;
since the signal handler will rearrange char events, that probably messes
with the undo group guards.
I resorted to adding a tailor-made readline cmd. We could probably remove
it and give the new behavior to expand-abbr, not sure.
Fixes#9730
File names that have lots of spaces look quite ugly when inserted as
completions because every space will have a backslash.
Add an initial heuristic to decide when to use quotes instead of
backslash escapes.
Quote when
1. it's not an autosuggestion
2. we replace the token or insert a fresh one
3. we will add a space at the end
In future we could relax some of these requirements.
Requirement 2 means we don't quote when appending to an existing token.
Need to find a natural behavior here.
Re 3, if the completion adds no space, users will probably want to add more
characters, which looks a bit weird if the token has a trailing quote.
We could relax this requirement for directory completions, so «ls so»
completes to «ls 'some dir with spaces'/».
Closes#5433
I think commit 8386088b3 (Update commandline state changes eagerly as well,
2024-04-11) broke the alt-s binding.
This is because we update the commandline state snapshot (which is consumed
by builtin commandline and others) only at key points. This seems like a
dubious optimization. With the new streamlined bind execution semantics,
this doesn't really work anymore; any shell command can run any number of
commands like "commandline -i foo" which should synchronize.
Do the simple thing of calculating the snapshot whenever needed.
Commit c3cd68dda (Process shell commands from bindings like regular char
events, 2024-03-02) mentions a "weird ordering difference".
The issue is that "commandline -f foo" goes through the input
queue while other commands are executed directly.
For example
bind ctrl-g "commandline -f end-of-line; commandline -i x"
is executed in the wrong order. Fix that.
This doesn't yet work for "commandline -f exit" but that can be fixed easily.
It's hard to imagine anyone would rely on the existing behavior. "commandline
-f" in bindings is mostly used for repainting the commandline.
If a binding was input starting with "\e", it's usually a raw control sequence.
Today we display the canonical version like:
bind --preset alt-\[,1,\;,5,C foo
even if the input is
bind --preset \e\[1\;5C foo
Make it look like the input again. This looks more familiar and less
surprising (especially since we canonicalize CSI to "alt-[").
Except that we use the \x01 representation instead of \ca because the
"control" part can be confusing. We're inside an escape sequence so it seems
highly unlikely that an ASCII control character actually comes from the user
holding the control key.
The downside is that this hides the canonical version; it might be surprising
that a raw-escape-sequence binding can be erased using the new syntax and
vice versa.
Some terminals send the focus-in sequences ("^[I") whenever focus reporting is
enabled. We enable focus reporting whenever we are finished running a command.
If we run two commands without reading in between, the focus sequences
will show up on the terminal.
Fix this by enabling focus-reporting as late as possible.
This fixes the problem with `^[I` showing up when running "cat" in
gnome-terminal https://github.com/fish-shell/fish-shell/issues/10411.
This begs the question if we should do the same for CSI u and bracketed paste.
It's difficult to answer that; let's hope we find motivating test cases.
If we enable CSI u too late, we might misinterpret key presses, so for now
we still enable those as early as possible.
Also, since we now read immediately after enabling focus events, we can get
rid of the hack where we defer enabling them until after the first prompt.
When I start a fresh terminal, the ^[I no longer shows up.
See the changelog additions for user-visible changes.
Since we enable/disable terminal protocols whenever we pass terminal ownership,
tests can no longer run in parallel on the same terminal.
For the same reason, readline shortcuts in the gdb REPL will not work anymore.
As a remedy, use gdbserver, or lobby for CSI u support in libreadline.
Add sleep to some tests, otherwise they fall (both in CI and locally).
There are two weird failures on FreeBSD remaining, disable them for now
https://github.com/fish-shell/fish-shell/pull/10359/checks?check_run_id=23330096362
Design and implementation borrows heavily from Kakoune.
In future, we should try to implement more of the kitty progressive
enhancements.
Closes#10359
A long standing issue is that bindings cannot mix special input functions
and shell commands. For example,
bind x end-of-line "commandline -i x"
silently does nothing. Instead we have to do lift everything to shell commands
bind x "commandline -f end-of-line; commandline -i x"
for no good reason.
Additionally, there is a weird ordering difference between special input
functions and shell commands. Special input functions are pushed into the
the queue whereas shell commands are executed immediately.
This weird ordering means that the above "bind x" still doesn't work as
expected, because "commandline -i" is processed before "end-of-line".
Finally, this is all implemented via weird hack to allow recursive use of
a mutable reference to the reader state.
Fix all of this by processing shell commands the same as both special input
functions and regular chars. Hopefully this doesn't break anything.
Fixes#8186Fixes#10360Closes#9398
Call fish_should_add_to_history to see if a command should be saved
If it returns 0, it will be saved, if it returns anything else, it
will be ephemeral.
It gets the right-trimmed text as the argument.
If it doesn't exist, we do the historical behavior of checking for a
leading space.
That means you can now turn that off by defining a
`fish_should_add_to_history` that just doesn't check it.
documentation based on #9298
It appears that the shift-delete key escape sequence is not being generated
because there's no mapping for it in screen-256color, causing the test to fail.
Switch to using f1 for the test.
This makes it so code like
```fish
echo foo
echo bar
```
is collapsed into
```fish
echo foo
echo bar
```
One empty line is allowed, more is overkill.
We could also allow more than one for e.g. function endings.
Commit e5b34d5cd (Suppress autosuggesting during backspacing like browsers do,
2012-02-06) disabled autosuggestion when backspacing. Autosuggestions are
re-enabled whenever we insert anything in the command line. Undo uses a
different code path to insert into the command line, which does not re-enable
autosuggestion.
Fix that.
Also re-enable autosuggestion when undo erases from the command line.
This seems like the simplest approach. It's not clear if there's a better
behavior; browsers don't agree on one in any case.
This is the last remnant of the old percent expansion.
It has the downsides of it, in that it is annoying to combine with
anything:
```fish
echo %self/foo
```
prints "%self/foo", not fish's pid.
We have introduced $fish_pid in 3.0, which is much easier to use -
just like a variable, because it is one.
If you need backwards-compatibility for < 3.0, you can use the
following shim:
```fish
set -q fish_pid
or set -g fish_pid %self
```
So we introduce a feature-flag called "remove-percent-self" to turn it
off.
"%self" will simply not be special, e.g. `echo %self` will print
"%self".
This stops you from doing e.g.
```fish
set pager command less
echo foo | $pager
```
Currently, it would run the command *builtin*, which can only do
`--search` and similar, and would most likely end up printing its own
help.
That means it very very likely won't work, and the code is misguided -
it is trying to defeat function resolution in a way that won't do what
the author wants it to.
The alternative would be to make the command *builtin* execute the
command, *but*
1. That would require rearchitecting and rewriting a bunch of it and
the parser
2. It would be a large footgun, in that `set EDITOR command foo` will
only ever work inside fish, but $EDITOR is also used outside.
I don't want to add a feature that we would immediately have to discourage.
Commit b768b9d3f (Use fuzzy subsequence completion for options names as well,
2024-01-27) allowed completing "oa" to "--foobar", which is a false positive,
especially because it hides other valid completions of non-option arguments.
Let's at least require a leading dash again before completing option names.
Version 2.1.0 introduced subsequence matching for completions but as the
changelog entry mentions, "This feature [...] is not yet implemented for
options (like ``--foobar``)". Add it. Seems like a strict improvement,
pretty much.
Issue #10194 reports Cobra completions do
set -l args (commandline -opc)
eval $args[1] __complete $args[2..] (commandline -ct | string escape)
The intent behind "eval" is to expand variables and tildes in "$args".
Fair enough. Several of our own completions do the same, see the next commit.
The problem with "commandline -o" + "eval" is that the former already
removes quotes that are relevant for "eval". This becomes a problem if $args
contains quoted () or {}, for example this command will wrongly execute a
command substituion:
git --work-tree='(launch-missiles)' <TAB>
It is possible to escape the string the tokens before running eval, but
then there will be no expansion of variables etc. The problem is that
"commandline -o" only unescapes tokens so they end up in a weird state
somewhere in-between what the user typed and the expanded version.
Remove the need for "eval" by introducing "commandline -x" which expands
things like variables and braces. This enables custom completion scripts to
be aware of shell variables without eval, see the added test for completions
to "make -C $var/some/dir ".
This means that essentially all third party scripts should migrate from
"commandline -o" to "commandline -x". For example
set -l tokens
if commandline -x >/dev/null 2>&1
set tokens (commandline -xpc)
else
set tokens (commandline -opc)
end
Since this is mainly used for completions, the expansion skips command
substitutions. They are passed through as-is (instead of cancelling or
expanding to nothing) to make custom completion scripts work reasonably well
in the common case. Of course there are cases where we would want to expand
command substitutions here, so I'm not sure.
Commit 5f849d0 changed control-C to print an inverted ^C and then a newline.
The original motivation was
> In bash if you type something and press ctrl-c then the content of the line
> is preserved and the cursor is moved to a new line. In fish the ctrl-c just
> clears the line. For me the behaviour of bash is a bit better, because it
> allows me to type something then press ctrl-c and I have the typed string
> in the log for further reference.
This sounds like a valid use case in some scenarios but I think that most
abandoned commands are noise. After all, the user erased them. Also, now that
we have undo that can be used to get back a limited set of canceled commands.
I believe the original motivation for existing behavior (in other shells) was
that TERM=dumb does not support erasing characters. Similarly, other shells
like to leave behind other artifacts, for example when using tab-completion
or in their interactive menus but we generally don't.
Control-C is the obvious way to quickly clear a multi-line commandline.
IPython does the same. For the other behavior we have Alt-# although that's
probably not very well-known.
Restore the old Control-C behavior of simply clearing the command line.
Our unused __fish_cancel_commandline still prints the ^C. For folks who
have explicitly bound ^C to that, it's probably better to keep the existing
behavior, so let's leave this one.
Previous attempt at #4713 fizzled.
Closes#10213