Commit graph

604 commits

Author SHA1 Message Date
Johannes Altmanninger
3b30d92b62 Commit transient edit when closing pager
When selecting items in the pager, only the latest of those items is kept
in the edit history, as so-called transient edit.  Each new transient edit
evicts any old transient edit (via undo).

If the pager is closed by a command that performs another transient edit
(like history-token-search-backward) we thus inadvertently undo (= remove)
the token inserted by the pager.  Fix this by closing a transient edit
session when closing the pager.  Token search will start its own session.

Fixes #9160
2022-08-31 07:49:49 +02:00
Fabian Boehm
4dfcd4cb4e reader: Check bounds for color
This fixes a crash when you open the history pager and then do
history-token-search-backward (e.g. alt+. or alt-up).

It would sometimes crash because the `colors.at(i)` was an
out-of-bounds access.

Note: This might still leave the highlighting offset in some
cases (not quite sure why), but at least it doesn't *crash*, and the
search generally *works*.
2022-08-26 15:02:05 +02:00
ridiculousfish
3eae0a9b6a clang-format all C++ files
This mostly re-sorts headers that got desorted after the IWYU
application in 14d2a6d8ff.
2022-08-21 15:02:19 -07:00
Aaron Gyes
14d2a6d8ff IWYU-guided #include rejiggering.
Let's hope this doesn't causes build failures for e.g. musl: I just
know it's good on macOS and our Linux CI.

It's been a long time.

One fix this brings, is I discovered we #include assert.h or cassert
in a lot of places. If those ever happen to be in a file that doesn't
include common.h, or we are before common.h gets included, we're
unawaringly working with the system 'assert' macro again, which
may get disabled for debug builds or at least has different
behavior on crash. We undef 'assert' and redefine it in common.h.

Those were all eliminated, except in one catch-22 spot for
maybe.h: it can't include common.h. A fix might be to
make a fish_assert.h that *usually* common.h exports.
2022-08-20 23:55:18 -07:00
ridiculousfish
2a0e0d6721 Remove the intern'd strings component
Intern'd strings were intended to be "shared" to reduce memory usage but
this optimization doesn't carry its weight. Remove it. No functional
change expected.
2022-08-13 12:51:36 -07:00
ridiculousfish
e0a4d49ef3 Bravely stop appending a newline in reader_shell_test
This newline apparently dates back to when we required all statements to
be terminated; but our AST no longer requires that so we can remove
this. No functional change expected here.
2022-08-07 14:03:33 -07:00
ridiculousfish
1dff1cb2c4 Factor out handling of readline_cmd_t::execute
This reduces the size of handle_readline_command.
No functional change.
2022-08-07 13:37:56 -07:00
Johannes Altmanninger
095c093af6 Fix "commandline --paging-mode" false negative when there is no room for pager, attempt 2
The previous fix was reverted because it broke another scenario.  Add tests
for both scenarios.

The first test exposes another problem: autosuggestions are sometimes not
recomputed after selecting the first completion with Tab Tab. Fix that too.
2022-07-31 07:14:56 +02:00
Aaron Gyes
7b18a70724 Revert "Fix "commandline --paging-mode" false negative when there is no room for pager"
This reverts commit 1edcd8ab29.

The commit broke hitting <TAB> to show the pager, followed by
down-or-search.
2022-07-30 18:15:10 -07:00
Johannes Altmanninger
a447cc38a9 Hint at more matches at the bottom of the history pager 2022-07-30 23:27:24 +02:00
Johannes Altmanninger
1af9b8e430 Prefix history pager results with a fake prompt
This makes it easy to see where the individual commands start.  Perhaps we
can get rid of this once we have syntax highlighting for the commands in
the history pager, or if we add timestamps as descriptions.
2022-07-30 23:27:24 +02:00
Johannes Altmanninger
453aac14af Advance pager history search with Control-R/Control-S
Note that every change to the search field still starts a new search, from
the end of history. We could change this in future but it's unclear to me
what the expected behavior is. I don't find the traditional readline behavior
very intuitive.
2022-07-30 23:27:24 +02:00
Johannes Altmanninger
24e04daa22 Teach history search to move forward in time
Will use this for forward incremental search.

No functional change.
2022-07-30 23:27:24 +02:00
Johannes Altmanninger
dcff0a2f2b Add Control+R incremental history search in pager
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
2022-07-30 23:27:24 +02:00
Johannes Altmanninger
b0233c9aa7 Revert "Refactor: inline clear_pager()"
The next patch wants to add state that should be reset when we clear the
pager, which will happen in this function.

This reverts commit b25b291d38.

No functional change.
2022-07-30 23:27:24 +02:00
Johannes Altmanninger
9a0d8e67df Extract function for smartcase history search
To be used in the commit after next.

No functional change.
2022-07-30 23:27:24 +02:00
Johannes Altmanninger
3954200555 Centralize how we invalidate pager rendering after completions change
The pager's rendering_needs_update() function detects some but not all
scenarios where a rendering is stale. In particular, it does not compare
the completion strings.

To make this work, we manually invalidate the pager rendering whenever we
update completion strings. The history pager needs the same functionality,
so let's move it into the pager.

No functional change.
2022-07-30 23:27:24 +02:00
Michael Forster
f09d2c4e6e Use env_dispatch to update cursor selection mode 2022-07-30 09:49:07 -07:00
Michael Forster
7d198fa404 Add an initial test for fish_cursor_selection_mode 2022-07-30 09:49:07 -07:00
Michael Forster
5cf67c2d61 Use dedicated variable to configure selection size
This addresses code review feedback to not couple the purely visual
concept of cursor style with the logical concept of the selection size.
Instead this now uses a dedicated variable
`$fish_select_char_after_cursor` to determine whether to extend the
selection beyond the cursor:

* fish_select_char_after_cursor = 1 or unset -> extend selection
* all other cases -> place the selection end that the cursor
2022-07-30 09:49:07 -07:00
Michael Forster
a7d943793e Consider cursor width when updating selection
This fixes the handling of the right end of the selection. Currently the
right end is considered to be at the cursor position + 1. When using a
`block` or `underline` cursor this is arguably correct, because the
cursor has a width of 1 and spans from the current position to the next:
```
    x x [x x x̲] x
```

This is incorrect though (or at least very unintuitive), when using a
`line` cursor:
```
    x x [x x|x] x
```

This commit changes the strategy for determining the end of the
selection in the following way:

* If the current cursor as determined by `$fish_cursor_<bind_mode>` is
  set to `line`, then a cursor width of `0` is assumed.
* In all other cases, including `block` and `underscore` as well as when
  no value is set we retain the previous behavior of assuming a cursor
  width of `1`.
```
    x x [x x x̲] x
    x x [x x|]x x
```

This change should not affect many users, because the selection is
probably used most by vi-mode users, who are also likely to use a
block cursor.
2022-07-30 09:49:07 -07:00
Johannes Altmanninger
1edcd8ab29 Fix "commandline --paging-mode" false negative when there is no room for pager
The pager still works even if there is no room to render it.  So let's make
"commandline --paging-mode" return true if there is an off-screen pager.

This fixes the problem with the upcoming history-pager described in
https://github.com/fish-shell/fish-shell/pull/9089#issuecomment-1196945456
2022-07-28 22:08:33 +02:00
Johannes Altmanninger
1fc3d51dde Fix misleading comment in set_buffer_maintaining_pager()
This function used to clear the pager search field but it no longer does.

No functional change.
2022-07-28 10:40:54 +02:00
Johannes Altmanninger
8729623cec Make ESCAPE_ALL the default and call its inverse ESCAPE_NO_PRINTABLES
ESCAPE_ALL is not really a helpful name. Also it's the most common flag.
Let's make it the default so we can remove this unhelpful name.

While at it, let's add a default value for the flags argument, which helps
most callers.

The absence of ESCAPE_ALL makes it only escape nonprintable characters
(with some exceptions). We use this for displaying strings in the completion
pager as well as for the human-readable output of "set", "set -S", "bind"
and "functions".

No functional change.
2022-07-27 11:24:35 +02:00
Johannes Altmanninger
0c97fea5c4 Make pager refilter completions after undo/redo in search field
Almost all edits to our commandline are funneled through
reader_data_t::push_edit(). Notable exceptions are undo/redo (which move
across existing edits instead). Due to an oversight, undo/redo fail to
trigger commandline update hooks. Fix that.

Our behavior of triggering hooks only for the search field looks weird. I
reckon that the command line eventually catches up, but this means we trigger
some hooks redundantly. Once we figure that out we can remove the new function.
2022-07-26 15:29:52 +02:00
Johannes Altmanninger
fe2f6f0c63 Fix Escape in pager not removing the inserted completion if search field was used
command_line_has_transient_edit tracks the actual command line, not the
pager search field. We accidentally reset it after modifying the search field
which causes unexpected behavior - the commandline added by the completion
pager remains even after I press Escape.
2022-07-26 15:29:52 +02:00
Johannes Altmanninger
3d8f643a5e Remove duplicate logic to clear the transient bit when inserting into commandline
This is already done by the above call to insert_char.

No functional change.
2022-07-26 15:20:35 +02:00
Johannes Altmanninger
671ad1f4a6 Fix typo 2022-07-26 15:20:19 +02:00
Johannes Altmanninger
12d4b50d5f Remove unused parameter from set_fully_disclosed() 2022-07-24 17:11:48 +02:00
Johannes Altmanninger
368b68ff47 Minor simplification of term_donate/term_steal
No functional change.
2022-07-24 17:11:48 +02:00
SeekingBlues
173914af65
Highlight history searches correctly (#9066)
Previously, the search text is used to find out which part of the
updated command line should be highlighted during a history search. This
approach will cause the incorrect part to be highlighted when the line
contains multiple instances of the search text.

To address this, we have to find out exactly where to highlight, i.e.
the offset of the current token in the command line (0 if not a token
search) plus the offset of the search text in the match.
2022-07-13 16:48:04 +02:00
ridiculousfish
50f6b06251 Replace a bunch of ASSERT_IS_MAIN_THREAD
Switch these to a new function parser.assert_can_execute(), in
preparation for allowing execution off of the main thread.
2022-06-20 12:31:36 -07:00
ridiculousfish
bfa83470d4 Reimplement autosuggestion-triggered completion loading
This concerns what happens if the user types e.g. `grep --i` and grep or
its completions have not yet been loaded. Previously we would "bounce to
the main thread" from within the autosuggestion thread to load grep's
completions. However under concurrent execution, this may deadlock as the
main thread is waiting for something else.

In the new implementation, complete simply records the commands that it
would autoload, and returns them back to the caller, where the caller can
decide how to handle them.

In general iothread_perform_on_main risks deadlock under concurrent
execution and we should try to get rid of it.

There should be no user-visible change from this fix.
2022-06-19 15:15:17 -07:00
ridiculousfish
17bd7d0e40 Switch completion_request_options_t from a list of flags to a struct
This is simpler and allows potentially hanging more fields off of it
later.
2022-06-19 11:23:10 -07:00
ridiculousfish
9f2cc4df36 Save the screen status more often
The fix for #3481 caused us to save the screen status after external
commands were run, fixing an unnecessary abandon-line when switching
modes. But we may also run commands not directly as part of a binding,
but instead via an on-variable event, e.g. for fish_bind_mode.

Extend this fix to all bindings, guarded by changes to exec_count. Now
any time an external command runs as part of a binding we should pick up
changes to the tty and not abandon the line.

Fixes #3481 again.
2022-06-12 13:16:29 -07:00
ridiculousfish
b8ad117e87 Save the screen status after running command bindings
This concerns running a key binding which invokes a command. If that
command modifies the tty, then fish will spot the modification later and
then react to it by redrawing the prompt. However tty modifications may
be benign or desirable; for example switching the cursor from a line to
a block. Fix this by re-fstating the tty after running external
commands.

Fixes #3481
2022-06-06 11:47:27 -07:00
ridiculousfish
299ed9f903 Allow 'commandline' to set the commandline from the prompt
This means that running `commandline foo` will indeed set the text of
the command line to `foo`; it won't get cleared immediately.

Fixes #8807
2022-06-04 15:33:55 -07:00
SeekingBlues
cf620c829b Improve newline behavior of kill-whole-line
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.
2022-06-04 13:45:25 -07:00
ridiculousfish
4e42740ca3 Propertly type flags arguments
Instead of `int flags` write `complete_flags_t flags`, etc.
No functional change here.
2022-06-01 10:02:09 -07:00
ridiculousfish
d83e51a8a2 Rename check_cancel_from_fish_signal to fish_is_unwinding_for_exit
"unwinding_for_exit" mixes up SIGHUP handling and also the exit builtin;
this is still pretty messy.
2022-05-28 16:35:40 -07:00
ridiculousfish
ec6fd088f2 Migrate initializing CMD_DURATION from reader to env
This puts the initialization of CMD_DURATION at home with other
default-initialized variables. No user-visible change expected from
this.
2022-05-22 12:29:51 -07:00
ridiculousfish
4d3261dadc Bravely stop initializing the term size from reader_init
The terminal size in all cases should have been initialized in env_init,
so no reason to do it here. No user visible change expected from this.
2022-05-22 12:28:05 -07:00
ridiculousfish
1893204067 event_fire_generic to take its arguments directly
Just mild refactoring, no functional change.
2022-05-14 10:33:47 -07:00
Johannes Altmanninger
bfd5e8dfbe Do not stomp token if tab-expansion of wildcards exceeds limit or is canceled
Hitting tab on "echo **" will often result in more than 256 matches.
Commit 143757e8c (Expand wildcards on tab, 2021-11-27) describes this scenario

> If the expansion would produce more than 256 items, we flash the command
> line and do nothing, since it would make the commandline overfull.

Yet we actually erase the "**" token, which seems wrong since we already
flash the command line. Fix this, at the cost of making the code a bit uglier.

I tried to write a test in tests/pexpects/wildcard_tab.py but that doesn't
seem to work because pexpect provides only a "dumb" terminal.  I wonder if we
can test what we write to the screen without depending on a terminal emulator.
2022-05-14 14:31:30 +02:00
ridiculousfish
143757e8c6 Expand wildcards on tab
Prior to this change, if you tab-completed a token with a wildcard (glob), we
would invoke ordinary completions. Instead, expand the wildcard, replacing
the wildcard with the result of expansions. If the wildcard fails to expand,
flash the command line to signal an error and do not modify it.

Example:

    > touch file(seq 4)
    > echo file*<tab>

becomes:

    > echo file1 file2 file3 file4

whereas before the tab would have just added a space.

Some things to note:

1. If the expansion would produce more than 256 items, we flash the command
line and do nothing, since it would make the commandline overfull.

2. The wildcard token can be brought back through Undo (ctrl-Z).

3. This only kicks in if the wildcard is in the "path component
   containing the cursor." If the wildcard is in a previous component,
   we continue using completions as normal.

Fixes #954.
2022-04-10 13:53:22 -07:00
ridiculousfish
2d945afd58 Factor applying completions out of handle_readline_command
The handle_readline_command function is getting unwieldy, so factor it
better to reduce its length. No functional change here.
2022-04-10 13:41:21 -07:00
Aaron Gyes
7031a736a7 don't check if unsigned el->position() < 0 2022-04-07 10:16:26 -07:00
Fabian Homborg
fa1ecb8c67 reader: Some light stringification 2022-03-25 16:06:10 +01:00
Fabian Homborg
f98398b418 event: Pass name as wcstring
This passed a wchar_t, only to then construct a wcstring out of it.
Instead let's just pass it directly and move it.
2022-03-25 16:06:10 +01:00
Fabian Homborg
2101dd4add Let nextd-or-forward-word binding move like normal forward_word
Broken in #8358, this caused nextd-or-forward-word to actually be
nextd-or-forward-bigword.

See #8790.
2022-03-22 22:09:42 +01:00