Commit Graph

893 Commits

Author SHA1 Message Date
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
ccoVeille
90e916e164 Fix typo in tests 2025-01-26 20:30:48 -08:00
ccoVeille
b6a1bedab9 Fix typos in comments 2025-01-26 20:30:48 -08:00
Johannes Altmanninger
c651a79cb6 Fix regression causing builtin commandline to report wrong relative cursor
Regressed in 55fd43d86c (Port reader, 2023-12-22).

Fixes #11085
2025-01-26 15:51:05 +01:00
Fabian Boehm
eab9e647f4 checks/tmux-history-pager: Disable on CI in general
Keeps failing for timing reasons and it's already quite slow.

See #11036
2025-01-21 17:32:27 +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
d3c37de753 Back out "Always treat brace at command start as compound statement"
This backs out commit 98750e1ae5.
2025-01-19 18:57:21 +01:00
Johannes Altmanninger
92bd366c1b Back out "Allow if/then/fi, while/do/done and for/do/done"
This backs out commit e32572e4e6.
2025-01-19 18:57:13 +01:00
Fabian Boehm
5b0622cf00 Disable tmux-history-pager test on ASAN 2025-01-19 18:54:56 +01:00
Fabian Boehm
0494b1b608 tests/checks/exec: Match entire env line 2025-01-19 18:47:28 +01:00
Fabian Boehm
494bdfa013 Revert accidentally pushed fork
Revert "README for this fork"

This reverts commit 97db461e7f.

Revert "Allow foo=bar global variable assignments"

This reverts commit 45a2017580.

Revert "Interpret () in command position as subshell"

This reverts commit 0199583435.

Revert "Allow special variables $?,$$,$@,$#"

This reverts commit 4a71ee1288.

Revert "Allow $() in command position"

This reverts commit 4b99fe2288.

Revert "Turn off full LTO"

This reverts commit b1213f1385.

Revert "Back out "bind: Remove "c-" and "a-" shortcut notation""

This reverts commit f43abc42f9.

Revert "Un-hide documentation of non-fish shell builtins"

This reverts commit 485201ba2e.
2025-01-19 18:34:59 +01:00
Johannes Altmanninger
45a2017580 Allow foo=bar global variable assignments
override fixes
2025-01-19 18:29:07 +01:00
Johannes Altmanninger
0199583435 Interpret () in command position as subshell 2025-01-19 18:29:07 +01:00
Johannes Altmanninger
4a71ee1288 Allow special variables $?,$$,$@,$# 2025-01-19 18:29:07 +01:00
Johannes Altmanninger
e32572e4e6 Allow if/then/fi, while/do/done and for/do/done 2025-01-19 18:29:07 +01:00
Johannes Altmanninger
98750e1ae5 Always treat brace at command start as compound statement 2025-01-19 18:29:07 +01:00
Johannes Altmanninger
efce176ceb Support help argument in "{ -h"
Unlike other builtins, "{" is a separate token, not a keyword-string
token.

Allow the left brace token as command string; produce it when parsing
"{ -h"/"{ --help" (and nowhere else).  By using a decorated statement,
we reuse logic for redirections etc.

Other syntax elements like "and" are in the builtin list, which
- adds highlighting logic
- adds it to "builtin --names"
- makes it runnable as builtin
  (e.g. "builtin '{'" would hypothetically print the man page)

These don't seem very important (highlighting for '{' needs to match
'}' anyway).

Additionally, making it a real builtin would mean that we'd need to
deactivate a few places that unescape "{" to BRACE_BEGIN.

Let's not add it to the built in list. Instead, simply synthesize
builtin_generic in the right spot.

I'm assuming we want "{ -h" to print help, but '"{" -h' to run an
external command, since the latter is historical behavior.  This works
naturally with the above fake builtin approach which never tries to
unescape the left brace.
2025-01-19 18:29:07 +01:00
kerty
f26ebac8dd Fix macOS quotation issue in test tmux-multiline-prompt.fish 2025-01-19 18:29:07 +01:00
kerty
4ce8037e73 Fix grep regex in test locale-numeric.fish 2025-01-19 18:29:07 +01:00
kerty
8116e80140 Add test for history pager 2025-01-19 18:29:07 +01:00
Johannes Altmanninger
7ad47c34e8 Fix regression causing scrollback-push to not clear text below cursor
If a child program crashes with some text rendered below the cursor,
we fail to clear that text. For example run vim, "pkill -9 vim" and
observe that scrollback-push fails to clean up the leftover text.
Fix that.
2025-01-19 18:29:07 +01:00
Fabian Boehm
fb2caf63e5 Fix error for "fish --foo" without option argument
Wgetopt needs a ":" at the beginning to turn on this type of error.

I'm not sure why that is now, and we might want to change it (but tbh
wgetopt could do with a replacement anyway).

Fixes #11049
2025-01-17 10:03:19 +01:00
Johannes Altmanninger
ba4ead6ead Stop saving autosuggestions that we can't restore
Sorry, commit 51adba6ee0 (Restore autosuggestion after corrected
typo, 2025-01-10) was pushed too early.  One issue is that it saves
autosuggestions also when we edit in the middle, where we can't
restore it.  We'd still restore it in some cases, even though it
doesn't apply. This breaks invariants that may cause various problems
when interacting with the autosuggestion.

Fix it by only saving the autosuggestion when we will be able to
restore it correctly.
2025-01-17 09:58:26 +01:00
David Adam
d6e001ac7e fix tests for 24abbb6de7 2025-01-15 23:28:08 +08:00
Johannes Altmanninger
1bf2b43d30 Allow { } for command grouping, like begin / end
For compound commands we already have begin/end but

> it is long, which it is not convenient for the command line
> it is different than {} which shell users have been using for >50 years

The difference from {} can break muscle memory and add extra steps
when I'm trying to write simple commands that work in any shell.

Fix that by embracing the traditional style too.

---

Since { and } have always been special syntax in fish, we can also
allow

	{ }
	{ echo }

which I find intuitive even without having used a shell that supports
this (like zsh. The downside is that this doesn't work in some other
shells.  The upside is in aesthetics and convenience (this is for
interactive use). Not completely sure about this.

---

This implementation adds a hack to the tokenizer: '{' is usually a
brace expansion. Make it compound command when in command position
(not something the tokenizer would normally know). We need to disable
this when parsing a freestanding argument lists (in "complete somecmd
-a "{true,false}").  It's not really clear what "read -t" should do.
For now, keep the existing behavior (don't parse compound statements).

Add another hack to increase backwards compatibility: parse something
like "{ foo }" as brace statement only if it has a space after
the opening brace.  This style is less likely to be used for brace
expansion. Perhaps we can change this in future (I'll make a PR).

Use separate terminal token types for braces; we could make the
left brace an ordinary string token but since string tokens undergo
unescaping during expansion etc., every such place would need to know
whether it's dealing with a command or an argument.  Certainly possible
but it seems simpler (especially for tab-completions) to strip braces
in the parser.  We could change this.

---

In future we could allow the following alternative syntax (which is
invalid today).

	if true {
	}
	if true; {
	}

Closes #10895
Closes #10898
2025-01-15 11:18:46 +01:00
Johannes Altmanninger
10dd8a8e73 Add range to closing-unopened brace error
The error on "echo }" is needlessly inconsistent with "echo )" and
"echo (}" etc; fix that I guess.
2025-01-15 10:54:18 +01:00
Johannes Altmanninger
debfdf0a39 Fix inconsistent error message on quoted keyword
Commit bdfbdaafcc (Forbid subcommand keywords in variables-as-commands
(#10249), 2024-02-06) banned "set x command; $x foo" because the
parser will not recognize "$x" as decorator.
That means that we would execute only the builtin stub,
which usually exist only for the --help argument.

This scenario does not apply for keywords that are quoted or contain
line continuations. We should not treat «"command"» differently
from «command».  Fix this inconsistency to reduce confusion.
2025-01-15 10:54:18 +01:00
Johannes Altmanninger
6d18f57e96 Make ! a builtin too, fixing "! -h"
UnLike other aliases (":.["), ! is special in the grammar but in the
few cases like "! -h" where we parse it as decorated statement they
are equals. Add it to the built in list, so the help argument works.

It can still be overridden, so this should not break anything.
2025-01-15 10:54:18 +01:00
Johannes Altmanninger
40f5aac764 Fix forward-token hiccup at operators
For better or worse, backward-token completely skips over operators
like > & |.
forward-token is (accidentally?) inconsistent with that. Fix that.

Skipping over those tokens might be wrong weird.  Maybe not for
redirections since they are tighly coupled to their target.  Maybe we
can improve this in future.
2025-01-15 10:52:43 +01:00
Fabian Boehm
2508cc9de6 Disable some more tests under CI
tmux-commandline can fail with

```
prompt 4>     commandline -i "echo $(printf %0"$COLUMNS"d)"
```

And I just can't even.

job_summary is annoyingly tight.

Also count cancel_event as a *skip*, not success.
2025-01-14 20:31:48 +01:00
Johannes Altmanninger
24e216ae82 Fix regression causing missing autosuggestions after (
Some checks are pending
make test / ubuntu (push) Waiting to run
make test / ubuntu-32bit-static-pcre2 (push) Waiting to run
make test / ubuntu-asan (push) Waiting to run
make test / macos (push) Waiting to run
Rust checks / rustfmt (push) Waiting to run
Rust checks / clippy (push) Waiting to run
Commit 4f3d6427ce (Fix regression causing crash in "commandline -j",
2025-01-12) wasn't quite right; it mishandles the edge case where
the current process has no token, fix that.
2025-01-13 22:22:42 +01:00
Johannes Altmanninger
4f3d6427ce Fix regression causing crash in "commandline -j"
Commit 3fcc6482cb (Fix parse_util_process_extent including too much
on the left, 2024-12-24) changed the process extent based on the
observation that "A\n\n\nB" comprises three tokens with ranges 0..1,
1..2 and 4..5. Prior to that commit, the second process extent was
2..5, which seems a bit weird because it includes newlines.

Weirdness aside, the real reason for changing it was this snippet in
the autosuggestion performer, where we compute the process extent
around cursor, and check if the line at process start matches the
cached search string.

        // Search history for a matching item unless this line is not a continuation line or quoted.
        if range_of_line_at_cursor(
            &command_line,
            parse_util_process_extent(&command_line, cursor_pos, None).start,
        ) == search_string_range

Given "A\n\n\nB" and cursor_pos=1 commit 3fcc6482cb changed the output
from 2..5 to 4..5. This brings problems:
1. leading spaces will not be included (which is probably
   inconsequential but still ugly).
2. the specified cursor position is not included in the given range.

We could paper over 2 by computing min(cursor_pos)
but that would leave 1.

For now let's revert and solve the autosuggestion issue in a less
brittle way.
2025-01-12 19:55:17 +01:00
Fabian Boehm
aa77892be4 fish_indent: Read from stdin, take two
This needs to work both in builtin and command mode.

We should probably clarify how we're passing FDs around, and I suspect
we may close fds in places we don't expect.
2025-01-12 16:17:49 +01:00
Fabian Boehm
b43b0e0195
Rewrite test driver in python (#11028)
This replaces the test_driver.sh/test.fish/interactive.fish system with a test driver written in python that calls into littlecheck directly and runs pexpect in a subprocess.

This means we reduce the reliance on the fish that we're testing, and we remove a posix sh script that is a weird stumbling block (see my recent quest to make it work on directories with spaces).

To run specific tests, e.g. all the tmux tests and bind.py:

tests/test_driver.py target/release/ tests/checks/tmux*.fish tests/pexpects/bind.py
2025-01-11 21:13:19 +01:00
Johannes Altmanninger
51adba6ee0 Restore autosuggestion after corrected typo
Backspace signals that the user is not happy with the commandline,
and by extension the autosuggestion.

For this reason, backspace suppresses autosuggestions until the next
text insertion.

However if I
1. type something that has an autosuggestion
2. type *one* wrong letter (removing the autosuggestion)
3. type backspace

backspace does not visibly suppress any autosuggestion but rhater
signal that the user wants to go back to the previous state of the
commandline, which does have an autosuggestion.

Enable this scenario by caching the autosuggestion when it's
invalidated. On certain edits that make the cached autosuggestion
valid again, restore it from the cache.  Currently, only do this up
to a single backspace.  Could extend that in future.

This implementation is really bad.. but it's a start.
Weirdly, it does not restore the cache on undo; but that's
inconsequential because undo doesn't suppress autosuggestion as
of today.

Closes #3549
2025-01-11 18:58:49 +01:00
Johannes Altmanninger
7c539b9539 Rename the readline function for deleting active history item
history-pager-delete now also works for regular history search,
so rename it.
2025-01-11 18:58:49 +01:00
Fabian Boehm
b8208d72f7 Remove test for broken tmux output
Quite flaky on CI.

See #11036
2025-01-09 21:06:15 +01:00
Johannes Altmanninger
0e512f8033 Fix spurious blank lines when executing scrolled commandline
The result of

	commandline -i ": '$(seq $LINES)"\n"first scrolled line'"

is a commandline that is scrolled by one line.

Before executing that commandline, we move the cursor down by one
too many line. This is a regression from 610338cc70 (On undo after
execute, restore the cursor position, 2024-12-21). Fix that.

The test also demonstrates an unrelated problem, probably specific
to tmux.
2025-01-09 14:43:21 +01:00
Fabian Boehm
8304fd0fd0 tmux-job: Add more sleeps
Some checks are pending
make test / ubuntu (push) Waiting to run
make test / ubuntu-32bit-static-pcre2 (push) Waiting to run
make test / ubuntu-asan (push) Waiting to run
make test / macos (push) Waiting to run
Rust checks / rustfmt (push) Waiting to run
Rust checks / clippy (push) Waiting to run
2025-01-08 19:10:38 +01:00
Fabian Boehm
d3762f11b5 tmux-commandline: Print $LINES
Maybe this'll show us what the issue on NetBSD is
2025-01-08 19:10:38 +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
e11e62674f Fix bad layout computation with right prompt
Some checks are pending
make test / ubuntu (push) Waiting to run
make test / ubuntu-32bit-static-pcre2 (push) Waiting to run
make test / ubuntu-asan (push) Waiting to run
make test / macos (push) Waiting to run
Rust checks / rustfmt (push) Waiting to run
Rust checks / clippy (push) Waiting to run
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
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
Fabian Boehm
e66f6878b5 Make tests usable with path with spaces
This is somewhat subtle:

The #RUN line in a littlecheck file will be run by a posix shell,
which means the substitutions will also be mangled by it.

Now, we *have* shell-quoted them, but unfortunately what we need is to
quote them for inside a pre-existing layer of quotes, e.g.

    # RUN: fish -C 'set -g fish %fish'

here, %fish can't be replaced with `'path with spaces/fish'`, because
that ends up as

    # RUN: fish -C 'set -g fish 'path with spaces/fish''

which is just broken.

So instead, we pass it as a variable to that fish:

    # RUN: fish=%fish fish...

In addition, we need to not mangle the arguments in our test_driver.

For that, because we insist on posix shell, which has only one array,
and we source a file, we *need* to stop having that file use
arguments.

Which is okay - test_env.sh could previously be used to start a test,
and now it no longer can because that is test_*driver*.sh's job.

For the interactive tests, it's slightly different:

pexpect.spawn(foo) is sensitive to shell metacharacters like space.

So we shell-quote it.

But if you pass any args to pexpect.spawn, it no longer uses a shell,
and so we cannot shell-quote it.

There could be a better way to fix this?
2025-01-01 16:45:43 +01:00
Fabian Boehm
cb3d004a5a tests: Run filter-ctrl with %fish explicitly 2025-01-01 16:45:43 +01:00
Fabian Boehm
5e10d75a19 Tests: Don't cd to the tests directory!
We:

1. Set up a nice TMPDIR for our tests to use
2. Immediately `cd` to the directory containing the test runner.

So instead we don't do (2), and stay in the temp directory, and
explicitly use all the things from the test runner directory.

I am fairly certain that cmake papered over this by adding a second
layer of temp dir.
2025-01-01 16:45:43 +01:00
Fabian Boehm
b531cc8b43 tests: Specifically #require fish_test_helper when needed 2025-01-01 16:45:43 +01:00
Fabian Boehm
6848e70e87 Disable two tests on NetBSD
Some checks are pending
make test / ubuntu (push) Waiting to run
make test / ubuntu-32bit-static-pcre2 (push) Waiting to run
make test / ubuntu-asan (push) Waiting to run
make test / macos (push) Waiting to run
Rust checks / rustfmt (push) Waiting to run
Rust checks / clippy (push) Waiting to run
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
Some checks are pending
make test / ubuntu (push) Waiting to run
make test / ubuntu-32bit-static-pcre2 (push) Waiting to run
make test / ubuntu-asan (push) Waiting to run
make test / macos (push) Waiting to run
Rust checks / rustfmt (push) Waiting to run
Rust checks / clippy (push) Waiting to run
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
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