Compare commits

..

172 Commits

Author SHA1 Message Date
Fabian Boehm
dc63404c96 Create a temp dir per test
The main weirdness here is that

`with tempfile.TemporaryDirectory() as foo`

will have foo as a string, not foo.name???
2025-01-09 17:24:24 +01:00
Fabian Boehm
5507bcc425 Sort globs 2025-01-08 19:29:51 +01:00
Fabian Boehm
c3442602ef histfile: Change path to test history
Note that these technically would have to be fish-escaped
2025-01-08 19:11:07 +01:00
Fabian Boehm
3437d63507 Adjust one test
We now add these as functions even in the checks, which is entirely benign.
2025-01-08 19:11:07 +01:00
Fabian Boehm
695ae02aa5 Delete sh test driver 2025-01-08 19:11:07 +01:00
Fabian Boehm
e1059b5e43 Add a timeout to pexpect tests
timeout nicer
2025-01-08 19:11:07 +01:00
Fabian Boehm
f1cf64fba0 Rewrite test driver in python 2025-01-08 19:11:07 +01:00
Fabian Boehm
8304fd0fd0 tmux-job: Add more sleeps 2025-01-08 19:10:38 +01:00
Fabian Boehm
f4f786633d pexpects/bind: Add missing expect_prompt 2025-01-08 19:10:38 +01:00
Fabian Boehm
ec3b3fe321 pexpects/signals: Decrease a timeout that should be reached
Saves ~10% of the *total* testing time (except for `cargo test`)
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
Fabian Boehm
6db0f39676 exit_nohang: Harden a bit 2025-01-08 19:10:38 +01:00
Branch Vincent
7970ca55af completions: add fish-lsp (#11017) 2025-01-08 11:25:36 -06:00
David Adam
ccbbae95ef update copyright years to be unbounded
There is no legal need to have the year written here and it's a chore to
keep it up to date.
2025-01-08 20:38:43 +08:00
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
Klaus Hipp
4def0ac616 Revert "Fix typo in npm completions: isntall -> install" (#11014)
* Revert "Fix typo in npm completions: isntall -> install"

This reverts commit f4b01bb638.

* Add comments about typos in `npm` completions
2025-01-07 12:32:16 -06:00
Steve Walker
b574a5e4f6 fix python completion #10943 2025-01-07 23:30:27 +08:00
Klaus Hipp
9b67b2ae07 Fix typos in docs (#11015) 2025-01-06 19:40:30 -06:00
Klaus Hipp
ea4e4a4279 Fix completion typos for apt-build, htop and wget (#11016) 2025-01-06 19:39:47 -06:00
Johannes Altmanninger
3405621dee Update littlecheck to fix spurious "not found" error on exit 127
Commit b6d76ae: we now use lines like "# RUN: fish=%fish %fish".
If a test exits with 127 we try to look up the command but use the
wrong name, which leads to unintelligible errors if the test exits
with 127 for other reasons.
2025-01-06 06:40:43 +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
704b911168 Back out "Bind ctrl-l to clear-screen again for now"
As of the parent commits this should no longer cause breakage.

This backs out commit 07dd088d76.
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
Lzu Tao
f9b79926f1 Add more convenient key bindings for VI mode
To make it more familiar to vi/vim users.

In all mode, ctrl-k is bind to kill-line.

In Vi visual mode:
* press v or i turn into normal or insert mode respectively.
* press I turn to insert mode and move the cursor to beginning of line.
* because fish doesn't have upcase/locase-selection, and most people reach for
  g-U rather than g-u, g-U binds to togglecase-selection temporarily.
2025-01-05 23:00:21 +08:00
David Adam
6c3150aa05 docs/interactive: update key bindings added for 4.0 2025-01-05 22:27:00 +08:00
Johannes Altmanninger
07dd088d76 Bind ctrl-l to clear-screen again for now
Testing has revealed some problems on BSD and Windows terminals and
the Linux Console, let's revert to the old implementation until these
are fixed.  Leaving the changelog entry for now since it shouldn't
take long.

See #11003
2025-01-05 08:20:53 +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
cornmander
d842a6560e Add completions for Google Cloud commands. (#11005)
The `gcloud` and `gsutil` Google Cloud commands use argcomplete, so integrating them is easy with the `__fish_argcomplete_complete` function.
2025-01-04 19:45:05 -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
Lzu Tao
7eb254f2ba Add completion for gem-fetch 2025-01-04 21:26:03 +08:00
idealseal
2e12a2b6c4 feat(comp): Update completions for resolvectl 2025-01-04 20:42:31 +08:00
idealseal
a780e4da15 feat(comp): Update completion for md5sum 2025-01-04 20:39:33 +08:00
Thayne McCombs
33dd823f45 fix[completions]: Add set-timeout to bootctl 2025-01-04 20:15:53 +08: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
870a8f77a0 completions/scp: replace version detection
Version detection seems unreliable (see
https://github.com/fish-shell/fish-shell/issues/10445#issuecomment-2566232705
) so let's test for the actual feature.  On modern versions,"scp -O"
means "Use  the legacy SCP protocol for file transfers instead",
so presence of this feature indicates we are good.
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
David Adam
670541eec8 fish_jj_prompt: don't error if jj not installed 2025-01-03 12:38:14 +08:00
Johannes Altmanninger
0debddc9e5 Add a simple fish_jj_prompt
jj is often colocated with Git so the Git prompt also works, but
jj is always in a detached HEAD state, which is atypical for Git.
The jj prompt improves things by showing the revision ID which is
usually more useful than the commit ID.

This prompt is mostly adapted from the defaults for "jj log -r @".

Showing conflicting/empty commits seems useful.
Also perhaps bookmarks and tags, not sure.

The main problem with this prompt is that due to --ignore-working-copy,
the information may be stale.  That will be rectified after every jj
command, so hopefully this doesn't cause issues.
2025-01-03 00:03:58 +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
Alexei Mikhailov
9b26fff278 completions/exercism: use generate script
Exercism ships with it's own completions and a generation script, so let's use
that one instead.
2025-01-02 21:57:17 +08:00
Klaus Hipp
2b46d97c68 Update code completions 2025-01-02 14:11:24 +08:00
David Adam
65ced4e2bb Cargo.lock: update downstream dependencies 2025-01-02 13:20:15 +08:00
David Adam
3710142d1d Cargo.lock: update errno 2025-01-02 13:18:54 +08:00
David Adam
0c9c5e3a34 Cargo.toml/lock: upgrade serial_test
Slims the dependency tree down a bit; no breaking changes affect fish.
2025-01-02 13:09:54 +08:00
David Adam
53912777af Cargo.lock: upgrade cc 2025-01-02 12:38:50 +08: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
David Adam
6714818e5d Cargo.toml: update libc 2025-01-02 10:44:23 +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
a4f4ae76cb staticbuilds: Run tests 2025-01-01 16:45:56 +01:00
Fabian Boehm
c3de539d46 test_driver: Error out if $FISHDIR isn't given
This avoids confusion when you forget to set it and run it on the
wrong fish.
2025-01-01 16:45:43 +01:00
Fabian Boehm
7bb38355e8 test_driver: Some more errors 2025-01-01 16:45:43 +01:00
Fabian Boehm
5520ee3c65 Document 2025-01-01 16:45:43 +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
e9b9ee8d63 Fix docs if binary dir has a space
For some reason this is double-quoted if we quote this.
2025-01-01 16:45:43 +01:00
Fabian Boehm
17d57b70d0 littlecheck: Update to shell-quote replacements
Commit bb07435e3e4cbd34fcb667ec927353d176a0b2e8
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
050fe09af1 Compile fish_test_helper in the test driver 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
63e705a778 Let tests find fish and associated binaries via $FISHDIR
The default is still "../test/root/bin/", but we now pass this
through,
so you *can* run

`FISHDIR=$PWD ../tests/test_driver.sh $PWD/../tests/test.fish`
2025-01-01 16:45:43 +01:00
Fabian Boehm
1df8de06c1 Move littlecheck/pexpect to tests
This removes the need for a bunch of setup, and makes it easier to
make the tests agnostic to our test root setup.
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
Hong Xu
64ed47bf4e Update .editorconfig to use "unset" instead of "off" (#10972)
This is inline with the [EditorConfig spec](https://spec.editorconfig.org/). The [EditorConfig Wiki](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#max_line_length) was outdated and misleading, but have updated now.
2024-12-31 15:04:37 -06: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
Fabian Boehm
d5efef1cc5 __fish_complete_subcommand: Just complete -C for a given commandline
Fixes #10980.

This would, if a commandline was given, still revert to checking
the *real* commandline if it was empty.

Unfortunately, in those cases, it could have found a command and tried
to complete it.

If a commandline is given, that is what needs to be completed.

(note this means this is basically useless in completions that use it
like `sudo` and could just be replaced with `complete -C"$commandline"`)
2024-12-30 21:01:21 +01:00
Fabian Boehm
e715c3e3ff help: Add special error for $BROWSER/$fish_help_browser being wrong 2024-12-30 21:01:21 +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
Johannes Altmanninger
e1e963ae66 Move cursor on mouse click via kitty's OSC 133 click_events=1
When the user clicks somewhere in the prompt, kitty asks the shell
to move the cursor there (since there is not much else to do).

This is currently implemented by sending an array of
forward-char-passive commands.  This has problems, for example it
is really slow on large command lines (probably because we repaint
everytime).

Implement kitty's `click_events=1` flag to set the
position directly.  To convert from terminal-coordinates
to fish-coordinates, query [CSI 6 n Report Cursor
Position](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)
and use it to compute the left prompt's terminal-coordinates (which
are (0, 0) in fish-coordinates).

Unfortunately this doesn't yet work correctly while the terminal
is scrolled.  This is probably because the cursor position is wrong
if off-screen.  To fix that we could probably record the cursor
position while not scrolled, but it doesn't seem terribly important
(the existing implementation also doesn't get it right).

We still turn off mouse reporting.  If we turned it on, it
would be harder to select text in the terminal itself (not fish).
This would typically mean that mouse-drag will alter fish's
selection and shift+mouse-drag or alt+mouse-drag can be used.

To improve this, we could try to synchronize the selection: if parts
of the fish commandline are selected in the terminal's selection,
copy that to fish's selection and vice versa.

Or maybe there is an intuitive criteria, like: whenever we receive a
mouse event outside fish, turn off mouse reporting, and turn it back on
whenver we receive new keyboard input.  One problem is that we lose
one event (though we could send it back to the terminal). Another
problem is we would turn it back on too late in some scenarios.

Closes #10932
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
ca9c5f4cec Move some fake readline commands to a separate type 2024-12-30 10:50:01 +01:00
Johannes Altmanninger
48ae19b4b1 Update some stale doc comments 2024-12-30 10:50:01 +01:00
Johannes Altmanninger
7ec1487016 Deduplicate call to select() 2024-12-30 10:50:01 +01:00
Johannes Altmanninger
bc26481558 Retry writing some escape sequences on EINTR
Maybe we should be using SA_RESTART?
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
41e82c8c9e Protect some cursor movements against untimely ctrl-c
Commit 01dbfb0a3f (replace writestr() with fwprintf() in reader.cpp,
2016-12-20) accidentally replaced a retry-on-EINTR write with a
non-retrying version. Commit 7f31acbf9b (Prevent fish_title output
from triggering a bel, 2022-02-02) fixed this for some cases but
not all, fix that.
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
376bf3a982 Remove redundant return value from write_loop()
This function ought to match the standard write_all().
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
1e384900fa kitty kbd: stop parsing CSI R as F3
This has been removed, see kitty commit cd92d50a0 (Keyboard protocol:
Remove CSI R from the allowed encodings of the F3 key as it conflicts
with the *Cursor Position Report* escape code, 2022-12-24).
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
cde503b0a8 Mention lack of support for ctrl-backspace and alternatives
Closes #10936
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
69f0d960cf Fix off-by-one error in Vi-style upcase-word at commandline end
cursor_selection_mode=inclusive means the commandline position is
bounded by the last character. Fix a loop that fails to account
for this.

Fixes d51f669647 (Vi mode: avoid placing cursor beyond last character,
2024-02-14).

This change looks very odd because if the commandline is like

	echo foo.

it makes us try to uppercase the trailing period even though that's
not part of word range.  Hopefully this is harmless.

Note that there seem to be more issues remaining, for example Vi-mode
paste leaves the cursor in an out-of-bounds odd position.

Fixes #10952
Closes #10953

Reported-by: Lzu Tao <taolzu@gmail.com>
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
ca28d0a78f Add missing test for Vi mode $
PR #10953 reports missing coverage for the change to update_buff_pos()
in d51f669647 (Vi mode: avoid placing cursor beyond last character,
2024-02-14).

Add a case demonstrating how $ should not move the cursor past the
last character. Goes without saying that it's really ugly that we
update_buff_pos() must be so defensive here, ideally we wouldn't pass
it out-of-bounds positions.
2024-12-30 10:50:01 +01:00
Johannes Altmanninger
6043644f52 completions/status: add buildinfo 2024-12-30 10:50:01 +01:00
Grant Hutchins
1227b6765c Improve documentation for string escape
Before, it unnecessarily stated that there are three `--style` options, when
there are actually four.

I also align the default `--style=script` argument to the beginning of the line
to match the other options visually for easier scanning.
2024-12-29 13:48:34 -08:00
Fabian Boehm
905c7310c6 checks/type: Relax sh path even more
Fixes #10970
2024-12-29 22:11:34 +01:00
Ilya Grigoriev
b1064ac3a0 completions/tmux: add skeleton "Windows and Panes" bindings (#10854)
These are quite mechanical, but include all the commands (as of tmux
3.5a) in the "Windows and Panes" section of `man tmux`. For these
commands, I included the target-pane/session/client/window flags and the
-F formatstring flags (but not the less generic flags specific to
individual commands).

Nice completion is implemented for those flags where the helper
functions were already implemented previously.

After this, tmux pane<tab> will hopefully be useful.

A few TODOs mention low-hanging fruit for somebody who better
understands fish's `complete` command syntax (or a future me).

Another piece of low-hanging fruit would be completion for all the
target-window flags. This PR merely lists them.
2024-12-29 15:37:21 +01:00
EmilyGraceSeville7cf
1bda6043c8 feat(completion) support batsh command 2024-12-29 15:36:00 +01:00
EmilyGraceSeville7cf
d8d5913159 feat(completion): support folderify command 2024-12-29 15:35:25 +01:00
Benjamin Kellermann
2ac1523e54 add completion for btrbk (#10752)
* add completion for btrbk

completions for btrbk https://github.com/digint/btrbk/

* change indent + spaces
2024-12-29 15:33:29 +01:00
Łukasz Wieczorek
9cea5e0732 Remove redundant newlines, add .idea to gitignore
* Add .idea/ to git ignored directories.

* Remove redundant newline.

* Remove redundant newline.

* Remove redundant newlines.

* Remove redundant newline.

* Remove redundant newline.

* Add missing newline at end of file.

* Remove redundant newline.

* Remove redundant newlines.
2024-12-29 15:31:03 +01:00
Fabian Boehm
6f9ca42a30 Add status buildinfo (#10896)
This can be used to get some information on how fish was built - the
version, the build system, the operating system and architecture, the
features.
2024-12-29 13:37:28 +01:00
Joan Bruguera Micó
b8df9648f2 Create new base directories with mode 0700
If base directories (e.g. $HOME/.config/fish) need to be created,
create them with mode 0700 (i.e. restricted to the owner).
This both keeps the behavior of old fish versions (e.g. 3.7.1) and is
compliant with the XDG Base Directory Specification.

See: https://specifications.freedesktop.org/basedir-spec/0.8/#referencing
2024-12-28 12:13:48 -08:00
Fabian Boehm
66b80041cc Create release-with-debug cargo profile, hook it up with cmake
Fixes #10959
2024-12-28 16:03:40 +01:00
Kid
a579abb81b docs: Distinguish documents in sidebar 2024-12-28 08:42:46 +01:00
Peter Ammon
b97598fa6c Clean up some logic around handling the parser blocks
Fix a todo. Enforce reverse iteration order.
2024-12-27 16:42:38 -08:00
Peter Ammon
64cb86ac26 Stop copying node sources so aggressively in parse_execution
Eliminates some allocations and fixes a TODO.
2024-12-27 15:47:34 -08:00
Peter Ammon
a14906f52f Fix a todo!
Stop cloning the delimiter unnecessarily in builtin read.
2024-12-27 15:00:59 -08:00
Peter Ammon
36d7049749 Minor cleanup of other unsafe impl 2024-12-27 14:46:46 -08:00
Peter Ammon
4b9767ce83 Remove as_ptr from IoData
We don't need this. Also improve IoChain::remove().
2024-12-27 14:36:55 -08:00
Peter Ammon
f6d76d2057 Remove some unsafe impls of Send / Sync
We no longer have C++ so we don't need these; Rust does the right thing by
default.
2024-12-27 14:14:47 -08:00
Peter Ammon
659c926dbd Additional cleanup of io buffering
Eliminate some ugly bits. No functional change expected.
2024-12-27 14:09:07 -08:00
Peter Ammon
56da15d11f Rework the file descriptor monitor
[Do NOT cherry-pick to 4.0 - this needs more time to be tested]

fish sometimes needs to capture the output of a command or block of
commands. Examples include fish_prompt or any command substitution
("cmdsubs"). It does this the obvious way: by creating a pipe, using dup2
to replace stdout of the command with the write end of the pipe, and then
reading from the read end into a buffer, until EOF or the command
substitution completes. Importantly, this task also overlaps with waiting
for the process to exit; that is when executing:

    set var (some_cmd)

fish needs to both wait on `some_cmd` and ALSO read its output into memory.
This is awkward to do in a portable way in a single thread (though maybe
doable on Linux with pidfd). So we wait and read on different threads.

To make things worse, command substitutions may themselves create
additional command substitutions (recursion, etc). Creating a read thread
for every command substitution would result in excessive threads. So rather
than a thread per cmdsub, we have a single dedicated thread that handles
ALL command substitutions, by multiplexing multiple file descriptors via
select/poll. This is the "fd monitor." You hand it a file descriptor and it
lets you know when it's readable, and then you can read from it (via a
callback). Also, it has a "wakeup" fd: if you write to that then the fd
monitor wakes up, figures out what it has to do, and resumes.

When the command substitution ends, we need to remove the fd from the fd
monitor, because we intend to close it. You might object "the commands in
the cmdsub have all completed so the write end of the pipe has been closed
so the fd monitor can just notice that the pipe is closed" but it's not so:
consider the horrible case of `set var (yes &)` and abandon all hope.

The current mechanism for removing the fd from the monitor is called a
"poke." We tell the fd monitor (through a "control" self-pipe) to
explicitly wake up the item. It then invokes the callback ("pokes") the
item on the dedicated fd monitor thread. The item notices that the command
substitution is complete, and it returns a value meaning "remove me" and
the fd monitor does so. The client thread is stuck waiting for this process
to complete.

So basically removing a fd from the monitor requires a round trip to its
dedicated thread. This is slow and also complicated (Rust doesn't have
futures)!

So let's not do that.

The big idea is to remove this round-trip synchronization. That is, when we
intend to remove the fd from the fd monitor, we _just do it_ and then close
the fd. Use a lock rather than a round-trip to the thread. Crucially that
lock is unlocked while the monitor thread waits in select/poll.

This invites all sorts of races:

1. fish might remove and close the fd right before the monitor polls it. It
   will thus attempt to poll a closed fd.
2. fish might remove and close the fd, and then something else opens a file
   and receives the same fd. Now the fd monitor will poll an fd that was
   never added.
3. fish might remove and close the fd _while the fd monitor is polling it_.
   What happens then? (Turns out on macOS we get EBADF, and on Linux the fd is
   marked readable).

The Big Idea is that *all of these races are benign*. As long as
poll/select doesn't crash or hang, we don't care *what* it returns, because
the source of truth are the set of items stored in the fd monitor and these
item IDs are never recycled. (This also assumes that it's OK to select/poll
on random file descriptors; there ought to be no side effects).

Not only is this a large simplification since we no longer need that round
trip, it's a substantial performance improvement as well. The
"aliases.fish" benchmark goes from 164 to 154 msec on my Mac, and from 124
to 112 msec on my Linux machine - nearly 10%.

Add some tests to verify our assumptions about the behavior of closing or
replacing a file descriptor during poll. But even if these fail, all we
care about is that poll/select doesn't crash or hang.
2024-12-27 13:23:11 -08:00
Peter Ammon
5e59762117 FdMonitor: Use a HashMap instead of Vec of items
Preparing for a substantial optimization.
2024-12-27 13:23:11 -08:00
Peter Ammon
69fdbc89d6 Refactor FdMonitorItem readability checks
No functional change. Preparing for an optimization.
2024-12-27 13:21:44 -08:00
Peter Ammon
244c55f9ce FdMonitor: change_signaller to be held strongly not weakly
There's no reason to use Weak here, especially since we just unwrap it. There's
no reference cycles, so just share the data via Arc.
2024-12-27 13:21:44 -08:00
Peter Ammon
b7ae159824 Remove the ability for FdMonitorItems to have timeouts
FdMonitor is used to monitor a set of file descriptors and invoke a callback
when one becomes readable. Prior to this commit, they coudl also have the
callback invoked on timeout. fish used to use this feature but no longer does;
remove it.
2024-12-27 13:03:49 -08:00
Peter Ammon
6dad396498 Clean up some stale comments 2024-12-27 13:03:49 -08:00
Fabian Boehm
f5a02e590d Fix tmux-multiline-prompt check 2024-12-27 21:02:38 +01:00
Fabian Boehm
36c632889b pexpects: Fix some escapes
Python has become stricter about unknown `\x` in strings, firing a
SyntaxWarning right now.

They need to be `\\x`.
2024-12-27 20:05:10 +01:00
Dmitry Gerasimov
c473aa60a7 completions/dnf: Fix completions for DNF5 (#9862)
Since DNF5 there's no implicit \n in repoquery output. For DNF4 this change
leaves blank lines in the output, but they are ignored anyway.
2024-12-26 12:01:49 -08:00
David Adam
6515862095 Debian packaging: move comments to their own lines 2024-12-26 14:53:04 +08:00
phanium
94dfe1b053 Fix alt-e cursor position restore on Vim <= 8 (#10946) 2024-12-26 06:35:37 +01:00
David Adam
0b52b72ebc Debian packaging: comment on reason for runtime dependencies 2024-12-26 13:22:30 +08:00
David Adam
eade6a5672 Debian packaging: add some missing runtime dependencies 2024-12-26 13:21:33 +08:00
David Adam
044cea1bf3 update CMake requirement
find_rust uses LIST(POP_BACK), which was added in 3.15.
2024-12-26 13:20:00 +08:00
David Adam
74b1247461 Debian packaging: reformat dependencies 2024-12-26 13:19:41 +08:00
Fabian Boehm
9b8793a2df docs: Use grid in the CSS (#10942)
Instead of hardcoded 230px margin.

This also makes the ToC only take up a third of the screen when
narrow, and lets you scroll the rest.

Without, you'd have to scroll past the *entire* ToC, which is awkward

Remaining issue is the search box up top. Since this disables the one
in the sidebar once the window gets too narrow, that one is important,
and it isn't *great*
2024-12-25 14:50:27 +01:00
Blair Noctis
6c63139d23 refactor: macroize SIGNAL_TABLE entries
reducing boilerplate and chance of typo
2024-12-24 15:25:10 +01:00
Mahmoud Al-Qudsi
f3dd4ee022 Fix typo in hard-coded name of SIGSTKFLT 2024-12-23 14:29:00 -06:00
Mahmoud Al-Qudsi
7bafb0d1ae CHANGELOG: Fix Sphinx error on unnamed section 2024-12-23 13:54:21 -06:00
Mahmoud Al-Qudsi
46072e0fd6 completions/llm: Add completions for all subcommands 2024-12-23 13:50:10 -06:00
Mahmoud Al-Qudsi
c09a9246a1 completions/llm: Fix broken completion 2024-12-23 13:47:19 -06:00
Fabian Boehm
e2596d13cd Remove SIGUNUSED
It is, as the name implies, unused - it became SIGSYS, which we
already check.

Since it is entirely undefined on some architectures it causes a build
failure there, see discussion in #10633
2024-12-23 17:06:22 +01:00
Johannes Altmanninger
0153579a4c Fix build in non-colocated jj workspaces 2024-12-23 15:14:13 +01:00
Johannes Altmanninger
c1b460525c Temporary workaround for BSD WEXITSTATUS libc bug
The libc crate has a bug on BSD where WEXITSTATUS is not an 8-bit
value, causing assertion failures.

Any libc higher than our 0.2.155 would increase our MSRV, see libc
commit 5ddbdc29f (Bump MSRV to 1.71, 2024-01-07), so we want to
woraround this anyway.  It's probably not worth using a patched
version of libc since it's just one line.

While at it, tighten some types I guess.

Upstream fix: https://github.com/rust-lang/libc/pull/4213

Closes #10919
2024-12-23 14:34:59 +01:00
Johannes Altmanninger
5de6f4bb3d Provide old implementation of cancel-commandline as fallback
__fish_cancel_commandline was unused (even before) and has some issues
on multiline commandlines. Make it use the previously active logic.

Closes #10935
2024-12-23 14:34:59 +01:00
Johannes Altmanninger
54cc932215 Attempt to fix clippy lints 2024-12-23 14:34:59 +01:00
Johannes Altmanninger
e3864c752a Changelog: move integration branch entries there
See f237fb7b on the integration branch.
2024-12-23 14:34:59 +01:00
Johannes Altmanninger
03a9f4a775 sourcehut builds: remove obsolete "env"
As of efe4083dce (fish.spec/.builds: drop SHOW_INTERACTIVE_LOG,
2022-06-08) this is no longer necessary.
2024-12-23 08:40:02 +01:00
Johannes Altmanninger
7e5af914be Remove interactive-only completion hacks
I don't think these characters cause problems in filenames?
2024-12-23 08:40:02 +01:00
Johannes Altmanninger
ab4606430e Sort parser keywords 2024-12-23 08:40:02 +01:00
Fabian Boehm
774b7c7b5b staticbuilds: Make mac builds statically linked
This is the default on musl, but not other libcen
2024-12-22 22:25:27 +01:00
Fabian Boehm
6b1a9ef7ce staticbuilds: Add macos job 2024-12-22 22:21:42 +01:00
Fabian Boehm
c74afd4198 CHANGELOG 2024-12-22 18:16:07 +01:00
Fabian Boehm
3dc49d9d93 Allow installable builds to be installed into a specific path (#10923)
* Pass path to install()

It was dirty that it would re-get $HOME there anyway.

* Import wcs2osstring

* Allow installable builds to use a relocatable tree

If you give a path to `--install`, it will install fish into a
relocatable tree there, so

PATH/share/fish contains the datafiles
PATH/bin/fish contains the fish executable
PATH/etc/fish is sysconf

I am absolutely not sold on that last one - the way I always used
sysconfdir is that it is always /etc. This would be easy to fix but
should probably also be fixed for "regular" relocatable builds (no
idea who uses them).

An attempt at #10916

* Move install path into "install/" subdir

* Disable --install harder if not installable
2024-12-22 18:16:07 +01:00
Integral
b19a467ea6 Replace some PathBuf with Path avoid unnecessary heap allocation (#10929) 2024-12-21 12:34:27 -06:00
Johannes Altmanninger
381b38af0a Skip tmux multiline prompt test for BusyBox less
BusyBox less is present on alpine CI; it doesn't support the "+q"
command passing style, so it's not directly usable by this test.
2024-12-21 14:41:41 +01:00
Johannes Altmanninger
965bc78d33 Work around weird CI failures due to missing pre-execute \r\n
I forgot that 610338cc70 (On undo after execute, restore the cursor
position, 2024-12-21) would cause a fallout to tests:

It makes us reuse in another place our usual cursor-movement sequences.

This causes failures like this (linebreaks added for readability):

	Testing file pexpects/bind.py:Failed to match pattern: (?:\r\n|\x1b\[2 q)[^\n]*def abc\r\n
	bind.py:45: timeout from expect_prompt(TO_END + "def abc\r\n")  # emacs transpose words, default timeout: no delay

	Escaped buffer:
	\x1b[?2004h\x1b[>4;1m\x1b[=5u\x1b=\rprompt 2>echo \rprompt 2>echo abc \rprompt 2>echo def abc\r
	prompt 2>echo def abc\x1b[?2004l\x1b[>4;0m\x1b[=0u\x1b>\x1b]133;C\x07def abc\r\n\x1b]133;D;0\x07\x1b[?25h⏎
	\r⏎ \r\rprompt 3>\x1b[?2004h\x1b[>4;1m\x1b[=5u\x1b=

It seems that we don't print anything where we should print something
like "\r\n" or "\e[2 q" to move the cursor below the command line.

I haven't gotten to the bottom of this but it might be related to
terminfo. Once we get rid of that, we can unconditionally print
our canonical movement sequences.

This issue seems to only affect tests, since fish operates fine in
a sourcehut CI system. Let's ignore it for now.
2024-12-21 14:37:57 +01:00
Johannes Altmanninger
610338cc70 On undo after execute, restore the cursor position
Ever since 149594f974 (Initial revision, 2005-09-20), we move the
cursor to the end of the commandline just before executing it.

This is so we can move the cursor to the line below the command line,
so moving the cursor is relevant if one presses enter on say, the
first line of a multi-line commandline.

As mentioned in #10838 and others, it can be useful to restore the
cursor position when recalling commandline from history. Make undo
restore the position where enter was pressed, instead of implicitly
moving the cursor to the end. This allows to quickly correct small
mistakes in large commandlines that failed recently.

This requires a new way of moving the cursor below the command line.
Test changes include unrelated cleanup of history.py.
2024-12-21 13:10:34 +01:00
Johannes Altmanninger
f9fb026085 Document possible CMake/Rust versions usable for Git bisect
rustc and CMake are usually backwards compatible but with Corrosion
in the mix this is often not the case.
Here's the canonical place to document it.
2024-12-21 13:07:01 +01:00
224 changed files with 3398 additions and 2807 deletions

View File

@@ -24,4 +24,4 @@ tasks:
ninja
- test: |
cd fish-shell/build
env ninja test
ninja test

View File

@@ -20,4 +20,4 @@ tasks:
ninja
- test: |
cd fish/build
env ninja test
ninja test

View File

@@ -20,7 +20,6 @@ linux_task:
# container:
# <<: *step
# image: ghcr.io/krobelus/fish-ci/focal-32bit:latest
tests_script:
# cirrus at times gives us 32 procs and 2 GB of RAM
# Unrestriced parallelism results in OOM
@@ -30,7 +29,6 @@ linux_task:
- cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCTEST_PARALLEL_LEVEL=6 ..
- ninja -j 6 fish
- ninja fish_run_tests
only_if: $CIRRUS_REPO_OWNER == 'fish-shell'
linux_arm_task:
@@ -41,7 +39,6 @@ linux_arm_task:
- name: jammy-armv7-32bit
arm_container:
image: ghcr.io/fish-shell/fish-ci/jammy-armv7-32bit
tests_script:
# cirrus at times gives us 32 procs and 2 GB of RAM
# Unrestriced parallelism results in OOM
@@ -52,7 +49,6 @@ linux_arm_task:
- ninja -j 6 fish
- file ./fish
- ninja fish_run_tests
# CI task disabled during RIIR transition
only_if: false && $CIRRUS_REPO_OWNER == 'fish-shell'
@@ -92,5 +88,4 @@ freebsd_task:
- sudo -u fish-user -s cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCTEST_PARALLEL_LEVEL=1 ..
- sudo -u fish-user sh -c '. $HOME/.cargo/env; ninja -j 6 fish'
- sudo -u fish-user sh -c '. $HOME/.cargo/env; ninja fish_run_tests'
only_if: $CIRRUS_REPO_OWNER == 'fish-shell'

View File

@@ -22,7 +22,7 @@ indent_size = 2
indent_size = 2
[share/{completions,functions}/**.fish]
max_line_length = off
max_line_length = unset
[{COMMIT_EDITMSG,git-revise-todo}]
max_line_length = 80

View File

@@ -1,4 +1,4 @@
name: make fish_run_tests
name: make test
on: [push, pull_request]
@@ -29,7 +29,7 @@ jobs:
- name: make
run: |
make VERBOSE=1
- name: make fish_run_tests
- name: make test
run: |
make VERBOSE=1 test
@@ -55,7 +55,7 @@ jobs:
- name: make
run: |
make VERBOSE=1
- name: make fish_run_tests
- name: make test
run: |
make VERBOSE=1 test
@@ -93,7 +93,7 @@ jobs:
- name: make
run: |
make VERBOSE=1
- name: make fish_run_tests
- name: make test
env:
FISH_CI_SAN: 1
ASAN_OPTIONS: check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=1:fast_unwind_on_malloc=0
@@ -133,9 +133,9 @@ jobs:
# - name: make
# run: |
# make
# - name: make fish_run_tests
# - name: make test
# run: |
# make fish_run_tests
# make test
macos:
@@ -161,6 +161,6 @@ jobs:
- name: make
run: |
make VERBOSE=1
- name: make fish_run_tests
- name: make test
run: |
make VERBOSE=1 test

View File

@@ -12,7 +12,7 @@ env:
CMAKE_BUILD_PARALLEL_LEVEL: "4"
jobs:
staticbuilds:
staticbuilds-linux:
runs-on: ubuntu-latest
@@ -29,19 +29,55 @@ jobs:
sudo apt install python3-sphinx
rustup target add x86_64-unknown-linux-musl
rustup target add aarch64-unknown-linux-musl
sudo apt install musl-tools crossbuild-essential-arm64 -y
sudo apt install musl-tools crossbuild-essential-arm64 python3-pexpect tmux -y
- name: Build
run: |
CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2" CMAKE_WITH_GETTEXT=0 CC=aarch64-linux-gnu-gcc RUSTFLAGS="-C linker=aarch64-linux-gnu-gcc -C link-arg=-lgcc -C link-arg=-D_FORTIFY_SOURCE=0" cargo build --release --target aarch64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-musl
- name: Test
run: |
FISHDIR=target/x86_64-unknown-linux-musl/release/ tests/test_driver.sh tests/test.fish
FISHDIR=target/x86_64-unknown-linux-musl/release/ tests/test_driver.sh tests/interactive.fish
- name: Compress
run: |
tar -cazf fish-amd64.tar.xz -C target/x86_64-unknown-linux-musl/release/ fish{,_indent,_key_reader}
tar -cazf fish-aarch64.tar.xz -C target/aarch64-unknown-linux-musl/release/ fish{,_indent,_key_reader}
- uses: actions/upload-artifact@v4
with:
name: fish
name: fish-static-linux
path: |
fish-amd64.tar.xz
fish-aarch64.tar.xz
retention-days: 14
staticbuilds-macos:
runs-on: macos-latest
permissions:
contents: read
steps:
- uses: dtolnay/rust-toolchain@1.70
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Prepare
run: |
sudo pip3 install --break-system-packages sphinx
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
- name: Build
run: |
RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target aarch64-apple-darwin
RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-apple-darwin
- name: Compress
run: |
tar -cazf fish-macos-aarch64.tar.xz -C target/aarch64-apple-darwin/release/ fish{,_indent,_key_reader}
tar -cazf fish-macos-amd64.tar.xz -C target/x86_64-apple-darwin/release/ fish{,_indent,_key_reader}
- uses: actions/upload-artifact@v4
with:
name: fish-static-macos
path: |
fish-macos-amd64.tar.xz
fish-macos-aarch64.tar.xz
retention-days: 14

3
.gitignore vendored
View File

@@ -102,3 +102,6 @@ target/
# Generated by clangd
/.cache
# JetBrains editors.
.idea/

View File

@@ -31,7 +31,7 @@ PREFIX?=/usr/local
build/fish: build/$(BUILDFILE)
$(CMAKE) --build build
# Don't split the mkdir into its own rule because that would cause CMake to regenerate the build
# Don't split the mkdir into its own rule because that would cause CMake to regenerate the build
# files after each build (because it adds the mdate of the build directory into the out-of-date
# calculation tree). GNUmake supports order-only dependencies, BSDmake does not seem to.
build/$(BUILDFILE):
@@ -48,11 +48,7 @@ clean:
.PHONY: test
test: build/fish
$(CMAKE) --build build --target fish_run_tests
.PHONY: fish_run_tests
fish_run_tests: build/fish
$(CMAKE) --build build --target fish_run_tests
$(CMAKE) --build build --target test
.PHONY: run
run: build/fish

View File

@@ -1,7 +1,54 @@
fish 4.0.0 (released February 27, 2025)
fish 4.1.0 (released ???)
=========================
Notable improvements and fixes
------------------------------
Deprecations and removed features
---------------------------------
Scripting improvements
----------------------
Interactive improvements
------------------------
- Autosuggestions are now also provided in multi-line command lines. Like `ctrl-r`, autosuggestions operate only on the current line.
- New feature flag ``buffered-enter-noexec`` with the following effect:
when typing a command and :kbd:`enter` while the previous one is still running, the new one will no longer execute immediately. Similarly, keys that are bound to shell commands will be ignored.
This mitigates a security issue where a command like ``cat malicious-file.txt`` could write terminal escape codes prompting the terminal to write arbitrary text to fish's standard input.
Such a malicious file can still potentially insert arbitrary text into the command line but can no longer execute it directly (:issue:`10987`).
New or improved bindings
^^^^^^^^^^^^^^^^^^^^^^^^
- :kbd:`ctrl-z` (undo) after executing a command will restore the previous cursor position instead of placing the cursor at the end of the command line.
- The OSC 133 prompt marking feature has learned about kitty's ``click_events=1`` flag, which allows moving fish's cursor by clicking.
- :kbd:`ctrl-l` no longer clears the screen but only pushes to the terminal's scrollback all text above the prompt (via a new special input function ``scrollback-push``).
This feature depends on the terminal advertising via XTGETTCAP support for the ``indn`` and ``cuu`` terminfo capabilities,
and on the terminal supporting Synchronized Output (which is used by fish to detect features).
If any is missing, the binding falls back to ``clear-screen``.
Completions
^^^^^^^^^^^
Improved terminal support
^^^^^^^^^^^^^^^^^^^^^^^^^
Other improvements
------------------
For distributors
----------------
fish 4.0b1 (released December 17, 2024)
=======================================
fish's core code has been ported from C++ to Rust (:issue:`9512`). This means a large change in dependencies and how to build fish. However, there should be no direct impact on users. Packagers should see the :ref:`For Distributors <rust-packaging>` section at the end.
These are the draft release notes for fish 4.0.0. Like this release of fish itself, they are in beta and are not complete. Please report any issues you find.
.. ignore: 751 2037 2037 3017 3018 3162 3299 4770 4865 5284 5991 6981 6996 7172 9332 9439 9440 9442 9452 9469 9480 9482 9520 9536 9541 9542 9544 9554 9556 9559 9561 9563 9566 9567 9568 9573 9575 9576 9579 9585 9586 9588 9589 9591 9592 9593 9594 9599 9600 9603 9607 9608 9612 9613 9615 9616 9619 9621 9625 9626 9630 9636 9637 9638 9641 9642 9643 9653 9654 9658 9661 9666 9671 9673 9688 9725 9726 9729 9735 9739 9745 9746 9751 9754 9765 9767 9768 9771 9777 9778 9786 9816 9818 9821 9839 9845 9856 9859 9861 9863 9864 9867 9869 9873 9874 9879 9881 9893 9894 9896 9902 9916 9923 9925 9927 9928 9930 9947 9948 9950 9952 9962 9963 9966 9968 9980 9981 9984 9990 9991 10040 10061 10090 10101 10102 10108 10114 10115 10121 10128 10129 10143 10145 10146 10161 10173 10174 10175 10179 10180 10181 10182 10184 10185 10186 10188 10195 10198 10200 10201 10204 10210 10214 10219 10220 10222 10223 10227 10228 10232 10235 10237 10241 10243 10244 10245 10246 10251 10254 10260 10263 10267 10268 10270 10272 10276 10277 10278 10279 10281 10288 10290 10291 10293 10305 10306 10307 10308 10309 10316 10317 10321 10327 10328 10329 10330 10336 10338 10340 10342 10345 10346 10347 10348 10349 10353 10354 10355 10356 10357 10358 10360 10366 10368 10370 10371 10372 10373 10377 10379 10381 10388 10389 10390 10395 10398 10400 10403 10404 10407 10408 10409 10411 10412 10415 10417 10418 10427 10429 10434 10438 10439 10440 10441 10442 10443 10445 10446 10448 10450 10451 10452 10456 10457 10462 10463 10464 10466 10467 10471 10473 10474 10479 10481 10485 10486 10487 10490 10491 10492 10494 10499 10500 10503 10505 10507 10508 10509 10510 10511 10512 10513 10518 10519 10520 10524 10528 10529 10530 10538 10541 10542 10547 10548 10549 10555 10560 10562 10564 10565 10568 10569 10572 10573 10574 10575 10578 10580 10582 10583 10588 10591 10594 10595 10596 10609 10622 10623 10627 10628 10634 10635 10636 10637 10640 10646 10647 10649 10650 10652 10653 10654 10655 10657 10659 10662 10664 10667 10669 10670 10674 10679 10681 10685 10686 10687 10688 10689 10697 10698 10702 10707 10708 10712 10713 10716 10718 10719 10721 10726 10727 10728 10731 10760 10762 10763 10767 10770 10775 10776 10778 10779 10782 10784 10789 10792 10795 10796 10801 10812 10817 10825 10836 10839 10844 10845 10847 10851 10858 10863 10864 10873 10874 10880 10885 10891 10894 10907
fish's core code has been ported from C++ to Rust (:issue:`9512`).
This means a large change in dependencies and how to build fish.
Packagers should see the :ref:`For Distributors <rust-packaging>` section at the end.
Notable backwards-incompatible changes
--------------------------------------
@@ -9,7 +56,10 @@ Notable backwards-incompatible changes
- As part of a larger binding rework, ``bind`` gained a new key notation.
In most cases the old notation should keep working, but in rare cases you may have to change a ``bind`` invocation to use the new notation.
See :ref:`below <changelog-new-bindings>` for details.
- :kbd:`ctrl-c` now calls a new bind function called ``clear-commandline``. The old behavior, which leaves a "^C" marker, is available as ``cancel-commandline`` (:issue:`10935`)
- Terminals that fail to ignore unrecognized OSC or CSI sequences may display garbage. We know cool-retro-term and emacs' ansi-term are affected,
most mainstream terminals are not.
- :kbd:`alt-left` and :kbd:`alt-right` will now move by one argument (which may contain quoted spaces), not just one word like :kbd:`ctrl-left` and :kbd:`ctrl-right` do.
- :kbd:`alt-backspace` will delete an entire argument, not just one word. The old word behavior has been moved to :kbd:`ctrl-backspace`. If your terminal doesn't support `ctrl-backspace`, consider using :kbd:`ctrl-w`, or :kbd:`alt-b` + :kbd:`alt-d`.
- ``random`` will produce different values from previous versions of fish when used with the same seed, and will work more sensibly with small seed numbers.
The seed was never guaranteed to give the same result across systems,
so we do not expect this to have a large impact (:issue:`9593`).
@@ -24,9 +74,8 @@ Notable backwards-incompatible changes
set -Ua fish_features no-qmark-noglob
The flag will eventually be made read-only, making it impossible to turn off.
- Terminals that fail to ignore unrecognized OSC or CSI sequences may display garbage. We know cool-retro-term and emacs' ansi-term are affected, but most mainstream terminals are not.
- fish no longer searches directories from the Windows system/user ``$PATH`` environment variable for Linux executables. To execute Linux binaries by name (i.e. not with a relative or absolute path) from a Windows folder, make sure the ``/mnt/c/...`` path is explicitly added to ``$fish_user_paths`` and not just automatically appended to ``$PATH`` by ``wsl.exe`` (:issue:`10506`).
- Under Microsoft Windows Subsystem for Linux 1 (not WSL 2), backgrounded jobs that have not been disowned and do not terminate on their own after a ``SIGHUP`` + ``SIGCONT`` sequence will be explicitly killed by fish on exit (after the usual prompt to close or disown them) to work around a WSL 1 deficiency that sees backgrounded processes that run into ``SIGTTOU`` remain in a suspended state indefinitely (:issue:`5263`). The workaround is to explicitly ``disown`` processes you wish to outlive the shell session.
- Under Microsoft Windows Subsystem for Linux 1 (not WSL 2) , backgrounded jobs that have not been disowned and do not terminate on their own after a ``SIGHUP`` + ``SIGCONT`` sequence will be explicitly killed by fish on exit (after the usual prompt to close or disown them) to work around a WSL 1 deficiency that sees backgrounded processes that run into ``SIGTTOU`` remain in a suspended state indefinitely (:issue:`5263`). The workaround is to explicitly ``disown`` processes you wish to outlive the shell session.
Notable improvements and fixes
------------------------------
@@ -43,30 +92,23 @@ Notable improvements and fixes
- ``bind ctrl-x,alt-c 'do something'`` binds a sequence of two keys.
Any key argument that starts with an ASCII control character (like ``\e`` or ``\cX``) or is up to 3 characters long, not a named key, and does not contain ``,`` or ``-`` will be interpreted in the old syntax to keep compatibility for the majority of bindings.
Keyboard protocols can be turned off by disabling the "keyboard-protocols" feature flag::
set -Ua fish_features no-keyboard-protocols
This is a temporary measure to work around buggy terminals (:issue:`11056`), which appear to be relatively rare.
Use this if something like "=0" or "=5u" appears in your commandline mysteriously.
- fish can now be built as a self-installing binary (:issue:`10367`). That means it can be easily built on one system and copied to another, where it can extract supporting files.
To do this, run::
cargo install --path . # in a clone of the fish repository
# or `cargo build --release` and copy target/release/fish{,_indent,_key_reader} wherever you want
The first time it runs interactively, it will extract all the data files to ``~/.local/share/fish/install/``. A specific path can be used for the data files with ``fish --install=PATH`` To uninstall, remove the fish binaries and that directory.
The first time it runs interactively, it will extract all the data files to ``~/.local/share/fish/install/``. To uninstall, remove the fish binaries and that directory.
This build system is experimental; the main build system, using ``cmake``, remains the recommended approach for packaging and installation to a prefix.
- A new function ``fish_should_add_to_history`` can be overridden to decide whether a command should be added to the history (:issue:`10302`).
- :kbd:`ctrl-c` during command input no longer prints ``^C`` and a new prompt, but merely clears the command line. This restores the behavior from version 2.2. To revert to the old behavior, use ``for mode in (bind --list-modes); bind -M $mode ctrl-c cancel-commandline-traditional; end`` (:issue:`10213`).
- Bindings can now mix special input functions and shell commands, so ``bind ctrl-g expand-abbr "commandline -i \n"`` works as expected (:issue:`8186`).
- Special input functions run from bindings via ``commandline -f`` are now applied immediately, instead of after the currently executing binding (:issue:`3031`, :issue:`10126`).
- Special input functions run from bindings via ``commandline -f`` are now applied immediately, instead of after the currently executing binding (:issue:`3031`).
For example, ``commandline -i foo; commandline | grep foo`` succeeds now.
- Undo history is no longer truncated after every command, but kept for the lifetime of the shell process.
- The :kbd:`ctrl-r` history search now uses glob syntax (:issue:`10131`).
- The :kbd:`ctrl-r` history search now operates only on the line or command substitution at cursor, making it easier to combine commands from history (:issue:`9751`).
- The :kbd:`ctrl-r` history search now operates only on the line or command substitution at cursor, making it easier to combine commands from history.
- Abbreviations can now be restricted to specific commands. For instance::
abbr --add --command git back 'reset --hard HEAD^'
@@ -96,7 +138,6 @@ Deprecations and removed features
If this happens, you can use the ``reset`` command from ``ncurses`` to restore the terminal state.
- ``fish_key_reader --verbose`` no longer shows timing information.
- Terminal information is no longer read from hashed terminfo databases, or termcap databases (:issue:`10269`). The vast majority of systems use a non-hashed terminfo database, which is still supported.
- ``source`` returns an error if used without a filename or pipe/redirection (:issue:`10774`).
Scripting improvements
----------------------
@@ -123,8 +164,6 @@ Scripting improvements
- A new ``path basename -E`` option that causes it to return the basename ("filename" with the directory prefix removed) with the final extension (if any) also removed. This is a shorter version of ``path change-extension "" (path basename $foo)`` (:issue:`10521`).
- A new ``math --scale-mode`` option to select ``truncate``, ``round``, ``floor``, ``ceiling`` as you wish; the default value is ``truncate``. (:issue:`9117`).
- ``random`` is now less strict about its arguments, allowing a start larger or equal to the end. (:issue:`10879`)
- ``function --argument-names`` now produces an error if a read-only variable name is used, rather than simply ignoring it (:issue:`10842`).
- Tilde expansion in braces (that is, ``{~,}``) works correctly (:issue:`10610`).
Interactive improvements
------------------------
@@ -144,20 +183,11 @@ Interactive improvements
- Measuring a command with ``time`` now considers the time taken for command substitution (:issue:`9100`).
- ``fish_add_path`` now automatically enables verbose mode when used interactively (in the command line), in an effort to be clearer about what it does (:issue:`10532`).
- fish no longer adopts TTY modes of failed commands (:issue:`10603`).
- ``complete -e cmd`` now prevents autoloading completions for ``cmd`` (:issue:`6716`).
- `complete -e cmd` now prevents autoloading completions for `cmd` (:issue:`6716`).
- fish's default color scheme no longer uses the color "blue", as it has bad contrast against the background in a few terminal's default palettes (:issue:`10758`, :issue:`10786`)
The color scheme will not be upgraded for existing installs. If you want, you should select it again via ``fish_config``.
- Command lines which are larger than the terminal are now displayed correctly, instead of multiple blank lines being displayed (:issue:`7296`).
- Prompts that use external commands will no longer produce an infinite loop if the command crashes (:issue:`9796`).
- Undo (:kbd:`ctrl-z`) restores the cursor position too (:issue:`10838`).
- The output of ``jobs`` shows "-" for jobs that have the same process group ID as the fish process, rather than "-2" (:issue:`10833`).
- Job expansion (``%1`` syntax) works properly for jobs that are a mixture of external commands and functions (:issue:`10832`).
- Command lines which have more lines than the terminal can be displayed and edited correctly (:issue:`10827`).
- Functions that have been erased are no longer highlighted as valid commands (:issue:`10866`).
- ``not``, ``time``, and variable assignments (that is ``not time a=b env``) is correctly recognized as valid syntax (:issue:`10890`).
- The Web-based configuration removes old right-hand-side prompts again, fixing a regression in fish 3.4.0 (:issue:`10675`).
- Further protection against programs which crash and leave the terminal in an inconsistent state (:issue:`10834`, :issue:`11038`).
- A workaround for git being very slow on macOS has been applied, improving performance after a fresh boot (:issue:`10535`).
New or improved bindings
^^^^^^^^^^^^^^^^^^^^^^^^
@@ -165,6 +195,7 @@ New or improved bindings
- During up-arrow history search, :kbd:`shift-delete` will delete the current search item and move to the next older item. Previously this was only supported in the history pager.
- :kbd:`shift-delete` will also remove the currently-displayed autosuggestion from history, and remove it as a suggestion.
- :kbd:`ctrl-Z` (also known as :kbd:`ctrl-shift-z`) is now bound to redo.
- :kbd:`alt-delete` now deletes the argument (which may contain quoted spaces) right of the cursor.
- Some improvements to the :kbd:`alt-e` binding which edits the command line in an external editor:
- The editor's cursor position is copied back to fish. This is currently supported for Vim and Kakoune.
- Cursor position synchronization is only supported for a set of known editors, which are now also detected in aliases which use ``complete --wraps``. For example, use ``complete --wraps my-vim vim`` to synchronize cursors when ``EDITOR=my-vim``.
@@ -179,22 +210,18 @@ New or improved bindings
- :kbd:`ctrl-delete` deletes the next word (same as :kbd:`alt-d`).
- New special input functions:
- ``forward-char-passive`` and ``backward-char-passive`` are like their non-passive variants but do not accept autosuggestions or move focus in the completion pager (:issue:`10398`).
- ``forward-token``, ``backward-token``, ``kill-token``, and ``backward-kill-token`` are similar to the ``*-bigword`` variants but for the whole argument token (which includes escaped spaces) (:issue:`2014`).
- ``clear-commandline``, which merely clears the command line, as an alternative to ``cancel-commandline`` which prints ``^C`` and a new prompt (:issue:`10213`).
- ``forward-token``, ``backward-token``, ``kill-token``, and ``backward-kill-token`` are similar to the ``*-bigword`` variants but for the whole argument token which includes escaped spaces (:issue:`2014`).
- The ``accept-autosuggestion`` special input function now returns false when there was nothing to accept (:issue:`10608`).
- Vi mode has seen some improvements but continues to suffer from the lack of people working on it.
- New default cursor shapes for insert and replace mode.
- :kbd:`ctrl-n` in insert mode accepts autosuggestions (:issue:`10339`).
- Insert-mode :kbd:`ctrl-n` accepts autosuggestions (:issue:`10339`).
- Outside insert mode, the cursor will no longer be placed beyond the last character on the commandline.
- When the cursor is at the end of the commandline, a single :kbd:`l` will accept an autosuggestion (:issue:`10286`).
- The cursor position after pasting (:kbd:`p`) has been corrected.
- Added an additional binding, :kbd:`_`, for moving to the beginning of the line (:issue:`10720`).
- When the cursor is at the start of a line, escaping from insert mode no longer moves the cursor to the previous line.
- Added bindings for clipboard interaction, like :kbd:`",+,p` and :kbd:`",+,y,y`.
- Deleting in visual mode now moves the cursor back, matching vi (:issue:`10394`).
- The :kbd:`;`, :kbd:`,`, :kbd:`v`, :kbd:`V`, :kbd:`I`, and :kbd:`gU` bindings work in visual mode (:issue:`10601`, :issue:`10648`).
- Support :kbd:`%` motion (:issue:`10593`).
- :kbd:`ctrl-k` to remove the contents of the line beyond the cursor in all modes (:issue:`10648`).
- Support `ab` and `ib` vi text objects. New input functions are introduced ``jump-{to,till}-matching-bracket`` (:issue:`1842`).
- The :kbd:`E` binding now correctly handles the last character of the word, by jumping to the next word (:issue:`9700`).
@@ -204,16 +231,13 @@ Completions
- Option completion now uses fuzzy subsequence filtering, just like non-option completion (:issue:`830`).
This means that ``--fb`` may be completed to ``--foobar`` if there is no better match.
- Completions that insert an entire token now use quotes instead of backslashes to escape special characters (:issue:`5433`).
- Normally, file name completions start after the last ``:`` or ``=`` in a token.
- Historically, file name completions are provided after the last ``:`` or ``=`` within a token.
This helps commands like ``rsync --files-from=``.
This special meaning can now disabled by escaping these separators as ``\:`` and ``\=``.
If the ``=`` or ``:`` is actually part of the filename, it will be escaped as ``\:`` and ``\=``,
and no longer get this special treatment.
This matches Bash's behavior.
Note that this escaping is usually not necessary since the completion engine already tries
to guess whether the separator is actually part of a file name.
- Various new completion scripts and numerous updates to existing ones.
- Completions could hang if the ``PAGER`` environment variable was sent to certain editors on macOS, FreeBSD and some other platforms. This has been fixed (:issue:`10820`).
- Generated completions are now stored in ``$XDG_CACHE_HOME/fish`` or ``~/.cache/fish`` by default (:issue:`10369`)
- A regression in fish 3.1, where completing a command line could change it completely, has been fixed (:issue:`10904`).
Improved terminal support
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,14 +253,10 @@ Improved terminal support
Other improvements
------------------
- ``status`` gained a ``buildinfo`` subcommand, to print information on how fish was built, to help with debugging (:issue:`10896`).
- ``fish_indent`` will now collapse multiple empty lines into one (:issue:`10325`).
- ``fish_indent`` now preserves the modification time of files if there were no changes (:issue:`10624`).
- Performance in launching external processes has been improved for many cases (:issue:`10869`).
- Performance and interactivity under Windows Subsystem for Linux has been improved, with a workaround for Windows-specific locations being appended to ``$PATH`` by default (:issue:`10506`).
- On macOS, paths from ``/etc/paths`` and ``/etc/manpaths`` containing colons are handled correctly (:issue:`10684`).
- Additional filesystems such as AFS are properly detected as remote, which avoids certain hangs due to expensive filesystem locks (:issue:`10818`).
- A spurious error when launching multiple instances of fish for the first time has been removed (:issue:`10813`).
.. _rust-packaging:
@@ -245,23 +265,10 @@ For distributors
fish has been ported to Rust. This means a significant change in dependencies, which are listed in the README. In short, Rust 1.70 or greater is required, and a C++ compiler is no longer needed (although a C compiler is still required, for some C glue code and the tests).
CMake remains the recommended build system, because of cargo's limited support for installing support files. Version 3.5 remains the minimum supported version. The Xcode generator for CMake is not supported any longer (:issue:`9924`). CMake builds default to optimized release builds (:issue:`10799`).
CMake remains the recommended build system, because of cargo's limited support for installing support files. Version 3.5 remains the minimum supported version. The Xcode generator for CMake is not supported any longer (:issue:`9924`)
fish no longer depends on the ncurses library, but still uses a terminfo database. When packaging fish, please add a dependency on the package containing your terminfo database instead of curses.
The ``test`` target was removed as it can no longer be defined in new CMake versions. Use ``make fish_run_tests``. Any existing test target will not print output if it fails (:issue:`11116`).
The Web-based configuration has been rewritten to use Alpine.js (:issue:`9554`).
--------------
fish 4.0b1 (released December 17, 2024)
=======================================
A number of improvements were included in fish 4.0.0 following the beta release of 4.0b1. These include fixes for regressions, improvements to completions and documentation, and the removal of a small number of problematic changes.
The full list of fixed issues can be found on the `GitHub milestone page for 4.0-final <https://github.com/fish-shell/fish-shell/milestone/43>`_.
--------------
fish 3.7.1 (released March 19, 2024)

View File

@@ -81,8 +81,6 @@ create_target(fish_key_reader)
# Set up the docs.
include(cmake/Docs.cmake)
# A helper for running tests.
add_executable(fish_test_helper src/fish_test_helper.c)
# Set up tests.
include(cmake/Tests.cmake)

View File

@@ -126,4 +126,3 @@ enforcement ladder](https://github.com/mozilla/diversity).
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -43,7 +43,7 @@ Guidelines
In short:
- Be conservative in what you need (keep to the agreed minimum supported Rust version, limit new dependencies)
- Use automated tools to help you (including ``make fish_run_tests`` and ``build_tools/style.fish``)
- Use automated tools to help you (including ``make test`` and ``build_tools/style.fish``)
Contributing completions
========================
@@ -196,8 +196,13 @@ The tests can be found in three places:
- tests/pexpects for interactive tests using `pexpect <https://pexpect.readthedocs.io/en/stable/>`__
When in doubt, the bulk of the tests should be added as a littlecheck test in tests/checks, as they are the easiest to modify and run, and much faster and more dependable than pexpect tests. The syntax is fairly self-explanatory. It's a fish script with the expected output in ``# CHECK:`` or ``# CHECKERR:`` (for stderr) comments.
If your littlecheck test has a specific dependency, use ``# REQUIRE: ...`` with a posix sh script.
The pexpects are written in python and can simulate input and output to/from a terminal, so they are needed for anything that needs actual interactivity. The runner is in build_tools/pexpect_helper.py, in case you need to modify something there.
Tests are run in a temporary $HOME, but that is shared among the tests by default. If you need a temporary directory for your test, you should create one (e.g. with ``mktemp``).
The pexpects are written in python and can simulate input and output to/from a terminal, so they are needed for anything that needs actual interactivity. The runner is in tests/pexpect_helper.py, in case you need to modify something there.
If you need a command to do something weird to test something, maybe add it to the ``fish_test_helper`` binary (in tests/fish_test_helper.c), or see if it can already do it.
Local testing
-------------
@@ -207,7 +212,16 @@ The tests can be run on your local computer on all operating systems.
::
cmake path/to/fish-shell
make fish_run_tests
make test
Or you can run them on a fish, without involving cmake::
cargo build
FISHDIR=target/debug tests/test_driver.sh tests/test.fish # script tests, the checks
FISHDIR=target/debug tests/test_driver.sh tests/interactive.fish # interactive tests, the pexpects
Here, ``FISHDIR`` refers to a directory with ``fish``, ``fish_indent`` and ``fish_key_reader`` in it.
In this example we're in the root of the git repo and have run ``cargo build`` without ``--release``, so it's a debug build.
Git hooks
---------
@@ -235,7 +249,7 @@ One possibility is a pre-push hook script like this one:
done
if [ "x$isprotected" = x1 ]; then
echo "Running tests before push to master"
make fish_run_tests
make test
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "Tests failed for a push to master, we can't let you do that" >&2
@@ -245,7 +259,7 @@ One possibility is a pre-push hook script like this one:
exit 0
This will check if the push is to the master branch and, if it is, only
allow the push if running ``make fish_run_tests`` succeeds. In some circumstances
allow the push if running ``make test`` succeeds. In some circumstances
it may be advisable to circumvent this check with
``git push --no-verify``, but usually that isnt necessary.

View File

@@ -1,7 +1,7 @@
Fish is a smart and user-friendly command line shell.
Copyright (C) 2005-2009 Axel Liljencrantz
Copyright (C) 2009-2024 fish-shell contributors
Copyright (C) 2009- fish-shell contributors
fish is free software.

137
Cargo.lock generated
View File

@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "allocator-api2"
version = "0.2.18"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "autocfg"
@@ -31,9 +31,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.1.30"
version = "1.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945"
checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333"
dependencies = [
"jobserver",
"libc",
@@ -54,9 +54,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "cpufeatures"
version = "0.2.14"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
dependencies = [
"libc",
]
@@ -71,19 +71,6 @@ dependencies = [
"typenum",
]
[[package]]
name = "dashmap"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
"hashbrown 0.14.5",
"lock_api",
"once_cell",
"parking_lot_core",
]
[[package]]
name = "digest"
version = "0.10.7"
@@ -102,12 +89,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
@@ -118,7 +105,6 @@ dependencies = [
"cc",
"errno",
"fish-printf",
"lazy_static",
"libc",
"lru",
"nix",
@@ -150,9 +136,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
[[package]]
name = "generic-array"
@@ -166,15 +152,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.14.5"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
dependencies = [
"allocator-api2",
"equivalent",
@@ -190,17 +170,11 @@ dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.159"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "lock_api"
@@ -224,7 +198,7 @@ version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [
"hashbrown 0.15.0",
"hashbrown",
]
[[package]]
@@ -365,24 +339,24 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "portable-atomic"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
[[package]]
name = "proc-macro2"
version = "1.0.87"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
@@ -404,9 +378,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "redox_syscall"
version = "0.5.7"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [
"bitflags",
]
@@ -440,7 +414,7 @@ dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn 2.0.79",
"syn",
"walkdir",
]
@@ -463,6 +437,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scc"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28e1c91382686d21b5ac7959341fcb9780fa7c03773646995a87c950fa7be640"
dependencies = [
"sdd",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -470,26 +453,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serial_test"
version = "1.0.0"
name = "sdd"
version = "3.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "538c30747ae860d6fb88330addbbd3e0ddbe46d662d032855596d8a8ca260611"
checksum = "478f121bb72bbf63c52c93011ea1791dca40140dfe13f8336c4c5ac952c33aa9"
[[package]]
name = "serial_test"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9"
dependencies = [
"dashmap",
"lazy_static",
"once_cell",
"parking_lot",
"scc",
"serial_test_derive",
]
[[package]]
name = "serial_test_derive"
version = "1.0.0"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69"
checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn",
]
[[package]]
@@ -523,20 +512,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "syn"
version = "1.0.109"
version = "2.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3"
dependencies = [
"proc-macro2",
"quote",
@@ -563,9 +541,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.13"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "version_check"
@@ -595,16 +573,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
"windows-sys",
]
[[package]]

View File

@@ -3,6 +3,7 @@ resolver = "2"
members = ["printf"]
[workspace.package]
# To build revisions that use Corrosion (those before 2024-01), CMake 3.19 and Rustc 1.78 seem to work.
rust-version = "1.70"
edition = "2021"
@@ -34,8 +35,7 @@ pcre2 = { git = "https://github.com/fish-shell/rust-pcre2", tag = "0.2.9-utf32",
bitflags = "2.5.0"
errno = "0.3.0"
lazy_static = "1.4.0"
libc = "0.2.155"
libc = "0.2"
# lru pulls in hashbrown by default, which uses a faster (though less DoS resistant) hashing algo.
# disabling default features uses the stdlib instead, but it doubles the time to rewrite the history
# files as of 22 April 2024.
@@ -65,7 +65,7 @@ portable-atomic = { version = "1", default-features = false, features = [
] }
[dev-dependencies]
serial_test = { version = "1.0.0", default-features = false }
serial_test = { version = "3", default-features = false }
[build-dependencies]
cc = "1.0.94"

View File

@@ -16,4 +16,3 @@ WORKDIR /src
RUN cmake3 . &&\
make &&\
make install

View File

@@ -55,11 +55,7 @@ clean:
.PHONY: test
test: build/fish
$(CMAKE) --build build --target fish_run_tests
.PHONY: fish_run_tests
fish_run_tests: build/fish
$(CMAKE) --build build --target fish_run_tests
$(CMAKE) --build build --target test
.PHONY: install
install: build/fish

View File

@@ -8,5 +8,4 @@ for file in *.fish
echo FAILING FILE $file
end
end
end

View File

@@ -227,7 +227,7 @@ fn has_small_stack(_: &Target) -> Result<bool, Box<dyn Error>> {
}
fn setup_paths() {
fn get_path(name: &str, default: &str, onvar: PathBuf) -> PathBuf {
fn get_path(name: &str, default: &str, onvar: &Path) -> PathBuf {
let mut var = PathBuf::from(env::var(name).unwrap_or(default.to_string()));
if var.is_relative() {
var = onvar.join(var);
@@ -250,7 +250,7 @@ fn get_path(name: &str, default: &str, onvar: PathBuf) -> PathBuf {
rsconf::rebuild_if_env_changed("PREFIX");
rsconf::set_env_value("PREFIX", prefix.to_str().unwrap());
let datadir = get_path("DATADIR", "share/", prefix.clone());
let datadir = get_path("DATADIR", "share/", &prefix);
rsconf::set_env_value("DATADIR", datadir.to_str().unwrap());
rsconf::rebuild_if_env_changed("DATADIR");
@@ -261,7 +261,7 @@ fn get_path(name: &str, default: &str, onvar: PathBuf) -> PathBuf {
};
rsconf::set_env_value("DATADIR_SUBDIR", datadir_subdir);
let bindir = get_path("BINDIR", "bin/", prefix.clone());
let bindir = get_path("BINDIR", "bin/", &prefix);
rsconf::set_env_value("BINDIR", bindir.to_str().unwrap());
rsconf::rebuild_if_env_changed("BINDIR");
@@ -270,16 +270,16 @@ fn get_path(name: &str, default: &str, onvar: PathBuf) -> PathBuf {
// If we get our prefix from $HOME, we should use the system's /etc/
// ~/.local/share/etc/ makes no sense
if prefix_from_home { "/etc/" } else { "etc/" },
datadir.clone(),
&datadir,
);
rsconf::set_env_value("SYSCONFDIR", sysconfdir.to_str().unwrap());
rsconf::rebuild_if_env_changed("SYSCONFDIR");
let localedir = get_path("LOCALEDIR", "locale/", datadir.clone());
let localedir = get_path("LOCALEDIR", "locale/", &datadir);
rsconf::set_env_value("LOCALEDIR", localedir.to_str().unwrap());
rsconf::rebuild_if_env_changed("LOCALEDIR");
let docdir = get_path("DOCDIR", "doc/fish", datadir.clone());
let docdir = get_path("DOCDIR", "doc/fish", &datadir);
rsconf::set_env_value("DOCDIR", docdir.to_str().unwrap());
rsconf::rebuild_if_env_changed("DOCDIR");
}
@@ -292,7 +292,7 @@ fn get_version(src_dir: &Path) -> String {
return var;
}
let path = PathBuf::from(src_dir).join("version");
let path = src_dir.join("version");
if let Ok(strver) = read_to_string(path) {
return strver.to_string();
}
@@ -321,17 +321,36 @@ fn get_version(src_dir: &Path) -> String {
// or because it refused (safe.directory applies to `git describe`!)
// So we read the SHA ourselves.
fn get_git_hash() -> Result<String, Box<dyn std::error::Error>> {
let gitdir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(".git");
let gitdir = Path::new(env!("CARGO_MANIFEST_DIR")).join(".git");
let jjdir = Path::new(env!("CARGO_MANIFEST_DIR")).join(".jj");
let commit_id = if gitdir.exists() {
// .git/HEAD contains ref: refs/heads/branch
let headpath = gitdir.join("HEAD");
let headstr = read_to_string(headpath)?;
let headref = headstr.split(' ').collect::<Vec<_>>()[1].trim();
// .git/HEAD contains ref: refs/heads/branch
let headpath = gitdir.join("HEAD");
let headstr = read_to_string(headpath)?;
let headref = headstr.split(' ').collect::<Vec<_>>()[1].trim();
// .git/refs/heads/branch contains the SHA
let refpath = gitdir.join(headref);
// Shorten to 9 characters (what git describe does currently)
let refstr = &read_to_string(refpath)?[0..9];
// .git/refs/heads/branch contains the SHA
let refpath = gitdir.join(headref);
// Shorten to 9 characters (what git describe does currently)
read_to_string(refpath)?
} else if jjdir.exists() {
let output = Command::new("jj")
.args([
"log",
"--revisions",
"@",
"--no-graph",
"--ignore-working-copy",
"--template",
"commit_id",
])
.output()
.unwrap();
String::from_utf8_lossy(&output.stdout).to_string()
} else {
return Err("did not find either of .git or .jj".into());
};
let refstr = &commit_id[0..9];
let refstr = refstr.trim();
let version = env!("CARGO_PKG_VERSION").to_owned();

View File

@@ -8,7 +8,6 @@
code, tt {
font-family: ui-monospace, Menlo, monospace;
}
</style>
</head>
<body>

View File

@@ -29,7 +29,7 @@ add_custom_target(sphinx-docs
# sphinx-manpages needs the fish_indent binary for the version number
add_custom_target(sphinx-manpages
env FISH_BUILD_VERSION_FILE="${CMAKE_CURRENT_BINARY_DIR}/${FBVF}"
env FISH_BUILD_VERSION_FILE=${CMAKE_CURRENT_BINARY_DIR}/${FBVF}
${SPHINX_EXECUTABLE}
-j auto
-q -b man

View File

@@ -8,11 +8,13 @@ set(CMAKE_FOLDER tests)
# pass but it should not be considered a failed test run, either.
set(SKIP_RETURN_CODE 125)
# Even though we are using CMake's ctest for testing, we still define our own `make fish_run_tests` target
# Even though we are using CMake's ctest for testing, we still define our own `make test` target
# rather than use its default for many reasons:
# * CMake doesn't run tests in-proc or even add each tests as an individual node in the ninja
# dependency tree, instead it just bundles all tests into a target called `test` that always just
# shells out to `ctest`, so there are no build-related benefits to not doing that ourselves.
# * CMake devs insist that it is appropriate for `make test` to never depend on `make all`, i.e.
# running `make test` does not require any of the binaries to be built before testing.
# * The only way to have a test depend on a binary is to add a fake test with a name like
# "build_fish" that executes CMake recursively to build the `fish` target.
# * Circling back to the point about individual tests not being actual Makefile targets, CMake does
@@ -30,6 +32,15 @@ add_custom_target(fish_run_tests
USES_TERMINAL
)
# If CMP0037 is available, also make an alias "test" target.
# Note that this policy may not be available, in which case definining such a target silently fails.
cmake_policy(PUSH)
if(POLICY CMP0037)
cmake_policy(SET CMP0037 OLD)
add_custom_target(test DEPENDS fish_run_tests)
endif()
cmake_policy(POP)
# The "test" directory.
set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test)
@@ -60,17 +71,11 @@ if(NOT FISH_IN_TREE_BUILD)
VERBATIM)
endif()
# Copy littlecheck.py
configure_file(build_tools/littlecheck.py littlecheck.py COPYONLY)
# Copy pexpect_helper.py
configure_file(build_tools/pexpect_helper.py pexpect_helper.py COPYONLY)
# Suppress generating Xcode schemes for all tests, there's too many.
set(CMAKE_XCODE_GENERATE_SCHEME 0)
# CMake being CMake, you can't just add a DEPENDS argument to add_test to make it depend on any of
# your binaries actually being built before `make fish_run_tests` is executed (requiring `make all` first),
# your binaries actually being built before `make test` is executed (requiring `make all` first),
# and the only dependency a test can have is on another test. So we make building fish
# prerequisites to our entire top-level `test` target.
function(add_test_target NAME)
@@ -84,22 +89,19 @@ add_custom_target(tests_buildroot_target
COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_INSTALL_DIR}
COMMAND env DESTDIR=${TEST_INSTALL_DIR} ${CMAKE_COMMAND}
--build ${CMAKE_CURRENT_BINARY_DIR} --target install
# Put fish_test_helper there too:
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/fish_test_helper
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}/bin
# Also symlink fish to where the tests expect it to be:
COMMAND ${CMAKE_COMMAND} -E create_symlink
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}
${TEST_ROOT_DIR}
DEPENDS fish fish_test_helper)
DEPENDS fish)
FILE(GLOB FISH_CHECKS CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/tests/checks/*.fish)
foreach(CHECK ${FISH_CHECKS})
get_filename_component(CHECK_NAME ${CHECK} NAME)
get_filename_component(CHECK ${CHECK} NAME_WE)
add_test(NAME ${CHECK_NAME}
COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.sh
${CMAKE_CURRENT_BINARY_DIR}/tests/test.fish ${CHECK}
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.py ${CMAKE_CURRENT_BINARY_DIR}
checks/${CHECK}.fish
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests
)
set_tests_properties(${CHECK_NAME} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
@@ -111,8 +113,8 @@ FILE(GLOB PEXPECTS CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/tests/pexpects/*.py)
foreach(PEXPECT ${PEXPECTS})
get_filename_component(PEXPECT ${PEXPECT} NAME)
add_test(NAME ${PEXPECT}
COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.sh
${CMAKE_CURRENT_BINARY_DIR}/tests/interactive.fish ${PEXPECT}
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.py ${CMAKE_CURRENT_BINARY_DIR}
pexpects/${PEXPECT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests
)
set_tests_properties(${PEXPECT} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})

6
debian/control vendored
View File

@@ -20,13 +20,17 @@ Vcs-Browser: https://github.com/fish-shell/fish-shell
Package: fish
Architecture: any
# for col and lock
Depends: bsdextrautils,
Depends: bsdextrautils | bsdmainutils,
file,
# for the gettext command
gettext-base,
# for nroff and preconv
groff-base,
man-db,
# for terminal definitions
ncurses-base,
# for kill
procps,
python3 (>=3.5),
${misc:Depends},

4
debian/copyright vendored
View File

@@ -5,12 +5,12 @@ Source: https://fishshell.com/
Files: *
Copyright: 2005-2009 Axel Liljencrantz <axel@liljencrantz.se>
2009-2024 fish-shell contributors
2009- fish-shell contributors
License: GPL-2
Files: doc_src/python_docs_theme/*
Copyright: 2001-2017 Python Software Foundation
2020-2024 fish-shell contributors
2020- fish-shell contributors
License: Python
Files: share/tools/web_config/js/alpine.js

View File

@@ -19,4 +19,4 @@ allow = [
[sources.allow-org]
# 1 or more github.com organizations to allow git sources for
github = ["fish-shell"]
github = ["fish-shell"]

View File

@@ -125,7 +125,6 @@ This first creates a function ``vim_edit`` which prepends ``vim`` before its arg
This creates an abbreviation "4DIRS" which expands to a multi-line loop "template." The template enters each directory and then leaves it. The cursor is positioned ready to enter the command to run in each directory, at the location of the ``!``, which is itself erased.
::
abbr --command git co checkout
Turns "co" as an argument to "git" into "checkout". Multiple commands are possible, ``--command={git,hg}`` would expand "co" to "checkout" for both git and hg.

View File

@@ -162,7 +162,7 @@ The following special input functions are available:
start selecting text
``cancel``
close the pager if it is open, or undo the most recent completion if one was just inserted, or otherwise cancel the current commandline and replace it with a new empty one
cancel the current commandline and replace it with a new empty one
``cancel-commandline``
cancel the current commandline and replace it with a new empty one, leaving the old one in place with a marker to show that it was cancelled
@@ -170,11 +170,11 @@ The following special input functions are available:
``capitalize-word``
make the current word begin with a capital letter
``clear-commandline``
empty the entire commandline
``clear-screen``
clears the screen and redraws the prompt. if the terminal doesn't support clearing the screen it is the same as ``repaint``.
clears the screen and redraws the prompt.
``scrollback-push``
pushes earlier output to the terminal scrollback, positioning the prompt at the top.
``complete``
guess the remainder of the current token

View File

@@ -71,7 +71,7 @@ The following options change what part of the commandline is printed or updated:
Selects the current token
**--search-field**
Use the pager search field instead of the command line. Returns false if the search field is not shown.
Use the pager search field instead of the command line. Returns false is the search field is not shown.
The following options change the way ``commandline`` prints the current commandline buffer:

View File

@@ -34,17 +34,17 @@ The following options are available:
See :ref:`Debugging <debugging-fish>` below for details.
**-o** or **--debug-output=DEBUG_FILE**
Specifies a file path to receive the debug output, including categories and :envvar:`fish_trace`.
The default is standard error.
Specifies a file path to receive the debug output, including categories and :envvar:`fish_trace`.
The default is stderr.
**-i** or **--interactive**
The shell is interactive.
**--install[=PATH]**
When built as self-installable (via cargo), this will unpack fish's data files and place them in ``~/.local/share/fish/install/``.
fish will also ask to do this automatically when run interactively.
When built as self-installable (via cargo), this will unpack fish's datafiles and place them in ~/.local/share/fish/install/.
Fish will also ask to do this automatically when run interactively.
If PATH is given, fish will install itself into a relocatable directory tree rooted at that path.
That means it will install the data files to PATH/share/fish and copy itself to PATH/bin/fish.
That means it will install the datafiles to PATH/share/fish and copy itself to PATH/bin/fish.
**-l** or **--login**
Act as if invoked as a login shell.

View File

@@ -20,7 +20,7 @@ Description
fish will search the working directory to resolve relative paths but will not search :envvar:`PATH` .
If no file is specified and a file or pipeline is connected to standard input, or if the file name ``-`` is used, ``source`` will read from standard input. If no file is specified and there is no redirected file or pipeline on standard input, an error will be printed.
If no file is specified and stdin is not the terminal, or if the file name ``-`` is used, stdin will be read.
The exit status of ``source`` is the exit status of the last job to execute. If something goes wrong while opening or reading the file, ``source`` exits with a non-zero status.

View File

@@ -59,7 +59,7 @@ highlight_language = "fish-docs-samples"
# -- Project information -----------------------------------------------------
project = "fish-shell"
copyright = "2024, fish-shell developers"
copyright = "fish-shell developers"
author = "fish-shell developers"
issue_url = "https://github.com/fish-shell/fish-shell/issues"

View File

@@ -303,7 +303,7 @@ Some bindings are common across Emacs and vi mode, because they aren't text edit
- :kbd:`alt-enter` inserts a newline at the cursor position. This is useful to add a line to a commandline that's already complete.
- :kbd:`alt-left` (````) and :kbd:`alt-right` (````) move the cursor one word left or right (to the next space or punctuation mark), or moves forward/backward in the directory history if the command line is empty. If the cursor is already at the end of the line, and an autosuggestion is available, :kbd:`alt-right` (````) (or :kbd:`alt-f`) accepts the first word in the suggestion.
- :kbd:`alt-left` (````) and :kbd:`alt-right` (````) move the cursor one argument left or right, or moves forward/backward in the directory history if the command line is empty. If the cursor is already at the end of the line, and an autosuggestion is available, :kbd:`alt-right` (````) (or :kbd:`alt-f`) accepts the first argument in the suggestion.
- :kbd:`ctrl-left` (````) and :kbd:`ctrl-right` (````) move the cursor one word left or right. These accept one word of the autosuggestion - the part they'd move over.
@@ -364,13 +364,11 @@ To enable emacs mode, use :doc:`fish_default_key_bindings <cmds/fish_default_key
- :kbd:`ctrl-b`, :kbd:`ctrl-f` move the cursor one character left or right or accept the autosuggestion just like the :kbd:`left` (````) and :kbd:`right` (````) shared bindings (which are available as well).
- :kbd:`alt-b`, :kbd:`alt-f` move the cursor one word left or right, or accept one word of the autosuggestion. If the command line is empty, moves forward/backward in the directory history instead.
- :kbd:`ctrl-n`, :kbd:`ctrl-p` move the cursor up/down or through history, like the up and down arrow shared bindings.
- :kbd:`delete` or :kbd:`backspace` or :kbd:`ctrl-h` removes one character forwards or backwards respectively.
- :kbd:`alt-backspace` removes one word backwards. If supported by the terminal, :kbd:`ctrl-backspace` does the same.
- :kbd:`ctrl-backspace` removes one word backwards and :kbd:`alt-backspace` removes one argument backwards.
- :kbd:`alt-<` moves to the beginning of the commandline, :kbd:`alt->` moves to the end.
@@ -482,7 +480,6 @@ Command mode is also known as normal mode.
- :kbd:`p` pastes text from the :ref:`killring`.
- :kbd:`u` undoes the most recent edit of the command line.
- :kbd:`ctrl-r` redoes the most recent edit.
- :kbd:`[` and :kbd:`]` search the command history for the previous/next token containing the token under the cursor before the search was started. See the :ref:`history <history-search>` section for more information on history searching.
@@ -504,8 +501,6 @@ Insert mode
- :kbd:`backspace` removes one character to the left.
- :kbd:`ctrl-n` accepts the autosuggestion.
.. _vi-mode-visual:
Visual mode

View File

@@ -2022,21 +2022,19 @@ You can see the current list of features via ``status features``::
qmark-noglob on 3.0 ? no longer globs
regex-easyesc on 3.1 string replace -r needs fewer \\'s
ampersand-nobg-in-token on 3.4 & only backgrounds if followed by a separating character
remove-percent-self off 4.0 %self is no longer expanded (use $fish_pid)
test-require-arg off 4.0 builtin test requires an argument
keyboard-protocols on 4.0 Use keyboard protocols (kitty, xterm's modifyotherkeys
remove-percent-self off 3.8 %self is no longer expanded (use $fish_pid)
test-require-arg off 3.8 builtin test requires an argument
buffered-enter-noexec off 4.1 enter typed while executing will not execute
Here is what they mean:
- ``stderr-nocaret`` was introduced in fish 3.0 and cannot be turned off since fish 3.5. It can still be tested for compatibility, but a ``no-stderr-nocaret`` value will simply be ignored. The flag made ``^`` an ordinary character instead of denoting an stderr redirection. Use ``2>`` instead.
- ``qmark-noglob`` was also introduced in fish 3.0 (and made the default in 4.0). It makes ``?`` an ordinary character instead of a single-character glob. Use a ``*`` instead (which will match multiple characters) or find other ways to match files like ``find``.
- ``regex-easyesc`` was introduced in 3.1 (and made the default in 3.5). It makes it so the replacement expression in ``string replace -r`` does one fewer round of escaping. Before, to escape a backslash you would have to use ``string replace -ra '([ab])' '\\\\\\\\$1'``. After, just ``'\\\\$1'`` is enough. Check your ``string replace`` calls if you use this anywhere.
- ``ampersand-nobg-in-token`` was introduced in fish 3.4 (and made the default in 3.5). It makes it so a ``&`` i no longer interpreted as the backgrounding operator in the middle of a token, so dealing with URLs becomes easier. Either put spaces or a semicolon after the ``&``. This is recommended formatting anyway, and ``fish_indent`` will have done it for you already.
- ``remove-percent-self`` turns off the special ``%self`` expansion. It was introduced in 4.0. To get fish's pid, you can use the :envvar:`fish_pid` variable.
- ``test-require-arg`` removes :doc:`builtin test <cmds/test>`'s one-argument form (``test "string"``. It was introduced in 4.0. To test if a string is non-empty, use ``test -n "string"``. If disabled, any call to ``test`` that would change sends a :ref:`debug message <debugging-fish>` of category "deprecated-test", so starting fish with ``fish --debug=deprecated-test`` can be used to find offending calls.
- ``keyboard-protocols`` lets fish turn on various keyboard protocols including the kitty keyboard protocol.
It was introduced in 4.0 and is on by default.
Disable it with ``no-keyboard-protocols`` to work around bugs in your terminal.
- ``stderr-nocaret`` was introduced in fish 3.0 (and made the default in 3.3). It makes ``^`` an ordinary character instead of denoting an stderr redirection, to make dealing with quoting and such easier. Use ``2>`` instead. This can no longer be turned off since fish 3.5. The flag can still be tested for compatibility, but a ``no-stderr-nocaret`` value will simply be ignored.
- ``qmark-noglob`` was also introduced in fish 3.0 (and made the default in 3.8). It makes ``?`` an ordinary character instead of a single-character glob. Use a ``*`` instead (which will match multiple characters) or find other ways to match files like ``find``.
- ``regex-easyesc`` was introduced in 3.1. It makes it so the replacement expression in ``string replace -r`` does one fewer round of escaping. Before, to escape a backslash you would have to use ``string replace -ra '([ab])' '\\\\\\\\$1'``. After, just ``'\\\\$1'`` is enough. Check your ``string replace`` calls if you use this anywhere.
- ``ampersand-nobg-in-token`` was introduced in fish 3.4. It makes it so a ``&`` i no longer interpreted as the backgrounding operator in the middle of a token, so dealing with URLs becomes easier. Either put spaces or a semicolon after the ``&``. This is recommended formatting anyway, and ``fish_indent`` will have done it for you already.
- ``remove-percent-self`` turns off the special ``%self`` expansion. It was introduced in 3.8. To get fish's pid, you can use the :envvar:`fish_pid` variable.
- ``test-require-arg`` removes :doc:`builtin test <cmds/test>`'s one-argument form (``test "string"``. It was introduced in 3.8. To test if a string is non-empty, use ``test -n "string"``. If disabled, any call to ``test`` that would change sends a :ref:`debug message <debugging-fish>` of category "deprecated-test", so starting fish with ``fish --debug=deprecated-test`` can be used to find offending calls.
- ``buffered-enter-noexec`` typing enter during command execution will insert a newline into the next commandline instead of executing it.
These changes are introduced off by default. They can be enabled on a per session basis::
@@ -2057,6 +2055,12 @@ Prefixing a feature with ``no-`` turns it off instead. E.g. to reenable the ``?`
set -Ua fish_features no-qmark-noglob
Currently, the following features are enabled by default:
- stderr-nocaret - ``^`` no longer redirects stderr, use ``2>``. Enabled by default in fish 3.3.0. No longer changeable since fish 3.5.0.
- regex-easyesc - ``string replace -r`` requires fewer backslashes in the replacement part. Enabled by default in fish 3.5.0.
- ampersand-nobg-in-token - ``&`` in the middle of a word is a normal character instead of backgrounding. Enabled by default in fish 3.5.0.
.. _event:
Event handlers

View File

@@ -6,7 +6,7 @@ License
License for fish
----------------
``fish`` Copyright © 2005-2009 Axel Liljencrantz, 2009-2024 fish-shell contributors. ``fish`` is released under the GNU General Public License, version 2.
``fish`` Copyright © 2005-2009 Axel Liljencrantz, 2009- fish-shell contributors. ``fish`` is released under the GNU General Public License, version 2.
``fish`` includes other code licensed under the GNU General Public License, version 2, including GNU ``printf``.

View File

@@ -36,5 +36,4 @@ WORKDIR /home/fishuser
COPY fish_run_tests.sh /
CMD /fish_run_tests.sh

View File

@@ -38,5 +38,4 @@ WORKDIR /home/fishuser
COPY fish_run_tests.sh /
CMD /fish_run_tests.sh

View File

@@ -35,5 +35,4 @@ WORKDIR /home/fishuser
COPY fish_run_tests.sh /
CMD /fish_run_tests.sh

View File

@@ -6,4 +6,3 @@
<true/>
</dict>
</plist>

View File

@@ -84,7 +84,7 @@ fn smoke() {
#[test]
fn test_format_string_str() {
let mut s: &str = "hello%world%%%%%";
assert_eq!(s.is_empty(), false);
assert!(!s.is_empty());
for (idx, c) in s.char_indices() {
assert_eq!(s.at(idx), Some(c));
}
@@ -98,7 +98,7 @@ fn test_format_string_str() {
assert_eq!(s.take_literal(&mut buffer), "world%%");
s.advance_by(1); // advancing over one more %
assert_eq!(s.is_empty(), true); // remaining content is empty
assert!(s.is_empty()); // remaining content is empty
}
#[cfg(feature = "widestring")]
@@ -122,7 +122,7 @@ fn test_format_string_wstr() {
assert_eq!(s.take_literal(&mut buffer), "world%%");
s.advance_by(1); // advancing over one more %
assert_eq!(s.is_empty(), true); // remaining content is empty
assert!(s.is_empty()); // remaining content is empty
}
#[test]

1
share/completions/!.fish Normal file
View File

@@ -0,0 +1 @@
complete ! --wraps not

View File

@@ -1,6 +1,6 @@
complete -c VBoxSDL -l startvm -x -d "Set virtual machine to start" -a "(__fish_print_VBox_vms)"
complete -c VBoxSDL -l separate -d "Run separate VM process or attach to a running VM"
complete -c VBoxSDL -l seperate -d "Run separate VM process or attach to a running VM"
complete -c VBoxSDL -l hda -f -d "Set temporary first hard disk"
complete -c VBoxSDL -l fda -f -d "Set temporary first floppy disk"
complete -c VBoxSDL -l cdrom -r -d "Set temporary CDROM/DVD" -a "none\tunmount"

1
share/completions/[.fish Normal file
View File

@@ -0,0 +1 @@
complete [ --wraps test

View File

@@ -14,7 +14,7 @@ complete -c acpi -s A -l without-ac-adapter -d 'Suppress ac-adapter information'
complete -c acpi -s V -l everything -d 'Show every device, overrides above options'
complete -c acpi -s s -l show-empty -d 'Show non-operational devices'
complete -c acpi -s S -l hide-empty -d 'Hide non-operational devices'
complete -c acpi -s c -l cooling -d 'Show cooling device information'
complete -c acpi -s c -l celcius -d 'Use celsius as the temperature unit'
complete -c acpi -s f -l fahrenheit -d 'Use fahrenheit as the temperature unit'
complete -c acpi -s k -l kelvin -d 'Use kelvin as the temperature unit'
complete -c acpi -s d -l directory -d '<dir> path to ACPI info (/proc/acpi)'

View File

@@ -72,7 +72,7 @@ function __fish_bind_complete
printf '%sshift-\tShift modifier…\n' $prefix
set -l key_names minus comma backspace delete escape \
enter up down left right pageup pagedown home end insert tab \
space f(seq 12)
space menu printscreen f(seq 12)
printf '%s\tNamed key\n' $prefix$key_names
end
end

View File

@@ -1,14 +1,5 @@
set -l commands status install update remove is-installed random-seed systemd-efi-options reboot-to-firmware list set-default set-oneshot set-timeout set-timeout-oneshot
# Execute `bootctl list` and return entries
function __bootctl_entries
if not type -q jq
return 1
end
bootctl list --json short | jq '.[] | "\(.id)\t\(.showTitle)"' --raw-output
end
complete -c bootctl -f
complete -c bootctl -n "not __fish_seen_subcommand_from $commands" -a status -d 'Show status of EFI variables'
complete -c bootctl -n "not __fish_seen_subcommand_from $commands" -a install -d 'Install systemd-boot'
@@ -22,7 +13,6 @@ complete -c bootctl -n "__fish_seen_subcommand_from reboot-to-firmware" -a 'true
complete -c bootctl -n "not __fish_seen_subcommand_from $commands" -a list -d 'List boot loader entries'
complete -c bootctl -n "not __fish_seen_subcommand_from $commands" -a set-default -d 'Set default boot loader entry'
complete -c bootctl -n "not __fish_seen_subcommand_from $commands" -a set-oneshot -d 'Set default boot loader entry (Once)'
complete -c bootctl -n "__fish_seen_subcommand_from set-default set-oneshot" -x -a '(__bootctl_entries)'
complete -c bootctl -n "not __fish_seen_subcommand_from $commands" -a set-timeout -d 'Set default boot loader timeout'
complete -c bootctl -n "not __fish_seen_subcommand_from $commands" -a set-timeout-oneshot -d 'Set default boot loader timeout (Once)'

View File

@@ -61,7 +61,7 @@ complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l pull -d 'If destina
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l remember -d 'Remember the specified location as a default'
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l force -d 'Merge even if the destination tree has uncommitted changes'
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l reprocess -d 'Reprocess to reduce spurious conflicts'
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l uncommitted -d 'Apply uncommitted changes from a working copy, instead of branch changes'
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l uncommited -d 'Apply uncommitted changes from a working copy, instead of branch changes'
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l show-base -d 'Show base revision text in conflicts'
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l preview -d 'Instead of merging, show a diff of the merge'
complete -f -c bzr -n '__fish_seen_subcommand_from merge' -l interactive -s i -d 'Select changes interactively'

View File

@@ -5,7 +5,7 @@ complete -c create_ap -l version -d 'Print version number'
complete -c create_ap -s c -x -d 'Channel number'
complete -c create_ap -s w -x -a '1 2 1+2' -d 'WPA version to use'
complete -c create_ap -s n -d 'Disable Internet sharing'
complete -c create_ap -s m -x -a 'nat bridge none' -d 'Method for Internet sharing'
complete -c create_ap -s m -x -a 'nat brigde none' -d 'Method for Internet sharing'
complete -c create_ap -l psk -d 'Use 64 hex digits pre-shared-key'
complete -c create_ap -l hidden -d 'Make the Access Point hidden'
complete -c create_ap -l mac-filter -d 'Enable MAC address filtering'

View File

@@ -6,6 +6,6 @@ complete -c csvlens -l filter -r -d "Use this regex to filter rows to display by
complete -c csvlens -l find -r -d "Use this regex to find and highlight matches by default"
complete -c csvlens -s i -l ignore-case -d "Searches ignore case. Ignored if any uppercase letters are present in the search string"
complete -c csvlens -l echo-column -r -d "Print the value of this column to stdout for the selected row"
complete -c csvlens -l debug -d "Show stats for debugging"
complete -c csvlens -l debug "Show stats for debugging"
complete -c csvlens -s h -l help -f -d "Print help"
complete -c csvlens -s V -l version -f -d "Print version"

View File

@@ -2,10 +2,6 @@
# Completions for the dnf command
#
function __dnf_is_dnf5
path resolve -- $PATH/dnf | path filter | string match -q -- '*/dnf5'
end
function __dnf_list_installed_packages
dnf repoquery --cacheonly "$cur*" --qf "%{name}\n" --installed </dev/null
end
@@ -19,14 +15,9 @@ function __dnf_list_available_packages
return
end
set -l results
if __dnf_is_dnf5
# dnf5 provides faster completions than repoquery, but does not maintain the
# same sqlite db as dnf4
set results (dnf --complete=2 dnf install "$tok*")
else if type -q sqlite3
# dnf --cacheonly list --available gives a list of non-installed packages dnf is aware of,
# but it is slow as molasses. Unfortunately, sqlite3 is not available oob (Fedora Server 32).
# dnf --cacheonly list --available gives a list of non-installed packages dnf is aware of,
# but it is slow as molasses. Unfortunately, sqlite3 is not available oob (Fedora Server 32).
if type -q sqlite3
# This schema is bad, there is only a "pkg" field with the full
# packagename-version-release.fedorarelease.architecture
# tuple. We are only interested in the packagename.
@@ -46,7 +37,7 @@ function __dnf_list_available_packages
end
function __dnf_list_transactions
if not __dnf_is_dnf5 && type -q sqlite3
if type -q sqlite3
sqlite3 /var/lib/dnf/history.sqlite "SELECT id, cmdline FROM trans" 2>/dev/null | string replace "|" \t
end
end

View File

@@ -3,7 +3,7 @@
#
function __fish_doas_print_remaining_args
set -l tokens (commandline -xpc | string escape) (commandline -ct)
set -l tokens (commandline -xpc) (commandline -ct)
set -e tokens[1]
# These are all the options mentioned in the man page for openbsd's "doas" (in that order).
set -l opts a= C= L n s u=

View File

@@ -1,24 +0,0 @@
set -l commands repl init reactor make install bump diff publish
complete -c elm -f
# repl completions
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a repl -d 'Open up an interactive programming session'
complete -c elm -n "__fish_seen_subcommand_from repl" -l no-colors -d 'Turn off the colors in REPL'
complete -c elm -n "__fish_seen_subcommand_from repl" -l interpreter -d 'Path to an alternative JS interpreter'
# reactor completions
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a reactor -d 'Compile code with a click'
complete -c elm -n "__fish_seen_subcommand_from reactor" -l port -d 'Compile code with a click'
# make completions
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a make -d 'Compiles Elm code in JS or HTML'
complete -c elm -n "__fish_seen_subcommand_from make" -l output -F -r -d 'Specify the name of resulting JS file'
complete -c elm -n "__fish_seen_subcommand_from make" -l debug -d 'Turn on the time-travelling debugger'
complete -c elm -n "__fish_seen_subcommand_from make" -l optimize -d 'Turn on optimizations to make code smaller and faster'
complete -c elm -n "__fish_seen_subcommand_from make" -l docs -d 'Generate a JSON file of documentation for a package'
#other commands completions
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a init -d 'Start an Elm project'
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a install -d 'Fetches packages from Elm repository'
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a bump -d 'Figures out the next version number based on API changes'
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a diff -d 'See what changed in a package between different versions'
complete -c elm -n "not __fish_seen_subcommand_from $commands" -a publish -d 'Publishes your package on package.elm-lang.org so anyone in the community can use it'
complete -c elm -l help -d "Show a more detailed description"

View File

@@ -62,7 +62,7 @@ end
# Get the text after all env arguments and variables, so we can complete it as a regular command
function __fish_env_remaining_args -V is_gnu
set -l argv (commandline -xpc | string escape) (commandline -ct)
set -l argv (commandline -xpc) (commandline -ct)
if set -q is_gnu[1]
argparse -s i/ignore-environment u/unset= help version -- $argv 2>/dev/null
or return 0

View File

@@ -882,16 +882,9 @@ short\t<sha1> / <author> / <title line>
medium\t<sha1> / <author> / <author date> / <title> / <commit msg>
full\t<sha1> / <author> / <committer> / <title> / <commit msg>
fuller\t<sha1> / <author> / <author date> / <committer> / <committer date> / <title> / <commit msg>
reference\t<abbrev-hash> (<title-line>, <short-author-date>)
email\t<sha1> <date> / <author> / <author date> / <title> / <commit msg>
mboxrd\tLike email, but lines in the commit message starting with \"From \" are quoted with \">\"
raw\tShow the entire commit exactly as stored in the commit object
format:\tSpecify which information to show
"
__fish_git config -z --get-regexp '^pretty\.' 2>/dev/null | while read -lz key value
set -l name (string replace -r '^.*?\.' '' -- $key)
printf "%s\t%s\n" $name $value
end
format:\tSpecify which information to show"
end
end

View File

@@ -1,4 +1,4 @@
complete -c gprof -s A -l annotated-source -d "Print annotated source"
complete -c gprof -s A -l annoted-source -d "Print annotated source"
complete -c gprof -s b -l brief -d "Do not print explanations"
complete -c gprof -s C -l exec-counts -d "Print tally"
complete -c gprof -s i -l file-info -d "Display summary"

View File

@@ -14,7 +14,7 @@ set -l ip_all_commands $ip_commands $ip_addr $ip_link $ip_neigh $ip_route $ip_ru
function __fish_ip_commandwords
set -l skip 0
set -l cmd (commandline -xpc | string escape)
set -l cmd (commandline -xpc)
# Remove the first word because it's "ip" or an alias for it
set -e cmd[1]
set -l have_command 0

View File

@@ -1,20 +0,0 @@
complete -c lazygit -xa "status branch log stash"
complete -c lazygit -s h -l help -d 'Display help'
complete -c lazygit -s v -l version -d 'Print version'
complete -c lazygit -s p -l path -d 'Path of git repo' -xa "(__fish_complete_directories)"
# Config
complete -c lazygit -s c -l config -d 'Print the default config'
complete -c lazygit -o cd -l print-config-dir -d 'Print the config directory'
complete -c lazygit -o ucd -l use-config-dir -d 'Override default config directory with provided directory' -r
complete -c lazygit -o ucf -l use-config-file -d 'Comma separated list to custom config file(s)' -r
# Git
complete -c lazygit -s f -l filter -d 'Path to filter on in `git log -- <path>`' -r
complete -c lazygit -s g -l git-dir -d 'Equivalent of the --git-dir git argument' -r
complete -c lazygit -s w -l work-tree -d 'Equivalent of the --work-tree git argument' -xa "(__fish_complete_directories)"
# Debug
complete -c lazygit -s d -l debug -d 'Run in debug mode with logging'
complete -c lazygit -s l -l logs -d 'Tail lazygit logs; used with --debug'
complete -c lazygit -l profile -d 'Start the profiler and serve it on http port 6060'

View File

@@ -1,6 +1,4 @@
# Basic completions for simonw/llm
# A complete implementation for `llm [prompt]` but other subcommands
# can be further fleshed out.
# Completions for simonw/llm
set -l subcmds prompt aliases chat collections embed embed-models embed-multi install keys logs models openai plugins similar templates uninstall
function __fish_llm_subcmds
@@ -10,7 +8,7 @@ function __fish_llm_subcmds
"collections" "View/manage embedding collections" \
"embed" "Embed text and get/store result" \
"embed-models" "Manage available embedding models" \
"embed-multi\Store embeddings for multiple strings" \
"embed-multi" "Store embeddings for multiple strings" \
"install" "Install PyPI packages into llm env" \
"keys" "Manage stored API keys" \
"logs" "Explore logged prompts/responses" \
@@ -27,24 +25,117 @@ complete -c llm -n __fish_is_first_token -xa "(__fish_llm_subcmds)"
# This applies to the base command only
complete -c llm -n "not __fish_seen_subcommand_from $subcmds" -l version -d "Show version info"
# This applies to the base command or any subcommands
complete -c llm -l help -d "Show usage info"
complete -c llm -l help -d "Show command usage info" -x
function __fish_llm_models
llm models |
string replace -r '^[^:]+: ([^ ]+)(?: \\(aliases: )?([^),]+,?)?+.*$' '$1 $2' |
string replace -r '^[^:\\n]+: (\\S+)(?: \\(aliases: )?((?:[^),\\s]+,?)?+.*?)\\)?$' '$1 $2' |
string split ' ' -n |
string trim -c ','
end
function __fish_embedding_models
llm models |
string replace -r '^[^:\\n]+: (\\S+)(?: \\(aliases: )?((?:[^),\\s]+,?)?+.*?)\\)?$' '$1 $2' |
string split ' ' -n |
string trim -c ','
end
# The default subcommand is 'prompt'
set -l is_prompt "not __fish_seen_subcommand_from $subcmds || __fish_seen_subcommand_from prompt"
complete -c llm -n $is_prompt -s s -l system -d "System prompt to use"
complete -c llm -n $is_prompt -s m -l model -d "Model to use" -xa "(__fish_llm_models)"
complete -c llm -n $is_prompt -s a -l attachment -d "Attachment to use" -r -a'-'
complete -c llm -n $is_prompt -l at -d "Attachment type" -r
complete -c llm -n $is_prompt -l attachment-type -d "Attachment type" -r
complete -c llm -n $is_prompt -s n -l no-log -d "Don't log to db"
complete -c llm -n $is_prompt -s l -l log -d "Log prompt/reply to db"
complete -c llm -n $is_prompt -s c -l continue -d "Continue most recent conversation"
complete -c llm -n $is_prompt -l key -d "API key to use"
complete -c llm -n $is_prompt -l save -d "Save prompt as template with name" -r
set -l condition "not __fish_seen_subcommand_from $subcmds || __fish_seen_subcommand_from prompt"
complete -c llm -n $condition -s s -l system -d "System prompt to use" -r
complete -c llm -n $condition -s m -l model -d "Model to use" -xa "(__fish_llm_models)"
complete -c llm -n $condition -s a -l attachment -d "Attachment to use" -ra'-'
complete -c llm -n $condition -l at -d "Attachment type" -r
complete -c llm -n $condition -l attachment-type -d "Attachment type" -r
complete -c llm -n $condition -s n -l no-log -d "Don't log to db" -x
complete -c llm -n $condition -s l -l log -d "Log prompt/reply to db" -x
complete -c llm -n $condition -s c -l continue -d "Continue most recent conversation" -x
complete -c llm -n $condition -l key -d "API key to use" -r
complete -c llm -n $condition -l save -d "Save prompt as template with name" -x
# llm aliases
set -l condition "__fish_seen_subcommand_from aliases"
complete -c llm -n $condition -xa list -d "List current aliases" -x
complete -c llm -n $condition -xa path -d "Print path of llm's aliases.json" -x
complete -c llm -n $condition -xa remove -d "Remove an llm alias" -r
complete -c llm -n $condition -xa set -d "Set an alias for a model" -r
# llm aliases
set -l condition "__fish_seen_subcommand_from chat"
complete -c llm -n $condition -s s -l system -d "System prompt to use" -r
complete -c llm -n $condition -s m -l model -d "Model to use" -xa "(__fish_llm_models)"
complete -c llm -n $condition -l cid -d "Continue conversation with given id" -x
complete -c llm -n $condition -l conversation -d "Continue conversation with given id" -x
complete -c llm -n $condition -s t -l template -d "Template to use" -x
complete -c llm -n $condition -s p -l param -d "Set template parameter to value" -x
complete -c llm -n $condition -s o -l option -d "Set key/value option for model" -x
complete -c llm -n $condition -l no-stream -d "Do not stream output" -x
complete -c llm -n $condition -l key -d "API key to use" -x
# llm collections
set -l condition "__fish_seen_subcommand_from collections"
complete -c llm -n $condition -xa list -d "List collections" -x
complete -c llm -n $condition -xa delete -d "Delete specified collection" -x
complete -c llm -n $condition -xa path -d "Print path to embeddings database" -x
# llm embed
set -l condition "__fish_seen_subcommand_from embed"
complete -c llm -n $condition -s i -l input -d "File to embed" -r
complete -c llm -n $condition -s m -l model -d "Model to use" -xa "(__fish_embedding_models)"
complete -c llm -n $condition -l store -d "Store the text itself in the db" -x
complete -c llm -n $condition -s d -l database -d "Path to db to use" -r
complete -c llm -n $condition -s c -l content -d "Text content to embed" -x
complete -c llm -n $condition -l binary -d "Treat input as binary" -x
complete -c llm -n $condition -l metadata -d "JSON object metadata to store" -x
complete -c llm -n $condition -s f -l format -d "Output format" -xa "json blob base64 hex"
# llm embed-models
set -l condition "__fish_seen_subcommand_from embed-models"
complete -c llm -n $condition -xa list -d "List available embedding models" -x
complete -c llm -n $condition -xa default -d "Show or set default embedding model" -x
# llm embed-multi
set -l condition "__fish_seen_subcommand_from embed-multi"
complete -c llm -n $condition -l format -xa "json csv tsv nl" -d "Format of input (default: auto-detected)"
complete -c llm -n $condition -l files -r -d "Embed files in DIR matching GLOB"
complete -c llm -n $condition -l encoding -r -d "Encoding to use when reading input"
complete -c llm -n $condition -l binary -d "Treat input as binary"
complete -c llm -n $condition -l sql -x -d "Read input using this SQL query"
complete -c llm -n $condition -l attach -x -d "Attach db ALIAS from PATH"
complete -c llm -n $condition -l batch-size -x -d "Batch size to use for embeddings"
complete -c llm -n $condition -l prefix -x -d "Prefix to add to the IDs"
complete -c llm -n $condition -s m -l model -d "Embedding model to use" -xa "(__fish_embedding_models)"
complete -c llm -n $condition -l store -d "Store the text itself in the db"
complete -c llm -n $condition -s d -l database -d "Path to db to use"
# llm install
set -l condition "__fish_seen_subcommand_from install"
complete -c llm -n $condition -s U -l upgrade -d "Upgrade packages to latest version" -x
complete -c llm -n $condition -s e -l editable -d "Install project in editable mode from PATH" -r
complete -c llm -n $condition -l force-reinstall -d "Reinstall all packages, even if up-to-date" -x
complete -c llm -n $condition -l no-cache-dir -d "Disable cache" -x
# llm keys
set -l condition "__fish_seen_subcommand_from keys"
complete -c llm -n $condition -xa list -d "List names of all stored keys"
complete -c llm -n $condition -xa get -d "Print saved key"
complete -c llm -n $condition -xa path -d "Print path of llm's keys.json"
complete -c llm -n $condition -xa set -d "Save a key in llm's keys.json"
# llm logs
set -l condition "__fish_seen_subcommand_from logs"
complete -c llm -n $condition -xa list -d "List recent prompts and responses"
complete -c llm -n $condition -xa off -d "Turn off logging"
complete -c llm -n $condition -xa on -d "Turn on logging"
complete -c llm -n $condition -xa path -d "Print path to llm's logs.db"
complete -c llm -n $condition -xa status -d "Show current status of db logging"
# llm models
set -l condition "__fish_seen_subcommand_from models"
complete -c llm -n $condition -xa list -d "List available models" -x
complete -c llm -n $condition -xa default -d "Show or set default model" -x
# llm plugins
set -l condition "__fish_seen_subcommand_from plugins"
complete -c llm -n $condition -l all -d "Include built-in/default plugins" -x

View File

@@ -169,7 +169,7 @@ complete -c pkg -n '__fish_pkg_is list' -xa '(pkg query "%n")'
complete -c pkg -n '__fish_pkg_is add update' -s f -l force -d "Force a full download of a repository"
# alias
set -l with_package_names all-depends annotations build-depends cinfo comment csearch desc iinfo isearch \
set -l with_packge_names all-depends annotations build-depends cinfo comment csearch desc iinfo isearch \
list options origin provided-depends roptions shared-depends show size
for alias in (pkg alias -lq)

View File

@@ -16,12 +16,12 @@ complete -c pygmentize -s o -d "Set output file"
complete -c pygmentize -s s -d "Read one line at a time"
complete -c pygmentize -s l -d "Set lexer" -x -a "(__fish_print_pygmentize lexers Lexer)"
complete -c pygmentize -s g -d "Guess lexer"
complete -c pygmentize -s f -d "Set formatter" -x -a "(__fish_print_pygmentize formatters Formatter)"
complete -c pygmentize -s O -d "Set coma-separated options" -x
complete -c pygmentize -s f -d "Set formater" -x -a "(__fish_print_pygmentize formaters Formater)"
complete -c pygmentize -s O -d "Set coma-seperated options" -x
complete -c pygmentize -s P -d "Set one option" -x
complete -c pygmentize -s F -d "Set filter" -x -a "(__fish_print_pygmentize filters Filter)"
complete -c pygmentize -s S -d "Print style definition for given style" -x -a "(__fish_print_pygmentize styles Style)"
complete -c pygmentize -s L -d "List lexers, formatters, styles or filters" -x -a "lexers formatters styles filters"
complete -c pygmentize -s L -d "List lexers, formaters, styles or filters" -x -a "lexers formaters styles filters"
complete -c pygmentize -s N -d "Guess and print lexer name based on given file"
complete -c pygmentize -s H -d "Print detailed help" -x -a "lexer formatter filter"
complete -c pygmentize -s v -d "Print detailed traceback on unhandled exceptions"

View File

@@ -35,7 +35,7 @@ complete -c python3 -n __fish_python_no_arg -s x -d 'Skip first line of source,
complete -c python3 -n __fish_python_no_arg -k -fa "(__fish_complete_suffix .py)"
complete -c python3 -n __fish_python_no_arg -fa - -d 'Read program from stdin'
complete -c python3 -n __fish_python_no_arg -s q -d 'Don\'t print version and copyright messages on interactive startup'
complete -c python3 -n __fish_python_no_arg -s X -x -d 'Set implementation-specific option' -a 'faulthandler showrefcount tracemalloc showalloccount importtime dev utf8 pycache_prefix=PATH:'
complete -c python3 -n __fish_python_no_arg -s X -x -d 'Set implementation-specific option' -a 'faulthandler showrefcount tracemalloc showalloccount importtime dev utf8 pycache_prefex=PATH:'
complete -c python3 -n __fish_python_no_arg -s b -d 'Issue warnings for possible misuse of `bytes` with `str`'
complete -c python3 -n __fish_python_no_arg -o bb -d 'Issue errors for possible misuse of `bytes` with `str`'
complete -c python3 -n __fish_python_no_arg -s m -d 'Run library module as a script (terminates option list)' -xa '(python3 -c "import pkgutil; print(\'\n\'.join([p[1] for p in pkgutil.iter_modules()]))")'

View File

@@ -1,23 +1,21 @@
function __run0_slice
systemctl -t slice --no-legend --no-pager --plain | string split -nf 1 ' '
systemctl -t slice --user --no-legend --no-pager --plain | string split -nf 1 ' '
end
#
# Completion for run0
#
complete -c run0 -xa "(__fish_complete_subcommand)"
complete -c run0 -s h -l help -d "Show help"
complete -c run0 -s V -l version -d "Show version"
complete -c run0 -s u -l user -d "Switches to the specified user instead of root" -xa "(__fish_complete_users)"
complete -c run0 -s g -l group -d "Switches to the specified group instead of root" -xa "(__fish_complete_groups)"
complete -c run0 -l no-ask-password -d "Do not query the user for authentication for privileged operations"
complete -c run0 -l machine -d "Execute operation on a local container" -xa "(machinectl list --no-legend --no-pager | string split -f 1 ' ')"
complete -c run0 -l property -d "Sets a property on the service unit that is created" -x
complete -c run0 -l description -d "Description for unit" -x
complete -c run0 -l slice -d "Make the new .service unit part of the specified slice, instead of user.slice." -xa "(__run0_slice)"
complete -c run0 -l slice-inherit -d "Make the new .service unit part of the slice the run0 itself has been invoked in"
complete -c run0 -l nice -d "Runs the invoked session with the specified nice level" -xa "(seq -20 19)"
complete -c run0 -s D -l chdir -d "Set working directory" -xa "(__fish_complete_directories)"
complete -c run0 -l setenv -d "Runs the invoked session with the specified environment variable set" -x
complete -c run0 -l background -d "Change the terminal background color to the specified ANSI color" -x
complete -c run0 -l pty -d "Request allocation of a pseudo TTY for stdio"
complete -c run0 -l pipe -d "Request redirect pipe for stdio"
complete -c run0 -l shell-prompt-prefix -d "Set a shell prompt prefix string" -x
complete -c run0 -l no-ask-password -d 'Do not query the user for authentication for privileged operations'
complete -c run0 -l unit -d 'Use this unit name instead of an automatically generated one'
complete -c run0 -l property -d 'Sets a property on the service unit that is created'
complete -c run0 -l description -d 'Provide a description for the service unit that is invoked'
complete -c run0 -l slice -d 'Make the new .service unit part of the specified slice, instead of user.slice.'
complete -c run0 -l slice-inherit -d 'Make the new .service unit part of the slice the run0 itself has been invoked in'
complete -c run0 -s u -l user -a "(__fish_complete_users)" -x -d "Switches to the specified user instead of root"
complete -c run0 -s g -l group -a "(__fish_complete_groups)" -x -d "Switches to the specified group instead of root"
complete -c run0 -l nice -d 'Runs the invoked session with the specified nice level'
complete -c run0 -s D -l chdir -d 'Runs the invoked session with the specified working directory'
complete -c run0 -l setenv -d 'Runs the invoked session with the specified environment variable set'
complete -c run0 -l background -d 'Change the terminal background color to the specified ANSI color'
complete -c run0 -l machine -d 'Execute operation on a local container'
complete -c run0 -s h -l help -d 'Print a short help text and exit'
complete -c run0 -l version -d 'Print a short version string and exit'
complete -c run0 -x -a '(__fish_complete_subcommand)'

View File

@@ -5,9 +5,9 @@ __fish_complete_ssh scp
function __scp2ssh_port_number
# There is a silly inconsistency between the ssh and scp commands regarding the short flag name
# for specifying the TCP port number. This function deals with that by extracting the port
# number if present and emitting it as a flag appropriate for ssh.
# number if present.
set -l port (commandline -c | string match -r -- ' -P ?(\d+)\b')
and echo -p\n$port[2]
and echo $port[2]
end
function __scp_remote_target
@@ -44,20 +44,25 @@ complete -c scp -d "Local Path" -n "not string match @ -- (commandline -ct)"
# Remote path
# Get the list of remote files from the scp target.
if string match -rq 'OpenSSH(_for_Windows)?_(?<major>\d+)\.*' -- (ssh -V 2>&1) && test "$major" -ge 9
complete -c scp -d "Remote Path" -f -n "commandline -ct | string match -e ':'" -a "
(__scp_remote_target):( \
command ssh (__scp2ssh_port_number) -o 'BatchMode yes' (__scp_remote_target) command\ ls\ -dp\ (__scp_remote_path_prefix)\* 2>/dev/null
)
"
else
complete -c scp -d "Remote Path" -f -n "commandline -ct | string match -e ':'" -a "
(__scp_remote_target):( \
command ssh (__scp2ssh_port_number) -o 'BatchMode yes' (__scp_remote_target) command\ ls\ -dp\ (__scp_remote_path_prefix | string unescape)\* 2>/dev/null |
complete -c scp -d "Remote Path" -f -n "commandline -ct | string match -e ':'" -a '
(__scp_remote_target):(
if not set -q __fish_scp_sftp
set -l tmp (mktemp)
if scp -P(__scp2ssh_port_number) -o "BatchMode yes" -q -O $tmp (__scp_remote_target):/dev/null
set -g __fish_scp_sftp true
else
set -g __fish_scp_sftp false
end
rm $tmp
end
if $__fish_scp_sftp
command ssh -p(__scp2ssh_port_number) -o "BatchMode yes" (__scp_remote_target) command\ ls\ -dp\ (__scp_remote_path_prefix)\* 2>/dev/null
else
command ssh -p(__scp2ssh_port_number) -o "BatchMode yes" (__scp_remote_target) command\ ls\ -dp\ (__scp_remote_path_prefix | string unescape)\* 2>/dev/null |
string escape -n
end
)
"
end
'
complete -c scp -s 3 -d "Copies between two remote hosts are transferred through the local host"
complete -c scp -s B -d "Batch mode"

View File

@@ -15,6 +15,7 @@ complete -f -c status -n "not __fish_seen_subcommand_from $__fish_status_all_com
complete -f -c status -n "not __fish_seen_subcommand_from $__fish_status_all_commands" -a is-full-job-control -d "Test if all new jobs are put under job control"
# The subcommands that are not "is-something" which don't change the fish state.
complete -f -c status -n "not __fish_seen_subcommand_from $__fish_status_all_commands" -a buildinfo -d "Print information on how this version fish was built"
complete -f -c status -n "not __fish_seen_subcommand_from $__fish_status_all_commands" -a current-command -d "Print the name of the currently running command or function"
complete -f -c status -n "not __fish_seen_subcommand_from $__fish_status_all_commands" -a current-commandline -d "Print the currently running command with its arguments"
complete -f -c status -n "not __fish_seen_subcommand_from $__fish_status_all_commands" -a current-filename -d "Print the filename of the currently running script"

View File

@@ -3,7 +3,7 @@
#
function __fish_sudo_print_remaining_args
set -l tokens (commandline -xpc | string escape) (commandline -ct)
set -l tokens (commandline -xpc) (commandline -ct)
set -e tokens[1]
# These are all the options mentioned in the man page for Todd Miller's "sudo.ws" sudo (in that order).
# If any other implementation has different options, this should be harmless, since they shouldn't be used anyway.

View File

@@ -1,5 +1,6 @@
function __fish_complete_svn_diff --description 'Complete "svn diff" arguments'
set -l cmdl (commandline -cxp | string escape)
set -l cmdl (commandline -cxp)
#set -l cmdl svn diff --diff-cmd diff --extensions '-a -b'
set -l diff diff
set -l args
while set -q cmdl[1]

View File

@@ -1,75 +1,25 @@
function __fish_tmux_sessions -d 'available sessions'
tmux list-sessions -F "#S"\t"#{session_windows} windows created: #{session_created_string} [#{session_width}x#{session_height}]#{session_attached}" | sed 's/0$//;s/1$/ (attached)/' 2>/dev/null
tmux list-sessions -F "#S #{session_windows} windows created: #{session_created_string} [#{session_width}x#{session_height}]#{session_attached}" | sed 's/0$//;s/1$/ (attached)/' 2>/dev/null
end
function __fish_tmux_clients -d 'connected clients'
tmux list-clients -F "#{client_tty}"\t"#S: Created: #{client_created_string} [#{client_width}x#{client_height} #{client_termname}]" 2>/dev/null
tmux list-clients -F "#{client_tty} #S: Created: #{client_created_string} [#{client_width}x#{client_height} #{client_termname}]" 2>/dev/null
end
function __fish_tmux_panes -d 'window panes'
#fully qualified pane names
tmux list-panes -F '#S:#W.#P'\t'session:window.pane' 2>/dev/null
tmux list-panes -F '#S:#W.#P session:window.pane' 2>/dev/null
#panes by themselves
tmux list-panes -F '#P'\t'pane' 2>/dev/null
tmux list-panes -F '#P pane' 2>/dev/null
#windows by themselves
tmux list-panes -F '#W'\t'window' 2>/dev/null
tmux list-panes -F '#W window' 2>/dev/null
end
#don't allow dirs in the completion list...
complete -c tmux -x
############### Begin: Dynamic Completions Using `tmux list-commands` ###############
# The dynamic completions are exhaustive. The manual completions below override
# them with better-documented completions and custom completions for some
# arguments, e.g. for target panes, but only have partial coverage.
function __fish_tmux_parse_lscm_usage
set -l lscm (tmux list-commands -F "#{command_list_name} #{command_list_alias}"\t"#{command_list_usage}" 2>/dev/null)
or return
for cmd_tab_usage in $lscm
set -l split_command (string split --max 2 \t -- $cmd_tab_usage)
set -l cmdnames $split_command[1]
set -l usage $split_command[2]
complete -c tmux -n __fish_use_subcommand -a "$cmdnames"
# $usage has the form '[-ABCD] [-L|-S|-U] [-e arg-name] [positional-arg-name]'
for item in (string match -ag --regex '\[([^\]]+)\]' $usage)
if not set -l item (string trim -l -c - -- $item)
continue
end
if set -l split_item (string split -n --max 2 " " -- "$item")
# The option should always have length 1 by tmux convention,
# but we double-check to avoid syntax errors.
if [ "$(string length $split_item[1])" = 1 ]
complete -c tmux -xs $split_item[1] -n "__fish_seen_subcommand_from $cmdnames" -d "$split_item[2]"
end
else
for char in (string split '' -- "$item")
if string match -q -r '\||-' -- $char
# TODO: Actually treat exclusive args, [-L|-S|-U], as exclusive
# For now, we just ignore the `-`s and `|`s
continue
end
complete -c tmux -n "__fish_seen_subcommand_from $cmdnames" -s $char
end
end
end
end
end
__fish_tmux_parse_lscm_usage
functions -e __fish_tmux_parse_lscm_usage
# Completions for `tmux list-commands` itself
set -l all_commands (tmux list-commands -F "#{command_list_name} #{command_list_alias}" 2>/dev/null)
and complete -c tmux -n "__fish_seen_subcommand_from list-commands lscm" -x -a "$all_commands"
############### End: Dynamic Completions Using `tmux list-commands` ###############
############### Begin: Front Flags ###############
#these do not require parameters
complete -c tmux -n __fish_use_subcommand -s 2 -d 'Force tmux to assume the terminal supports 256 colours'
@@ -167,9 +117,6 @@ complete -c tmux -xs c -n "__fish_seen_subcommand_from $switchc" -a '(__fish_tmu
#commands with the -F format flag
complete -c tmux -n "__fish_seen_subcommand_from $lsc $ls" -xs F -d 'format string'
#commands that take shell commands
complete -c tmux -x -n "__fish_seen_subcommand_from $new " -a '(__fish_complete_subcommand --fcs-skip=2)'
############### End: Clients and Sessions ###############
############### Begin: Windows and Panes ###############
@@ -211,56 +158,35 @@ set -l swapw "swap-window swapw"
set -l unlinkw "unlink-window unlinkw"
complete -c tmux -n __fish_use_subcommand -a $breakp -d 'break pane off into a new window'
complete -c tmux -n __fish_use_subcommand -a $capturep -d 'capture contents of a pane into a buffer'
complete -c tmux -n "__fish_seen_subcommand_from $capturep" -xs a -d 'capture alternate screen'
complete -c tmux -n "__fish_seen_subcommand_from $capturep" -xs p -d 'output to stdout'
complete -c tmux -n "__fish_seen_subcommand_from $capturep" -xs e -d 'include color escapes'
complete -c tmux -n "__fish_seen_subcommand_from $capturep" -xs C -d 'escape non-printable chars'
complete -c tmux -n __fish_use_subcommand -a $chooseclient -d 'interactively choose client'
complete -c tmux -n __fish_use_subcommand -a $choosetree -d 'interactively choose session/window/pane'
complete -c tmux -n __fish_use_subcommand -a $customizemode -d 'interactively customize settings'
complete -c tmux -n __fish_use_subcommand -a $displayp -d 'display a visible indicator for each pane'
complete -c tmux -n __fish_use_subcommand -a $findw -d 'interactively choose window matching pattern'
complete -c tmux -n __fish_use_subcommand -a $joinp -d 'split destination pane and move source pane into one of the halves'
# $joinp takes a subset of $splitw arguments
complete -c tmux -n "__fish_seen_subcommand_from $joinp $splitw" -xs b -d 'before target'
complete -c tmux -n "__fish_seen_subcommand_from $joinp $splitw" -xs h -d 'horizontal'
complete -c tmux -n "__fish_seen_subcommand_from $joinp $splitw" -xs v -d 'vertical'
complete -c tmux -n "__fish_seen_subcommand_from $joinp $splitw" -xs l -d 'size in lines/cols'
complete -c tmux -n "__fish_seen_subcommand_from $joinp $splitw" -xs f -d 'full height/width'
complete -c tmux -n __fish_use_subcommand -a $killp -d 'destroy a pane'
complete -c tmux -n __fish_use_subcommand -a $killw -d 'destroy a window'
complete -c tmux -n __fish_use_subcommand -a $lastp -d 'select the previusly selected pane'
complete -c tmux -n __fish_use_subcommand -a $lastw -d 'select the previusly selected window'
complete -c tmux -n __fish_use_subcommand -a $linkw -d 'link source window to destination window'
complete -c tmux -n __fish_use_subcommand -a $lsp -d 'list panes'
complete -c tmux -n "__fish_seen_subcommand_from $lsp" -xs s -d 'all in session'
complete -c tmux -n __fish_use_subcommand -a $lsw -d 'list windows'
complete -c tmux -n __fish_use_subcommand -a $movew -d 'move window'
# TODO: Should accept shell command
complete -c tmux -n __fish_use_subcommand -a $neww -d 'create a new window'
complete -c tmux -n "__fish_seen_subcommand_from $neww" -xs k -d 'replace if exists'
complete -c tmux -n "__fish_seen_subcommand_from $neww" -xs S -d 'select if exists'
complete -c tmux -n __fish_use_subcommand -a $nextl -d 'rearrange panes in a window according to the next layout'
complete -c tmux -n __fish_use_subcommand -a $next -d 'move to the next window in the session'
# TODO: Should accept shell command
complete -c tmux -n __fish_use_subcommand -a $pipep -d 'pipe output from pane to a shell command'
complete -c tmux -n __fish_use_subcommand -a $prevl -d 'rearrange panes in a window according to the previous layout'
complete -c tmux -n __fish_use_subcommand -a $prev -d 'move to the previous window in the session'
complete -c tmux -n __fish_use_subcommand -a $renamew -d 'rename a window'
complete -c tmux -n __fish_use_subcommand -a $resizep -d 'resize a pane'
complete -c tmux -n "__fish_seen_subcommand_from $resizep" -xs M -d 'begin mouse resize'
complete -c tmux -n "__fish_seen_subcommand_from $resizep" -xs T -d 'trim below cursor'
complete -c tmux -n __fish_use_subcommand -a $resizew -d 'resize a window'
# TODO: Should accept shell command
complete -c tmux -n __fish_use_subcommand -a $respawnp -d 'reactivate a pane where a command exited'
# TODO: Should accept shell command
complete -c tmux -n __fish_use_subcommand -a $respawnw -d 'reactivate a window where a command exited'
complete -c tmux -n __fish_use_subcommand -a $rotatew -d 'rotate panes within a window'
@@ -269,21 +195,9 @@ set -l layouts 'even-horizontal even-vertical main-horizontal main-horizontal-mi
complete -c tmux -n "__fish_seen_subcommand_from $selectl" -x -a "$layouts" -d 'predefined layout'
complete -c tmux -n __fish_use_subcommand -a $selectp -d 'activate specific pane'
complete -c tmux -n "__fish_seen_subcommand_from $selectp" -xs d -d 'disable input'
complete -c tmux -n "__fish_seen_subcommand_from $selectp" -xs e -d 'enable input'
complete -c tmux -n "__fish_seen_subcommand_from $selectp" -xs l -d 'previously selected'
complete -c tmux -n "__fish_seen_subcommand_from $selectp" -xs m -d 'mark'
complete -c tmux -n "__fish_seen_subcommand_from $selectp" -xs M -d 'unmark'
complete -c tmux -n __fish_use_subcommand -a $selectw -d 'activate specific window'
complete -c tmux -n "__fish_seen_subcommand_from $selectw" -xs l -d 'previously selected'
complete -c tmux -n "__fish_seen_subcommand_from $selectw" -xs p -d 'previous'
complete -c tmux -n "__fish_seen_subcommand_from $selectw" -xs n -d 'next'
# TODO: Should accept shell command
complete -c tmux -n __fish_use_subcommand -a $splitw -d 'create a new pane by splitting target-pane'
# See also $joinp's arguments
complete -c tmux -n "__fish_seen_subcommand_from $splitw" -xs I -d 'show stdin contents'
complete -c tmux -n __fish_use_subcommand -a $swapp -d 'swap two panes'
complete -c tmux -n __fish_use_subcommand -a $swapw -d 'swap two windows'
complete -c tmux -n __fish_use_subcommand -a $unlinkw -d 'unlink target-window'
@@ -309,33 +223,6 @@ complete -c tmux -n "__fish_seen_subcommand_from $resizew $reswpawnw $rotatew $s
complete -c tmux -n "__fish_seen_subcommand_from $displayp" -xs t -d 'target client'
complete -c tmux -n "__fish_seen_subcommand_from $lsp" -xs t -d 'target'
#commands that take shell commands
complete -c tmux -x -n "__fish_seen_subcommand_from $neww $pipep $respawnp $respawnw $splitw" \
-a '(__fish_complete_subcommand --fcs-skip=2)'
# Common boolean flags. TODO: -P for "print info", -Z for "zoom"
complete -c tmux -n "__fish_seen_subcommand_from $breakp $joinp $linkw $neww $movew $splitw $swapp $swapp" -xs d -d 'do not activate'
set -l updownleftright "$resizep $resizew $selectp "
complete -c tmux -n "__fish_seen_subcommand_from $updownleftright" -xs D -d 'down'
complete -c tmux -n "__fish_seen_subcommand_from $updownleftright" -xs U -d 'up'
complete -c tmux -n "__fish_seen_subcommand_from $updownleftright" -xs L -d 'left'
complete -c tmux -n "__fish_seen_subcommand_from $updownleftright" -xs R -d 'right'
set -l before_after "$breakp $linkw $movew $neww "
complete -c tmux -n "__fish_seen_subcommand_from $before_after" -xs a -d 'after'
complete -c tmux -n "__fish_seen_subcommand_from $before_after" -xs b -d 'before'
# Boolean flags, ct'd. Unclear why these are not -a/-b for after/before
set -l updownnextprev "$rotatew $swapp "
complete -c tmux -n "__fish_seen_subcommand_from $updownnextprev" -xs D -d 'down/next'
complete -c tmux -n "__fish_seen_subcommand_from $updownnextprev" -xs U -d 'up/prev'
# Boolean flags, ct'd. When `-a` does not mean "after"
complete -c tmux -n "__fish_seen_subcommand_from $lsp $lsw" -xs a -d 'all on this server'
complete -c tmux -n "__fish_seen_subcommand_from $killp $killw" -xs a -d 'all except chosen'
complete -c tmux -n "__fish_seen_subcommand_from $prev $next" -xs a -d 'with alert'
############### End: Windows and Panes ###############
############### Begin: Key Bindings ###############

View File

@@ -1,2 +0,0 @@
complete -c unbuffer -a "(__fish_complete_subcommand)" -x
complete -c unbuffer -s p -d "Read from stdin for pipeline use, exit when stdin closes"

View File

@@ -75,7 +75,7 @@ function __fish_virsh_get_networks
set -l network_autostart $network[3]
set -l network_persistent $network[4]
set -l network_qualities $network_state (test $network_autostart = 'yes'; and echo 'autostart') (test $network_persistent = 'yes'; and echo 'persistent')
set -l network_qualities $network_state (test $network_autostart = 'yes'; and echo 'autostart') (test $network_persistent = 'yes'; and echo 'persistant')
set -l show true
if set -q argv[1]
for filter in $argv

View File

@@ -51,7 +51,7 @@ end
# don't want to inherit all completions from git
function __fish_complete_yadm_like_git
# Remove the first word from the commandline because that is "yadm"
set -l cmdline (commandline -xpc | string escape; commandline -ct)[2..-1]
set -l cmdline (commandline -xpc; commandline -ct)[2..-1]
# `yadm gitconfig` is same as `git config`
if __fish_seen_subcommand_from gitconfig

View File

@@ -1,4 +1,4 @@
# This is meant to be bound to something like ctrl-c
function __fish_cancel_commandline
commandline -f cancel-commandline
commandline -f cancel-commandline-traditional
end

View File

@@ -134,9 +134,8 @@ function __fish_complete_mount_opts
data_err={ignore,abort} \
barrier={0,1} \
user_xattr \
acl
set -l token (commandline -tc | string replace -r '^-o' -- '')
acl \
set -l token (commandline -tc | string replace -r '^-o' -- '')
set -l args (string split , -- $token)
if test (count $args) -ne 0

View File

@@ -128,14 +128,6 @@ end" >$__fish_config_dir/config.fish
complete -x -p "/etc/init.d/*" -a reload --description 'Reload service configuration'
end
#
# We want to show our completions for the [ (test) builtin, but
# we don't want to create a [.fish. test.fish will not be loaded until
# the user tries [ interactively.
#
complete -c [ --wraps test
complete -c ! --wraps not
#
# Only a few builtins take filenames; initialize the rest with no file completions
#

View File

@@ -54,8 +54,8 @@ function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mod
$legacy_bind --preset $argv -k sright forward-bigword
$legacy_bind --preset $argv -k sleft backward-bigword
bind --preset $argv alt-right nextd-or-forward-word
bind --preset $argv alt-left prevd-or-backward-word
bind --preset $argv alt-right nextd-or-forward-token
bind --preset $argv alt-left prevd-or-backward-token
bind --preset $argv alt-up history-token-search-backward
bind --preset $argv alt-down history-token-search-forward
@@ -66,8 +66,8 @@ function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mod
bind --preset $argv alt-l __fish_list_current_token
bind --preset $argv alt-o __fish_preview_current_file
bind --preset $argv alt-w __fish_whatis_current_token
bind --preset $argv ctrl-l clear-screen
bind --preset $argv ctrl-c clear-commandline
bind --preset $argv ctrl-l scrollback-push repaint
bind --preset $argv ctrl-c cancel-commandline
bind --preset $argv ctrl-u backward-kill-line
bind --preset $argv ctrl-k kill-line
bind --preset $argv ctrl-w backward-kill-path-component

View File

@@ -18,7 +18,7 @@ function __fish_whatis_current_token -d "Show man page entries or function descr
and set desc "$token - $funcinfo[5]"
case builtin
set desc (__fish_print_help $token | awk "/./ { getline; print; exit }" | string trim)
set desc (__fish_print_help $token | awk "/./ {print; exit}")
case file
set -l tmpdesc (whatis $token 2>/dev/null)

View File

@@ -57,11 +57,18 @@ function fish_default_key_bindings -d "emacs-like key binds"
bind --preset $argv alt-u upcase-word
bind --preset $argv alt-c capitalize-word
bind --preset $argv alt-backspace backward-kill-word
bind --preset $argv alt-backspace backward-kill-token
bind --preset $argv ctrl-backspace backward-kill-word
bind --preset $argv alt-delete kill-token
bind --preset $argv ctrl-delete kill-word
bind --preset $argv alt-b prevd-or-backward-word
bind --preset $argv alt-f nextd-or-forward-word
bind --preset $argv alt-b backward-word
bind --preset $argv alt-f forward-word
if test "$TERM_PROGRAM" = Apple_Terminal
# Terminal.app sends \eb for alt+left, \ef for alt+right.
# Yeah.
$legacy_bind --preset $argv alt-b prevd-or-backward-word
$legacy_bind --preset $argv alt-f nextd-or-forward-word
end
bind --preset $argv alt-\< beginning-of-buffer
bind --preset $argv alt-\> end-of-buffer

View File

@@ -0,0 +1,19 @@
function fish_jj_prompt
# If jj isn't installed, there's nothing we can do
# Return 1 so the calling prompt can deal with it
if not command -sq jj
return 1
end
jj log 2>/dev/null --no-graph --ignore-working-copy --color=always --revisions @ \
--template '
concat(
" ",
separate(" ",
format_short_change_id_with_hidden_and_divergent_info(self),
bookmarks,
tags,
if(conflict, label("conflict", "×")),
if(empty, label("empty", "(empty)"))
),
)'
end

View File

@@ -1,7 +1,8 @@
function fish_vcs_prompt --description "Print all vcs prompts"
# If a prompt succeeded, we assume that it's printed the correct info.
# This is so we don't try svn if git already worked.
fish_git_prompt $argv
fish_jj_prompt $argv
or fish_git_prompt $argv
or fish_hg_prompt $argv
or fish_fossil_prompt $argv
# The svn prompt is disabled by default because it's quite slow on common svn repositories.

View File

@@ -64,7 +64,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
# Default (command) mode
bind -s --preset :,q exit
bind -s --preset -m insert ctrl-c clear-commandline repaint-mode
bind -s --preset -m insert ctrl-c cancel-commandline repaint-mode
bind -s --preset -M default h backward-char
bind -s --preset -M default l forward-char
bind -s --preset -m insert enter execute

View File

@@ -20,7 +20,7 @@ function funced --description 'Edit function definition'
if set -q _flag_interactive
set editor fish
else if set -q _flag_editor
echo $_flag_editor | read -at editor
set editor $_flag_editor
else if set -q VISUAL
echo $VISUAL | read -at editor
else if set -q EDITOR
@@ -37,8 +37,11 @@ function funced --description 'Edit function definition'
set init function $funcname\n\nend
end
if not type -q -f "$editor[1]"
echo (_ "funced: The value for \$EDITOR '$editor' could not be used because the command '$editor[1]' could not be found") >&2
# Break editor up to get its first command (i.e. discard flags)
set -l editor_cmd
echo $editor | read -ta editor_cmd
if not type -q -f "$editor_cmd[1]"
echo (_ "funced: The value for \$EDITOR '$editor' could not be used because the command '$editor_cmd[1]' could not be found") >&2
set editor fish
end
@@ -85,7 +88,7 @@ function funced --description 'Edit function definition'
while true
set -l checksum (__fish_md5 "$tmpname")
if not $editor $tmpname
if not $editor_cmd $tmpname
echo (_ "Editing failed or was cancelled")
else
# Verify the checksum (if present) to detect potential problems

View File

@@ -34,6 +34,10 @@ function help --description 'Show help for the fish shell'
if set -q BROWSER
# User has manually set a preferred browser, so we respect that
echo $BROWSER | read -at fish_browser
if not type -q $fish_browser[1]
printf (_ 'help: %s is not a valid command: %s\n') '$fish_browser' "$fish_browser"
return 2
end
else
# No browser set up, inferring.
# We check a bunch and use the last we find.
@@ -93,6 +97,11 @@ function help --description 'Show help for the fish shell'
end
end
end
else
if not type -q $fish_browser[1]
printf (_ 'help: %s is not a valid command: %s\n') '$fish_help_browser' "$fish_browser"
return 2
end
end
# In Cygwin, start the user-specified browser using cygstart,

View File

@@ -1255,7 +1255,7 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
token.typ == ParseTokenType::string
&& !matches!(
token.keyword,
ParseKeyword::kw_end | ParseKeyword::kw_else | ParseKeyword::kw_case
ParseKeyword::kw_case | ParseKeyword::kw_end | ParseKeyword::kw_else
)
}
}
@@ -3337,6 +3337,14 @@ fn consume_excess_token_generating_error(&mut self) {
ParseTokenType::string => {
// There are three keywords which end a job list.
match tok.keyword {
ParseKeyword::kw_case => {
parse_error!(
self,
tok,
ParseErrorCode::unbalancing_case,
"'case' builtin not inside of switch block"
);
}
ParseKeyword::kw_end => {
parse_error!(
self,
@@ -3353,14 +3361,6 @@ fn consume_excess_token_generating_error(&mut self) {
"'else' builtin not inside of if block"
);
}
ParseKeyword::kw_case => {
parse_error!(
self,
tok,
ParseErrorCode::unbalancing_case,
"'case' builtin not inside of switch block"
);
}
_ => {
internal_error!(
self,

View File

@@ -21,6 +21,8 @@
#![allow(unstable_name_collisions)]
#![allow(clippy::uninlined_format_args)]
#[cfg(feature = "installable")]
use fish::common::wcs2osstring;
#[allow(unused_imports)]
use fish::future::IsSomeAnd;
use fish::{
@@ -30,7 +32,7 @@
},
common::{
escape, get_executable_path, save_term_foreground_process_group, scoped_push_replacer,
str2wcstring, wcs2osstring, wcs2string, PACKAGE_NAME, PROFILING_ACTIVE, PROGRAM_NAME,
str2wcstring, wcs2string, PACKAGE_NAME, PROFILING_ACTIVE, PROGRAM_NAME,
},
env::{
environment::{env_init, EnvStack, Environment},
@@ -42,7 +44,7 @@
fprintf, function, future_feature_flags as features,
history::{self, start_private_mode},
io::IoChain,
nix::{getpid, isatty},
nix::{getpid, getrusage, isatty, RUsage},
panic::panic_handler,
parse_constants::{ParseErrorList, ParseTreeFlags},
parse_tree::ParsedSource,
@@ -63,7 +65,6 @@
};
use std::ffi::{CString, OsStr, OsString};
use std::fs::File;
use std::mem::MaybeUninit;
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::rc::Rc;
@@ -191,10 +192,9 @@ fn install(confirm: bool, dir: PathBuf) -> bool {
return true;
}
#[cfg(any(clippy, not(feature = "installable")))]
#[cfg(clippy)]
fn install(_confirm: bool, _dir: PathBuf) -> bool {
eprintln!("Fish was built without support for self-installation");
return false;
unreachable!()
}
/// container to hold the options specified within the command line
@@ -236,13 +236,7 @@ fn tv_to_msec(tv: &libc::timeval) -> i64 {
}
fn print_rusage_self() {
let mut rs = MaybeUninit::uninit();
if unsafe { libc::getrusage(libc::RUSAGE_SELF, rs.as_mut_ptr()) } != 0 {
let s = CString::new("getrusage").unwrap();
unsafe { libc::perror(s.as_ptr()) }
return;
}
let rs: libc::rusage = unsafe { rs.assume_init() };
let rs = getrusage(RUsage::RSelf);
let rss_kb = if cfg!(target_os = "macos") {
// mac use bytes.
rs.ru_maxrss / 1024
@@ -279,7 +273,7 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
// Detect if we're running right out of the CMAKE build directory
if exec_path.starts_with(env!("CARGO_MANIFEST_DIR")) {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
FLOG!(
config,
"Running out of target directory, using paths relative to CARGO_MANIFEST_DIR:\n",
@@ -352,7 +346,7 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
PathBuf::from(home).join(DATA_DIR).join(DATA_DIR_SUBDIR)
} else {
PathBuf::from(DATA_DIR).join(DATA_DIR_SUBDIR)
Path::new(DATA_DIR).join(DATA_DIR_SUBDIR)
};
let bin = if cfg!(feature = "installable") {
exec_path.parent().map(|x| x.to_path_buf())
@@ -363,7 +357,7 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
FLOG!(config, "Using compiled in paths:");
paths = ConfigPaths {
data,
sysconf: PathBuf::from(SYSCONF_DIR).join("fish"),
sysconf: Path::new(SYSCONF_DIR).join("fish"),
doc: DOC_DIR.into(),
bin,
}
@@ -532,7 +526,7 @@ fn fish_parse_opt(args: &mut [WString], opts: &mut FishCmdOpts) -> ControlFlow<i
const PRINT_DEBUG_CATEGORIES_ARG: char = 2 as char;
const PROFILE_STARTUP_ARG: char = 3 as char;
const SHORT_OPTS: &wstr = L!("+:hPilNnvc:C:p:d:f:D:o:");
const SHORT_OPTS: &wstr = L!("+hPilNnvc:C:p:d:f:D:o:");
const LONG_OPTS: &[WOption<'static>] = &[
wopt(L!("command"), RequiredArgument, 'c'),
wopt(L!("init-command"), RequiredArgument, 'C'),
@@ -772,7 +766,7 @@ fn throwing_main() -> i32 {
.write(true)
.truncate(true)
.create(true)
.open(debug_path.clone())
.open(&debug_path)
{
Ok(dbg_file) => {
// Rust sets O_CLOEXEC by default
@@ -817,10 +811,9 @@ fn throwing_main() -> i32 {
save_term_foreground_process_group();
}
let mut paths: Option<ConfigPaths> = None;
// If we're not executing, there's no need to find the config.
if !opts.no_exec {
paths = Some(determine_config_directory_paths(OsString::from_vec(
let paths: Option<ConfigPaths> = if !opts.no_exec {
let paths = Some(determine_config_directory_paths(OsString::from_vec(
wcs2string(&args[0]),
)));
env_init(
@@ -828,7 +821,10 @@ fn throwing_main() -> i32 {
/* do uvars */ !opts.no_config,
/* default paths */ opts.no_config,
);
}
paths
} else {
None
};
// Set features early in case other initialization depends on them.
// Start with the ones set in the environment, then those set on the command line (so the
@@ -845,7 +841,7 @@ fn throwing_main() -> i32 {
// Construct the root parser!
let env = Rc::new(EnvStack::globals().create_child(true /* dispatches_var_changes */));
let parser: &Parser = &Parser::new(env, CancelBehavior::Clear);
let parser = &Parser::new(env, CancelBehavior::Clear);
parser.set_syncs_uvars(!opts.no_config);
if !opts.no_exec && !opts.no_config {
@@ -1008,7 +1004,6 @@ fn fish_xdm_login_hack_hack_hack_hack(cmds: &mut [OsString], args: &[WString]) -
return false;
}
let mut result = false;
let cmd = &cmds[0];
if cmd == "exec \"${@}\"" || cmd == "exec \"$@\"" {
// We're going to construct a new command that starts with exec, and then has the
@@ -1020,7 +1015,8 @@ fn fish_xdm_login_hack_hack_hack_hack(cmds: &mut [OsString], args: &[WString]) -
}
cmds[0] = new_cmd;
result = true;
true
} else {
false
}
result
}

View File

@@ -9,21 +9,21 @@
use std::{ops::ControlFlow, os::unix::prelude::OsStrExt};
use libc::{STDIN_FILENO, TCSANOW, VEOF, VINTR};
use libc::{STDIN_FILENO, STDOUT_FILENO, TCSANOW, VEOF, VINTR};
#[allow(unused_imports)]
use fish::future::IsSomeAnd;
use fish::{
builtins::shared::BUILTIN_ERR_UNKNOWN,
common::{shell_modes, str2wcstring, PROGRAM_NAME},
common::{shell_modes, str2wcstring, write_loop, PROGRAM_NAME},
env::env_init,
eprintf, fprintf,
input::input_terminfo_get_name,
input_common::{
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, InputEventQueue,
InputEventQueuer,
InputEventQueuer, KITTY_PROGRESSIVE_ENHANCEMENTS_QUERY,
},
key::{self, char_to_symbol, Key},
key::{char_to_symbol, Key},
panic::panic_handler,
print_help::print_help,
printf,
@@ -101,9 +101,6 @@ fn process_input(continuous_mode: bool, verbose: bool) -> i32 {
continue;
};
let c = kevt.key.codepoint;
if c == key::Invalid {
continue;
}
if verbose {
printf!("# decoded from: ");
for byte in kevt.seq.chars() {
@@ -140,6 +137,7 @@ fn setup_and_process_keys(continuous_mode: bool, verbose: bool) -> i32 {
unsafe { libc::tcsetattr(STDIN_FILENO, TCSANOW, &*shell_modes()) };
terminal_protocol_hacks();
let _ = write_loop(&STDOUT_FILENO, KITTY_PROGRESSIVE_ENHANCEMENTS_QUERY);
if continuous_mode {
eprintf!("\n");

View File

@@ -132,7 +132,7 @@ fn abbr_show(streams: &mut IoStreams) -> Option<c_int> {
for abbr in abbrs.list() {
result.clear();
let mut add_arg = |arg: &wstr| {
if !result.is_empty() && !result.ends_with("=") {
if !result.is_empty() {
result.push_str(" ");
}
result.push_utfstr(arg);

View File

@@ -475,7 +475,7 @@ pub fn commandline(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr])
rstate.cursor_pos + 1
- parse_util_get_offset_from_line(
&rstate.text,
i32::try_from(parse_util_lineno(&rstate.text, rstate.cursor_pos) - 1)
i32::try_from(parse_util_lineno(&rstate.text, rstate.cursor_pos))
.unwrap(),
)
.unwrap_or_default()
@@ -633,9 +633,7 @@ pub fn commandline(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr])
);
commandline_set_buffer(None, Some(new_pos));
} else {
streams
.out
.append(sprintf!("%lu\n", current_cursor_pos - range.start));
streams.out.append(sprintf!("%lu\n", current_cursor_pos));
}
return STATUS_CMD_OK;
}

View File

@@ -686,15 +686,15 @@ pub fn read(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> Opt
continue;
}
// todo!("don't clone")
let delimiter = opts
.delimiter
.clone()
.or_else(|| {
let ifs = parser.vars().get_unless_empty(L!("IFS"));
ifs.map(|ifs| ifs.as_string())
})
.unwrap_or_default();
let mut ifs_delimiter = WString::new();
let delimiter: &wstr = opts.delimiter.as_deref().unwrap_or_else(|| {
ifs_delimiter = parser
.vars()
.get_unless_empty(L!("IFS"))
.map(|var| var.as_string())
.unwrap_or_default();
&ifs_delimiter
});
if delimiter.is_empty() {
// Every character is a separate token with one wrinkle involving non-array mode where
@@ -735,7 +735,7 @@ pub fn read(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> Opt
if opts.delimiter.is_none() {
// We're using IFS, so tokenize the buffer using each IFS char. This is for backward
// compatibility with old versions of fish.
let tokens = split_string_tok(&buff, &delimiter, None)
let tokens = split_string_tok(&buff, delimiter, None)
.into_iter()
.map(|s| s.to_owned())
.collect();
@@ -743,7 +743,7 @@ pub fn read(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> Opt
var_ptr += 1;
} else {
// We're using a delimiter provided by the user so use the `string split` behavior.
let splits = split_about(&buff, &delimiter, usize::MAX, false)
let splits = split_about(&buff, delimiter, usize::MAX, false)
.into_iter()
.map(|s| s.to_owned())
.collect();
@@ -757,7 +757,7 @@ pub fn read(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> Opt
// compatibility with old versions of fish.
// Note the final variable gets any remaining text.
let mut var_vals: Vec<WString> =
split_string_tok(&buff, &delimiter, Some(vars_left(var_ptr)))
split_string_tok(&buff, delimiter, Some(vars_left(var_ptr)))
.into_iter()
.map(|s| s.to_owned())
.collect();
@@ -775,7 +775,7 @@ pub fn read(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> Opt
// We're using a delimiter provided by the user so use the `string split` behavior.
// We're making at most argc - 1 splits so the last variable
// is set to the remaining string.
let splits = split_about(&buff, &delimiter, argc - 1, false);
let splits = split_about(&buff, delimiter, argc - 1, false);
assert!(splits.len() <= vars_left(var_ptr));
for split in splits {
parser.set_var_and_fire(argv[var_ptr], opts.place, vec![split.to_owned()]);

View File

@@ -50,7 +50,7 @@ pub fn r#return(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) ->
Err(e) => return e,
};
let has_function_block = parser.blocks().iter().any(|b| b.is_function_call());
let has_function_block = parser.blocks_iter_rev().any(|b| b.is_function_call());
// *nix does not support negative return values, but our `return` builtin happily accepts being
// called with negative literals (e.g. `return -1`).

View File

@@ -873,7 +873,7 @@ fn builtin_break_continue(
// Paranoia: ensure we have a real loop.
// This is checked in the AST but we may be invoked dynamically, e.g. just via "eval break".
let mut has_loop = false;
for b in parser.blocks().iter().rev() {
for b in parser.blocks_iter_rev() {
if [BlockType::while_block, BlockType::for_block].contains(&b.typ()) {
has_loop = true;
break;

View File

@@ -422,45 +422,6 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> O
}
return retval;
}
STATUS_BUILDINFO => {
let version = str2wcstring(crate::BUILD_VERSION.as_bytes());
let target = str2wcstring(env!("BUILD_TARGET_TRIPLE").as_bytes());
let host = str2wcstring(env!("BUILD_HOST_TRIPLE").as_bytes());
let profile = str2wcstring(env!("BUILD_PROFILE").as_bytes());
streams.out.append(L!("Build system: "));
let buildsystem = match option_env!("CMAKE") {
Some("1") => "CMake",
_ => "Cargo",
};
streams.out.appendln(str2wcstring(buildsystem.as_bytes()));
streams.out.append(L!("Version: "));
streams.out.appendln(version);
if target == host {
streams.out.append(L!("Target (and host): "));
streams.out.appendln(target);
} else {
streams.out.append(L!("Target: "));
streams.out.appendln(target);
streams.out.append(L!("Host: "));
streams.out.appendln(host);
}
streams.out.append(L!("Profile: "));
streams.out.appendln(profile);
streams.out.append(L!("Features: "));
let features: &[&str] = &[
#[cfg(gettext)]
"gettext",
#[cfg(feature = "installable")]
"installable",
#[cfg(target_feature = "crt-static")]
"crt-static",
];
streams
.out
.appendln(str2wcstring(features.join(" ").as_bytes()));
streams.out.appendln("");
return STATUS_CMD_OK;
}
ref s => {
if !args.is_empty() {
streams.err.append(wgettext_fmt!(
@@ -473,6 +434,45 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> O
return STATUS_INVALID_ARGS;
}
match s {
STATUS_BUILDINFO => {
let version = str2wcstring(crate::BUILD_VERSION.as_bytes());
let target = str2wcstring(env!("BUILD_TARGET_TRIPLE").as_bytes());
let host = str2wcstring(env!("BUILD_HOST_TRIPLE").as_bytes());
let profile = str2wcstring(env!("BUILD_PROFILE").as_bytes());
streams.out.append(L!("Build system: "));
let buildsystem = match option_env!("CMAKE") {
Some("1") => "CMake",
_ => "Cargo",
};
streams.out.appendln(str2wcstring(buildsystem.as_bytes()));
streams.out.append(L!("Version: "));
streams.out.appendln(version);
if target == host {
streams.out.append(L!("Target (and host): "));
streams.out.appendln(target);
} else {
streams.out.append(L!("Target: "));
streams.out.appendln(target);
streams.out.append(L!("Host: "));
streams.out.appendln(host);
}
streams.out.append(L!("Profile: "));
streams.out.appendln(profile);
streams.out.append(L!("Features: "));
let features: &[&str] = &[
#[cfg(gettext)]
"gettext",
#[cfg(feature = "installable")]
"installable",
#[cfg(target_feature = "crt-static")]
"crt-static",
];
streams
.out
.appendln(str2wcstring(features.join(" ").as_bytes()));
streams.out.appendln("");
return STATUS_CMD_OK;
}
STATUS_BASENAME | STATUS_DIRNAME | STATUS_FILENAME => {
let res = parser.current_filename();
let function = res.unwrap_or_default();
@@ -599,10 +599,7 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> O
streams.out.appendln(path);
}
}
STATUS_BUILDINFO
| STATUS_SET_JOB_CONTROL
| STATUS_FEATURES
| STATUS_TEST_FEATURE => {
STATUS_SET_JOB_CONTROL | STATUS_FEATURES | STATUS_TEST_FEATURE => {
unreachable!("")
}
}

View File

@@ -852,10 +852,10 @@ fn parse_number(arg: &wstr, number: &mut Number, errors: &mut Vec<WString>) -> b
} else {
errors.push(wgettext_fmt!("Argument is not a number: '%ls'", arg));
}
} else if floating.map_or(false, |x| x.is_nan()) {
} else if floating.is_ok_and(|x| x.is_nan()) {
// NaN is an error as far as we're concerned.
errors.push(wgettext!("Not a number").to_owned());
} else if floating.map_or(false, |x| x.is_infinite()) {
} else if floating.is_ok_and(|x| x.is_infinite()) {
errors.push(wgettext!("Number is infinite").to_owned());
} else if integral == Err(Error::Overflow) {
errors.push(wgettext_fmt!("Result too large: %ls", arg));

View File

@@ -169,7 +169,7 @@ pub fn r#type(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> O
if !opts.get_type {
streams.out.append(wgettext_fmt!("%ls is a builtin\n", arg));
} else if opts.get_type {
streams.out.append(L!("builtin\n"));
streams.out.append(wgettext!("builtin\n"));
}
if !opts.all {
continue;

View File

@@ -36,13 +36,22 @@ fn find_wait_handles(
handles: &mut Vec<WaitHandleRef>,
) -> bool {
// Has a job already completed?
// TODO: we can avoid traversing this list if searching by pid.
let mut matched = false;
let wait_handles: &mut WaitHandleStore = &mut parser.mut_wait_handles();
for wh in wait_handles.iter() {
if wait_handle_matches(query, wh) {
handles.push(wh.clone());
matched = true;
match query {
WaitHandleQuery::Pid(pid) => {
if let Some(wh) = wait_handles.get_by_pid(pid) {
handles.push(wh);
matched = true;
}
}
_ => {
for wh in wait_handles.iter() {
if wait_handle_matches(query, wh) {
handles.push(wh.clone());
matched = true;
}
}
}
}

View File

@@ -119,8 +119,10 @@ pub struct EscapeFlags: u32 {
const NO_TILDE = 1 << 2;
/// Replace non-printable control characters with Unicode symbols.
const SYMBOLIC = 1 << 3;
/// Escape : and =
const SEPARATORS = 1 << 4;
/// Escape ,
const COMMA = 1 << 4;
const COMMA = 1 << 5;
}
}
@@ -181,6 +183,7 @@ pub fn escape_string(s: &wstr, style: EscapeStringStyle) -> WString {
/// Escape a string in a fashion suitable for using in fish script.
fn escape_string_script(input: &wstr, flags: EscapeFlags) -> WString {
let escape_printables = !flags.contains(EscapeFlags::NO_PRINTABLES);
let escape_separators = flags.contains(EscapeFlags::SEPARATORS);
let escape_comma = flags.contains(EscapeFlags::COMMA);
let no_quoted = flags.contains(EscapeFlags::NO_QUOTED);
let no_tilde = flags.contains(EscapeFlags::NO_TILDE);
@@ -292,6 +295,13 @@ fn escape_string_script(input: &wstr, flags: EscapeFlags) -> WString {
ANY_STRING_RECURSIVE => {
out += L!("**");
}
':' | '=' => {
if escape_separators {
need_escape = true;
out.push('\\');
}
out.push(c);
}
',' => {
if escape_comma {
need_escape = true;
@@ -1359,9 +1369,7 @@ pub fn valid_func_name(name: &wstr) -> bool {
/// A rusty port of the C++ `write_loop()` function from `common.cpp`. This should be deprecated in
/// favor of native rust read/write methods at some point.
///
/// Returns the number of bytes written or an IO error.
pub fn write_loop<Fd: AsRawFd>(fd: &Fd, buf: &[u8]) -> std::io::Result<usize> {
pub fn write_loop<Fd: AsRawFd>(fd: &Fd, buf: &[u8]) -> std::io::Result<()> {
let fd = fd.as_raw_fd();
let mut total = 0;
while total < buf.len() {
@@ -1377,7 +1385,7 @@ pub fn write_loop<Fd: AsRawFd>(fd: &Fd, buf: &[u8]) -> std::io::Result<usize> {
}
}
}
Ok(total)
Ok(())
}
/// A rusty port of the C++ `read_loop()` function from `common.cpp`. This should be deprecated in

View File

@@ -10,7 +10,7 @@
};
use crate::{
common::charptr2wcstring,
common::{charptr2wcstring, escape_string, EscapeFlags, EscapeStringStyle},
reader::{get_quote, is_backslashed},
util::wcsfilecmp,
wutil::sprintf,
@@ -96,7 +96,7 @@ pub struct CompletionMode {
bitflags! {
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct CompleteFlags: u16 {
pub struct CompleteFlags: u8 {
/// Do not insert space afterwards if this is the only completion. (The default is to try insert
/// a space).
const NO_SPACE = 1 << 0;
@@ -115,8 +115,6 @@ pub struct CompleteFlags: u16 {
const DUPLICATES_ARGUMENT = 1 << 6;
/// This completes not just a token but replaces an entire line.
const REPLACES_LINE = 1 << 7;
/// If replacing the entire token, keep the "foo=" prefix.
const KEEP_VARIABLE_OVERRIDE_PREFIX = 1 << 8;
}
}
@@ -739,16 +737,13 @@ fn perform_for_commandline_impl(&mut self, cmdline: WString) {
if cmd_tok.location_in_or_at_end_of_source_range(cursor_pos) {
let equals_sign_pos = variable_assignment_equals_pos(current_token);
if let Some(pos) = equals_sign_pos {
let first = self.completions.len();
self.complete_param_expand(
&current_token[..pos + 1],
&current_token[pos + 1..],
/*do_file=*/ true,
/*handle_as_special_cd=*/ false,
cur_tok.is_unterminated_brace,
);
for c in &mut self.completions[first..] {
c.flags |= CompleteFlags::KEEP_VARIABLE_OVERRIDE_PREFIX;
}
return;
}
// Complete command filename.
@@ -847,6 +842,7 @@ fn perform_for_commandline_impl(&mut self, cmdline: WString) {
// This function wants the unescaped string.
self.complete_param_expand(
L!(""),
current_argument,
do_file,
handle_as_special_cd,
@@ -1528,6 +1524,7 @@ fn complete_param_for_command(
/// Perform generic (not command-specific) expansions on the specified string.
fn complete_param_expand(
&mut self,
variable_override_prefix: &wstr,
s: &wstr,
do_file: bool,
handle_as_special_cd: bool,
@@ -1568,7 +1565,8 @@ fn complete_param_expand(
// foo=bar => expand the whole thing, and also just bar
//
// We also support colon separator (#2178). If there's more than one, prefer the last one.
let sep_index = if get_quote(s, s.len()).is_some() {
let quoted = get_quote(s, s.len()).is_some();
let sep_index = if quoted {
None
} else {
let mut end = s.len();
@@ -1586,15 +1584,50 @@ fn complete_param_expand(
};
let complete_from_start = sep_index.is_none() || !string_prefixes_string(L!("-"), s);
let first_from_start = self.completions.len();
if let Some(sep_index) = sep_index {
let sep_string = s.slice_from(sep_index + 1);
let mut local_completions = Vec::new();
if matches!(
expand_string(
sep_string.to_owned(),
&mut local_completions,
flags,
self.ctx,
None,
)
.result,
ExpandResultCode::error | ExpandResultCode::overflow
) {
FLOGF!(complete, "Error while expanding string '%ls'", sep_string);
}
// Any COMPLETE_REPLACES_TOKEN will also stomp the separator. We need to "repair" them by
// inserting our separator and prefix.
Self::escape_opening_brackets(&mut local_completions, s);
Self::escape_separators(
&mut local_completions,
variable_override_prefix,
self.flags.autosuggestion,
true,
quoted,
);
let prefix_with_sep = s.as_char_slice()[..sep_index + 1].into();
for comp in &mut local_completions {
comp.prepend_token_prefix(prefix_with_sep);
}
if !self.completions.extend(local_completions) {
return;
}
}
if complete_from_start {
let mut flags = flags;
// Don't do fuzzy matching for files if the string begins with a dash (issue #568). We could
// consider relaxing this if there was a preceding double-dash argument.
if string_prefixes_string(L!("-"), s) {
flags -= ExpandFlags::FUZZY_MATCH;
}
let first = self.completions.len();
if matches!(
expand_to_receiver(s.to_owned(), &mut self.completions, flags, self.ctx, None)
.result,
@@ -1602,53 +1635,50 @@ fn complete_param_expand(
) {
FLOGF!(complete, "Error while expanding string '%ls'", s);
}
Self::escape_opening_brackets(&mut self.completions[first_from_start..], s);
}
let Some(sep_index) = sep_index else {
return;
};
// We generally expand both, the whole token ("foo=bar") and also just the "bar"
// suffix. If the whole token is a valid path prefix, completions of just the suffix
// are probably false positives, and are confusing when I'm using completions to list
// directory contents. Apply a wonky heuristic to work around the most visible case --
// the empty suffix -- where all files in $PWD are completed/autosuggested.
if self.completions[first_from_start..]
.iter()
.any(|c| !c.replaces_token())
&& sep_index + 1 == s.len()
{
return;
}
let sep_string = s.slice_from(sep_index + 1);
let mut local_completions = Vec::new();
if matches!(
expand_string(
sep_string.to_owned(),
&mut local_completions,
flags,
self.ctx,
None,
)
.result,
ExpandResultCode::error | ExpandResultCode::overflow
) {
FLOGF!(complete, "Error while expanding string '%ls'", sep_string);
}
Self::escape_opening_brackets(&mut local_completions, s);
// Any COMPLETE_REPLACES_TOKEN will also stomp the separator. We need to "repair" them by
// inserting our separator and prefix.
let prefix_with_sep = s.as_char_slice()[..sep_index + 1].into();
for comp in &mut local_completions {
comp.prepend_token_prefix(prefix_with_sep);
}
if !self.completions.extend(local_completions) {
return;
Self::escape_opening_brackets(&mut self.completions[first..], s);
let have_token = !s.is_empty();
Self::escape_separators(
&mut self.completions[first..],
variable_override_prefix,
self.flags.autosuggestion,
have_token,
quoted,
);
}
}
fn escape_separators(
completions: &mut [Completion],
variable_override_prefix: &wstr,
append_only: bool,
have_token: bool,
is_quoted: bool,
) {
for c in completions {
if is_quoted && !c.replaces_token() {
continue;
}
// clone of completion_apply_to_command_line
let add_space = !c.flags.contains(CompleteFlags::NO_SPACE);
let no_tilde = c.flags.contains(CompleteFlags::DONT_ESCAPE_TILDES);
let mut escape_flags = EscapeFlags::SEPARATORS;
if append_only || !add_space || (!c.replaces_token() && have_token) {
escape_flags.insert(EscapeFlags::NO_QUOTED);
}
if no_tilde {
escape_flags.insert(EscapeFlags::NO_TILDE);
}
if c.replaces_token() {
c.completion = variable_override_prefix.to_owned()
+ &escape_string(&c.completion, EscapeStringStyle::Script(escape_flags))[..];
} else {
c.completion =
escape_string(&c.completion, EscapeStringStyle::Script(escape_flags));
}
assert!(!c.flags.contains(CompleteFlags::DONT_ESCAPE));
c.flags |= CompleteFlags::DONT_ESCAPE;
}
}
/// Complete the specified string as an environment variable.
/// Returns `true` if this was a variable, so we should stop completion.
fn complete_variable(&mut self, s: &wstr, start_offset: usize) -> bool {
@@ -1676,7 +1706,7 @@ fn complete_variable(&mut self, s: &wstr, start_offset: usize) -> bool {
};
let mut desc = WString::new();
if self.flags.descriptions && !self.flags.autosuggestion {
if self.flags.descriptions && self.flags.autosuggestion {
// $history can be huge, don't put all of it in the completion description; see
// #6288.
if env_name == "history" {

View File

@@ -1,3 +1,5 @@
use std::ops::Range;
#[allow(unused_imports)]
use crate::future::IsSomeAnd;
use crate::highlight::HighlightSpec;
@@ -142,31 +144,8 @@ pub fn at(&self, idx: usize) -> char {
self.text.char_at(idx)
}
pub fn line_at_cursor(&self) -> &wstr {
let start = self.text[0..self.position()]
.as_char_slice()
.iter()
.rposition(|&c| c == '\n')
.map(|newline| newline + 1)
.unwrap_or(0);
let end = self.text[self.position()..]
.as_char_slice()
.iter()
.position(|&c| c == '\n')
.map(|pos| self.position() + pos)
.unwrap_or(self.len());
// Remove any traililng newline
self.text[start..end].trim_matches('\n')
}
pub fn clear(&mut self) {
if self.is_empty() {
return;
}
self.push_edit(
Edit::new(0..self.len(), L!("").to_owned()),
/*allow_coalesce=*/ false,
);
pub fn offset_to_line(&self, offset: usize) -> usize {
self.text[0..offset].chars().filter(|&c| c == '\n').count()
}
/// Modify the commandline according to @edit. Most modifications to the
@@ -186,15 +165,15 @@ pub fn push_edit(&mut self, mut edit: Edit, allow_coalesce: bool) {
return;
}
if range.is_empty() && edit.replacement.is_empty() {
return; // nop
}
// Assign a new group id or propagate the old one if we're in a logical grouping of edits
if self.edit_group_level.is_some() {
edit.group_id = Some(self.edit_group_id);
}
let edit_does_nothing = range.is_empty() && edit.replacement.is_empty();
if edit_does_nothing {
return;
}
if self.undo_history.edits_applied != self.undo_history.edits.len() {
// After undoing some edits, the user is making a new edit;
// we are about to create a new edit branch.
@@ -362,3 +341,27 @@ fn cursor_position_after_edit(edit: &Edit) -> usize {
let removed = chars_deleted_left_of_cursor(edit);
cursor.saturating_sub(removed)
}
pub fn range_of_line_at_cursor(buffer: &wstr, cursor: usize) -> Range<usize> {
let start = buffer[0..cursor]
.as_char_slice()
.iter()
.rposition(|&c| c == '\n')
.map(|newline| newline + 1)
.unwrap_or(0);
let mut end = buffer[cursor..]
.as_char_slice()
.iter()
.position(|&c| c == '\n')
.map(|pos| cursor + pos)
.unwrap_or(buffer.len());
// Remove any trailing newline
if end != start && buffer.char_at(end - 1) == '\n' {
end -= 1;
}
start..end
}
pub fn line_at_cursor(buffer: &wstr, cursor: usize) -> &wstr {
&buffer[range_of_line_at_cursor(buffer, cursor)]
}

View File

@@ -27,7 +27,7 @@
use crate::wutil::{fish_wcstol, wgetcwd, wgettext};
use std::sync::atomic::Ordering;
use libc::{c_int, uid_t, STDOUT_FILENO, _IONBF};
use libc::{c_int, confstr, uid_t, STDOUT_FILENO, _IONBF};
use once_cell::sync::OnceCell;
use std::collections::HashMap;
use std::ffi::CStr;
@@ -568,7 +568,7 @@ fn setup_user(vars: &EnvStack) {
/// Make sure the PATH variable contains something.
fn setup_path() {
use crate::libc::{confstr, _CS_PATH};
use crate::libc::_CS_PATH;
let vars = EnvStack::globals();
let path = vars.get_unless_empty(L!("PATH"));

View File

@@ -14,7 +14,7 @@
use crate::wchar::prelude::*;
use crate::wutil::fish_wcstol_radix;
use lazy_static::lazy_static;
use once_cell::sync::Lazy;
use std::cell::{RefCell, UnsafeCell};
use std::collections::HashSet;
use std::ffi::CString;
@@ -201,16 +201,28 @@ fn changed_exported(&mut self) {
}
}
// RefCell except we promise it can be used as Sync.
// Safety: in order to do anything with this, the caller must be holding ENV_LOCK.
struct EnvNodeSyncCell(RefCell<EnvNode>);
impl EnvNodeSyncCell {
fn new(node: EnvNode) -> Self {
Self(RefCell::new(node))
}
}
unsafe impl Sync for EnvNodeSyncCell {}
/// EnvNodeRef is a reference to an EnvNode. It may be shared between different environments.
/// The type Arc<RefCell<...>> may look suspicious, but all accesses to the EnvNode are protected by a global lock.
/// All accesses to the EnvNode are protected by a global lock.
#[derive(Clone)]
struct EnvNodeRef(Arc<RefCell<EnvNode>>);
struct EnvNodeRef(Arc<EnvNodeSyncCell>);
impl Deref for EnvNodeRef {
type Target = RefCell<EnvNode>;
fn deref(&self) -> &Self::Target {
&self.0
&self.0 .0
}
}
@@ -219,7 +231,7 @@ fn new(is_new_scope: bool, next: Option<EnvNodeRef>) -> EnvNodeRef {
// Accesses are protected by the global lock.
#[allow(unknown_lints)]
#[allow(clippy::arc_with_non_send_sync)]
EnvNodeRef(Arc::new(RefCell::new(EnvNode {
EnvNodeRef(Arc::new(EnvNodeSyncCell::new(EnvNode {
env: VarTable::new(),
new_scope: is_new_scope,
export_gen: 0,
@@ -248,9 +260,6 @@ fn iter(&self) -> EnvNodeIter {
}
}
// Safety: in order to do anything with an EnvNodeRef, the caller must be holding ENV_LOCK.
unsafe impl Sync for EnvNodeRef {}
/// Helper to iterate over a chain of EnvNodeRefs.
struct EnvNodeIter {
current: Option<EnvNodeRef>,
@@ -276,10 +285,7 @@ fn next(&mut self) -> Option<EnvNodeRef> {
}
}
lazy_static! {
// All accesses to the EnvNode are protected by a global lock.
static ref GLOBAL_NODE: EnvNodeRef = EnvNodeRef::new(false, None);
}
static GLOBAL_NODE: Lazy<EnvNodeRef> = Lazy::new(|| EnvNodeRef::new(false, None));
/// Recursive helper to snapshot a series of nodes.
fn copy_node_chain(node: &EnvNodeRef) -> EnvNodeRef {
@@ -293,7 +299,7 @@ fn copy_node_chain(node: &EnvNodeRef) -> EnvNodeRef {
};
#[allow(unknown_lints)]
#[allow(clippy::arc_with_non_send_sync)]
EnvNodeRef(Arc::new(RefCell::new(new_node)))
EnvNodeRef(Arc::new(EnvNodeSyncCell::new(new_node)))
}
/// A struct wrapping up parser-local variables. These are conceptually variables that differ in

16
src/env/var.rs vendored
View File

@@ -102,7 +102,7 @@ pub struct EnvVarFlags: u8 {
pub struct EnvVar {
/// The list of values in this variable.
/// Arc allows for cheap copying
values: Arc<Box<[WString]>>,
values: Arc<[WString]>,
/// The variable's flags.
flags: EnvVarFlags,
}
@@ -111,8 +111,8 @@ impl Default for EnvVar {
fn default() -> Self {
use std::sync::OnceLock;
/// A shared read-only empty list.
static EMPTY_LIST: OnceLock<Arc<Box<[WString]>>> = OnceLock::new();
let empty_list = EMPTY_LIST.get_or_init(|| Arc::new(Box::new([])));
static EMPTY_LIST: OnceLock<Arc<[WString]>> = OnceLock::new();
let empty_list = EMPTY_LIST.get_or_init(|| Arc::new([]));
EnvVar {
values: Arc::clone(empty_list),
@@ -130,7 +130,7 @@ pub fn new(value: WString, flags: EnvVarFlags) -> Self {
/// Creates a new `EnvVar`.
pub fn new_vec(values: Vec<WString>, flags: EnvVarFlags) -> Self {
EnvVar {
values: Arc::new(values.into_boxed_slice()),
values: values.into(),
flags,
}
}
@@ -199,15 +199,15 @@ pub fn get_delimiter(&self) -> char {
}
/// Returns a copy of the variable with new values.
pub fn setting_vals(&mut self, values: Vec<WString>) -> Self {
pub fn setting_vals(&self, values: Vec<WString>) -> Self {
EnvVar {
values: Arc::new(values.into_boxed_slice()),
values: values.into(),
flags: self.flags,
}
}
/// Returns a copy of the variable with the export flag changed.
pub fn setting_exports(&mut self, export: bool) -> Self {
pub fn setting_exports(&self, export: bool) -> Self {
let mut flags = self.flags;
flags.set(EnvVarFlags::EXPORT, export);
EnvVar {
@@ -217,7 +217,7 @@ pub fn setting_exports(&mut self, export: bool) -> Self {
}
/// Returns a copy of the variable with the path variable flag changed.
pub fn setting_pathvar(&mut self, pathvar: bool) -> Self {
pub fn setting_pathvar(&self, pathvar: bool) -> Self {
let mut flags = self.flags;
flags.set(EnvVarFlags::PATHVAR, pathvar);
EnvVar {

View File

@@ -2,7 +2,7 @@
use crate::complete::complete_invalidate_path;
use crate::curses::{self, Term};
use crate::env::{setenv_lock, unsetenv_lock, EnvMode, EnvStack, Environment};
use crate::env::{CURSES_INITIALIZED, DEFAULT_READ_BYTE_LIMIT, READ_BYTE_LIMIT, TERM_HAS_XN};
use crate::env::{CURSES_INITIALIZED, READ_BYTE_LIMIT, TERM_HAS_XN};
use crate::flog::FLOG;
use crate::function;
use crate::input_common::{update_wait_on_escape_ms, update_wait_on_sequence_key_ms};
@@ -339,9 +339,15 @@ fn handle_read_limit_change(vars: &EnvStack) {
}
});
// Clippy should recognize comments in an empty match branch as a valid pattern!
#[allow(clippy::single_match)]
match read_byte_limit {
Some(new_limit) => READ_BYTE_LIMIT.store(new_limit, Ordering::Relaxed),
None => READ_BYTE_LIMIT.store(DEFAULT_READ_BYTE_LIMIT, Ordering::Relaxed),
None => {
// TODO: reset READ_BYTE_LIMIT to the default value on receiving an invalid value
// instead of persisting the previous value, which may or may not have been the
// default.
}
}
}

View File

@@ -522,13 +522,13 @@ fn open_temporary_file(
}
/// Writes our state to the fd. path is provided only for error reporting.
fn write_to_fd(&mut self, fd: impl AsFd, path: &wstr) -> std::io::Result<usize> {
fn write_to_fd(&mut self, fd: impl AsFd, path: &wstr) -> std::io::Result<()> {
let fd = fd.as_fd();
let contents = Self::serialize_with_vars(&self.vars);
let res = write_loop(&fd, &contents);
match res.as_ref() {
Ok(_) => {
Ok(()) => {
// Since we just wrote out this file, it matches our internal state; pretend we read from it.
self.last_read_file = file_id_for_fd(fd);
}
@@ -602,9 +602,9 @@ fn generate_callbacks_and_update_exports(
let existing = self.vars.get(key);
// See if the value has changed.
let old_exports = existing.map_or(false, |v| v.exports());
let old_exports = existing.is_some_and(|v| v.exports());
let export_changed = old_exports != new_entry.exports();
let value_changed = existing.map_or(false, |v| v != new_entry);
let value_changed = existing.is_some_and(|v| v != new_entry);
if export_changed || value_changed {
self.export_generation += 1;
}

Some files were not shown because too many files have changed in this diff Show More