In many cases we currently discard escaped newlines, since they
are often unnecessary (when used around &|;). Escaped newlines
are useful for structuring argument lists. Allow them for variable
assignments since they are similar.
Closes#7955
This would print the default "Argument is invalid" error string, which
is *true* but not super obvious, because `test` doesn't always perform
numeric conversion, and that's the bit that failed here.
This refactors the behavior of string match with capture groups to
correctly handle multiple arguments. Now the variable capture applies to
the first match, as documented. Fixes#7938.
string match is documented as setting an unset variable if a capture group
is unmatched in an otherwise matched regex, and if the `--all` flag is not
provided. However prior to this fix, it instead set a variable containing
the empty string as a single value. Correct the implementation to match
the documentation.
Note that if the `--all` flag is provided we continue to set empty
strings, which is documented.
This removes the relative XDG paths, which could have potentially
confused tmux, and also starts the window with the correct size
instead of adjusting the size afterwards.
Fixes#7926.
Also switches the default status order for non-informative to the informative one:
stagedstate invalidstate dirtystate untrackedfiles stashstate
instead of
dirty staged stash untracked
Things like
```fish
complete command -n '__fish_seen_subcommand_from subcommand'
--force-files
```
would not be obeyed because we only checked force-files when there was
an option.
Fixes#7920.
This correctly sets $status when a builtin succeeds but its output fails;
for example if the output is redirected to a file and that write fails.
Fixes#7857
* math: Make function parentheses optional
It's a bit annoying to use parentheses here because that requires
quoting or escaping.
This allows the parens to be omitted, so
math sin pi
is the same as
math 'sin(pi)'
Function calls have the lowest precedence, so
math sin 2 + 6
is the same as
math 'sin(2 + 6)'
* Add more tests
* Add a note to the docs
* even moar docs
Moar docca
* moar tests
Call me Nikola Testla
It's not super clear what $SHLVL is useful for, but the current
definition is essentially
"number of shells in the parent processes + 1"
which isn't *super useful*?
Bash's behavior here is a bit weird in that it increments $SHLVL
basically always, but since it auto-execs the last process it will
decrement it again, so in practice it's often not incremented.
E.g.
```
> echo $SHLVL
1
> bash -c 'echo $SHLVL; bash'
2
>> echo $SHLVL
2
```
Both bashes here end up having the same $SHLVL because this is
equivalent to `echo $SHLVL; exec bash`. Running `echo $SHLVL` and then
`bash -c 'echo $SHLVL'` in an interactive bash will have a different
result (1 and 2) because that doesn't *exec* the inner bash.
That's not something we want to get into, so what we do is increment
$SHLVL in every interactive fish. Non-interactive fish will simply
import the existing value.
That means if you had e.g. a bash that runs a fish script that ends up
opening a new fish session, you would have a $SHLVL of *2* - one for the
bash, and one for the inner fish.
We key this off is_interactive_session() (which can also be enabled
via `fish -i`) because it's easy and because `fish -i` is asking for
fish to be, in some form, "interactive".
That means most of the time $SHLVL will be "how many shells am I deep,
how often do I have to `exit`", except for when you specifically asked
for a fish to be "interactive". If that's a problem, we can rethink it.
Fixes#7864.
This cleans up some exit code processing. Previously a failed exec
would produce exit code 125 unconditionally, while a failed posix_spawn
would produce exit code 1 (!).
With this change, fish reports exit code 126 for not-executable, and 127
for file-not-found. This matches bash.
We have no idea why this was even a thing. For now simply set it to
"all"/"full" (why these two names? no idea) at startup and allow
changing it later.
Settting it *immediately* when defining the variable sets it too soon
because we don't have the interactive signal handlers
enabled (including the one for SIGTTOU), so let's first settle for
this little piece of awkwardness.
This needs widespread testing, so we merge it early, immediately after
the release.
Fixes#5036Fixes#5832Fixes#7721
(and probably numerous others)
I believe they are both equivalent for our particular purpose, since we
only care about enforcing the size fish sees.
`resize-window` was only introduced in tmux 2.9, which isn't available
at least on Ubuntu 18.04 LTS (currently using tmux 2.6) and probably
many others.
(Clever idea to use tmux here!)
Consider
$ complete -c foo -a 'aab aaB' -f
$ foo A<TAB>
since 28d67c8 we would insert the common prefix AND show the pager.
Due to case-insensitive comparison, "b/B" was considered to be part
of the prefix. Since the prefix is added to each pager item [1]
we get wrong results. Fix this by removing the insensitive comparison
between completions - I don't think it was of much use anyway.
Commandline tokens are still matched case-insensitively, this is
just about completions.
Test this by running interactive fish inside tmux (pexpect's terminal
emulation not have enough capabilities). Also add tests for recent
interactive regressions #7526 and #7738.
Closes#3978
[1]: b38a23a would solve this differently by giving every pager item
its own prefix, but was reverted since it needs more fixes.
This should cover most cases - the user didn't install the docs and is
trying to view the man page via __fish_print_help, so we don't have a
way to show anything.
But `help thing` will fall back to the online version of the docs,
which should work if there's an internet connection.
See #7824.
This is broken on OpenBSD because it apparently doesn't have a /proc
we can query, so it just gives "fish".
Since it's unnecessary in this context just skip it.
* Rewrite the real file if history file is a symlink
When the history file is a symbolic link, `fish` used to overwrite
the link with a real file whenever it saved history. This makes
it follow the symlink and overwrite the real file instead.
The same issue was fixed for the `fish_variables` file in 622f2868e
from https://github.com/fish-shell/fish-shell/pull/7728.
This makes `fish_history` behave in the same way. The implementation
is nearly identical.
Since the tests for the two issues are so similar, I combined them
together and slightly expanded the older test.
This also addresses https://github.com/fish-shell/fish-shell/issues/7553.
* Add user-facing error when history renaming fails
Currently, when history file renaming fails, no message is shown to the
user. This happens, for instance, if the history file is a symlink
pointing to another filesystem.
This copies code (with a bit of variation, after reviewer comments) from
589eb34571/src/env_universal_common.cpp (L486-L491)
into `history.cpp`, so that a message is shown to the user.
* fixup! Rewrite the real file if history file is a symlink
This reverts commit e240d81ff8 and
introduces a more compatible method of finding newly added fish scripts
to syntax check.
`find -newer` is the original and is supported by everything under the
sun (including FreeBSD, NetBSD, Solaris, OpenIndiana, macOS 10.10, WSL,
and more), and if not, the tests will succeed anyway. `find -mnewer` was
added later around the time `find -cnewer` and co (which checks the
creation date rather than the modification date) was introduced, but
apparently the GNU version of coreutils never introduced the `-mnewer`
alias for `-newer`.
Yes, this is hacky and yes it would be ideal if the build system is the
one that picked which tests to run rather than the test itself picking.
But let's not pretend that our tests are idealogically ideal or pure
right now and until we fix the mess that is our CMake test integration
(e.g. use ctest and configure each test to be run separately with
configurable payloads, etc) eight seconds is still eight seconds, and
again, the CI isn't affected.
My find (GNU findutils 4.8.0) prints
> find: unknown predicate `-mnewer'
So we would have to test for support.
Also this is *super* hacky - tests aren't supposed to keep files
around, this is something you would do in the build system.
This reverts commit ddd0e28b4f.
Only check fish files that have been modified since the last time they
were checked. (This continues with the assumption that we are testing
for broken /usr/share fish scripts and not breakage of the fish parser,
which is covered by all the other tests.)
This saves 8 seconds on an NVMe disk under WSL. Won't affect integrity
of CI runs, which start with a blank slate each time.
Apparently the grep on FreeBSD doesn't do \s or \t. Since we're
looking for an actual tab, just give it an actual tab.
See https://builds.sr.ht/~faho/job/448496.
This `set -e` had a cartesian product that caused it to remove the
indexes separately, so the later indexes were off - removing the first
and then the second ends up removing the first and then the
old-*third* which is now the second.
Just quote the expansion so it runs in one go.
Fixes#7776
The user may write for example:
echo foo >&5
and fish would try to output to file descriptor 5, within the fish process
itself. This has unpredictable effects and isn't useful. Make this an
error.
Note that the reverse is "allowed" but ignored:
echo foo 5>&1
this conceptually dup2s stdout to fd 5, but since no builtin writes to fd
5 we ignore it.
fish_indent used to increment the indentation level whenever we saw an escaped
newline. This broke because of recent changes to parse_util_compute_indents().
Since parse_util_compute_indents() function already indents continuations
there is not much to do for fish_indent - we can simply query the indentation
level of the newline. Reshuffle the code since we need to pass the offset
of the newline. Maybe this can even be simplified further.
Fixes#7720
Otherwise this would look weird if you had, say, a tab in there.
See #7716.
(note that this doesn't handle e.g. zero-width-joiners, because those
aren't currently escaped. we might want to add an escape mode for
unprintable characters, but for combining codepoints that's tricky!)
After commit 6dd6a57c60, 3 remaining
builtins were affected by uint8_t overflow: `exit`, `return`, and
`functions --query`.
This commit:
- Moves the overflow check from `builtin_set_query` to `builtin_run`.
- Removes a conflicting int -> uint8_t conversion in `builtin_return`.
- Adds tests for the 3 remaining affected builtins.
- Simplifies the wording for the documentation for `set --query`.
- Does not change documentation for `functions --query`, because it does
not state the exit code in its API.
- Updates the CHANGELOG to reflect the change to all builtins.
Prior to this fix, if stdin were explicitly closed, then builtins would
silently fail. For example:
count <&-
would just fail with status 1. Remove this limitation and allow each
builtin to handle a closed stdin how it sees fit.
builtin_set_query returns the number of missing variables. Because the
return value passed to the shell is an 8-bit unsigned integer, if the
number of missing variables is a multiple of 256, it would overflow to 0.
This commit saturates the return value at 255 if there are more than 255
missing variables.
Prior to this change, the checks/git.fish test would fail if run from a
git interactive rebase (such as via `git rebase -i --exec 'ninja test'`),
because git itself would inject stuff into the environment. Teach the git
test how to clean up its environment first before running.
This needs to be rewritten, I'm pretty sure we have like 6 of these
kinds of ad-hoc "is this quoted" things lying around.
But for now, at least don't just check if the *previous* character was
a backslash.
Fixes#7685.
This goes to a separate file because that makes option parsing easier
and allows profiling both at the same time.
The "normal" profile now contains only the profile data of the actual
run, which is much more useful - you can now profile a function by
running
fish -C 'source /path/to/thing' --profile /tmp/thefunction.prof -c 'thefunction'
and won't need to filter out extraneous information.
Expansion parses slices like "$PATH[1..2]", but so does "set" when assigning
"set PATH[1..2] . .". Commit be06f842a ("Allow to omit indices in index
range expansions") forgot the latter.
This makes the fish_git_prompt variable handlers kick in, meaning we
see the informative chars.
The big question here is what happens if there's a non-UTF-8 locale in
the test.
Theoretically we set LC_CTYPE, but.....
This used to print a literal DEL character in the output for `bind`,
which wouldn't actually show up and made it hard to figure out what
the key was.
So we just escape it back to how we actually used it - `\x7f`.
Fixes#7631.
A weird interaction between grouped short options and our weird option
parsing that puts unknown options back:
```
echo "-n foo"
```
would see the `-n`, turn off printing newlines, interpret the " " as
another grouped short option, see that there is no short option for
space and put the entire token back on the arguments pile.
So it would print "-n foo" *without a newline*.
Fix this by keeping an old state of the options around and reverting
it when putting options back.
The alternative is *probably* to forbid the " " short option in
wgetopt, then check if an option group contains it and error out, but
this should only really be a problem in `echo` because that is,
AFAICT, the only thing that puts the options back.
Fixes#7614
This adds a test to ensure that if a long running background process is
launched from a command substitution, that process does not cause the
cmdsub to hang. That could easily happen if we just wait for the pipe to
close; this is verifying that we are also checking for the job to complete.
Don't go into implicit interactive mode without ever executing
anything - not even `exit` or reacting to ctrl-d. That just renders
the shell useless and unquittable.
It was always a bit ridiculous that argparse required `X-longflag` if
that "X" short flag was never actually used anywhere.
Since the short letter is for getopt's benefit, we can hack around
this with our old friend: Unicode Private Use Areas.
We have a counter, starting at 0xE000 and going to 0xF8FF, that counts
up for all options that don't have a short flag and provides one. This
gives us up to 6400 long-only options.
6.4K should be enough for everybody.
Prior to this change, a glob like `**/file.txt` would only match
`file.txt` in subdirectories; the `**` must match at least one directory.
This is historical behavior.
With this change we move a little closer to bash's implementation by
allowing a literal `**` segment to match in the current directory. That
is, `**/foo` will match both `foo` and `bar/foo`, while `b**/foo` will
only match `bar/foo`.
Fixes#7222.
This would tell you a function was "Defined in - @ line 1" for every
function defined via `source`.
Really, ideally we'd figure out where the *source* call was, but that'
much more complicated, so we just give a comprehensible message.
This matches what we do in --profile's output:
```
> source /home/alfa/.config/fish/config.fish
--> set -gx XDG_CACHE_HOME /home/alfa/.cache
--> set -gx XDG_CONFIG_HOME /home/alfa/.config
--> set -gx XDG_DATA_HOME /home/alfa/.local/share
```
instead of
```
+ source /home/alfa/.config/fish/config.fish
+++ set -gx XDG_CACHE_HOME /home/alfa/.cache
+++ set -gx XDG_CONFIG_HOME /home/alfa/.config
+++ set -gx XDG_DATA_HOME /home/alfa/.local/share
```
E.g. if we do `string match -q`, and we find a match, nothing about
the input can change anything, so we quit early.
This is mainly useful for performance, but it also allows `string`
with `-q` to be used with infinite input (e.g. `yes`).
Alternative to #7495.
Currently a bit limited, unfortunately printf's `%a` specifier is
absolutely unreadable.
So we add `hex` and `octal` with `0x` and `0` prefixes respectively,
and also take a number but currently only allow 16 and 8.
The output is truncated to integer, so scale values other than 0 are
invalid and 0 is implied.
The docs mention this may change.
The '--import' flag was used for importing named capture groups, but it
was decided to always import them unconditionally. This flag was causing
the tests to fail.
This was typically overridden by "too many/few arguments", but it's
actually incorrect:
sin(55
has the correct number of arguments to `sin`, but it's lacking
the closing `)`.
This switch is no longer necessary when only one command is given.
Internally completions are stored separately for each command,
so we only every print one command name per "complete" line anyway.
These aliases seem to be common, see #7389 and others. This prevents
recursion on that example, so `alias ssh "env TERM=screen ssh"` will just
have the same completions as ssh.
Checking the last token is a heuristic which hopefully works for most
cases. Users are encouraged to use functions instead of aliases.
I am not sure why this worked, actually.
These tests did not have $fish set anywhere, and on my fresh OpenBSD
VM it ended up calling whatever that calls "fish" (I think it's that
"Go fish!" game?).