Commit graph

5164 commits

Author SHA1 Message Date
Johannes Altmanninger
964d3fff15 Keep undo history across prompts
After abandoning a commandline (for example with ctrl-c) it's nice to be
able to restore it. There is little reason to discard the requisite undo
information, so keep it.
2024-04-29 09:20:09 +02:00
ridiculousfish
3afe0bb569 Remove LoopedRead and LoopedWrite
These were unused.
2024-04-28 11:15:48 -07:00
Johannes Altmanninger
301e4d497e Make shift-delete also delete current autosuggestion
This is a bit more convenient than using "history delete".
2024-04-27 10:54:31 +02:00
Anurag Singh
62a8b48fd1 Move generated completions to cache directory 2024-04-27 10:39:30 +02:00
Fabian Boehm
1503be4287 parse_execution: Use an exhaustive match instead of an assert
This could also be "cancel", which we didn't check and instead
asserted out.
2024-04-27 08:19:00 +02:00
Johannes Altmanninger
fb99edae92 Stop using comma from command substitution in brace expansion
Fixes #5048
2024-04-26 18:15:47 +02:00
Fabian Boehm
69583f3030
Allow restricting abbreviations to specific commands (#10452)
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
2024-04-24 18:09:04 +02:00
Johannes Altmanninger
24f0abe780 Fix decoding mulitbyte characters after escape prefix
Fixes #10457
2024-04-23 00:18:14 +02:00
Johannes Altmanninger
8d20bbfcd7 Fix bad assertion warning about disowned jobs that don't get their proper pgroup
Running

    echo foo | vim -

gets us in a weird situation because we put the job in fish's process groups.
It causes us to not set a PGID for this job, so it can't be resumed among
other things.

Stopping the job with ctrl-z and try to exit the shell causes a crash in the
"There are still jobs active" warning because the PID for the job is still 0.
Let's remove the assertion to restore previous behavior, and hopefully fix
this later.
2024-04-21 21:32:44 +02:00
Johannes Altmanninger
fd61bad946 Further simplify terminal_protocols scoping
Remove the last non scoped place where we disable protocols (just before
exec(1)); it's not necessary with the current approach because we always
disable inside eval.
There is an edge case where we don't:

    fish -ic "exec bash"

leaving bash with CSI u enabled.  Disable that also in -ic mode where we
don't have a reader.

In future we should use the same approach for restore_term_mode() but I'm
not sure which one is better.
2024-04-21 21:32:44 +02:00
Johannes Altmanninger
99bf3d0dbb Fix imbalanced terminal protocols on SIGCHLD
We enable terminal protocols once at startup, and disable them before exit.
Additionally, we disable them while evaluating commands (see 8164855b7 (Disable
terminal protocols throughout evaluation, 2024-04-02))..

Thirdly, we re-enable protocols inside builtin read (where it's disabled
because we are evaluating something).  All of these three are scoped and
statically guaranteed to not leak into each others scopes.

There is another place where we enable protocols non-scoped: when we
receive a notification that a job is stopped. If this is ever hit, things
will be imbalanced and we'll fail to restore the right terminal state,
or (more likely) crash due the assertion in terminal_protocols_enable().
This code path used to be necessary when we disabled protocols only while
actually executing an external command but we changed that in 8164855b7,
so it should no longer be.  Remove it.

I haven't been able to find a test case, I'll try to do that later.

The main reason we changed the scope of protocols was focus reporting (#10408).
We have given up on that for now (outside tmux where I can't get it to work)
so we might want to reconsider and go back to the "optimized" approach of
enabling it for as long as possible. But this is simpler, easier to verify.
2024-04-21 17:16:23 +02:00
Fabian Boehm
20243132fb Add <? input redirection
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)
2024-04-21 14:35:13 +02:00
Fabian Boehm
2c17d34971
Deprecate builtin test's one- and zero-argument modes (#10365)
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.
2024-04-21 14:25:54 +02:00
Johannes Altmanninger
e97a4fab71 Escape : and = in file completions
This is similar to f7dac82ed (Escape separators (colon and equals) to improve
completion, 2019-08-23) except we only escape : and = if they are the result of
file completions.  This way we avoid issues with custom completions like dd.
This also means that it won't work for things like __fish_complete_suffix
[*] but that can be fixed later, once we can serialize the DONT_ESCAPE flag.

By moving the escaping step earlier, this causes some unit test changes
which should not result in actual behavior change.

See also #6099

[*]: The new \: and \= does not leak from "complete -C" because that command
unescapes its output  -- unless --escape is given.
2024-04-20 13:34:08 +02:00
Johannes Altmanninger
db365b5ef8 Do not treat \: or \= as file completion anchor
Partially reapplies f7dac82ed (Escape separators (colon and equals) to
improve completion, 2019-08-23) which has been reverted.
2024-04-20 13:34:08 +02:00
Johannes Altmanninger
a046b73ec7 Extract test logic for computing and applying completion
Also move one test so all the bracket tests are contiguous.
2024-04-20 13:34:08 +02:00
Johannes Altmanninger
7dc0446c5c Match stdlib strip_prefix return value 2024-04-20 13:34:08 +02:00
Johannes Altmanninger
30fbd4280d Simplify match statement in escape_string_script 2024-04-20 13:34:08 +02:00
Johannes Altmanninger
24e4fdd695 Support "bind xyz" again
This was used in Vi mode (for yiw and "*p) so rejecting it is a bit reckless.
2024-04-20 13:34:08 +02:00
Johannes Altmanninger
565eb85d8b fish_key_reader: use canonical key name for ctrl-{c,d}
The uppercase version has a different meaning now.
2024-04-20 12:11:30 +02:00
Johannes Altmanninger
5ba21cd290 Send repaint requests through the input queue again
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.
2024-04-19 12:05:27 +02:00
Johannes Altmanninger
040cb04423 Escape nonprintable characters when reporting invalid key name
Part of #10450
2024-04-18 23:27:05 +02:00
Fabian Boehm
3b6a11f881 fmt 2024-04-18 22:26:14 +02:00
Fabian Boehm
6558c0a8e5 key: Actually do engage legacy mode if first char is control
This was already in the comment.

Fixes #10450
2024-04-18 22:18:51 +02:00
Johannes Altmanninger
bdd478bbd0 Disable focus reporting on non-tmux again for now
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
2024-04-18 10:38:15 +02:00
ridiculousfish
ed8f62e723 Reimplement WGetopter::exchange() using rotate_left
A simplification informed by the new test.
2024-04-17 12:41:16 -07:00
ridiculousfish
f990d52d2b Add a test for WGetopter::exchange() 2024-04-17 12:41:12 -07:00
Verte
13230cdda0 Rewrite wgetopt.rs to Rustier syntax and naming
From https://github.com/fish-shell/fish-shell/pull/9515

Closes #9515
2024-04-17 11:26:51 -07:00
ridiculousfish
a996cafeeb Make history::remove take a &wstr instead of a WString
While it does need to store the string, we also need to use the string after
storing it, so we aren't getting any advantage from passing by value. Just pass
by reference to simplify the call sites.
2024-04-15 09:47:46 -07:00
Anurag Singh
8a8c2656f3 remove unnecessarily silenced lint in history 2024-04-15 09:43:38 -07:00
Johannes Altmanninger
9af6a64fd2 Fix bad contrast in search match highlighting
This is another problem that has been bothering me for years: as mentioned
in 1dd901e52 (Maintain cursor in history prefix search, 2024-04-12), up-arrow
search highlights search matches but the contrast is really bad, especially in
command position, because the search matches --background=brblack is combined
with whatever foreground syntax highlighting the command has.  The history
pager had a similar problem (for the selected history item) but circumented
it by disabling syntax highlighting altogether for the selected item.

fish_color_search_match's foreground component is ignored.
Let's use it instead of syntax highlighting.

This fixes the contrast on some default colorschemes but the bryellow
foreground looks weirdly like an error/warning on some terminals.  Change it
to white. This needs a hack because we don't have a canonical way to tell
if a uvar has been set by the user. Fortunately the foreground component
hasn't been used at all so far, so we're not so much changing it as much as
initializing it.
2024-04-15 09:40:21 +02:00
Johannes Altmanninger
27b1f28108 Minimize key parsing fallback logic and update changelog 2024-04-15 09:40:21 +02:00
Johannes Altmanninger
47bb56efe6 Allow mapping new-style sequences that start with escape
On Konsole with

    function my-bindings
        bind --preset --erase escape
        bind escape,i 'echo escape i'
    end
    set fish_key_bindings my-bindings

the "escape,i" binding doesn't trigger.  This is because of our special
handling of the escape key prefix.  Other multi-key bindings like "bind j,k"
wait indefinitely for the second character.  But not "escape,i"; that one
has historically had a low timeout (fish_escape_delay_ms).  The motivation
is probably that we have a "escape" binding as well that shouldn't wait
indefinitely.

We can distinguish between the case of raw escape sequence binding like "\e123"
and a binding that talks about the actual escape key like "escape,i". For the
latter we don't need the special treatment of having a low timeout, so make it
fall back to "fish_sequence_key_delay_ms" which waits indefinitely by default.
2024-04-15 09:20:44 +02:00
Johannes Altmanninger
611a0572b1 builtins type/functions: indent interactively-defined functions
This means that in case no editor is defined, "fish_indent" is now required
to fix the indentation.

Fixes #8603
2024-04-15 08:32:31 +02:00
Johannes Altmanninger
47a446ae18 Teach fish_indent to only indent and unindent
To be used in the following commits.
2024-04-15 08:32:31 +02:00
Anurag Singh
c044d5e3f0 add history append subcommand 2024-04-15 08:31:16 +02:00
Johannes Altmanninger
e01fc62d69 Don't leak encoding of invalid codepoints into uvar file
When we read bytes like \xfc that don't produce a Unicode code point,
we encode them in a Unicode private use area.
This encoding should be transparent to the user.

We accidentally add it to uvar files as \uf6fc in this case.  When reading
it back, read_unquoted_escape() will fail at the "fish_reserved_codepoint(c)"
check. This check is to avoid external input being misinterpreted
as one of our in-band signalling characters like ANY_CHAR (for *).

For encoded raw bytes, this check probably doesn't really matter in terms of
security because the only thing we do with these bytes is convert them back
to raw. So we could allow unescaping them at this point, thus supporting
old uvar files.

However that seems like the wrong direction. PUA encoding should never leak.
So let's instead make sure to serialize it as \xfc instead of \f6fc going
forward.

Fixes #10313
2024-04-14 07:59:42 +02:00
Johannes Altmanninger
2329a3adb9 Extend fish_reserved_codepoint by encodings for named keys
This might prevent unexpected behavior when the terminal sends an input
character that matches one of our named keys like Enter.
2024-04-14 07:54:03 +02:00
Johannes Altmanninger
29b309dd5f shift-delete to delete current history search match
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
2024-04-13 20:23:51 +02:00
Johannes Altmanninger
00432df420 Trigger abbreviations after inserting process separators
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
2024-04-13 20:11:11 +02:00
Johannes Altmanninger
29dc307111 Insert some completions with quotes instead of backslashes
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
2024-04-13 15:34:21 +02:00
Johannes Altmanninger
cacfcf8089 Reuse parse_util_token_extent for completion insertion
We don't need all of its features here but this makes the "completion is
appended" case more similar to the "completion replaces token" case.
2024-04-13 15:33:05 +02:00
Johannes Altmanninger
dcd6c74248 Inline parse_util_get_quote_type()
Need to access the token extent in a following commit.
2024-04-13 15:33:05 +02:00
Johannes Altmanninger
8d88b4d358 Support quoted escaping also when ' or \ is present
Also, if there are more single quotes than double quotes and dollars, use
double quotes for quoting.
2024-04-13 15:33:05 +02:00
Johannes Altmanninger
88d6801720 Don't match new-style bindings against raw sequences
On Konsole, given

    bind escape,i 'echo escape i'
    bind alt-i 'echo alt-i'

pressing alt-i triggers the wrong binding.  This is because we treat "escape
followed by i" as "alt-i". This is to support raw sequences like "\ei"
which are probably meant as "alt-i" -- we match such inputs to both mappings.

This double matching is not necessary for new-style bindings which
unambiguously describe the key presses, so let's activate this sequence
matching only for bindings specified as raw sequences.

Conversely, we currently fail to match an XTerm raw binding for ctrl-enter:

    echo 'XTerm.vt100.formatOtherKeys: 0' | xrdb
    xterm -e fish
    bind \e\[27\;5\;13~ execute

because we decode this to a single char; we match the leading CSI but not
the entire sequence. So this is a raw binding where we accidentally
match full, modified keys. Fix that too (two birds with one stone).
2024-04-13 14:36:11 +02:00
Johannes Altmanninger
4f536d6a9b Update commandline state snapshot lazily
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.
2024-04-13 14:36:11 +02:00
Johannes Altmanninger
edb5cb7226 Fix restoring cursor position on redo with edit groups 2024-04-13 14:36:11 +02:00
Johannes Altmanninger
50d93cced1 Remove bad assertion
builtin read pushes a reader instance after enabling terminal protocols,
so this doesn't hold.

Fixes #10438
2024-04-12 14:20:45 +02:00
Johannes Altmanninger
1dd901e521 Maintain cursor in history prefix search
The search term highlighting looks looks really bad on the default theme
because the command is highlighted as dark blue and the search term adds
a dark background.  If this new feature motivates us to finally fix this,
that would be great.

Closes #10430
2024-04-12 13:08:52 +02:00
Johannes Altmanninger
8386088b3d Update commandline state changes eagerly as well
The new reader_execute_readline_cmd() runs apply_commandline_state_changes()
to make sure that given

    bind x "commandline --insert foo; commandline -f backward-char"

the backward-char command knows about the insertion of "foo".  This
causes problems when running "sleep 1&" and typing some characters -
the commandline will be cleared when the job finishes.  This is because
apply_commandline_state_changes() works with stale information in this case.

Let's call it as soon as we know it's needed.  This is less messy and fits
better with the new bind function semantics ("execute things in the order
they are written").
2024-04-12 12:00:24 +02:00