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.
Commit 2d234bb676 (Only request keyboard protocols once we know if kitty kbd
is supported, 2025-01-26) queries support for the kitty protocol and acted
upon it after having read next character.
Unfortunately this meant that we don't turn on the kitty protocol until after
we read a character -- since the CSI ? u response does not generate a char
event. Let's query for primary DA additionally, matching what fish does.
In future, we should do a timed wait as well, to avoid terminal responses
leaking when there we exit fish_key_reader too quickly.
Whenever we add logic to print a control sequence that we hadn't printed
before, there is a nonzero risk that a terminal mishandles it.
Terminal-specific workarounds cause pain but are probably better than not
being able to use any new commands provided by terminals.
There is no universal way to identify a terminal. Device attributes (primary
through tertiary) typically get spoofed responses, likely not good enough
for working around bugs in specific versions of a terminal.
The de-facto standard for the terminal name and version is XTVERSION.
It's usually specific to the terminal, except for something like VTE-based
terminals, where we get this (which seems good enough also)
printf '\x1b[>0q'; cat
^[P>|VTE(7803)^[\
Of course querying for XTVERSION can trigger terminal bugs just as well. Let's
start querying for it now -- even without a concrete use case -- to increase
the chance we can use it during crunch time when we don't want to test
anymore. (We typically discover buggy terminals only very late in the release
cycle, most prominently after a release).
Commit 4f536d6a9b (Update commandline state snapshot lazily,
2024-04-13) add an optimization to update the search field only if
necessary. The optimization accidentally prevents us from resetting
the search field.
Fixes#11161
Commit 82c4896809 (Fix unnecessary undo when exiting the history
pager with an empty cmd and no matches, 2025-02-02) was a nice fix
but failed to account for the code path where we switch from history
search to completion pager (and maybe also the inverse case). In this
case we don't want to undo the transient edit but commit it instead.
e697add5b5 (Feature flag to prevent executing off buffered keys, 2025-01-02)
breaks my expectations/habits, and it breaks Midnight Commander.
Additionally, I'm not aware of any case where it actually adds security.
We generally assume that terminal echoback sequences do not contain
control characters except for well-known escape sequences.
This backs out commit e697add5b5.
See #10987, #10991
Currently, when the history pager is selected, fish always one undo away from the original search term. If the search has no matches, the fish replaces the search term with itself (resulting in no visible change, but it is still treated as a transient edit). However, fish ignores undo operations where the replacement is "" by "", leading to an unnecessary undo. For example:
1. Type 'test'.
2. Do ctrl-c.
3. Open the history pager.
4. Make so there are no matches.
5. Exit - you will undo back to 'test'.
This commit also ensures that if you select a pager element that does not change the content of the commandline, it will not be added to the undo history.
Currently, if we return to the present, fish thinks that it still has a transient edit. This results in an unnecessary undo when performing a backward search. For example:
1. Type ': '.
2. Do a backward token search.
3. Do a forward token search.
4. Do another backward token search - this will result in the undo of ': '.
Currently, the search always restarts when moving from the present.
For example:
1. Do a few backward searches.
2. Use PageDown to return to the present.
3. Do another backward search.
4. Now, PageUp does nothing because the search was restarted, even if we maintained search mode.
Every reader gets their own wait handle which is wrong and not actually
needed - it's a singleton. We should probaly make it global. Let's
do an intermediate solution for now -- not much time this weekend ;).
Fixes#11110
There is no guarantee that Write::write() will write the entirety of the
provided buffer in one go, regardless of how short it is, because that depends
on the semantics of the underlying write handle (even if it was a
single byte, though in this case that would be because of an interrupt).
The only case I'm aware of that would guarantee a single Write::write() call
would suffice is when writing into a high-level memory-backed buffer, and we
can't make that guarantee (now or in perpetuity).
This is consistent with what we do for highlighting history search,
see d7354880e3 (Fix regression causing crash in token history search,
2025-01-27). In future, we should try to find a better fix (and a
better test).
Fixes the other problem described in #11096
The two terminals Midnight Commander and dvtm are special in that
they filter requests (or perhaps responses) like
printf "\x1b[0c"
and don't implement the response themselves -- so we never get
one. Let's work around that until we can fix it.
Disable the kitty protocol in mc for now (to keep the code simple),
though we could certainly re-enable it.
Fixes 64859fc242 (Blocking wait for responses to startup queries, 2025-01-25).
Today we might
1. enable modifyOtherKeys
2. get a reply indicating the kitty keyboard protocol is supported
3. because of 2, we never turn off modifyOtherKeys again
Let's get rid of this weird issue by enabling either modifyOtherKeys
or the kitty enhancements only after we know whether the kitty protocol
is supported.
This means we need to call terminal_protocols_enable_ifn() before every
call to readch() until the querying is done. Fortunately, this is
already in place in read_normal_chars(); there are other places that
call readch() but none of those is executed until querying has completed.
At startup we query for
- the cursor position (CSI 6 n)
- kitty keyboard protocol support (CSI ? u)
- terminfo capabilities via XTGETTCAP
Since we don't wait for responses, those can leak into child processes.
Some child processes like fzf cannot decode DCS replies. Plug the
leak by ending each round of querying by asking for the Primary Device
Attribute, and resume input processing only after a response has been
received, (or ctrl-c as an escape hatch).
This is a nice simplification. Tested with the lowest common
denominator (putty, Terminal.app and st).
Fixes#11079
The st terminal wrongly parses CSI ? u as DECRC. A fix has been
proposed upstream. Let's also work around it I guess (not to mention
that querying in the first place is also sort of a workaround).
This reverts commit ebdc3a0393.
Not discussed, includes a new thing that queries the terminal for the client OS
when what is really needed is just a `uname` - which would also work on Terminal.app.
Unlike other builtins, "{" is a separate token, not a keyword-string
token.
Allow the left brace token as command string; produce it when parsing
"{ -h"/"{ --help" (and nowhere else). By using a decorated statement,
we reuse logic for redirections etc.
Other syntax elements like "and" are in the builtin list, which
- adds highlighting logic
- adds it to "builtin --names"
- makes it runnable as builtin
(e.g. "builtin '{'" would hypothetically print the man page)
These don't seem very important (highlighting for '{' needs to match
'}' anyway).
Additionally, making it a real builtin would mean that we'd need to
deactivate a few places that unescape "{" to BRACE_BEGIN.
Let's not add it to the built in list. Instead, simply synthesize
builtin_generic in the right spot.
I'm assuming we want "{ -h" to print help, but '"{" -h' to run an
external command, since the latter is historical behavior. This works
naturally with the above fake builtin approach which never tries to
unescape the left brace.
If a child program crashes with some text rendered below the cursor,
we fail to clear that text. For example run vim, "pkill -9 vim" and
observe that scrollback-push fails to clean up the leftover text.
Fix that.
libc::getpid and getpgrp *cannot fail*, so an unsafe declaration here
is just noise.
I mean sure, if your libc is broken and these fail, but at that point
I'm comfortable declaring your computer a platypus that we do not need
to support.
Sorry, commit 51adba6ee0 (Restore autosuggestion after corrected
typo, 2025-01-10) was pushed too early. One issue is that it saves
autosuggestions also when we edit in the middle, where we can't
restore it. We'd still restore it in some cases, even though it
doesn't apply. This breaks invariants that may cause various problems
when interacting with the autosuggestion.
Fix it by only saving the autosuggestion when we will be able to
restore it correctly.
For better or worse, backward-token completely skips over operators
like > & |.
forward-token is (accidentally?) inconsistent with that. Fix that.
Skipping over those tokens might be wrong weird. Maybe not for
redirections since they are tighly coupled to their target. Maybe we
can improve this in future.
When pasting and executing a full line, the trailing newline character
will be included in history.
I usually manually delete the newline before executing, but sometimes
I forget. When I recall my (typically single-line) commands, it's
surprising that the cursor is on the blank second line.
The newline doesn't seem useful. Let's remove it automagically.
I wonder if anyone will be thrown off by this smart behavior.
In future, we can make this space trimming configurable, similar to
fish_should_add_to_history.
As mentioned in
https://github.com/fish-shell/fish-shell/pull/11045#discussion_r1915994998,
we need to refresh TTY timestamps to avoid timing-based issues.
For some context see
git log --grep='[Rr]efresh.* TTY'
Make things more consistent again. I don't know if all of these are
absolutely necessary, hoping to find out later (and consolidate this
logic in outputter).