Commit Graph

236 Commits

Author SHA1 Message Date
Johannes Altmanninger
11c7310f17 Prevent commandline modification inside abbreviation callbacks
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
2025-03-28 12:58:15 +01:00
James Falcon
0dbfb4ccb1 Remove directory name prefix in truncated completions
Sometimes, the dirname of a completion is much longer than the basename.

When the dirname is the same for many completions, a long common dirname
prefix makes it hard to see the interesting differences in the basenames.

Fix this by collapsing the dirname prefix to "…/".

In future, we should find a generic way to collapse completions that don't
contain slashes.

Closes #8618
Closes #11250
2025-03-21 00:53:06 +01:00
Peter Ammon
29ae571afa Make scoped_push nicer
In C++ it's easy to make an RAII-type object like "increment a counter for
the duration of this function." Such an object might accept a pointer or
reference, increment the value, and then restore it in its destructor. We
do this all the time - for example to mark a region of code as
non-interactive, etc.

Rust makes this more awkward, because now the reference is tracked by the
borrow checker: it "owns" the object for the duration of the function. This
leads to approaches like "zelf" where the object that marks the parser as
non-interactive itself becomes the new parser, but we can't call it "self"
and it's just yucky.

In this commit we introduce a notion of the "scoped data" of the Parser,
factored out of the library data. This is data which is typically set in a
scoped fashion: whether we are a subshell, are interactive, emit fish_trace
debugging info, etc. Crucially we set this as Rc: this allow the scope
itself to share data with the Parser and we can get rid of lots of "zelf"s.

Introduce a new function `Parser::push_scope` which creates a new scope and
allows modifying these variables associated with the scope. This ends up as
a nice simplification.
2025-03-15 16:43:16 -07:00
carsonzhu
4ce552bf94 Token search commands that only match the last token in each line
This add two commands history-last-token-search-backward and
history-last-token-search-forward which behaves like bash's yank-last-arg. So
similar to history-token-search-* but only considers the last argument for
each command.

Closes #10756
Closes #11258
2025-03-15 21:54:47 +01:00
Sander Machado
f4a8368c9e builtins: idiomatic error code passing
Remaining code smells:
- exec_subshell_internal needs to convert a number to a result

Closes #10948
2025-03-15 21:30:49 +01:00
Johannes Altmanninger
9f79fe17fc Quote only unique completions, use backslashes for ambiguous ones
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
2025-03-14 22:21:42 +01:00
Johannes Altmanninger
b08ff33291 Add hack to fix off-by-one error in Vi-mode cancel-commandline
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
2025-03-11 20:23:30 +01:00
lengyijun
18c4ee4b41 cleanup: rm strange code block 2025-03-11 20:01:49 +01:00
Johannes Altmanninger
2b4f150883 Fix regression causing crash on empty paste in Vi-mode
Fixes d51f669647 (Vi mode: avoid placing cursor beyond last character,
2024-02-14).

Closes #11256
2025-03-10 22:28:40 +01:00
Johannes Altmanninger
2930c85926 Add hack to restore cursor position on undo ofter exec again
See f2dde229aa (Revert changes to restore cursor position after undo,
2025-03-05).

I think there are two problems with tmux when doing a final redraw of a
larger-than-screen commandline.  One is easy to trigger independent of
f2dde229aa.  The other is reproduced by the broken output in the tmux test
removed by that commit. Should root-cause them later.

Use a hack for now; this also happens to fix the broken output in tmux.
2025-03-08 13:12:38 +01:00
Peter Ammon
f2dde229aa Revert changes to restore cursor position after undo
This feature is nice and desirable, but it was implemented in a intrusive way
by modifying the sequence of bytes we emit when running a command; this in
turn requires changing a bunch of tests.

This sequence hasn't changed in decades and the consequences of changing it
are hard to predict, given that it is likely terminal dependent; we've
already found a regression.

It's fine to reintroduce this but it should be done in a less intrusive way
(conceptually that seems straightforward - we're just remembering the cursor
position).

Revert "Fix spurious blank lines when executing scrolled commandline"

This reverts commit 0e512f8033.

Revert "On undo after execute, restore the cursor position "

This reverts commit 610338cc70.
2025-03-05 17:57:48 -08:00
Johannes Altmanninger
4378e73fc7 Add the commandline to the OSC 133 command start
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
2025-03-03 11:47:50 +01:00
Johannes Altmanninger
e5e932e970 Try to reduce write(3) calls for OSC 133 prompt markers
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).
2025-03-03 11:47:50 +01:00
Johannes Altmanninger
495083249b Fix regression causing cursor shape commands to leak into noninteractive shell
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.
2025-03-02 09:34:06 +01:00
Johannes Altmanninger
b6269438e9 Apply fish_color_search_match foreground only if explicit
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.
2025-03-02 07:08:30 +01:00
Johannes Altmanninger
fe7f13e5ad Fix fish_key_reader regression causing kitty protcol not being requested
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.
2025-03-01 14:31:53 +01:00
Johannes Altmanninger
b401aee4ce Reserve the ability to read XTVERSION
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).
2025-03-01 13:03:04 +01:00
Johannes Altmanninger
72f2433120 Fix search field state not resetting after search field is hidden
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
2025-02-19 10:44:00 +01:00
Johannes Altmanninger
cad42a0e53 Fix regression stomping commandline when completing after history search
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.
2025-02-12 14:24:06 +01:00
Johannes Altmanninger
b4b0b42792 Tweak replacing completions for directory-variable name
If we're only inserting a prefix of the variable name we're not gonna
add a space. We don't want to add a slash either.
2025-02-12 14:24:06 +01:00
Fabian Boehm
3350145371 Reader: Fix crash completing incomplete variable name
Regression in 4.1, not present in 4.0.

Fixes #11148
2025-02-11 22:17:09 +01:00
Johannes Altmanninger
4b20e3ad91 Back out "Feature flag to prevent executing off buffered keys"
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
2025-02-09 16:32:49 +01:00
Fabian Boehm
8ddb078db8 reader: Only maintain cursor position in non-empty prefix search
Otherwise this would always move the cursor to the beginning.

Fixes #11133

(cherry picked from commit db244e0492)
2025-02-05 22:14:47 +01:00
kerty
82c4896809 Fix unnecessary undo when exiting the history pager with an empty cmd and no matches
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.
2025-02-04 10:12:30 +01:00
kerty
5e4f801ad5 Fix unnecessary undo in backward history search after returning to the present
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 ': '.
2025-02-04 10:12:30 +01:00
kerty
c1c23269d2 Don't restart search if we maintain search mode
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.
2025-02-04 10:12:30 +01:00
Johannes Altmanninger
66e2b6d8c1 Fix query response wait confusion over builtin read
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
2025-02-01 09:25:53 +01:00
Mahmoud Al-Qudsi
cbedfc8a64 Use Write::write_all(), not write()
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).
2025-01-31 11:25:56 -06:00
Fabian Boehm
e63fea1127 reader: only flash entire commandline if token is empty
So `git add dsfiojdsoif<TAB>` flashes the token, `git add <TAB>`
flashes the entire commandline because there is no token to flash
2025-01-30 17:13:09 +01:00
Fabian Boehm
4ae3c487a6 reader: flash entire commandline if there's no completion
This is often the case if the token is empty, e.g `git add <TAB>`
outside of a git repo.
2025-01-30 16:24:35 +01:00
kerty
514f4b9e23 Rename some methods of ReaderHistorySearch to improve clarity 2025-01-27 18:19:04 +01:00
Johannes Altmanninger
b73c8abb79 Fix regression causing crash when history token search hits end
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
2025-01-27 18:13:07 +01:00
Johannes Altmanninger
d7354880e3 Fix regression causing crash in token history search
I'm not yet sure how to reproduce 4dfcd4cb4e (reader: Check bounds
for color, 2022-08-26).  Commit 55fd43d86c (Port reader, 2023-12-22)
accidentally changed historical behavior, fix that.

Fixes #11096
2025-01-27 06:32:15 +01:00
Johannes Altmanninger
fff421ad9c Work around mc and dvtm not responding to Primary DA
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).
2025-01-27 06:32:15 +01:00
ccoVeille
b6a1bedab9 Fix typos in comments 2025-01-26 20:30:48 -08:00
Johannes Altmanninger
2d234bb676 Only request keyboard protocols once we know if kitty kbd is supported
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.
2025-01-26 15:39:21 +01:00
Johannes Altmanninger
64859fc242 Blocking wait for responses to startup queries
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
2025-01-26 14:22:52 +01:00
Johannes Altmanninger
630a06cf8f Work around st terminal resetting cursor on CSI ? u
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).
2025-01-26 14:19:40 +01:00
Johannes Altmanninger
6e2c5d4365 Add trailing slash (not space) to variable name completions that produce valid paths
Closes #5798
2025-01-26 14:19:40 +01:00
kerty
3fdd2d3fc2 Small refactor of HighlightSpec 2025-01-23 17:09:29 +01:00
kerty
db546da3ca Made undo/redo not update autosuggestion if failed 2025-01-23 17:09:29 +01:00
kerty
6a9f1b925d Make flash highlight autosuggestion on failed deletion 2025-01-23 17:09:29 +01:00
kerty
bffbf0cd57 Make flash highlight relevant commandline section 2025-01-23 17:09:29 +01:00
kerty
b5c869d5e7 Make parse_util_token_extent return its output instead of mutating input. 2025-01-23 17:09:29 +01:00
kerty
4994000a27 Small refactor of Reader::flash 2025-01-23 17:09:29 +01:00
Johannes Altmanninger
8208a12a76 Back out "Support help argument in "{ -h""
This backs out commit efce176ceb.
2025-01-19 18:57:21 +01:00
Johannes Altmanninger
a7fdd8d002 Back out "Back out "Remove awkward assert""
This backs out commit e0c6384ed3.
2025-01-19 18:57:21 +01:00
Fabian Boehm
98a96f5b58 Revert "Swap alt-{left,right,backspace,delete} with ctrl-* on macOS"
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.
2025-01-19 18:52:10 +01:00
Johannes Altmanninger
ebdc3a0393 Swap alt-{left,right,backspace,delete} with ctrl-* on macOS
See https://github.com/fish-shell/fish-shell/issues/ 10926
2025-01-19 18:29:07 +01:00
Johannes Altmanninger
e0c6384ed3 Back out "Remove awkward assert"
This backs out commit 6126237bc4.
2025-01-19 18:29:07 +01:00