Commit graph

5648 commits

Author SHA1 Message Date
Johannes Altmanninger
6d551b4459 Fix status buildinfo error on invalid args 2025-01-08 12:06:28 +01:00
Johannes Altmanninger
cc9083e220 Add some logging for XTGETTCAP 2025-01-08 12:06:28 +01:00
Johannes Altmanninger
14df28382d Work around terminals that echo DCS queries
Some terminals such as conhost and putty cannot parse DCS commands,
and will echo them back.

Work around this by making sure that this echoed text will not
be visible.

Do so by temporarily enabling the alternative screen buffer when
sending DCS queries (in this case only XTGETTCAP).  The alternative
screen buffer feature seems widely supported, and easier to get right
than trying to clear individual lines etc.

The alternative screen may still be visible for a
short time.  Luckily we can use [Synchronized Output](
https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036)
to make sure the screen change is never visible to the user.

Querying support for that is deemed safe since it only requires a
CSI command.

Note that it seems that every terminal that supports Synchronized
Output also parses DCS commands successfully.  This means that we
could get away without the alternative screen buffer in practice.
Not sure yet.

The implementation is slightly more complex than necessary in that it
defines a redundant ImplicitEvent. This is for two reasons: 1. I have
a pending change that wants to use it, so this removes diff noise and
2. we historically have sc/input_common.rs not depend on src/output.rs.
I dont' think any are strong reasons though.
2025-01-08 12:06:28 +01:00
Johannes Altmanninger
e6d57f2fb2 Minor style fix 2025-01-08 12:06:28 +01:00
Johannes Altmanninger
834001087d Disable kitty keyboard protocol on iTerm again for now
It causes alt-left to be sent as left in some cases; see #11004.

Upstream issue: https://gitlab.com/gnachman/iterm2/-/issues/12105
2025-01-06 06:24:13 +01:00
Johannes Altmanninger
e697add5b5 Feature flag to prevent executing off buffered keys
If I run "sleep 3", type a command and hit enter, then there is no
obvious way to cancel or edit the imminent command other than ctrl-c
but that also cancels sleep, and doesn't allow editing. (ctrl-z sort
of works, but also doesn't allow editing).

Let's try to limit ourselves to inserting the buffered command
(translating enter to a newline), and only execute once the user
actually presses enter after the previous command is done.
Hide it behind a new feature flag for now.

By making things less scary, this might be more user-friendly, at
the risk of breaking expectations in some cases.

This also fixes a class of security issues where a command like
`cat malicious-file.txt` might output escape sequences, causing
the terminal to echo back a malicious command; such files can still
insert into the command line but at least not execute it directly.
(Since it's only fixed partially I'm not really sure if the security
issue is a good enough motivation for this particular change.)

Note that bracketed paste probably has similar motivation as this feature.

Part of #10987
Closes #10991
2025-01-06 06:24:13 +01:00
Johannes Altmanninger
af137e5e96 scrollback-push to query for indn/cuu via XTGETTCAP
Some terminals like the Linux console don't support indn (scroll
forward). Let's query for the presence of these features, and fall
back to the traditional behavior if absent.

For now, break with the tradition of using the terminfo database that
we read ourselves. Instead ask the terminal directly via XTGETTCAP.
This is a fairly young feature implemented by terminals like xterm,
foot and kitty, however xterm doesn't expose these capabilities at
this point.

This is a good opportunity to try XTGETTCAP, since these are
capabilities we haven't used before. Advantages of XTGETTCAP are that
it works across SSH and is independent of $TERM (of course ignoring
$TERM may also be breaking to some users). Let's see if it sees
adoption in practice.

Tested to work on foot and kitty, allowing the default ctrl-l binding
to work without erasing any screen content.

See #11003
2025-01-06 06:24:13 +01:00
Johannes Altmanninger
75832b3c5d scrollback-push to fall back to clear-screen if missing CPR feature
The new ctrl-l implementation relies on Cursor Position Reporting (CPR)
This may not work on exotic terminals that don't support CSI 6n yet

As a workaround, probe for this feature by sending a CSI 6n (CPR)
on startup.  Until the terminal responds, have scrollback-push fall
back to clear-screen.

The theoretical problem here is that we might handle scrollback-push
before we have handled the response to our feature probe. That seems
fairly unlikely; also e49dde87cc has the same characteristics.

This could query a capability instead (via XTGETTCAP or otherwise)
but I haven't found one; and this seems at least as reliable.

While at it, change the naming a bit.

See #11003
2025-01-06 05:53:24 +01:00
Johannes Altmanninger
dda4371679 Stop sending CSI 5n when querying for kitty keyboard support
After we query kitty keyboard protocol support,
we send CSI 5n, to also receive a response if
the protocol is not supported.

However we don't bother to wait for the response, so this extra
message is not really useful (only to get better logs).  Remove it.
2025-01-06 05:51:38 +01:00
Johannes Altmanninger
10f1f21a4f Don't send kitty kbd protocol probe until ECHO is disabled
With tmux 3.0 (from 2019) inside SSH, the CSI 5n response is echoed.
I guess with all other terminals we were just lucky.  Move it to
right after where we disable ECHO I guess.

In general, asynchronous requests create a lot of potential for error,
we should try to get away from them.
2025-01-06 05:51:38 +01:00
Johannes Altmanninger
109ef88831 Add menu and printscreen keys
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.
2025-01-06 05:43:22 +01:00
Johannes Altmanninger
93e0a33d41 Log human-readable values also for not-yet-decoded bytes 2025-01-05 03:37:31 +01:00
Stefan Boca
dcddffd222
refactor: misc cleanup (#10998)
* refactor EnvVar: Arc<Box<[WString]>> -> Arc<[WString]>

* remove unnecessary `&mut` from EnvVar methods

* clippy: use eq_ignore_ascii_case instead of manual comparison

see https://rust-lang.github.io/rust-clippy/master/index.html#manual_ignore_case_cmp

* clippy: use `is_some_and` and `is_ok_and` instead of `map_or`

see https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_or

* clippy: use `assert!()` instead of `assert_eq!()` with booleans
2025-01-04 19:49:44 -06:00
Mahmoud Al-Qudsi
b4e8cc8b79 Use explicit Timeout enum instead of magic constants
The FdReadableSet api was always intended to be converted to use Duration
instead of usec/msec once the ffi was removed. This lets us be explicit about
forever/infinite timeouts and removes the (small) chance of a collision between
u64::MAX and INFINITE.

I tried this out with `type Timeout = Option<Duration>` (only without the alias)
but was unhappy with easy it is to accidentally use `None` when you meant a
timeout of zero.
2025-01-04 18:40:36 -06:00
Mahmoud Al-Qudsi
83eb25d45f Mark function as test-only 2025-01-04 17:29:09 -06:00
Johannes Altmanninger
e11e62674f Fix bad layout computation with right prompt
Commit 1c4e5cadf2 (Autosuggestions in multi-line
command lines, 2024-12-15) accidentally passed an empty
"commandline_before_suggestion" to compute_layout() when there is
no autosuggestion.

Closes #10996
2025-01-04 00:54:06 +01:00
Johannes Altmanninger
e49dde87cc Probe for kitty keyboard protocol support
We unconditionally request kitty keyboard protocol's progressive
enhancements.

It seems that a lot of terminals fail to parse CSI commands that
contain '=' such as \x1b[=5u.

1. [Midnight Commander](0ea77d2ec7)
2. Prompt 3 App (private bug tracker)
3. JetBrains IDEs https://youtrack.jetbrains.com/issue/IJPL-166234
4. Termux https://github.com/termux/termux-app/issues/4338
5. Amazon Linux Web Console https://github.com/amazonlinux/amazon-linux-2023/issues/871

It is difficult to fix the four remaining ones in a
timely manner, so let's query for support as described in
https://sw.kovidgoyal.net/kitty/keyboard-protocol/#detection-of-support-for-this-protocol
This uses CSI 5 n (device status report), which is the older brother
of CSI 6 n (cursor position report) we use as of recently.

Query asynchronously and enable progressive enhancements as soon
as we get a response. In theory this allow `cat malicious-file.txt`
leading us to believe the protocol is supported.

See #10994
2025-01-03 23:20:19 +01:00
Fabian Boehm
edfdf210c4 Remove unnecessary use of errno 2025-01-03 19:34:57 +01:00
Johannes Altmanninger
996fec87f4 Demote logs about unexpected cursor position
As reported in
https://github.com/fish-shell/fish-shell/issues/10992#issuecomment-2568954940,
the user may reset the terminal and run scrollback-push without
repainting in between.  This means that the terminal will report
the cursor position y=0 x=0 which doesn't match what fish renders.
Fortunately, y=0 is a safe fallback value for the scrollback-push
use case.

While at it, fix an off-by-one error in a log.
2025-01-03 12:57:00 +01:00
Johannes Altmanninger
d823444c6e Apply autosuggestions from completions also if cursor is not at EOL
Before 1c4e5cadf2 (Autosuggestions in multi-line command lines,
2024-12-15), the completion code path in the autosuggestion performer
used to do something weird: it used to request completions for the
entire command line (with the implied cursor at end) but try to apply
the same completion at the actual cursor.

That commit changed this to request completions only up to the cursor
position, which could in theory make us produce valid completions even
if the cursor is not at end of the line.  However, that doesn't really
work since autosuggestions can only be rendered at the end of the line.
And the worst of it, that commit tries to compute

	line_at_cursor(&full_line, search_string_range.end)

which crashes as out-of-bounds if the completion needs to replace the token
(like a case-correcting completion does).

Let's apply completions to the end, matching how autosuggestions work
in general.
2025-01-03 12:56:04 +01:00
Johannes Altmanninger
abaeb4af2a scrollback-push to sanitize cursor position
I believe it's possible that the cursor position reported by the
terminal does not match fish's cursor.  In that case, overflow. Fix
that since we should not trust the terminal.

Also rename a confusingly named variable.

Mouse-click handling has a similar issue, fix that too.

FWIW, tmux always reports cursor position zero (\x1b[1;1R) when
querying from fish (but not when querying with printf).
Will investigate that next, see the linked issue.

Fixes #10992
2025-01-03 07:55:50 +01:00
Erick Howard
837c32f150 Move getrusage wrapper in timer.rs to shared nix wrapper module
Closes #10988
2025-01-02 23:40:41 +01:00
David Adam
70bd49f612 drop confstr implementation
Added in libc 0.2.163.

The constants for _CS_PATH are not implemented for some of the BSDs yet
(rust-lang/cmake#3612), so we need to keep our linking of this via the C
compiler for now.
2025-01-02 11:06:29 +08:00
Peter Ammon
7e9b35be48
Fix a clippy 2025-01-01 17:42:25 -08:00
Peter Ammon
7af9844de0
highlight: make PathFlags an ordinary struct
No need for fancy bitflags.
2025-01-01 17:42:14 -08:00
tranzystorekk
3129c9e939 environment_impl: drop usage of lazy_static 2025-01-01 12:23:24 -08:00
Erick Howard
967c4b2272
Code cleanup in src/bin/fish.rs to make it more idiomatic (#10975)
Code cleanup in `src/bin/fish.rs` to make it more idiomatic
2025-01-01 12:17:48 -06:00
Johannes Altmanninger
1c4e5cadf2 Autosuggestions in multi-line command lines
If I run

	$ command A
	$ command B
	$ command C

and find myself wanting to re-run the same sequence of commands
multiple times, I like to join them into a single command:

	$ command A &&
	    command B &&
	    command C

When composing this mega-commandline, history search can recall the
first one; the others I usually inserted with a combination of ctrl-k,
ctrl-x or the ctrl-r (since 232483d89a (History pager to only operate
on the line at cursor, 2024-03-22), which is motivated by exactly
this use case).

It's irritating that autosuggestions are missing, so try adding them.

Today, only single-line commands from history are suggested. In
future, we should perhaps also suggest any line from a multi-line
command from history.
2025-01-01 17:22:50 +01:00
Johannes Altmanninger
532abaddae Invalidate stale autosuggestions eagerly
If I type something that invalidates the autosuggestion, the
autosuggestion is still kept around in memory. This is used if
1. there is no valid autosuggestion for the new commandline
2. the user types something like "backspace backspace a"
   that both makes the cached autosuggestion valid again, and does
   not trigger autosuggestion suppression (hence backspace alone is
   not anough)

The fact that an autosuggestion might not match the current command
line makes it more difficult to implement autosuggestions on multiline
command lines.

For now let's invalidate autosuggestions eagerly, to enable the
next commit.  This heuristic invalidates too much but I don't think
that matters. We'll simply recompute the autosuggestion in those few
cases which.
2025-01-01 17:22:50 +01:00
Johannes Altmanninger
7049352e61 Extract function for potentially case-insensitive prefix check 2025-01-01 17:22:50 +01:00
Fabian Boehm
050fe09af1 Compile fish_test_helper in the test driver 2025-01-01 16:45:43 +01:00
Erick Howard
943adf4dd0 Avoid traversing wait handle list if searching by PID 2025-01-01 16:40:53 +01:00
Erick Howard
53dc7772eb Remove unnecessary clone when opening File for debug output 2025-01-01 16:34:40 +01:00
Fabian Boehm
6848e70e87 Disable two tests on NetBSD
One doesn't compile, the other's just borked for weird reasons
possibly related to tmux and $LINES?

With this, the test suite passes on NetBSD.
2024-12-31 13:04:28 +01:00
Johannes Altmanninger
13763fa318 Fix assertion error in when scrollback-push is enqueued from script
As soon as we start processing a scrollback-push readline command, we
pause execution of all other readline commands until scrollback-push
retires.  This means that we never get into a situation with two
active scrollback-push commands -- unless we are executing readline
commands via a script running "commandline -f":
since the first part of scrollback-push handling returns immediately,
the script will proceed before scrollback-push retires.

A second scrollback-push fails an assertion.  Work around that for now.
In future, scrollback-push should block when invoked by such a script,
just like it does when invoked from bindings.
2024-12-30 14:20:05 +01:00
Johannes Altmanninger
8910390602 Work around broken macOS CI seemingly missing parm_index in terminfo
Commit 83b0294fc9 (ctrl-l to scroll content instead of erasing screen,
2024-12-21) broke tests like tests/checks/tmux-autosuggestion.fish
on macOS CI.

I didn't get to the bottom of this but it's probably because terminfo
is broken on that CI system.

A (related?) failure mode can be observed using

	TERM=linux-m ssh my-mac tmux

ctrl-l moves the cursor but fails to scroll the text.

The only reason for using terminfo here was to be consistent with
the rest of the code base.  Let's use a hardcoded value instead;
I don't see why any terminal would deviate from xterm here.

This fixes macOS CI and the TERM=linux-m "misconfiguration".

It is possible that we should be using a different escape sequence
here; I'm not sure.
2024-12-30 14:20:05 +01:00
Johannes Altmanninger
b6c2a4c5db Remove trivial splice() call 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
a88de9d345 Remove unused data from autosuggestion cache 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
e8801d2ced Minor refactoring to reuse autosuggestion contructor 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
1d620356f8 Deduplicate command line update step when accepting autosuggestions 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
8bb6597b9b Deduplicate layout computation logic 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
8ae12973df Try to simplify commandline change hooks 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
459fc3c887 Fix failing history pager search replacing all lines
History pager search operates only on the current line, so a failing
search should only replace the current line with the search string.
2024-12-30 10:50:38 +01:00
Johannes Altmanninger
a719f9d537 Minor refactoring in handle_execute
A failing ctrl-r search term is inserted back into the command line.
This should go through the same code path as other editions.
2024-12-30 10:50:38 +01:00
Johannes Altmanninger
da0a93b24b Minor optimization in pager_selection_changed 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
8bb442f135 Minor cleanup in push_edit 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
3fcc6482cb Fix parse_util_process_extent including too much on the left 2024-12-30 10:50:38 +01:00
Johannes Altmanninger
83b0294fc9 ctrl-l to scroll content instead of erasing screen
On ctrl-l we send `\e[2J` (Erase in Display).  Some terminals interpret
this to scroll the screen content instead of clearing it. This happens
on VTE-based terminals like gnome-terminal for example.

The traditional behavior of ctrl-l erasing the screen (but not the
rest of the scrollback) is weird because:

1. `ctrl-l` is the easiest and most portable way to push the prompt
   to the top (and repaint after glitches I guess). But it's also a
   destructive action, truncating scrollback. I use it for scrolling
   and am frequently surprised when my scroll back is missing
   information.
2. the amount of lines erased depends on the window size.
   It would be more intuitive to erase by prompts, or erase the text
   in the terminal selection.

Let's use scrolling behavior on all terminals.

The new command could also be named "push-to-scrollback", for
consistency with others. But if we anticipate a want to add other
scrollback-related commands, "scrollback-push" is better.

This causes tests/checks/tmux-history-search.fish to fail; that test
seems pretty broken; M-d (alt-d) is supposed to delete the current
search match but there is a rogue "echo" that is supposed to invalidate
the search match.  I'm not sure how that ever worked.

Also, pexepect doesn't seem to support cursor position reporting,
so work around that.

Ref: https://codeberg.org/dnkl/foot/wiki#how-do-i-make-ctrl-l-scroll-the-content-instead-of-erasing-it
as of wiki commit b57489e298f95d037fdf34da00ea60a5e8eafd6d

Closes #10934
2024-12-30 10:50:38 +01:00
Johannes Altmanninger
84f19a931d Also ignore invalid recursive escape sequences
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).
2024-12-30 10:50:38 +01:00
Johannes Altmanninger
3201cb9f01 Stop parsing invalid CSI/SS3 sequences as alt-[/alt-o
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-[".
2024-12-30 10:50:38 +01:00