The logic added by 2dbaf10c36 (Also refresh TTY timestamps
after external commands from bindings, 2024-10-21) is obsoleted
by TtyHandoff. That module is also responsible for calling
reader_save_screen_state after it writes to the TTY, so we don't
actually need to check if it wrote anything.
When running fish inside SSH and local and remote OS differ, fish
uses key bindings for the remote OS, which is weird. Fix that by
asking the terminal for the OS name.
This should be available on foot and kitty soon, see
https://codeberg.org/dnkl/foot/pulls/2217#issuecomment-8249741
Ref: #11107
For historical reasons, fish does not implement the VT state
machine but uses a relatively low timeout when reading
escape sequences. This might be causing issues like
https://github.com/fish-shell/fish-shell/issues/11841#issuecomment-3544505235
so let's cautiously increase the timeout.
Make it opt-in and print a noisy error when we time out, so we can
find affected terminals.
We've removed several terminal-specific workarounds but also added
some recently. Most of the non-Apple issues have been reported
upstream. Many of our workarounds were only meant to be temporary.
Some workarounds are unreliable and some can cause introduce other
problems.
Add a feature flag we can use later to let users turn off workarounds.
This doesn't disable anything yet, mostly because because despite being
off-by-default, this might surprise people who use "fish_features=all".
The fix would be "fish_features=all,no-omit-term-workarounds".
So we'd want a high degree of confidence.
For now we'll use this only with the next commit.
Closes#11819
Frequently when I launch a new shell and type away, my input is
echoed in the terminal before fish gets a chance to set shell modes
(turn off ECHO and put the terminal into non-canonical mode).
This means that fish assumption about the cursor x=0 is wrong, which
causes the prompt (here '$ ') to be draw at the wrong place, making
it look like this:
ececho hello
This seems to have been introduced in 4.1.0 in a0e687965e (Fix
unsaved screen modification, 2025-01-14). Not sure how it wasn't a
problem before.
Fix this by clearing to the beginning of the line after turning off
ECHO but before we draw anything to the screen.
This turns this comment in the patch context into a true statement:
> This means that `printf %s foo; fish` will overwrite the `foo`
Note that this currently applies per-reader, so builtin "read" will
also clear the line before doing anything.
We could potentially change this in future, if we both
1. query the cursor x before we output anything
2. refactor the screen module to properly deal with x>0 states.
But even if we did that, it wouldn't change the fact that we want
to force x=0 if the cursor has only been moved due to ECHO, so I'm
not sure.
Also use the correct OSC number.
Note that this only works on few terminals (such as iTerm2). Not sure
if it's worth for us to have this feature but I guess multiple users
have requested it.
Unlike other shells, fish tries to make it easy to work with multiline
commands. Arguably, it's often better to use a full text editor but
the shell can feel more convenient.
Spreading long commands into multiple lines can improve readability,
especially when there is some semantic grouping (loops, pipelines,
command substitutions, quoted parts). Note that in Unix shell, every
quoted string can span multiple lines, like Python's triple quotes,
so the barrier to writing a multiline command is quite low.
However these commands are not autosuggested. From
1c4e5cadf2 (commitcomment-150853293)
> the reason we don't offer multi-line autosuggestion is that they
> can cause the command line to "jump" to make room for the second
> and third lines, if you're at the bottom of your terminal.
This jumping (as done by nushell for example) might be surprising,
especially since there is no limit on the height of a command.
Let's maybe avoid this jumping by rendering only however many lines
from the autosuggestion can fit on the screen without scrolling.
The truncation is hinted at by a single ellipsis ("…") after the
last suggested character, just like when a single-line autosuggestion
is truncated. (We might want to use something else in future.)
To implement this, query for the cursor position after every command,
so we know the y-position of the shell prompt within the terminal
window (whose height we already know).
Also, after we register a terminal window resize, query for the cursor
position before doing anything else (until we od #12004, only height
changes are relevant), to prevent this scenario:
1. move prompt to bottom of terminal
2. reduce terminal height
3. increase terminal height
4. type a command that triggers a multi-line autosuggestion
5. observe that it would fail to truncate properly
As a refresher: when we fail to receive a query response, we always
wait for 2 seconds, except if the initial query had also failed,
see b907bc775a (Use a low TTY query timeout only if first query
failed, 2025-09-25).
If the terminal does not support cursor position report (which is
unlikely), show at most 1 line worth of autosuggestion. Note that
either way, we don't skip multiline commands anymore. This might make
the behavior worse on such terminals, which are probably not important
enough. Alternatively, we could use no limit for such terminals,
that's probably the better fallback behavior. The only reason I didn't
do that yet is to stay a little bit closer to historical behavior.
Storing the prompt's position simplifies scrollback-push and the mouse
click handler, which no longer need to query. Move some associated
code to the screen module.
Technically we don't need to query for cursor position if the previous
command was empty. But for now we do, trading a potential optimization
for andother simplification.
Disable this feature in pexpect tests for now, since those are still
missing some terminal emulation features.
I think the interruption event is grouped next to the check-exit one
because it used to be implemented as check exit but with a global flag
(I didn't check whether that applied to master).
Move it to the logical place.
The readline state is never finished before the very first loop
iteration. Move the check for rls.finished next to the one that
implements "read -n1" -- in future we might use the return value
for both.
Some modern terminals allow creating tabs in a single window;
this functionality has a lot of overlap with what a window manager
already provides, so I'm not sure if it's a good idea. Regardless,
a lot of people still use terminal tabs (or even multiple levels of
tabs via tmux!), so let's add a fish-native way to set the tab title
independent of the window title.
Closes#2692
Commit eecc223 (Recognize and disable mouse-tracking CSI events,
2021-02-06) made fish disable mouse reporting whenever we receive a
mouse event. This was because at the time we didn't have a parser
for mouse inputs. We do now, so let's allow users to toggle mouse
support with
printf '\e[?1000h'
printf '\e[?1000l'
Currently the only mouse even we support is left click (to move cursor
in commandline, select pager items).
Part of #4918
See #12026
[ja: tweak patch and commit message]
Since commit 7e3fac561d (Query terminal only just before reading
from it, 2025-09-25),
fish -c 'read; cat'
fails to turn ICANON back on for cat.
Even before that commit, I don't know how this ever worked. Before or
after, we'd call tcsetattr() only to set our shell modes, not the
ones for external commands (term_donate)
I also don't think there's a good reason why we set modes twice
(between term_donate () and old_modes), but I'll make a minimal (=
safer) change for now until I understand this.
The only change from 7e3fac561d was that instead of doing things in
this order:
terminal_init()
set_shell_modes
read
reader_push()
reader_readline()
save & restore old_modes
cat
we now do
read
reader_push()
terminal_init()
set_shell_modes()
reader_readline()
save & restore old_modes
cat
So we call set_shell_modes() just before saving modes,
which obviously makes us save the wrong thing.
Again, not sure how that wasn't a problem before.
Fix it by saving modes before calling terminal_init().
Fixes#12024
If I run
history append 'echo -X'
and type "echo -x", it renders as "echo -X".
This is not wrong but can be pretty confusing, (since the
autosuggestion is the same length as the command line).
Let's favor the case typed by the user in this specific case I guess.
Should add a full solution later.
Part of #11452
This merges changes that make thread pools instanced. We no longer have
a single global thread pool. This results in significant simplifications
especially in the reader (no more "canary").
Prior to this commit, there was a singleton set of "debouncers" used to run
code in the background because it might perform blocking I/O - for example,
for syntax highlighting or computing autosuggestions. The complexity arose
because we might push or pop a reader. For example, a long-blocking, stale
autosuggestion thread might suddenly complete, but the reader it was for
(e.g. for `builtin_read`) is now popped. This was the basis for complex
logic like the "canary" to detect a dead Reader.
Fix this by making the Debouncers per-reader. This removes some globals and
complicated logic; it also makes this case trivial: a long-running thread
that finishes after the Reader is popped, will just produce a Result and
then go away, with nothing reading out that Result.
This also simplifies tests because there's no longer a global thread pool
to worry about. Furthermore we can remove other gross hacks like ForceSend.
This concerns threads spawned by the reader for tasks like syntax
highlighting that may need to perform I/O.
These are different from other threads typically because they need to
"report back" and have their results handled.
Create a dedicated module where this logic can live.
This also eliminates the "global" thread pool.