Commit graph

1424 commits

Author SHA1 Message Date
Mahmoud Al-Qudsi
c90ac7bf7f Fix tests on macOS 10.10
All usages of `mktemp` must go through the (fish-only) `mktemp` test function
that abstracts over the differences across multiple platforms/flavors.

Tests can be easily run individually via `ninja -C build test_xxx` and there
isn't a good reason to randomly manually override $HOME and $XDG_CONFIG_HOME for
a test here and a test there.

If it's absolutely necessary, littlecheck.py should be extended to support a
`%temp` variable initialized to a temporary directory and that can be used
instead of calling out to the platform-provided `mktemp` via a subshell.
2022-09-22 17:39:28 -05:00
Fabian Boehm
88e578a9ed Remove superfluous CHECK lines
Oops
2022-09-21 18:37:38 +02:00
Fabian Boehm
3dded49b9b tests/checks/test: Attempt to fix on old Ubuntu
For unknown reasons, the i686 launchpad builders fail on this date,
but apparently not the others.

Let's just remove it, we've tested dates older than the epoch, this is
slightly redundant.
2022-09-21 18:20:05 +02:00
Mahmoud Al-Qudsi
ed67f2d221 Drop a now-incorrect check test from checks/git.fish
As discussed in #9221, a bug in the autocomplete that was fixed in 66391922
caused completions to be incorrectly suppressed. The dropped test/check was
inadvertently relying on the buggy behavior and expected a git invocation to
generate no completions but there are, in fact, completions now that the bug has
been resolved.

cc @faho: I'm not sure if you want to replace this with a different check that
actually doesn't yield any completions or if you're happy with it just being
dropped.
2022-09-20 21:56:54 -05:00
Fabian Boehm
4ffcbe3526 tests/path: Allow a little slack
This was 86400 on some systems but 82800 on mine. I think that's a
timezone thing?
2022-09-20 16:17:32 +02:00
Fabian Boehm
9493e7725f tests/test: Don't use seconds in the mtime
This fails on old Ubuntu with:

> touch: invalid date format ‘190112112040.39’

Because we don't actually need the seconds here, we just use minute
resolution. It's fine.

Also use `path mtime`, because that's a portable way to get the mtime.
2022-09-20 16:10:17 +02:00
Fabian Boehm
8b1da4b63d path: Actually use mtime instead of ctime
Fixes #9222
2022-09-20 16:10:17 +02:00
Mahmoud Al-Qudsi
472fc3ec10 [tests] Fix pre-epoch test workaround on non-Linux
I forgot `stat` is non-portable. There's no great way to portably get a
machine-readable representation of stat(2) for a file. I don't want to ship our
own lstat(2) wrapper executable just for this test and don't want to fork out to
python or perl for this either - I just wanted to get the tests to pass under
WSL :'(

Anyway, just give up and make it skip just for WSL. If another OS fails this
test in the future, the comments and existing workaround will make it easy to
figure out what the problem is and what needs to be done. We'll cross that
bridge when we get there.
2022-09-16 19:38:49 -05:00
Mahmoud Al-Qudsi
613ecfc7e4 Fix pre-epoch test workaround
It turns out that not all systems print an unsigned integer as the output of
`stat -c %Y xxx` and the leading `-` can be misinterpreted as a parameter to
`string match`.
2022-09-16 18:58:21 -05:00
Mahmoud Al-Qudsi
f97650bf9a Fix stale references to getch() 2022-09-16 18:26:49 -05:00
Mahmoud Al-Qudsi
f1266dd8f5 [tests] Add count to "Wacky Handler" text
This makes it easier to figure out where the failure is taking place when the
output mismatches and the contents of the buffer are printed.
2022-09-16 18:26:49 -05:00
Mahmoud Al-Qudsi
32f7f5bd32 [tests] Increase tmux-sleep duration when not under CI
The tmux-complete test would regularly fail for me under WSL (AMD TR 1950X)
without this small increase in sleep time.
2022-09-16 18:26:49 -05:00
Mahmoud Al-Qudsi
30cd330b98 Fix test.fish pre-epoch comparisons on WSL and others
There's no guarantee (nor requirement) that the filesystem support pre-epoch
modification dates. If it doesn't, the `test` tests were failing to get the
expected results.

Skip the test if it seems the fs doesn't support pre-epoch timestamps
(determined by pre-epoch mt of `oldest` evaluating to 0 or the unix epoch).
2022-09-16 16:24:00 -05:00
Mahmoud Al-Qudsi
d2f6c925e1 Add checks for incomplete escape sequences
Also codify in tests the current, case-sensitive behavior of \C vs \c
2022-09-16 15:44:33 -05:00
Maxime Bouillot
d50e9ffff3
Add the possibility to ignore arguments in alliases (#9199)
* Replace ";" with "\n" in alias-generated functions

This can let us add a "#" in our aliases to make
them ignore additional arguments.

* Update changelog about aliases that ignore arguments

* Update test for alias.fish

This is now compliant with the aliases that can
ignore arguments.
2022-09-11 09:55:11 +02:00
ridiculousfish
5cf0778207 Claim the tty unconditionally in reader_data_t::readline
When fish runs with job control enabled, it transfers ownership of the
tty to a child process, and then reclaims the tty after the process
exits. If job control is disabled then fish does not transfer or reclaim
the tty.

It may happen that the child process creates a pgroup and then transfers
the tty to it. In that case fish will not attempt to reclaim the tty, as
fish did not transfer it. Then when fish reads from stdin it will
receive SIGTTIN instead of data.

Fix this by unconditionally claiming the tty in readline().

Fixes #9181
2022-09-09 13:43:29 -07:00
Fabian Boehm
bc1a5ba033 Test division by zero with min
This would actually return any finite argument before!
2022-09-09 18:52:45 +02:00
Fabian Boehm
24fd26ae6e Fix error for vararg functions with zero arguments 2022-09-09 18:52:45 +02:00
Fabian Boehm
c284c4ca99 Add length also for too-many/few-args error 2022-09-09 18:52:45 +02:00
Fabian Boehm
a3ee7da812 math: Add length to missing operator error 2022-09-09 18:52:45 +02:00
Fabian Boehm
52e065e479 math: Add error length
Like we now do for syntax errors, this marks the extent of the error.

Currently for unknown functions only, would be cool for division too
2022-09-09 18:52:45 +02:00
Fabian Boehm
5edba044a3 math: Give a proper error for division by zero
This errored out *later* because the result was infinite or NaN, but
it didn't actually stop evaluation.

I'm not sure if there is a way to get floating point math to turn an
infinity back into something that doesn't depend on a literal
infinity, but division by zero conceptually isn't a thing we can
support.

There's entire branches of maths dedicated to figuring out what
dividing by "basically zero" means and we don't have to get into it.
2022-09-09 18:52:45 +02:00
Fabian Boehm
41c22d5e60 Add string shorten
This is essentially the inverse of `string pad`.
Where that adds characters to get up to the specified width,
this adds an ellipsis to a string if it goes over a specific maximum width.
The char can be given, but defaults to our ellipsis string.
("…" if the locale can handle it and "..." otherwise)

If the ellipsis string is empty, it just truncates.

For arguments given via argv, it goes line-by-line,
because otherwise length makes no sense.

If "--no-newline" is given, it adds an ellipsis instead and removes all subsequent lines.

Like pad and `length --visible`, it goes by visible width,
skipping recognized escape sequences, as those have no influence on width.

The default target width is the shortest of the given widths that is non-zero.

If the ellipsis is already wider than the target width,
we truncate instead. This is safer overall, so we don't e.g. move into a new line.
This is especially important given our default ellipsis might be width 3.
2022-09-09 18:49:57 +02:00
Johannes Altmanninger
3b30d92b62 Commit transient edit when closing pager
When selecting items in the pager, only the latest of those items is kept
in the edit history, as so-called transient edit.  Each new transient edit
evicts any old transient edit (via undo).

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

Fixes #9160
2022-08-31 07:49:49 +02:00
Fabian Boehm
9e9c73e46a tests/signals.py: Kill leftover sleeps from python
This starts two sleep processes and expects them to be killed on
SIGHUP.

Unfortunately, if this ever fails the second run will also fail
because it'll see the old sleep still lying around (because it'll run
for 130 seconds).

So, what we do is:

1. Keep the pids for these specific sleeps
2. Check if any of them are still running (and only fail for them)
3. Kill them from python

Fixes #9152
2022-08-23 18:47:52 +02:00
Fabian Boehm
40733ca25b If relative path was used, use it
This was inadvertently changed in
ed78fd2a5f

Fixes #9143
2022-08-15 20:01:50 +02:00
Fabian Boehm
8d7416048d Don't skip caret for some errors
This checked specifically for "| and" and "a=b" and then just gave the
error without a caret at all.

E.g. for a /tmp/broken.fish that contains

```fish
echo foo

echo foo | and cat
```

This would print:

```
/tmp/broken.fish (line 3): The 'and' command can not be used in a pipeline
warning: Error while reading file /tmp/broken.fish
```

without any indication other than the line number as to the location
of the error.

Now we do

```
/tmp/broken.fish (line 3): The 'and' command can not be used in a pipeline
echo foo | and cat
           ^~^
warning: Error while reading file /tmp/broken.fish
```

Another nice one:

```
fish --no-config -c 'echo notprinted; echo foo; a=b'
```

failed to give the error message!

(Note: Is it really a "warning" if we failed to read the one file we
wer told to?)

We should check if we should either centralize these error messages
completely, or always pass them and remove this "code" system, because
it's only used in some cases.
2022-08-12 18:38:47 +02:00
Fabian Boehm
232ca25ff9 Add length to the parse_util syntax errors 2022-08-12 18:38:47 +02:00
Fabian Boehm
4b921cbc08 Clamp error carets to the end instead of refusing to print
This skipped printing a "^" line if the start or length of the error
was longer than the source.

That seems like the correc thing at first glance, however it means
that the caret line isn't skipped *if the file goes on*.

So, for example

```fish
echo "$abc["
```

by itself, in a file or via `fish -c`, would not print an error, but

```fish
echo "$abc["
true
```

would. That's not a great way to print errors.

So instead we just.. imagine the start was at most at the end.

The underlying issue why `echo "$abc["` causes this is that `wcstol`
didn't move the end pointer for the index value (because there is no
number there). I'd fix this, but apparently some of
our recursive variable calls absolutely rely on this position value.
2022-08-12 18:38:47 +02:00
Fabian Boehm
c3fb927c9a Add more tests
These were correct, but littlecheck escapes quotes!
2022-08-12 18:38:47 +02:00
Fabian Boehm
c1bf06d5b1 Print "^^" for a 2-wide error 2022-08-12 18:38:47 +02:00
Fabian Boehm
eaf92918e6 Fix error offset for command (foo)
This used the decorated statement offset when the expansion errors
refer to the command without decoration.
2022-08-12 18:38:47 +02:00
Fabian Boehm
a4fd3c194e Pass location of the *command* node without decorators
Fixes error location for unknown commands
2022-08-12 18:38:47 +02:00
Fabian Boehm
150409eabd Add acceptable errors to tests 2022-08-12 18:38:47 +02:00
Fabian Boehm
b2eea4b46f complete: Don't load completions if command isn't in $PATH
This stops us from loading the completions for e.g. `./foo` if there
is no `foo` in path.

This is because the completion scripts will call an unqualified `foo`,
and then error out.

This of course means if the script would work because it never calls
the command, we still don't load it.

Pathed completions via `complete --path` should be unaffected because
they aren't autoloaded anyway.

Workaround for #3117
Fixes #9133
2022-08-11 17:05:32 +02:00
Fabian Boehm
2191faf17e Fix tests
Turns out we checked one of the descriptions I had adjusted. Oops!
2022-08-10 18:02:12 +02:00
Fabian Boehm
37f7818bbb printf: Ignore any options
This was misguidedly "fixed" in
9e08609f85, which made printf error out
with any "-"-prefixed words as the first argument.

Note: This means currently `printf --help` doesn't print the help.
This also matches `echo`, and we currently don't have anything to make
a literal `--help` execute a builtin help except for keywords. Oh well.

Fixes #9132
2022-08-10 16:55:56 +02:00
Fabian Boehm
b89249de98 Reset the read byte limit to the default when unset
This used to be kept, so e.g. testing it with

    fish_read_limit=5 echo (string repeat -n 10 a)

would cause the prompt and such to error as well.

Also there was no good way to get back to the default value
afterwards.
2022-08-09 19:59:10 +02:00
Fabian Boehm
eac808a819
string repeat: Don't allocate repeated string all at once (#9124)
* string repeat: Don't allocate repeated string all at once

This used to allocate one string and fill it with the necessary
repetitions, which could be a very very large string.

Now, it instead uses one buffer and fills it to a chunk size,
and then writes that.

This fixes:

1. We no longer crash with too large max/count values. Before they
caused a bad_alloc because we tried to fill all RAM.
2. We no longer fill all RAM if given a big-but-not-too-big value. You
could've caused fish to eat *most* of your RAM here.
3. It can start writing almost immediately, instead of waiting
potentially minutes to start.

Performance is about the same to slightly faster overall.
2022-08-09 19:58:56 +02:00
Johannes Altmanninger
095c093af6 Fix "commandline --paging-mode" false negative when there is no room for pager, attempt 2
The previous fix was reverted because it broke another scenario.  Add tests
for both scenarios.

The first test exposes another problem: autosuggestions are sometimes not
recomputed after selecting the first completion with Tab Tab. Fix that too.
2022-07-31 07:14:56 +02:00
ridiculousfish
2410e27d10 Add a test and CHANGELOG fix for #9096 2022-07-30 10:14:19 -07:00
Michael Forster
6003edfb42 Add test for the default cursor selection mode
Also add documentation for the tests
2022-07-30 09:49:07 -07:00
Michael Forster
ef9994d55a Don't use Python f-strings in tests 2022-07-30 09:49:07 -07:00
Michael Forster
7d198fa404 Add an initial test for fish_cursor_selection_mode 2022-07-30 09:49:07 -07:00
Johannes Altmanninger
83893558f9 Make ESCAPE_NO_PRINTABLES behavior a bit less weird
Since the fix for #3892, this escaping style escapes

	\n to \\n

as well as

	\\ to \\\\
	\' to \\'

I believe these two are the only printable characters that are escaped with
ESCAPE_NO_PRINTABLES.
The rationale is probably to keep the encoding unambiguous and reversible.
However that doesn't justify escaping the single quote. Probably this was
an accident, so let's revert that part.

This has the nice effect that single quotes will no longer be escaped
when rendered in the completion pager (which is consistent with other
special characters). Try it:

    complete : -a "aaa\'\; aaaa\'\;" -f

Also this makes the error output of builtin bind consistent:

    $ bind -e --preset \;
    $ bind -e --preset \'
    $ bind \;
    bind: No binding found for sequence “;”
    $ bind \'
    bind: No binding found for sequence “'”

the last line is clearly better than the old version:

    bind: No binding found for sequence “\'”

In general, the fact that ESCAPE_NO_PRINTABLES escapes the (printable)
backslash is weird but I guess it's fine because it looks more consistent to
users, even though the result is an undocumented subset of the fish language.
2022-07-27 11:24:35 +02:00
Johannes Altmanninger
fe2f6f0c63 Fix Escape in pager not removing the inserted completion if search field was used
command_line_has_transient_edit tracks the actual command line, not the
pager search field. We accidentally reset it after modifying the search field
which causes unexpected behavior - the commandline added by the completion
pager remains even after I press Escape.
2022-07-26 15:29:52 +02:00
Fabian Boehm
ff497e25c0 tests: Rename a function
NetBSD actually has a /usr/bin/error by default, so we ended up
starting that.
2022-07-24 17:53:05 +02:00
Fabian Boehm
407a455cfd realpath: Use physical PWD
This was an inadvertent change from
cc632d6ae9.

Because we used wgetcwd directly before, we always got the "physical"
resolved $PWD.

There's an argument to be made to use the logical $PWD here as well
but I prefer not to make changes lik that in a random commit without
good reason.
2022-07-18 20:45:30 +02:00
Fabian Boehm
5dfb64b547
Add path mtime (#9057)
This can be used to print the modification time, like `stat` with some
options.

The reason is that `stat` has caused us a number of portability
headaches:

1. It's not available everywhere by default
2. The versions are quite different

For instance, with GNU stat it's `stat -c '%Y'`, with macOS it's `stat
-f %m`.

So now checking a cache file can be done just with builtins.
2022-07-18 20:39:01 +02:00
ridiculousfish
fa3ca60111 Add a tmux-sleep to tmux-history-search
This test was failing often on my local Mac; this sleep seems to make it
reliable again.
2022-07-16 17:46:12 -07:00
Aaron Gyes
77f6afa501 Add testcases for [ extensions
Some sanity checks for -ot, -nt, -ef

Try negative mtime values too, there was interesting behavior
there during development.
2022-07-16 12:40:36 -07:00
Fabian Boehm
d920610f96 Fix special readline functions after and/or
Here we needed to handle self-insert immediately, but we ended up
returning it.

Fixes #9051
2022-07-02 09:23:11 +02:00
Fabian Boehm
98ba66ed8e set_color: Print the given colors with --print-colors 2022-07-01 21:28:35 +02:00
Fabian Boehm
bd7934ccbf history: Refuse to merge in private mode
It makes *no* sense.

Fixes #9050.
2022-07-01 20:10:18 +02:00
Fabian Boehm
dde2d33098 set --show: Show the originally inherited value, if any
This adds a line to `set --show`s output like

```
$PATH: originally inherited as |/home/alfa/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/var/lib/flatpak/exports/bin|
```

to help with debugging.

Note that this means keeping an additional copy of the original
environment around. At most this would be one ARG_MAX's worth, which
is about 2M.
2022-06-27 20:33:26 +02:00
Fabian Boehm
bfeebca75a tests/argparse: Use set -l
This skips history, which takes a lot of time here!
2022-06-27 17:50:40 +02:00
Fabian Boehm
842af06c5d completions/git: Cache subcommand v2
This is sort of slow because it's called hundreds of times.

We used to have a cache, introduced in ad9b4290e, but it was removed
in fee5a9125a because it had
false-positives.

So what we do, because the issue is that this is called hundreds of
times per-commandline, we cache it keyed on the commandline.

This speeds up `complete -C'git sta'` by a factor of 2.3x.
2022-06-27 17:15:30 +02:00
Fabian Boehm
993448d552 argparse: Allow usage without optspecs
It's still useful without, for instance to implement a command that
takes no options, or to check min-args or max-args.

(technically no optspecs, no min/max args and --ignore-unknown does
nothing, but that's a very specific error that we don't need to forbid)

Fixes #9006
2022-06-27 17:02:20 +02:00
Johannes Altmanninger
fee5a9125a Revert "completions/git: cache subcommand computation"
Commit ad9b4290e optimized git completions by adding a completion that would
run on every completion request, which allows to precompute data used by
other completion entries. Unfortunately, the completion entry is not run
when the commandline contains a flag like `git -C`. If we didn't
already load git.fish, we'd error. Additionally, we got false positive
completions for `git diff -c`.

So this hack was a very bad idea. We should optimize in another way.
2022-06-26 23:02:26 +02:00
Fabian Boehm
13a9f6b64e printf: Print special error for invalid octal numbers
(tbh these were always a mistake)

See #9035
2022-06-23 18:12:43 +02:00
Fabian Boehm
045683f927 tests/fd: Error out early if more fds are open
This is simply an error in test setup. There's a limit to how far we
can isolate them from the system.

(it's possible new cmake versions close fds automatically since I
can't reproduce the original issue via `ninja test` or `make test`)

Fixes #9017
2022-06-17 09:33:42 +02:00
Fabian Boehm
8f08fe80fd Restyle codebase
Not a lot of changes, tbh
2022-06-16 18:43:28 +02:00
Fabian Boehm
7810f4e8a1 set: Only warn about uvar shadowing if the set succeeded
Otherwise there's really no point in doing so - we'd tell you that a
universal $status is shadowing a global, but we haven't actually
created one!
2022-06-13 20:53:15 +02:00
ridiculousfish
e0add36488 Revert "Skip tmux tests on Github Actions macOS"
The previous commit switched to using screen-256color instead of
tmux-256color, which makes these tests pass.

This reverts commit 1c4bb214d2.
2022-06-12 14:24:55 -07:00
ridiculousfish
c76ce101b8 Teach isolated-tmux to use screen-256color TERM on Mac
Mac does not ship tmux-256color terminfo, so teach our isolated-tmux
function to populate .tmux.conf with screen-256color instead, only on
macOS.
2022-06-12 14:24:36 -07:00
Fabian Boehm
1c4bb214d2 Skip tmux tests on Github Actions macOS
This lacks the tmux-256color terminfo entry, leading to spurious
warnings like

warning: Could not set up terminal. <= no check matches
warning: TERM environment variable set to \'tmux-256color\'. <= no check matches
warning: Check that this terminal type is supported on this system. <= no check matches
warning: Using fallback terminal type \'ansi\'. <= no check matches
2022-06-09 18:56:20 +02:00
David Adam
c20a71c99f tests: require a newish Python
Specifically, Python 3.5 changed the return value type from
inspect.getouterframes().

Anything older than that is way out of date anyway.
2022-06-08 21:13:09 +08:00
Fabian Boehm
0ea6703661 completions/git: Terminate pathspec magic
Git's pathspec system is kind of annoying:

>  A pathspec that begins with a colon : has special meaning. In the short form, the leading colon : is followed by zero or more "magic signature" letters (which optionally is terminated by another colon :), and the remainder is the pattern to match against the path. The "magic signature" consists of ASCII symbols that are neither alphanumeric, glob, regex special characters nor colon. The optional colon that terminates the "magic signature" can be omitted if the pattern begins with a character that does not belong to "magic signature" symbol set and is not a colon.

So if we complete `:/foo`, that "works" because "f" is alphanumeric
and so the "/" is the only magic character here.

If, however the filename starts with a magic character, that's used as
a magic signature.

So we do what the docs say and terminate the magic signature after the
"/" (which means "from the repo root").

Fixes #9004
2022-06-07 20:10:13 +02:00
Fabian Homborg
f9a170e5f2 git_prompt: Only show untracked files in informative mode if asked
This makes it so

1. The informative status can work without showing untracked
files (previously it was disabled if bash.showUntrackedFiles was
false)
2. If untrackedfiles isn't explicitly enabled, we use -uno, so git
doesn't have to scan all the files.

In a large repository (like the FreeBSD ports repo), this can improve
performance by a factor of 5 or up.
2022-06-07 13:30:03 +02:00
ridiculousfish
480f44cd0f Stop removing unfired one-shot handlers
In b0084c3fc4, we refactored out event handlers get removed. But this
also caused us to remove "one-shot" handlers even if they have not yet
been fired. Fix this.
2022-06-06 12:18:29 -07:00
ridiculousfish
299ed9f903 Allow 'commandline' to set the commandline from the prompt
This means that running `commandline foo` will indeed set the text of
the command line to `foo`; it won't get cleared immediately.

Fixes #8807
2022-06-04 15:33:55 -07:00
ridiculousfish
52cfb66cf7 Add a test for COMPLETE_AUTO_SPACE
Improves our test coverage a bit.
2022-06-02 17:25:59 -07:00
Fabian Homborg
661ea41861 fish_git_prompt: Use "dirty"/"staged" regex like informative
When switching this to use `git status`, I neglected to use the
correct definition of what a "dirty" and a "staged" change is.

So this now showed already staged files still as "dirty".

Fixes #8986
2022-06-01 17:24:08 +02:00
Fabian Homborg
64b34c8cda Allow complete to have multiple conditions
This makes it so `complete -c foo -n test1 -n test2` registers *both*
conditions, and when it comes time to check the candidate, tries both,
in that order. If any fails it stops, if all succeed the completion is offered.

The reason for this is that it helps with caching - we have a
condition cache, but conditions like

```fish
test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] length

test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] sub
```

defeats it pretty easily, because the cache only looks at the entire
script as a string - it can't tell that the first `test` is the same
in both.

So this means we separate it into

```fish
complete -f -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] length" -s V -l visible -d "Use the visible width, excluding escape sequences"
+complete -f -c string -n "test (count (commandline -opc)) -ge 2" -n "contains -- (commandline -opc)[2] length" -s V -l visible -d "Use the visible width, excluding escape sequences"
```

which allows the `test` to be cached.

In tests, this improves performance for the string completions by 30%
by reducing all the redundant `test` calls.

The `git` completions can also greatly benefit from this.
2022-05-30 20:47:14 +02:00
Fabian Boehm
4612343d6e
Merge pull request #8958 from faho/builtin-path
This adds a path builtin to deal with paths.

It offers the following subcommands:

    filter to go through a list of paths and only print the ones that pass some filter - exist, are a directory, have read permission, ...
    is as a shortcut for filter -q to only return true if one of the paths passed the filter
    basename, dirname and extension to print certain parts of the path
    change-extension to change the extension to a different one (as a string operation)
    normalize and resolve to canonicalize the paths in various flavors
    sort to sort paths, also only using the basename or dirname as a key

The definition of "extension" here was carefully considered and should line up with how extensions are actually used - ~/.bashrc doesn't have an extension, but ~/.conf.d does (".d").

These subcommands all compose well - they can read from arguments or stdin (like string), they can use null-delimited input or output (input is autodetected - if a NULL happens in the first PATH_MAX bytes it switches automatically).

It is both a failglob exception (so like set if a glob passed to it fails it just doesn't get any arguments for it instead of triggering an error), and passes output to command substitution buffers explicitly split (like string split0) so newlines are easy to handle.
2022-05-29 20:15:03 +02:00
Fabian Homborg
67b0860fe7 Rename sort --invert to sort --reverse/-r
To match sort(1).
2022-05-29 17:53:03 +02:00
Fabian Homborg
00949fccda Rename --what to --key
More sorty, less generic.
2022-05-29 17:48:40 +02:00
Fabian Homborg
e87ad48f9b Test and document symlink loop 2022-05-29 17:48:40 +02:00
Fabian Homborg
e088c974dd Fix path filter --invert
This would still remove non-existent paths, which isn't a strict
inversion and contradicts the docs.

Currently, to only allow paths that exist but don't pass a type check,
you'd have to filter twice:

path filter -Z foo bar | path filter -vfz

If a shortcut for this becomes necessary we can add it later.
2022-05-29 17:48:12 +02:00
Fabian Homborg
bc3d3de30a Also prepend "./" for filter if a filename starts with "-"
This is now added to the two commands that definitely deal with
relative paths.

It doesn't work for e.g. `path basename`, because after removing the
dirname prepending a "./" doesn't refer to the same file, and the
basename is also expected to not contain any slashes.
2022-05-29 17:48:12 +02:00
Fabian Homborg
c88f648cdf Add sort --unique 2022-05-29 17:48:12 +02:00
Fabian Homborg
4fec045073 sort: Use a stable sort
This allows e.g. sorting first by dirname and then by basename.
2022-05-29 17:48:12 +02:00
Fabian Homborg
640bd7b183 extension: Print empty entry if there is no extension
Because we now count the extension including the ".", we print an
empty entry.

This makes e.g.

```fish
set -l base (path change-extension '' $somefile)
set -l ext (path extension $somefile)
echo $base$ext
```

reconstruct the filename, and makes it easier to deal with files with
no extension.
2022-05-29 17:48:12 +02:00
Fabian Homborg
5cce6d01ad resolve: Normalize
This means "../" components are cancelled out even after non-existent
paths or files.

(the alternative is to error out, but being able to say `path resolve
/path/to/file/../../` over `path resolve (path dirname
/path/to/file)/../../` seems worth it?)
2022-05-29 17:48:11 +02:00
Fabian Homborg
b961afed49 normalize: Add "./" if a path starts with a "-" 2022-05-29 17:48:11 +02:00
Fabian Homborg
55c34cbb7c Use physical $PWD
Yeah, the macOS tests fail because it's started in /private/var... with a
$PWD of /var.... So resolve canonicalizes the path, which makes it no
longer match $PWD.

Simply use pwd -P
2022-05-29 17:48:11 +02:00
Fabian Homborg
23a5e53247 tests: Print $PWD if resolving fails
Seems to be a macOS issue
2022-05-29 17:48:11 +02:00
Fabian Homborg
2b8bb5bd7f path: Rename "real" to "resolve" 2022-05-29 17:48:11 +02:00
Fabian Homborg
479fde27d7 path: Make path real "work" with nonexistent paths
This just goes back until it finds an existent path, resolves that,
and adds the normalized rest on top.

So if you try

/bin/foo/bar////../baz

and /bin exists as a symlink to /usr/bin, it would resolve that, and
normalize the rest, giving

/usr/bin/foo/baz

(note: We might want to add this to realpath as well?)
2022-05-29 17:48:11 +02:00
Fabian Homborg
1c1e643218 WIP path: Make extensions start at the "."
This includes the "." in what `path extension` prints.

This allows distinguishing between an empty extension (just `.`) and a
non-existent extension (no `.` at all).
2022-05-29 17:48:11 +02:00
Fabian Homborg
de0a64a016 Update tests for change-extension's status 2022-05-29 17:48:11 +02:00
Fabian Homborg
ce7281905d Switch strip-extension to change-extension
This allows replacing the extension, e.g.

    > path change-extension mp4 foo.wmv
    foo.mp4
2022-05-29 17:48:11 +02:00
Fabian Homborg
00ed0bfb5d Rename base/dir to basename/dirname
"dir" sounds like it asks "is it a directory".
2022-05-29 17:48:11 +02:00
Fabian Homborg
f6fb347d98 Add "path" builtin
This adds a "path" builtin that can handle paths.

Implemented so far:

- "path filter PATHS", filters paths according to existence and optionally type and permissions
- "path base" and "path dir", run basename and dirname, respectively
- "path extension PATHS", prints the extension, if any
- "path strip-extension", prints the path without the extension
- "path normalize PATHS", normalizes paths - removing "/./" components
- and such.
- "path real", does realpath - i.e. normalizing *and* link resolution.

Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths.

All output is split explicitly, so paths with newlines in them are
handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So

    find . -print0 | path base -z

prints the basename of all files in the current directory,
recursively.

With "-Z" it also prints it null-separated.

(if stdout is going to a command substitution, we probably want to
skip this)

All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*.

Filtering
---------

`filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid".

It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used.

There currently is no way to only get "real" files, i.e. ignore links pointing to files.

Examples
--------

> path real /bin///sh
/usr/bin/bash

> path extension foo.mp4
mp4

> path extension ~/.config
  (nothing, because ".config" isn't an extension.)
2022-05-29 17:48:11 +02:00
ridiculousfish
cf2ca56e34 Allow trapping SIGINT and SIGTERM in scripts
This teaches `--on-signal SIGINT` (and by extension `trap cmd SIGINT`)
to work properly in scripts, not just interactively. Note any such
function will suppress the default behavior of exiting. Do this for
SIGTERM as well.
2022-05-28 17:44:13 -07:00
ridiculousfish
5917ae8baf Add a test for trap
Preparation to implement trapping in non-interactive mode.
2022-05-28 14:45:13 -07:00
Fabian Homborg
65b9c26fb4 complete: Print better error for -x -F
-x is a cheesy shortcut for `-rf`, so it conflicts with `-F`.

Fixes #8818.
2022-05-26 14:17:15 +02:00
Fabian Homborg
8f9348ee53 Make eval a reserved keyword
Like `set` and `read` before it, `eval` can be used to set variables,
and so it can't be shadowed by a function without loss of
functionality.

So this forbids it.

Incidentally, this means we will no longer try to autoload an
`eval.fish` file that's left over from an old version, which would
have helped with #8963.
2022-05-18 18:47:10 +02:00
Fabian Homborg
b548e1d8fe Fix tests
Oops, unclean extraction from larger work.
2022-05-17 17:21:42 +02:00
Fabian Homborg
b71416f610 fish_add_path: Also deduplicate the new paths
Previously, running `fish_add_path /foo /foo` would result in /foo
being added to $PATH twice.

Now we check that it hasn't already been given, so we skip the
second (and any further) occurence.
2022-05-17 17:05:56 +02:00