This reimplements ridiculousfish/control_r which is a more future-proof
approach than #6686.
Pressing Control+R shows history in our pager and allows to search filter
commands with the pager search field.
On the surface, this works just like in other shells; though there are
some differences.
- Our pager shows multiple results at a time.
- Other shells allow to use up arrow/down arrow to select adjacent entries
in history. Shouldn't be hard to implement but the hidden state might
confuse users and it doesn't play well with up-or-search, so this is
left out.
Users might expect the history pager to use subsequence matching (fuzzy
matching) like the completion pager, however due to the history pager design it
uses substring matching. We could change this in future, however that means
we would also want to change the ordering from "reverse-chronological" to
"longest common subsequence" (e.g. what fuzzy finders do), because otherwise
a query "fis" might give this ordering:
fsck /dev/disk/by-partlabel/Linux\x20filesystem
fish
which is probably not what the user wants.
The pager shows only a small number of history items at a time. This is
because, as explained above, the history pager does not support subsequence
matching, so navigating it does not scale well.
Closes#602
Previously, `kill-whole-line` kills the line and its following
newline. This is insufficient when we are on the last line, because
it would not actually clear the line. The cursor would stay on the
line, which is not the correct behavior for bindings like `dd`.
Also, `cc` in vi-mode used `kill-whole-line`, which is not correct
because it should not remove any newlines. We have to introduce
another special input function (`kill-inner-line`) to fix this.
Prior to this commit, setting a universal variable may trigger syncing
against the file which will modify other universal variables. But if we
want to support multiple environments we need the parser to decide when to
sync uvars. Shift the decision of when to sync to the parser itself. When a
universal variable is modified, now we just set a flag and it's up to the
(main) parser when to pick it up. This is hopefully just a refactoring with
no user-visible changes.
Say the user has a multi-char binding (typically an escape sequence), and a
signal arrives partway through the binding. The signal has an event handler
which enques some readline event, for example, `repaint`. Prior to this
change, the readline event would cause the multi-char binding to fail. This
would cause bits of the escape sequence to be printed to the screen.
Fix this by noticing when a sequence was "interrupted" by a non-char event,
and then rotating a sequence of such interruptions to the front of the
queue.
Fixes#8628
This concerns printing status messages for background jobs which have
stopped or finished. Previously fish would do this from two places:
1. Before running a command (including empty string)
2. If a signal is received during select()
So if the job finishes while fish is doing something else (like running an
event handler) then we would not print status messages until the user hit
return. This caused the job_summary.py test to be flaky.
Fix this by splitting the interrupt handler into two parts: a part that
handles signals (e.g. triggering exit from the reader), and a part that
always runs just before blocking in select(). This second part always
reaps jobs and prints their status messages. This narrows the window for a
job exit to be "missed" before fish blocks in select, and should make the
job_summary.py test more reliable.
This concerns the problem of "injecting" fancy fish bits like job reaping
into the "common" input stuff which is also used by fish_key_reader.
Instead of providing a callback, make the input event queue a base class
with virtual functions. This allows for a richer interface and simplifies
some memory management issues.
readb is used to read a single byte from stdin, or maybe update universal
variables, or maybe invoke completion handlers, etc. Previously it
returned char_event_t but this is more complex than necessary; instead we
can just have it return a single byte, or one of a few special error
codes. This makes the readb's role more clear.
"The" interrupt handler is used when we get a signal while waiting at the
prompt. Switch it from a global function pointer to an std::function. This
is a mild refactoring which itself will be replaced soon.
Now that timeouts are stored in the event queue peeker, we can remove the
notion of timeout events altogether. Instead you may ask for an event with
a timeout, and get back none on timeout. This simplifies how input events
work.
Fish was previously oblivious to the existence of mouse-tracking ANSI
escapes; this was mostly OK because they're disabled by default and we
don't enable them, but if a TUI application that turned on mouse
reporting crashed or exited without turning mouse reporting off, fish
would be left in an unusable state as all mouse reporting CSI sequences
would be posted to the prompt.
This can be tested by executing `printf '\x1b[?1003h'` at the prompt,
then clicking with any mouse button anywhere within the terminal window.
Previously, this would have resulted in seeming garbage being spewed to
the prompt; now, fish detects the mouse tracking CSIs posted to stdin by
the terminal emulator and a) ignores them to prevent invalid input, as
well as b) posts the CSI needed to disable future mouse tracking events
from being emitted on subsequent mouse interactions (until re-enabled).
Note that since we respond to a mouse tracking CSI rather than
pre-emptively disable mouse reporting, we do not need to do any sort of
feature detection to determine whether or not the terminal supports
mouse reporting (otherwise, if it didn't support it and we posted the
CSI anyway, we'd end up with exactly the kind of cruft posted to the
prompt that we're trying to avoid).
Fixes#4873
This is a stack-allocating utility class to peek up to N
characters/events out of an `event_queue_t` object. The need for a
hard-coded maximum peek length N at each call site is to avoid any heap
allocation, as this would be called in a hot path on every input event.
This allows directly inserting multiple characters/events in one go at
the front of the input queue, instead of needing to add them one-by-one
in reverse order.
In addition to improving performance in case of fragmented dequeue
allocation, this also is less error prone since a dev need not remember
to use reverse iterators when looping over a vector of peeked events.
This allows for multiple edits to be undone/redone in one go, as if they
were one edit.
Useful when a function is editing the commandline buffer via scripted
changes or via a keybinding so the internal changes to the buffer can be
abstracted away.
(Having extreme difficulty getting pexpect to play nice with the concept
of undo/redo...)
Currently binding `exit` to a key checks too late that it's exitted,
so it leaves the shell hanging around until the user does an execute
or similar.
As I understand it, the `exit` builtin is supposed to only exit the
current "thread" (once that actually becomes a thing), and the
bindings would probably run in a dedicated one, so the simplest
solution here is to just add an `exit` bind function.
Fixes#7604.
This was always awkward as fish script, and had problems with
interrupting the autoloading.
Note that we still leave the old function intact to facilitate easier
upgrading for now.
Fixes#7145.
This updates the behavior of tilde to match the behavior found in vim.
In vim, tilde toggles the case of the character under the cursor and
advances one character. In visual mode, the case of each selected
character is toggled, the cursor position moves to the beginning of
the selection, and the mode is changed to normal. In fish, tilde
capitalizes the current letter and advances one word. There is no
current tilde command for visual mode in fish.
This patch adds the readline commands `togglecase-letter` and
`togglecase-selection` to match the behavior of vim more closely. The
only difference is that in visual mode, the cursor is not modified.
Modifying the cursor in visual mode would require either moving it in
`togglecase-selection`, which seems outside its scope or adding
something like a `move-to-selection-start` readline command.
This adds a new readline command self-insert-notfirst, which is
analogous to self-insert, except that it does nothing if the cursor
is at the beginning. This will serve as a higher-performance implementation
for stripping leading spaces on paste.
Add the input function undo which is bound to `\c_` (control + / on
some terminals). Redoing the most recent chain of undos is supported,
redo is bound to `\e/` for now.
Closes#1367.
This approach should not have the issues discussed in #5897.
Every single modification to the commandline can be undone individually,
except for adjacent single-character inserts, which are coalesced,
so they can be reverted with a single undo. Coalescing is not done for
space characters, so each word can be undone separately.
When moving between history search entries, only the current history
search entry is reachable via the undo history. This allows to go back
to the original search string with a single undo, or by pressing the
escape key.
Similarly, when moving between pager entries, only the most recent
selection in the pager can be undone.
Prior to this fix, self-insert would always wait for a new character.
Track in char_event what sequence generated the readline event, and then
if the sequence is not empty, insert that sequence.
This will support implementing the space binding via pure readline
functions.
The enum starts at 0 (defined to be!), so we can eliminate this one.
That allows us to remove a reliance on the position of
beginning_of_line, and it would trigger a "type-limits" warning.
Also leave a comment because I actually hit that.
This was a sort of side channel that was only used to propagate redraws
after universal variable changes. We can eliminate it and handle these
more directly.
If we switch the bind mode, we add a "force-repaint" there just to
redraw the mode indicator.
That's quite wasteful and annoying, considering that sometimes the prompt can take
half a second.
So we add a "repaint-mode" function that just reexecutes the
mode-prompt and uses the cached values for the others.
Fixes#5783.
* Add "expand-abbr" bind function
This can be used to explictly allow expanding abbreviations.
* Make expanding abbr explicit
NOTE: This accepts them for space only, we currently also do it for \n
and \r.
* Remove now dead code
We no longer trigger an abbr implicitly, so we can remove the code
that does it.
* Fix comment
[ci skip]