This was an issue with "--no-execute", which has no variables and
therefore no $HOME:
```fish
fish --no-execute /path/to/file
```
would say the error is in `~/path/to/file`.
Instead, since this is just for a message, we simply return the
filename without doing the replacement.
Fixes#10171
Port of e318585021
These printed "Unknown error while evaluating command substitution".
Now they print something like
```
fish: for: status: cannot overwrite read-only variable
for status in foo; end
^~~~~^
in command substitution
fish: Invalid arguments
echo (for status in foo; end)
^~~~~~~~~~~~~~~~~~~~~~~^
```
for `echo (for status in foo; end)`
This is, of course, still not *great*. Mostly the `fish: Invalid
arguments` is basically entirely redundant.
An alternative is to simply skip the error message, but that requires some
more scaffolding (describe_with_prefix adds some error messages on its
own, so we can't simply say "don't add the prefix if we don't have a
message")
(cherry picked from commit 1b5eec2af6)
(cherry picked from commit 67faa107b0)
After accidentally running a command that includes a pasted password, I want
to delete command from history. Today we need to recall or type (part of)
that command and type "history delete". Let's maybe add a shortcut to do
this from the history pager.
The current shortcut is Shift+Delete. I don't think that's very discoverable,
maybe we should use Delete instead (but only if the cursor is at the end of
the commandline, otherwise delete a char).
Closes#9454
(cherry picked from commit 052823c120)
* wildcard: Remove file size from the description
We no longer add descriptions for normal file completions, so this was
only ever reached if this was a command completion, and then it was
only added if the file wasn't a regular file... in which case it can't
be an executable.
So this was dead.
* Make possible_link() a maybe
This gives us the full information, not just "no" or "maybe"
* wildcard: Rationalize file/command completions
This keeps the entry_t as long as possible, and asks it, so especially
on systems with working d_type we can get by without a single stat in
most cases.
Then it guts file_get_desc, because that is only used for command
completions - we have been disabling file descriptions for *years*,
and so this is never called there.
That means we have no need to print descriptions about e.g. broken symlinks, because those are not executable.
Put together, what this means is that we, in most cases, only do
an *access(2)* call instead of a stat, because that might be checking
more permissions.
So we have the following constellations:
- If we have d_type:
- We need a stat() for every _symlink_ to get the type (e.g. dir or regular)
(this is for most symlinks, if we want to know if it's a dir or executable)
- We need an access() for every file for executables
- If we do not have d_type:
- We need a stat() for every file
- We need an lstat() for every file if we do descriptions
(i.e. just for command completion)
- We need an access() for every file for executables
As opposed to the current way, where every file gets one lstat whether
with d_type or not, and an additional stat() for links, *and* an
access.
So we go from two syscalls to one for executables.
* Some more comments
* rust link option
* rust remove size
* rust accessovaganza
* Check for .dll first for WSL
This saves quite a few checks if e.g. System32 is in $PATH (which it
is if you inherit windows paths, IIRC).
Note: Our WSL check currently fails for WSL2, where this would
be *more* important because of how abysmal the filesystem performance
on that is.
This makes it so expand_intermediate_segment knows about the case
where it's last, only followed by a "/".
When it is, it can do without the file_id for finding links (we don't
resolve the files we get here), which allows us to remove a stat()
call.
This speeds up the case of `...*/` by quite a bit.
If that last component was a directory with 1000 subdirectories we
could skip 1000 stat calls!
One slight weirdness: We refuse to add links to directories that we already visited, even if they are the last component and we don't actually follow them. That means we can't do the fast path here either, but we do know if something is a link (if we get d_type), so it still works in common cases.
(cherry picked from commit 86803e4442)
This can be bound like `bind \cl clear-screen`, and is, by default
In contrast to the current way it doesn't need the external `clear`
command that was always awkward.
Also it will clear the screen and first draw the old prompt to remove
flicker.
Then it will immediately trigger a repaint, so the prompt will be overwritten.
(cherry picked from commit c4ca1a68d3)
This uses "screen.reset_line" to move the cursor without informing the
reader's machinery (because that deals with positions *in the
commandline*), but then only repainted "if needed" - meaning if the
reader thought anything changed.
That could lead to a situation where the cursor stays at column 0
until you do something, e.g. in
```fish
bind -m insert u undo
```
when you press alt+u - because the *escape* calls repaint-mode, which
puts the cursor in column 0, and then the undo doesn't, which keeps it
there.
Of course this binding should also `repaint-mode`, because it changes
the mode.
Some changes might be ergonomic:
1. Make repaint-mode the default if the mode changed (we would need to
skip it for bracketed-paste)
2. Make triggering the repaint easier - do we need to set
force_exec_prompt_and_repaint to false here as well?
Anyway, this
Fixes#7910
(cherry picked from commit ff433b0cb2)
This is a sensible thing to do, and fixes some cases where we're
state-dependent.
E.g. this fixes the case in the pager where some things are bold and
some aren't, because that bolding is (rather awkwardly) implicitly
triggered when we have a background, and so we don't notice we need to
re-do that bolding after we moved to the next line because we think we
still have the same color.
Fixes#9617
(cherry picked from commit 10d91b0249)
I sometimes find myself doing something like this:
- Look for a commandline that includes "echo" (as an example)
- Type echo, press up a few times
- I can't immediately find what I'm looking for
- Press ctrl-r to open up the history pager
- It uses the current commandline as the search string,
so now I'm looking for "echo foobar"
This makes it so if the search string already is in use, that's what
the history-pager picks as the initial search string.
(cherry picked from commit 5b44c26a19)
This used to print all codepoints outside of the ASCII range (i.e.
above 0x80) in \uXXXX or \UYYYYYYYY notation.
That's quite awkward, considering that this is about keys that are
being pressed, and many keyboards have actual symbols for these on
them - I have an "ö" key, so I would like to use `bind ö` and not
`bind \u00F6`. So we go by iswgraph.
On a slightly different note, `\e` was written as `\c[ (or \e)`. I do
not believe anyone really uses `\c[` (the `[` would need to
be escaped!), and it's confusing and unnecessary to even mention that.
(cherry picked from commit 55c425a0dd)
Similar to `time`, except that one is more common as a command.
Note that this will also allow `builtin and`, which is somewhat
useless, but then it is also useless outside of a pipeline.
Addition to #9985
(cherry picked from commit b454b3bc40)
This allows e.g. `foo | command time`, while still rejecting `foo | time`.
(this should really be done in the ast itself, but tbh most of
parse_util kinda should)
Fixes#9985
(cherry picked from commit 482616f101)
We have already run waccess with X_OK. We already *know* the file is
executable.
There is no reason to check again.
Restores some of the speedup from the fast_waccess hack that was
removed to fix#9699.
(cherry picked from commit ee75b45687)
We could end up overflowing if we print out something that's a multiple of the
chunk size, which would then finish printing in the chunk-printing, but not
break out early.
(cherry picked from commit 6325b3662d)
This confirmed that a file existed via access(file, F_OK).
But we already *know* that it does because this is the expansion for
the "trailing slash" - by definition all wildcard components up to
here have already been checked.
And it's not checking for directoryness either because it does F_OK.
This will remove one `access()` per result, which will cut the number
of syscalls needed for a glob that ends in a "/" in half.
This brings us on-par with e.g. `ls` (which uses statx while we use
newfstatat, but that should have about the same results)
Fixes#9891.
(cherry picked from commit 6823f5e337)
This makes `fish -c begin` fail with a status of 127 - it already
printed a syntax error so that was weird. (127 was the status for
syntax errors when piping to fish, so we stay consistent with that)
We allow multiple `-c` commands, and this will return the regular
status if the last `-c` succeeded.
This is fundamentally an extremely weird situation but this is the
simple targeted fix - we did nothing, unsuccessfully, so we should
fail.
Things to consider in future:
1. Return something better than 127 - that's the status for "unknown
command"!
2. Fail after a `-c` failed, potentially even checking all of them
before executing the first?
Fixes#9888
(cherry picked from commit a6c36a014c)
Vi visual mode selection highlighting behaves unexpectedly when the selection
foreground and background in the highlight spec don't match. The following
unexpected behaviors are:
* The foreground color is not being applied when defined by the
`fish_color_selection` variable.
* `set_color` options (e.g., `--bold`) would not be applied under the cursor
when selection begins in the middle of the command line or when the cursor
moves forward after visually selecting text backward.
With this change, visual selection respects the foreground color and any
`set_color` options are applied consistently regardless of where visual
selection begins and the position of the cursor during selection.
(cherry picked from commit 4ed53d4e3f)
Another from the "why are we asserting instead of doing something
sensible" department.
The alternative is to make exit() and return() compute their own exit
code, but tbh I don't want any *other* builtin to hit this either?
Fixes#9659
(cherry picked from commit a16abf22d9)
This isn't a great use of `assert` because it turns a benign "oh I
need to search again" bug into a crash.
Fixes#9628
(cherry picked from commit 7c91d009c1)
When we draw the prompt, we move the cursor to the actual
position *we* think it is by issuing a carriage return (via
`move(0,0)`), and then going forward until we hit the spot.
This helps when the terminal and fish disagree on the width of the
prompt, because we are now definitely in the correct place, so we can
only overwrite a bit of the prompt (if it renders longer than we
expected) or leave space after the prompt. Both of these are benign in
comparison to staircase effects we would otherwise get.
Unfortunately, midnight commander ("mc") tries to extract the last
line of the prompt, and does so in a way that is overly naive - it
resets everything to 0 when it sees a `\r`, and doesn't account for
cursor movement. In effect it's playing a terminal, but not committing
to the bit.
Since this has been an open request in mc for quite a while, we hack
around it, by checking the $MC_SID environment variable.
If we see it, we skip the clearing. We end up most likely doing
relative movement from where we think we are, and in most cases it
should be *fine*.
(cherry picked from commit b1b2294390)
Commit 3b30d92b6 (Commit transient edit when closing pager, 2022-08-31)
inadvertently introduced two regressions to history search:
1. It made Escape keeps the selected history entry,
instead of restoring the commandline before history search.
2. It made history search commands add undo entries.
Fix both of this issues.
Inadvertently broken in a2d816710f,
this made `cd .` no longer offer `cd ../` (same for general file completions
like `ls .`, which only offers dotfiles)
This meant we didn't actually do our weird en/decoding scheme for e.g.
a C locale, which meant that, when you then switch to a proper locale
the previous variables were broken.
I don't know how to test this automatically - none of my attempts seem
to ever *fail* with the old code, here's what you'd do manually:
- Run fish with an actual C locale (LC_ALL=C
fish_allow_singlebyte_locale=1 fish)
- `set -gx foo 💩`
- `set -e LC_ALL`
- `echo $foo` outputs "💩" if it works and "ð⏎" if it's broken.
Fixes#2613
This means cleaning out old universal variables is now just:
```fish
abbr --erase (abbr --list)
```
which makes upgrading much easier.
Note that this erases the currently defined variable and/or any
universal. It doesn't stop at the former because that makes it *easy*
to remove the universals (no running `abbr --erase` twice), and it
doesn't care about globals because, well, they would be gone on
restart anyway.
Fixes#9468.
Like I mentioned in #9089, 12 entries is a bit few.
So, instead, we do like we do for completions before disclosing and
pick half the screen (but at least X, in this case 12).
This avoids filling the entire screen, and will avoid an unsightly "X
more entries" (which requires scrolling down to fully disclose)
because it matches what the pager does.
Note: For multiline commands we can be pushed further upwards, and in
case of a multi-column layout we could fit more lines. That would
require asking the pager to fit as many as possible and give us back
the index of the last matching entry and rewinding the history search.
That's gonna be left as an exercise for later if it turns out to be necessary.