Commit graph

4256 commits

Author SHA1 Message Date
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
dfded633c6 Fix woption 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
9fdfad1d45 WIP Add path sort
This sorts paths by basename, dirname or full path - in future
possibly size or age.

It takes --invert to invert the sort and "--what=basename|dirname|..."
to specify what to sort

This can be used to implement better conf.d sorting, with something
like

```fish
set -l sourcelist
for file in (path sort --what=basename $__fish_config_dir/conf.d/*.fish $__fish_sysconf_dir/conf.d/*.fish $vendor_confdirs/*.fish)
```

which will iterate over the files by their basename. Then we keep a
list of their basenames to skip over anything that was already
sourced, like before.
2022-05-29 17:48:11 +02:00
Fabian Homborg
e429f76e9f append_with_separation: Default to wanting a newline
The recent change to skip the newline for `string` changed this, and
it also hit builtin path (which is in development separately, so it's
not like it broke master).

Let's pick a good default here.
2022-05-29 17:48:11 +02:00
Fabian Homborg
d13ba046b0 resolve: Use the new real path
This failed for

/bin/foo/bar

if /bin is a symlink to /usr/bin and foo doesn't exist.

It returned /bin/foo/bar instead of the correct /usr/bin/foo/bar.
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
4fced3ef5a Remove sticky filter
This isn't super useful, and having a caveat in the docs that it might
cause the entire filter to fail is awkward.

So just remove it.
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
17a8dd8f62 Move path to src/builtins 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
268a9d8db3 Prevent some copies 2022-05-29 17:48:11 +02:00
Fabian Homborg
359b487793 Use wchar overload of find_last_of
C++ is a silly language.
2022-05-29 17:48:11 +02:00
Fabian Homborg
8b27a69ae4 Reword comments to be about path, not string
No idea why this mentioned string so much.
2022-05-29 17:48:11 +02:00
Fabian Homborg
efb3ae6d49 Add path is shorthand for path filter -q
This replaces `test -e` and such.
2022-05-29 17:48:11 +02:00
Fabian Homborg
b23548b2a6 Add "-rwx" and "-fdl" shorthand
These are short flags for "--perm=read" and "--type=link" and such.

Not every type or permission has a shorthand - we don't want "-s" for
"suid". So just the big three each get one.
2022-05-29 17:48:11 +02:00
Fabian Homborg
48ac2ea1e0 Address feedback 2022-05-29 17:48:11 +02:00
Fabian Homborg
3f7e125b57 Also give path nullglob behavior
This is needed because you might feasibly give e.g. `path filter`
globs to further match, and they might already present no results.
It's also well-handled since path simply does nothing if given no paths.
2022-05-29 17:48:11 +02:00
Fabian Homborg
39d4a7d13a Actually name the switches "--null-in" and out
These were officially called "--null-input", but I just used
"--null-in" everywhere, which worked because getopt allows unambiguous abbreviations.

But since *I* couldn't keep it straight and the "put" is just
superfluous, let's remove it.
2022-05-29 17:48:11 +02:00
Fabian Homborg
0ff25d581c Infer splitting on NULL if one appears in the first PATH_MAX bytes
This is theoretically sound, because a path can only be PATH_MAX - 1
bytes long, so at least the PATH_MAXest byte needs to be a NULL.

The one case this could break is when something has a NULL-output mode
but doesn't bother printing the NULL for only one path, and that path
contains a newline. So we leave --null-in there, to force it on.
2022-05-29 17:48:11 +02:00
Fabian Homborg
3a9c52cefa Add --invert to filter/match
Like `grep -v`/`string match -v`.
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
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
ridiculousfish
ec6fd088f2 Migrate initializing CMD_DURATION from reader to env
This puts the initialization of CMD_DURATION at home with other
default-initialized variables. No user-visible change expected from
this.
2022-05-22 12:29:51 -07:00
ridiculousfish
4d3261dadc Bravely stop initializing the term size from reader_init
The terminal size in all cases should have been initialized in env_init,
so no reason to do it here. No user visible change expected from this.
2022-05-22 12:28:05 -07:00
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
ridiculousfish
ba7c84fe3b Add an error message when cd fails with ELOOP
This error is emitted if you try to `cd` into a symlink loop or very
long chain.
2022-05-15 11:58:40 -07:00
ridiculousfish
1893204067 event_fire_generic to take its arguments directly
Just mild refactoring, no functional change.
2022-05-14 10:33:47 -07:00
ridiculousfish
b0084c3fc4 Refactor event handler firing
This concerns what happens if one event handler removes another, when
both are responding to the same event. Previously we had a "double lock"
where we would traverse the list twice. Now track directly in the
handler when it is removed; this simplifies the code a lot. No
functional changes expected here.
2022-05-14 10:33:47 -07:00
ridiculousfish
31567cea63 Mild refactoring of how received signals are stored
No functional change here, just some cleanup.
2022-05-14 10:33:47 -07:00
Johannes Altmanninger
bfd5e8dfbe Do not stomp token if tab-expansion of wildcards exceeds limit or is canceled
Hitting tab on "echo **" will often result in more than 256 matches.
Commit 143757e8c (Expand wildcards on tab, 2021-11-27) describes this scenario

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

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

I tried to write a test in tests/pexpects/wildcard_tab.py but that doesn't
seem to work because pexpect provides only a "dumb" terminal.  I wonder if we
can test what we write to the screen without depending on a terminal emulator.
2022-05-14 14:31:30 +02:00
Fabian Homborg
32aef855b7 Initialize variable
gcc 12.1 complains this might be used uninitialized.
2022-05-11 21:28:26 +02:00
ridiculousfish
11cfa85a2a Correctly fire process_exit events even if the job has not yet exited
c4fb857dac (in 3.4.1) introduced a regression where process_exit
events would only fire once the job itself is complete. Allow
process_exit events to fire before that. Fixes #8914.
2022-05-08 15:27:25 -07:00
ridiculousfish
9efde28350 Revert "Optimize exit event generation"
This reverts commit 1b6ef6670f.

This optimimzation did not carry its weight in complexity.
2022-05-08 15:08:28 -07:00
ridiculousfish
1f7d4c7441 Fix CPU usage percentage calculation as reported by jobs
This rationalizes our types for computing CPU usage percentage and
fixes the computation. Fixes #8919.
2022-05-07 15:29:56 -07:00
Fabian Homborg
770a2582de Give special error for when file failed to execute but is executable
This is after we've tried to find the interpreter, so we would already
have complained about e.g. /usr/bin/pthyon not existing.

Realistically the most common case here is things that don't start
with a shebang like ELFs. Writing special extraction code here is
overkill, and I can't see a good function to do it for us.

But this should point you in the right direction.

Fixes #8938
2022-05-07 14:53:03 +02:00
Fabian Boehm
dd95e0a0ea
Setup $USER if passwd for $USER has different uid (#8879)
This gets the passwd entry for $USER (if it is set). If that gives the
same uid that geteuid() gives us, we assume the data is correct.

If not, we reset $USER (and $HOME if it's empty) from the passwd value for our UID.

This allows using $USER in a prompt even if you've `su`d. Bash gets around this by having a special escape in its $PS1 DSL that checks passwd instead.

Fixes #8583
2022-05-02 17:15:52 +02:00
Johannes Altmanninger
71ff8780c6 Revert "Fix inconsistent noexcept-ness between header/implementation"
This reverts commit ccb6cb1abe.

CI fails with

    /home/runner/work/fish-shell/fish-shell/src/autoload.cpp:148:1: error: function ‘autoload_t::autoload_t(autoload_t&&)’ defaulted on its redeclaration with an exception-specification that differs from the implicit exception-specification ‘’
      148 | autoload_t::autoload_t(autoload_t &&) noexcept = default;
          | ^~~~~~~~~~
    make[2]: *** [CMakeFiles/fishlib.dir/build.make:96: CMakeFiles/fishlib.dir/src/autoload.cpp.o] Error 1
    make[1]: *** [CMakeFiles/Makefile2:369: CMakeFiles/fishlib.dir/all] Error 2
    make: *** [Makefile:139: all] Error 2

Not sure what's wrong - it compiles fine on my machine. Will check later.
2022-04-24 21:46:01 +02:00
Johannes Altmanninger
ccb6cb1abe Fix inconsistent noexcept-ness between header/implementation
Even though we disable exceptions, we use noexcept in some
places to enable certain optimizations in std::vector, see
https://en.cppreference.com/w/cpp/utility/move_if_noexcept.

Some methods have noexcept only at their declaration (or only at the
definition).  This will be an error when compiling with "g++ -std=c++17". Make
both signatures match.
2022-04-24 21:31:51 +02:00
ridiculousfish
ed78fd2a5f Rationalize path-getting
This cleans up the path_get_path function which is used to resolve a
command name against $PATH, by removing the dependence on errno and
being explicit about which error is returned.

Should be no user-visible change here.
2022-04-23 15:24:27 -07:00
Fabian Homborg
4d8de32a16 Tests: Skip autosuggest_special harder
For some reason this still crashed? WTF?
2022-04-17 13:35:09 +02:00
Fabian Homborg
12e6a41423 Tests: Skip autosuggest_suggest_special under ASAN
This crashes on Ubuntu 20.04, which Github Actions uses.
2022-04-17 12:06:09 +02:00
ridiculousfish
bd9c6a64e3 Be careful to not touch curses variables if cur_term is null
Curses variables like `enter_italics_mode` are secretly defined to
dereference through the `cur_term` variable. Be sure we do not read or
write these curses variables if cur_term is NULL. See #8873, #8875.

Add a regression test.
2022-04-16 13:26:56 -07:00
ridiculousfish
1da952450f Migrate the "Apple Term hacks" from set_color to init_curses
Apple's terminfo has missing support for enter_italics_mode,
exit_italics_mode, and enter_dim_mode. Previously we would hack in such
support in set_color; migrate that to init_curses so we do it up-front
instead of opportunistically.
2022-04-16 13:26:42 -07:00
ridiculousfish
4b96dd9908 Mild refactoring of initialize_curses_using_fallbacks
No functional change here.
2022-04-16 12:45:25 -07:00
ridiculousfish
3d98fd4308 clang-format env.cpp and env_dispatch.cpp 2022-04-16 12:22:44 -07:00