These aren't typically used in the terminal but they are present on
many keyboards.
Also reorganize the named key constants a bit. Between F500 and
ENCODE_DIRECT_BASE (F600) we have space for 256 named keys.
(cherry picked from commit 109ef88831)
We parse "\e\e[x" as alt-modified "Invalid" key. Due to this extra
modifier, we accidentally add it to the input queue, instead of
dropping this invalid key.
We don't really want to try to extract some valid keys from this
invalid sequence, see also the parent commit.
This allows us to remove misplaced validation that was added by
e8e91c97a6 (fish_key_reader: ignore sentinel key, 2024-04-02) but
later obsoleted by 66c6e89f98 (Don't add collateral sentinel key to
input queue, 2024-04-03).
(cherry picked from commit 84f19a931d)
This situation can be triggered in practice inside a terminal like tmux
3.5 by running
tmux new-session fish -C 'sleep 2' -d reader -o log-file
and typing "alt-escape x"
The log shows that we drop treat this as alt-[ and drop the x on the floor.
reader: Read char alt-\[ -- Key { modifiers: Modifiers { ctrl: false,
alt: true, shift: false }, codepoint: '[' } -- [27, 91, 120]
This input ("\e[x") is ambiguous.
It looks like it could mean "alt-[,x". However that conflicts with a
potential future CSI code, so it makes no sense to try to support this.
Returning "None" from parse_csi() causes this weird behavior of
returning "alt-[" and dropping the rest of the parsed sequence.
This is too easy; it has even crept into a bunch of places
where the input sequence is actually valid like "VT200 button released"
but where we definitely don't want to report any key.
Fix the default: report no key for all unknown sequences and
intentionally-suppressed sequences. Treat it at "alt-[" only when
there is no input byte available, which is more or less unambiguous,
hence a strong enough signal that this is a actually "alt-[".
(cherry picked from commit 3201cb9f01)
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".
(cherry picked from commit a7c04890c9)
When two fish processes rewrite the uvar file concurrent, they rely on the
uvar file's mtime (queried after taking a lock, if locking is supported) to
tell us whether their view of the uvar file is still up-to-date. If it is,
they proceed to move it into place atomically via rename().
Since the observable mtime only updates on every OS clock tick, we call
futimens() manually to force-update that, to make sure that -- unless both
fish conincide on the same *nanosecond* -- other fish will notice that the
file changed.
Unfortunately, commit 77aeb6a2a8 (Port execution, 2023-10-08) accidentally
made us call futimens() only if clock_gettime() failed, instead of when
it succeeded. This means that we need to wait for the next clock tick to
observe a change in mtime.
Any resulting false negatives might have caused us to drop universal variable updates.
Reported in https://github.com/fish-shell/fish-shell/pull/11492#discussion_r2098948362
See #10300
(cherry picked from commit 8617964d4d)
When locking the uvar file, we retry whenever flock() fails with EINTR
(e.g. due to ctrl-c).
But not when locking the history file. This seems wrong; all other libc
functions in the "history_file" code path do retry.
Fix that. In future we should extract a function.
Note that there are other inconsistencies; flock_uvar_file() does not
shy away from remote file systems and does not respect ABANDONED_LOCKING.
This means that empirically probably neither are necessary; let's make things
consistent in future.
See https://github.com/fish-shell/fish-shell/pull/11492#discussion_r2095096200
Might help #10300
(cherry picked from commit 4d84e68dd4)
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
(cherry picked from commit e26b585ce5)
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
(cherry picked from commit 107e4d11de)
Commit b00899179f (Don't indent multi-line quoted strings; do indent inside
(), 2024-04-28) changed how we compute indents for string tokens with command
substitutions:
echo "begin
not indented
end $(
begin
indented
end)"(
begin
indented
end
)
For the leading quoted part of the string, we compute indentation only for
the first character (the opening quote), see 4c43819d32 (Fix crash indenting
quoted suffix after command substitution, 2024-09-28).
The command substitutions, we do indent as usual.
To implement the above, we need to separate quoted from non-quoted
parts. This logic crashes when indent_string_part() is wrongly passed
is_double_quoted=true.
This is because, given the string "$()"$(), parse_util_locate_cmdsub calls
quote_end() at index 4 (the second quote). This is wrong because that function
should only be called at opening quotes; this is a closing quote. The opening
quote is virtual here. Hack around this.
Fixes#11444
(cherry picked from commit 48704dc612)
Commit df3b0bd89f (Fix commandline state for custom completions with variable
overrides, 2022-01-26) made us push a transient command line for custom
completions based on a tautological null-pointer check ("var_assignments").
Commit 77aeb6a2a8 (Port execution, 2023-10-08) turned the null pointer into
a reference and replaced the check with "!ad.var_assignments.is_empty()".
This broke scenarios that relied on the transient commandline. In particular
the attached test cases rely on the transient commandline implicitly placing
the cursor at the end, irrespective of the cursor in the actual commandline.
I'm not sure if there is an easy way to identify these scenarios.
Let's restore historical behavior by always pushing the transient command line.
Fixes#11423
(cherry picked from commit 97641c7bf6)
As mentioned in
https://github.com/fish-shell/fish-shell/pull/9688#discussion_r1155089596,
commit b77d1d0e2b (Stop crashing on invalid Unicode input, 2024-02-27), Rust's
char type doesn't support arbitrary 32-bit values. Out-of-range Unicode
codepoints would cause crashes. That commit addressed this by converting
the encoded bytes (e.g. UTF-8) to special private-use-area characters that
fish knows about. It didn't bother to update the code path in builtin read
that relies on mbrtowc as well.
Fix that. Move and rename parse_codepoint() and rename/reorder its input/output
parameters.
Fixes#11383
(cherry picked from commit d9ba27f58f)
This also changes the single-byte locale code path to treat keyboard input
like "\x1ba" as alt-a instead of "escape,a". I can't off-hand reproduce
a problem with "LC_ALL=C fish_key_reader", I guess we always use a UTF-8
locale if available?
(cherry picked from commit b061178606)
This part of the code could use some love; when we happen to clear the
selected text, we should end the selection.
But that's not how it works today. This is fine for Vi mode, because Vi
mode never deletes in visual mode.
Let's fix the crash for now.
Fixes#11367
(cherry picked from commit af3b49bf9c)
With
bind ctrl-r 'sleep 1' history-pager
typing ctrl-r,escape crashes fish in the history pager completion callback,
because the history pager has already been closed.
Prior to 55fd43d86c (Port reader, 2023-12-22), the completion callback
would not crash open a pager -- which causes weird races with the
user input.
Apparently this crash as been triggered by running "playwright",
and -- while that's running typing ctrl-r ligh escape.
Those key strokes were received while the kitty keyboard protocol
was active, possibly a race.
Fixes#11355
(cherry picked from commit c94e30293a)
Consider command line modifications triggered from fish script via abbreviation
expansion:
function my-abbr-func
commandline -r ""
echo expanded
end
abbr -a foo --function my-abbr-func
Prior to commit 8386088b3d (Update commandline state changes eagerly as well,
2024-04-11), we'd silently ignore the command line modification.
This is because the abbreviation machinery runs something similar to
if my-abbr-func
commandline -rt expanded
end
except without running "apply_commandline_state_changes()" after
"my-abbr-func", so the «commandline -r ""» update is lost.
Commit 8386088b3d applies the commandline change immediately in the abbrevation
function callback, invalidating abbrevation-expansion state.
The abbreviation design does not tell us what should happen here. Let's ignore
commandline modifications for now. This mostly matches historical behavior.
Unlike historical behavior we also ignore modifications if the callback fails:
function my-abbr-func
commandline -r ""
false
end
Remove the resulting dead code in editable_line.
See #11324
(cherry picked from commit 11c7310f17)
In our C++ implementation, these tests were run serially. As pointed out in
https://github.com/fish-shell/fish-shell/issues/11254#issuecomment-2735623229
we run them in parallel now, which means that one test could be changing
the global locale used by another.
In theory this could be fine because all tests are setting setting the
global locale to the same thing but the existence of a lock suggests that
setlocale() is not guaranteed to be atomic, so it's possible that another
thread uses a temporarily-invalid locale.
Fixes#11254
(cherry picked from commit 1d78c8bd42)
We have this hack where any positional arguments are taken as argument
names if "--argument-names" is given, and that didn't check for
read-only variables.
Fixes#11295
(cherry picked from commit d203ee4d53)
The chances that xterm-256color breaks anything are miniscule.
In the features we use, there are basically no differences,
especially when you consider that we decode keys independently.
E.g. tmux-256color has differences, but they are either just taste
questions (xterm's clear_screen will also clear scrollback),
or they're just... not actually different?
Terminfo will claim that it uses a different cursor_up and
exit_attribute_mode, but it also understands the xterm ones,
and it sends a different key_home,
but we decode that even with TERM=xterm-256color.
In some cases, terminfo is also just outright *wrong* and will claim
something does not support italics when it does.
So, since the differences are very likely to simply not matter,
throwing a warning is more confusing than it is helpful.
(cherry picked from commit 642ec399ca)
Commit 29dc307111 (Insert some completions with quotes instead of backslashes,
2024-04-13) breaks some workflows. Given
touch '[test] file1'
touch '[test] file2'
ls tes<Tab>
we insert completions quoted, which is inconvenient when using globs.
This implicit quoting feature is somewhat minor. But quotes look nicer,
so let's try to keep them. Either way, users can ask for it by starting a
token with «"».
Use quoting only when we insert unique completions.
Closes#11271
(cherry picked from commit 9f79fe17fc)
The new cursor-end-mode "inclusive" (which is active in Vi mode) is causing
many issues.
One of them is because cancel-commandline wants to move to the end of the
command line before printing "^C". Since "inclusive" cursor mode prevents
the cursor from moving past the last character, that one will be overwritten
with a "^". Hack around this.
Closes#11261
(cherry picked from commit b08ff33291)
Since commit 0627c9d9af (Render control characters as Unicode Control Pictures,
2020-08-29), we render control character in the commandline as "␇" etc.
They can be inserted via either history search, or bindings such as
bind ctrl-g "commandline -i \a"
That commit incorrectly assumes that the prompt is rendered the same way as
the command line (which goes through "ScreenData" etc).
This is wrong -- prompt text is written to stdout as-is, and a prompt that
outputs \t (tab) or \a (BEL) is valid. The wrong assumption means that we
overestimate the width of prompts containing control characters.
(For some reason, after switching from Vi insert to Vi normal mode, we seem
to get the width right which means the command line jumps around)
Let's revert to the old width computation for any prompt text.
Closes#11252
(cherry picked from commit 4d81cf8af4)
For unknown reasons this assertion fails. This means that 1b9b893169 (After
reading corrupted history entry, keep reading older entries, 2024-10-06)
is not fully working. Go back to historical behavior for now.
Closes#11236
(cherry picked from commit 4f80e5cb54)
Midnight Commander 4.8.33 knows how to read the CSI u encoding of ctrl-o
(which is the only key it reads while the shell is in control). But it fails
to when numlock or capslock is active. Let's disable the kitty keyboard
protocol again until mc indicates that this is fixed.
Closes#10640
The other issue talked about in that issue is an unrelated mc issue, see
https://github.com/MidnightCommander/mc/issues/4597#issuecomment-2705900024
Ever since 149594f974 (Initial revision, 2005-09-20), we move the
cursor to the end of the commandline just before executing it.
This is so we can move the cursor to the line below the command line,
so moving the cursor is relevant if one presses enter on say, the
first line of a multi-line commandline.
As mentioned in #10838 and others, it can be useful to restore the
cursor position when recalling commandline from history. Make undo
restore the position where enter was pressed, instead of implicitly
moving the cursor to the end. This allows to quickly correct small
mistakes in large commandlines that failed recently.
This requires a new way of moving the cursor below the command line.
Test changes include unrelated cleanup of history.py.
(cherry picked from commit 610338cc70)
(cherry picked from commit 0e512f8033)
As reported on gitter, fish running inside a qemu console randomly fails to
recognize multi-byte sequences like "\e[D" (right); it sometimes recognizes
the first two bytes as "alt-[" and the last byte as the "D" key.
This because 8bf8b10f68 (Extended & human-friendly keys, 2024-03-30) changed
our approach to reading multi-byte key sequences. Previously, we'd wait
forever (or rather fish_sequence_key_delay_ms) for the "D" byte.
As of 8bf8b10f68, we assume the entire sequence is already present in the
input buffer; and stop parsing the sequence if stdin is not readable.
It would be more technically correct to implement the VT state machine but
then we'd probably want to to figure out a timeout or a reset key, in case
of transport or terminal issues.
Returning early is also what we have historically done for multi-byte code
points. Also, other terminal programs have been using it for many years
without problems.
I don't know why this happens in qemu but it seems we can work around by
setting a 1ms timeout. This timeout should be small enough two keys "escape"
and "[" typed by a human will still be seen separate.
Refs:
https://matrix.to/#/!YLTeaulxSDauOOxBoR:matrix.org/$Cfi9wL8FGLAI6_VAQWG2mG_VxsADUPvdPB46P41Jdbshttps://matrix.to/#/!YLTeaulxSDauOOxBoR:matrix.org/$O_-LZ1W7Dk6L_4Rj0MyCry6GtO2JQlEas8fH9PrSYT8
(cherry picked from commit e1be842167)
Given
$ cat ~/.config/kitty/kitty.conf
notify_on_cmd_finish unfocused 0.1 command notify-send "job finished with status: %s" %c
kitty will send a notification whenever a long-running (>.1s) foreground
command finishes while kitty is not focused.
The %c placeholder will be replaced by the commandline.
This is passed via the OSC 133 command start marker, kitty's fish shell
integration.
That integration has been disabled for fish 4.0.0 because it's no longer
necessary since fish already prints OSC 133. But we missed the parameter for
the command string. Fix it. (It's debatable whether the shell or the terminal
should provide this feature but I think we should fix this regression?)
Closes#11203
See https://github.com/kovidgoyal/kitty/issues/8385#issuecomment-2692659161
(cherry picked from commit 4378e73fc7)
Something like
write!(f, "foo{}bar", ...)
seems to call f.write_str() thrice.
Splitting a single OSC 133 command into three calls to write(3) might result in
odd situations if one of them fails. Let's try to do it in one in most cases.
Add a new buffered output type that can be used with write!(). This is
somewhat redundant given that we have scoped_buffer(). While at it, remove
the confused error handling. This doesn't fail unless we are OOM (and this
new type makes that more obvious).
(cherry picked from commit e5e932e970)
modifyOtherKeys with non-English or other non-default keyboard layouts will
cause wrong keys to be sent by WezTerm. Let's try to disable it for now.
Proposed upstream fix: https://github.com/wezterm/wezterm/pull/6748Closes#11204
As reported in
https://matrix.to/#/!YLTeaulxSDauOOxBoR:matrix.org/$CLuoHTdvcRj_8-HBBq0p-lmGWeix5khEtKEDxN2Ulfo
Running
fish -C '
fzf_key_bindings
echo fish_vi_key_bindings >>~/.config/fish/config.fish
fzf-history-widget
'
and pressing "enter" will add escape sequences like "[2 q" (cursor shape)
to fish's command line.
This is because fzf-history-widget binds "enter" to a filter
that happens to be a fish script:
set -lx FZF_DEFAULT_OPTS \
... \
"--bind='enter:become:string replace -a -- \n\t \n {2..} | string collect'" \
'--with-shell='(status fish-path)\\ -c)
The above ~/.config/fish/config.fish (redundantly) runs "fish_vi_key_bindings"
even in *noninteractive* shells, then "fish_vi_cursor" will print cursor
sequences in its "fish_exit" handler. The sequence is not printed to the
terminal but to fzf which doesn't parse CSI commands.
This is a regression introduced by a5dfa84f73 (fish_vi_cursor: skip if stdin
is not a tty, 2023-11-14). That commit wanted "fish -c read" to be able to
use Vi cursor. This is a noninteractive shell, but inside "read" we are
"effectively interactive". However "status is-interactive" does not tell
us that.
Let's use a more contained fix to make sure that we print escape sequences only
if either fish is interactive, or if we are evaluating an interactive read.
In general, "fish -c read" is prone to configuration errors, since we
recommend gating configuration (for bind etc) on "status is-interactive"
which will not run here.
(cherry picked from commit 495083249b)
Historically, up-arrow search matches have been highlighted by
1. using the usual foreground (from syntax highlighting)
2. using the background from $fish_color_search_match
Commit 9af6a64fd2 (Fix bad contrast in search match highlighting, 2024-04-15)
broke this by also applying the foreground from $fish_color_search_match.
As reported on gitter, there is a meaningful scenario where the foreground
from syntax highlighting should not be overwritten:
set fish_color_search_match --reverse
this copies the foreground from syntax highlighting to the background.
Since commit 9af6a64fd2 overwrites the foreground highlight, the resulting
background will be monocolored (black in my case) instead of whatever is
the syntax-colored foreground.
FWIW the reversed foreground will always be monocolored, because we have
always done 2.
Let's unbreak this scenario by using the foreground from
fish_color_search_match only if it's explicitly set (like we do since
9af6a64fd2).
This is hacky because an empty color is normally the same as "normal", but
it gets us closer to historical behavior. In future we should try to come
up with a better approach to color blending/transparency.
(cherry picked from commit b6269438e9)
iTerm has a bug where it'll send Option-Left as Left instead of the
proper Alt-Left. This was reported upstream and fixed in
480f059bce
which is contained in the 3.5.12-beta2 tag, so let's assume that fixes
it.
Fixes#11025
(not necessary in 4.1)
parse_util_lineno() returns 1-based line numbers but
parse_util_get_offset_from_line() expects zero based line offsets.
Fixes#11162
(cherry picked from commit afbdb9f268)