This didn't do all the syntax checks, so something like
fish -c 'echo foo; and $status'
complained of a missing command `0` (i.e. $status), and
fish -c 'echo foo | exec grep'
hit an assert!
So we do what read_ni does, parse each command into an ast, run
parse_util_detect_errors on it if it worked and then eval the ast.
It is possible to do this neater by modifying parser::eval, but I
can't find where.
This is slightly unclean. Even tho it would otherwise be syntactically
valid, using $status as a command is very very very likely to be an
error, like
if not $status
We have reports of this surprisingly regularly, including #2773.
Because $status can only ever be a value from 0 to 255, it is also
very unlikely to be an actual command, and that command is very
unlikely to do what you want.
So we simply point the user towards the "conditions" help section,
that should explain things.
This is opt-in through a new feature flag "ampersand-nobg-in-token".
When this flag and "qmark-noglob" are enabled, this command no longer
needs quoting:
curl https://example.com/thing?foo=bar&duran=duran
Compared to the previous approach e1570a4 ("Let '&' only separate as
the first char of a word"), this has some advantages:
1. "&&" and "&>" are no longer affected. They are still special, even
if used between tokens without spaces, like "echo bar&>foo".
Maybe this is not really *better*, but it avoids risking to annoy
users by breaking the old variant.
2. "&" is still special if at the end of a token, like in "sleep 1&".
Word movement is not affected by the semantics change, so Alt-F and
friends still stop at every "&".
Currently, if a "return" is given outside of a function, we'd just
throw an error.
That always struck me as a bit weird, given that scripts can also
return a value.
So simply let "return" outside also exit the script, kinda like "exit"
does.
However, unlike "exit" it doesn't quit an interactive shell - it seems
weird to have "return" do that as well. It sets $status, so it can be
used to quickly set that, in case you want to test something.
Today the reader exposes its internals directly, e.g. to the commandline
builtin. This is of course not thread safe. For example in concurrent
execution, running `commandline` twice in separate threads would cause a
race and likely a crash.
Fix this by factoring all the commandline state into a new type
'commandline_state_t'. Make it a singleton (there is only one command
line
after all) and protect it with a lock.
No user visible change here.
In the variable handler, we just go through the entire thing and keep
every element once.
If there's a duplicate, we set it again, which calls the handler
again.
This takes a bit of time, to be paid on each startup. On my system,
with 100 already deduplicated elements, that's about 4ms (compared to
~17ms for adding them to $PATH).
It's also semantically more complicated - now this variable
specifically is deduplicated? Do we just want "unique" variables that
can't have duplicates?
However: This entirely removes the pathological case of appending to
$fish_user_paths in config.fish (which should be an FAQ entry!), and the implementation is quite simple.
This adds a hack to the parser. Given a command
echo "x$()y z"
we virtually insert double quotes before and after the command
substitution, so the command internally looks like
echo "x"$()"y z"
This hack allows to reuse the existing logic for handling (recursive)
command substitutions.
This makes the quoting syntax more complex; external highlighters
should consider adding this if possible.
The upside (more Bash compatibility) seems worth it.
Closes#159
This apparently doesn't work at all under Github Actions with tsan, so let's skip it.
If anyone feels the need to dig deeper into this, have at it. I find
this distracting.
When the user presses control-C, fish marks a cancellation signal which
prevents fish script from running, allowing it to properly unwind.
Prior to this commit, the signal was cleared in the reader. However this
missed the case where a binding would set $fish_bind_mode which would
trigger event handlers: the event handlers would be skipped because of
the cancellation flag was still set. This is similar to #6937.
Let's clear the flag earlier, as soon as we it's set, in inputter_t.
Fixes#8125.
In some setups (eg. macports) $tmpdir can expand to more than
100 symbols and tests fail with 'socket file name too long'
errors.
Using relative path to socket file fixes the issue.
* string: Allow `collect --no-empty` to avoid empty ellision
Currently we still have that issue where
test -n (thing | string collect)
can return true if `thing` doesn't print anything, because the
collected argument will still be removed.
So, what we do is allow `--no-empty` to be used, in which case we
print one empty argument.
This means
test -n (thing | string collect -n)
can now be safely used.
"no-empty" isn't the best name for this flag, but string's design
really incentivizes reusing names, and it's not *terrible*.
* Switch to `--allow-empty`
`--no-empty` does the exact opposite for `string split` and split0.
Since `-a`/`--allow-empty` already exists, use it.
The tmux-prompt test was failing when run more than once, because
XDG_DATA_HOME has a leading double-dot, causing the uvars file to
leak across sessions. Descend more deeply into our tmpdir to isolate
our XDG_DATA_HOME.
This reverts commit b56b230076.
which somehow made us miss repaints on uvar notifications.
The commit was a workaround for a polling bug which was later properly
fixed by 7c5b8b855 ("Use the uvar notifier pipe timestamp to avoid
excessive polling"), so it's no longer necessary.
Add a system test. If I had a better understanding of the bug I could
probably write a better test.
Fixes#8088
We used to warn about PATH and CDPATH that are not valid directories,
but only if they contain colons.
However, the warning was a false positive because we would split
those values by colons anyway. So there is nothing left we want to
warn about.
Fixes#8095
sigint2 would hang (probably because of different semantics in signal
delivery?)
wcstod isn't implemented correctly, so math can't do hex numbers.
OpenBSD only passes the filename as argv[0] and doesn't give us another feature I know of, so status fish-path can't work.
* Try to set LC_CTYPE to something UTF-8 capable
When fish is started with LC_CTYPE=C (even just effectively, often via
LC_ALL=C!), it's basically broken. There's no way to handle non-ASCII
characters with a C locale unless we want to write our
locale-independent replacements for all of the system functions.
Since we're not going to do that, let's try to find *some locale* for
LC_CTYPE.
We already do that in __fish_setlocale, but that's
- a bit of a weird thing that reads unstandardized system
configuration files
- allows setting locale to C explicitly
So it's still easily possible to end up in a broken configuration.
Now, the issue with this is that there is (AFAICT) no portable way to
get a list of all allowed locales and C.UTF-8 is not standardized, so
we have no one locale to fall back on and are forced to try a few. The
list we have here is quite arbitrary, but it's a start.
Python does something similar and only tries C.UTF-8, C.utf8 and
"UTF-8".
Once C.UTF-8 is (hopefully) standardized, that will just start
working (tm).
Note that we do not *export* the fixed LC_CTYPE variable, so external
programs still have to deal with the C locale, but we have no real
business messing with the user's environment.
To turn it off: $fish_allow_singlebyte_locale, if set to something true (like "1"),
will re-run the locale initialization and skip the bit where we force
LC_CTYPE to be utf8-capable.
This is mainly used in our tests, but might also be useful if people
are trying to do something weird.
The hope is that the noshebang test was fixed on old glibc
through e74b9d53df. Revert the previous optimistic attempts to
fix these through adding sleeps and subshells.
This reverts commit b3da0bd5a2.
This reverts commit 8a86d3452f.
This is an attempt to solve the test failures on Launchpad's CI.
I'm assuming when we do a redirection like
foo > file
and then try to execute `file` immediately afterwards, we either
haven't written it soon enough or closed the file, so we get a "text
file busy" error.
So, when we do that in a new fish the file should be closed once it
quits.
See #8021.
When you try to execute a file directly after you've written to it,
you might, on some systems, get a "text file busy" error.
So we unfortunately have to sleep to avoid it.
See #8021 for where this was added,
537b3f6cb1 for the same problem.
Now that `$last_pid` is never fish's pid, we no longer need to force
jobs to run in their own pgroup. Restore the job control behavior to
what it was prior, so that signals may be delivered properly in
non-interactive mode.
This reverts commit 3255999794
Prior to this change, a function with an on-job-exit event handler must be
added with the pgid of the job. But sometimes the pgid of the job is fish
itself (if job control is disabled) and the previous commit made last_pid
an actual pid from the job, instead of its pgroup.
Switch on-job-exit to accept any pid from the job (except fish itself).
This allows it to be used directly with $last_pid, except that it now
works if job control is off. This is implemented by "resolving" the pid to
the internal job id at the point the event handler is added.
Also switch to passing the last pid of the job, rather than its pgroup.
This aligns better with $last_pid.
It is possible to run a function when a process exits via `function
--on-process-exit`, or when a job exits via `function --on-job-exits`.
Internally these were distinguished by the pid in the event: if it was
positive, then it was a process exit. If negative, it represents a pgid
and is a job exit. If zero, it fires for both jobs and processes, which is
pretty weird.
Switch to tracking these explicitly. Separate out the --on-process-exit
and --on-job-exit event types into separate types. Stop negating pgids as
well.
This switches builtin_wait from waiting on jobs in the active job list, to
waiting on the wait handles. The wait handles may be either derived from
the job list itself, or from saved wait handles from jobs that exited in
the background.
Fixes#7210
Prior to this fix, an escaped character like \x41 (hex for ascii A)
was interpreted the same was as A, so that $\x41 would be the same
as $A. Fix this by inserting an INTERNAL_SEPARATOR before these escapes,
so that we no longer treat it as part of the variable name.
This also affects brackets; don't treat echo $foo\1331\135 the same as
echo $foo[1].
Fixes#7969
This is the last time I'm doing this before I rip these particular
tests out.
As far as I know there is no actual *problem* here, this is just
failing through a combination of macOS and Github Actions being slow
as molasses.
So it is wasting our time and therefore worse than not having these
tests at all, especially since they very rarely fail for good reasons.
We would leave some escape delay tests intact with generous timeouts, which would provide 90%
of the coverage with 10% of the hassle.
This simply checks if the parser requested exit after running any
binding scripts (in read_normal_chars).
I think this means we no longer need the `exit` bind function.
Fixes#7967.
Just add some extra sleep time so it hopefully also works when the
CI system is overloaded. This succeeded >60 times in the CI, without
a single failure.
In case it legitimately fails again, we should provide simple steps
to reproduce the failure interactively (using "tmux attach").
The uvar issue only triggered because two fish are started - one is
running the tmux-complete script, the other one is running inside tmux.
We could reduce the complexity of this test by writing it in a
different language, like sh or python.
Reproducible at least on Linux, where the "named pipe" universal
variable notifier is used:
rm -rf build/test/xdg_config
XDG_CONFIG_HOME=build/test/xdg_config ./build/fish -c "xterm -e ./build/fish"
The child fish reacts to keyboard input with a noticeable initial
delay. This is because the universal variable file is polled over
a million times, even when I immediately press Control-D. This polling
prevents readb() from handling keyboard input.
Before commit 939aba02d ("Refactor input_common.cpp:readb"), readb()
reacted to keyboard input even when there were universal variable
notifications. Restore this behavior, but make sure to call the
universal variable notifier after the new "prepare_to_select" logic.
Maybe the problem is in the notifier but the old behavior was sane.
Fixes the problems described in
7a556ec6f2 (commitcomment-49773677)
Adding "-d uvars-file" to the reproducesr shows that we are checking
the uvar file repeatedly:
uvar-file: universal log sync
uvar-file: universal log sync elided based on fast stat()
uvar-file: universal log no modifications
This only uses the functions fish ships with, but still doesn't allow
any *customization*, which is the point of no-config.
This makes it a lot more usable, given that the actual normal prompt
and things are there.
This still doesn't set any colors, because we don't run
__fish_config_interactive because we don't read config.fish (any
config.fish), because that would run the snippets.
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.
Make it an ordinary struct wrapping a vector, instead of a template.
This is in preparation for using it more widely, for matching bindings
as well as mouse CSI sequences.
Also add some mouse-disabling tests.
This runs in 100ms increments, so there's not a lot of harm in trying
longer - it should take the same time everywhere it succeeded before.
But I've reproduced failures on FreeBSD 13 on sr.ht, so there's at
least one platform where a total time of 1 second isn't enough.
Now we do 50 tries, which is 5 seconds.
This could have been one iteration off, e.g.
```fish
function on-winch --on-signal winch
echo $LINES
end
```
Resize the terminal, it'll print e.g.
24
then run `echo $LINES` interactively, it might have a different answer.
This isn't beautiful, but it works. A better solution might be to make
the termsize vars electric and just always update them on read?
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.
When fish starts, it notices which pgroup owns the tty, and then it
restores that pgroup's tty ownership when it exits. However if fish does
not own the tty, then (on Mac at least) the tcsetpgrp call triggers a
SIGSTOP and fish will hang while trying to exit.
The first change is to ignore SIGTTOU instead of defaulting it. This
prevents the hang; however it risks re-introducing #7060.
The second change somewhat mitigates the risk of the first: only do the
restore if the initial pgroup is different than fish's pgroup. This
prevents some useless calls which might potentially steal the tty from
another process (e.g. in #7060).
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.
- Check for special characters *before* attempting to parse
- Also ignore lines with `{` and `*`
- Also skip lines with `<<` because that might be a heredoc (or a
- `<<<` herestring)
Fixes#7874.
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 concerns the behavior when running an external command from a key
binding. The history is:
Prior to 5f16a299a7, fish would run these external commands in shell
modes. This meant that fish would pick up any tty changes from external
commands (see #2114).
After 5f16a299a7, fish would save and restore its shell modes around
these external commands. This introduced a regression where anything the
user typed while a bound external command was executing would be echoed,
because external command mode has ECHO set in c_lflag. (This can be
reproed easily with `bind -q 'sleep 1'` and then pressing q and typing).
So 5f16a299a7 was reverted in fd9355966.
This commit partially reverts fd9355966. It has it both ways: external
commands are launched with shell modes, but/and shell modes are restored
after the external command completes. This allows commands to muck with
the tty, as long as they can handle getting shell modes; but it does not
enable ECHO mode so it fixes the regression found in #7770.
Fixes#7770. Fixes#2114 (for the third time!)
This partially reverts commit fd9355966e.
Unfortunately this causes input coming in while bind functions are
running to show up on screen.
Since the cure is worse than the disease let's just stop doing it.
My guess is this needs to *only* be done while running an external
command.
Fixes#7770
Reintroduces #2114
Partially reverts 5f16a299a7
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.
For reasons unclear to me, fish enables bold mode unconditionally if
the background is set.
However, this called a background "set" if it wasn't exactly the
"normal" color, whereas set_color --print-colors would set a color
of *none*.
We have three special non-color colors:
- "normal"
- "reset"
- "none"
All of these specify some form of absence of background color, so all
of them should be checked.
Fixes#7805
* 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
NetBSD's sleep quits when foregrounded sometimes. I'm not entirely
sure *why*, but this is reproducible with the default /bin/sh, so it's
not our fault.
Because this fails our tests, go back to using cat *there*, because we
can't use it on macOS - 4c9d01cab0.
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
This fails on FreeBSD on sr.ht and NetBSD on my own VM, but it works manually.
It also fails on macOS but I have no way to confirm.
I think it might be a problem in pexpect's platform support?
Either way, the test is valuable so just skip it there and solve it later.
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.
This was lost in
6bdbe732e40c2e325aa15fcf0f28ad0dedb3a551..c7160d7cb4970c2a03df34547f357721cb5e88db.
Note that we only print a term-support flog message for now, the
warning seems a bit much.
Fixes#7709.
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.
Prior to this change, `fish_private_mode` worked by just suppressing
history outright. With this change, `fish_private_mode` can be toggled on
and off. Commands entered while `fish_private_mode` is set are stored but
in memory only; they are not written to disk.
Fixes#7590Fixes#7589
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.
Before running a command, or before importing a command from bash history,
we perform error checking. As part of error checking we expand commands
including variables and globs. If the glob is very large, like `/**`, then
we could hang expanding it.
One fix would be to limit the amount of expansion from the glob, but
instead let's just not expand command globs when performing error checking.
Fixes#7407
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
```
This increases a 100ms timeout to 200ms, because we've hit it on
Github Actions:
```
INPUT 3904.65 ms (Line 223): set -g fish_escape_delay_ms 100\n
OUTPUT +1.74 ms (Line 224): \rprompt 25>
INPUT +0.71 ms (Line 230): echo abc def
INPUT +0.57 ms (Line 231): \x1b
INPUT +0.57 ms (Line 232): t\r
OUTPUT +2.41 ms (Line 234): \r\ndef abc\r\n
OUTPUT +1.63 ms (Line 234): \rprompt 26>
INPUT +0.75 ms (Line 239): echo ghi jkl
INPUT +0.57 ms (Line 240): \x1b
INPUT +134.98 ms (Line 242): t\r
```
In other places it decreases sleeps where we just wait for a timeout to elapse, in which case we don't need much longer than the timeout.
And again clang-format does something I don't like:
- if (found != end && std::strncmp(found->name, name, len) == 0 && found->name[len] == 0) return found;
+ if (found != end && std::strncmp(found->name, name, len) == 0 && found->name[len] == 0)
+ return found;
I *know* this is a bit of a long line. I would still quite like having
no brace-less multi-line if *ever*. Either put the body on the same
line, or add braces.
Blergh
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.
Prior to this fix, when key binding is a script command (i.e. not a
readline command), fish would run that key binding using fish's shell
tty modes. Switch to using the external tty modes. This re-fixes
issue #2214.
With the upcoming fix to place the tty in external-proc mode, add a sleep
which resolves a race between emitting a newline and restoring it to shell
mode.
Prior to this change, when a process resumes because it is brought back
to the foreground, we would reset the terminal attributes to shell mode.
This fixed#2114 but subtly introduced #7483.
This backs out 9fd9f70346, re-introducing #2114 and re-fixing #7483.
A followup fix will re-fix #2114; these are broken out separately for
bisecting purposes.
Fixes#7483.
I *think* this might sometimes (on CI) be eating the prompt, so that the actual `prompt`
part of `expect_prompt` doesn't find anything.
On Github Actions we see things like:
```
Testing file pexpects/generic.py ... Failed to match pattern: prompt 5
generic.py:35: timeout from expect_prompt("echo .history.*")
[...]
OUTPUT +1.08 ms (Line 31): \rprompt 4>
INPUT +0.35 ms (Line 34): echo $history[1]\n
OUTPUT +1.58 ms (Line 35): echo $history[1]\r\necho $history[1]\r\n⏎ \r⏎ \r\rprompt 5>
```
so the prompt *is* printed, it's just not correctly matched.
Apparently on macOS SIGTSTP (from control-Z) causes `read()` to return
EINTR.
This means `cat | cat` will exit as soon as it's backgrounded and
brought back.
So instead we use `sleep`, which won't read(), and therefore is
impervious to these puny attacks.
See discussion in #7447.
The classic mistake: Some of these have a bit of a delay, but it's supposed to
be *under* the timeout, so it needs to be *shorter* not longer to
increase the slack.
We just had the following output on Github Actions:
INPUT +0.94 ms (Line 34): echo ghi jkl
INPUT +0.72 ms (Line 35): \x1b
INPUT +63.12 ms (Line 37): t\r
The default escape delay is 30ms, that had 60ms between an escape and
a tab, so it missed it.
So: We have to increase the delay for CI's benefit. Let's try with
80ms, because otherwise we'd have to bump up other timeouts and the
bind tests take long enough as it is.
Github Action's macOS builds are even more resource-starved (even tho
they use the same provider?) than
Travis, but Travis is unusable to us now, so....
In some cases the completion we come up with may be unexpected, e.g.
if you have files like
/etc/realfile
and
/etc/wrongfile
and enter "/etc/gile", it will accept "wrongfile" because "g" and
"ile" are in there - it's a substring insertion match.
The underlying cause was a typo, so it should be easy to go back.
So we do a bit of magic and let "cancel" undo, but only right after a
completion was accepted via complete or complete-and-search.
That means that just reflexively pressing escape would, by default, get you back to
the old token and let you fix your mistake.
We don't do this when the completion was accepted via the pager,
because 1. there's more of a chance to see the problem there and 2.
it's harder to redo in that case.
Fixes#7433.
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 `)`.
We've heard news of this regressing, so let's add the test that should
have been there already (mea culpa!).
Because we now use POSIX_VDISABLE, this should also work in tandem
with ctrl-space (which sends NUL), but we can't test *that* because
some systems might not have POSIX_VDISABLE.
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.
Ensure that the increment= param is set via keyword, not via positional arg.
This mistake was masking a bug where the "^a b c" match was not being tested,
because it was being set as the value for increment!
This switches the 'increment' param from "after" to "before." Instead
of expect_prompt saying if the next prompt will be incremented, each
call site says if it should have been incremented sinec the last prompt.
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?).
If the padding is not divisible by the char's width without remainder,
we pad the remainder with spaces, so the total width of the output is correct.
Also add completions, changelog entry, adjust documentation, add examples
with emoji and some tests. Apply some minor style nitpicks and avoid extra
allocations of the input strings.
Prior to this change, tab completing with a variable assignment like
`VAR=val cmd<tab>` would parse out and apply VAR=val, then recursively
invoke completions. This caused some awkwardness around the wrap chain -
if a wrapped command had a variable completion we risked infinite
recursion. A secondary problem is that we would run any command
substitutions inside variable assignment, which the user does not expect
to run until pressing enter.
With this change, we explicitly track variable assignments encountered
during tab completion, including both those explicitly given on the
command line and those found during wrap chain walk. We then apply them
while suppressing command substitutions.
In preparation for applying variable assignments (VAR=VAL cmd), separate
them out from the command when performing completions. This includes both
those that the user typed, and any that come about through
completion --wraps.
The "wrap chain" refers to a sequence of commands which wrap other
commands, for completion purposes. One possibility is that a wrap chain
will produce a combinatorial explosion or even an infinite loop, so there
needs to be logic to prevent that. Part of that logic is encapsulated in a
visited set (wrap_chain_visited_set_t) to prevent exploring the same item
twice.
Prior to this change, we stored pairs (command, wrapped_command). But we
only really need to store the wrapped command. Switch to that.
One consequence is that if a command wraps another command in more than
one way, we won't explore both ways. This seems unlikely in practice.
Detect recursive calls to builtin complete and the internal completion in
the same place.
In 0a0149cc2 (Prevent infinite recursion when completion wraps variable assignment)
we don't print an error when completing certain aliases like:
alias vim "A=B vim"
But we also gave no completions.
We could make this case work, but I think that trying to salvage situations
like this one is way too complex. Instead, let the user know by printing an
error. Not sure if the style of the error fits.
We could add some heuristic to alias to not add --wraps in some cyclic cases.
This reads any additional positional arguments given to `fish -c` into
$argv.
We don't handle the first argument specially (as `$0`) as that's confusing and
doesn't seem very useful.
Fixes#2314.
This makes history searches case-insensitive, unless the search string
contains an uppercase character.
This is what vim calls "smartcase".
Fixes#7273.
Closes#7344
Apply a targeted fix to the place where complete() is called to handle nested
variable assignments. Sadly, reporting an error is probably not okay here,
because people might legitimately use aliases like:
alias vim "A=B command vim"
This is all a bit ugly, and I hope to find a cleaner solution. Supporting
completions on commandlines like `x=$PWD cd $x/ ` is a nice feature but it
comes with some complexity.
"function --argument" is not a thing, it's "--argument-names". This only
accidentally works because our getopt is awful and allows abbreviated
long options.
Similarly, one argparse test used "--d" instead of "-d" or "--def".
Since builtins don't actually have the streams connected, but instead
read input via the io_streams_t objects, this would just always say
what *fish's* fds were.
Instead, pass along some of the stream data to check those
specifically - nobody cares that `test`s fd 0 *technically* is stdin.
What they want to know is that, if they used another program in that
place, it would connect to the TTY.
This is pretty hacky - I abused static variables for this, but
since it's two bools and an int it's probably okay.
See #1228.
Fixes#4766.
This re-enables the test that eval retains pgroups, from #6806.
The old version was racey and failed a lot. In the new version, we use
temp files to resolve the race.
The case for symlinked directories being duplicated a lot isn't there,
but there *is* a usecase for adding the symlink rather than the
target, and that's homebrew.
E.g. homebrew installs ruby into /usr/local/Cellar/ruby/2.7.1_2/bin,
and links to it from /usr/local/opt/ruby/bin. If we add the target, we
would miss updates.
Having path entries that point to the same location isn't a big
problem - it's a path lookup, so it takes a teensy bit longer. The
canonicalization is mainly so paths don't end up duplicated via weird
spelling and so relative paths can be used.
Taken from GNU realpath, this one makes realpath not resolve symlinks.
It still makes paths absolute and handles duplicate and trailing
slashes.
(useful in fish_add_path)
With a commandline like
```
a b c d
```
and the cursor at the beginning, this would eat "a b", which isn't a
sensible bigword.
Bigword should be "a word, with optional leading whitespace".
This was caused by an overly zealous state-machine that always ate one
char and only *then* started eating leading whitespace.
Instead eat *a character*, and if it was whitespace go on eating
whitespace, and if it was a printable go straight to only eating
printables.
Fixes#7325.
This can easily lead to an infinite loop, if a variable handler
triggers a repaint and the variable is set in the prompt, e.g. some of
the git variables.
A simple way to reproduce:
function fish_mode_prompt
commandline -f repaint
end
Repainting executes the mode prompt, which triggers a repaint, which
triggers the mode prompt, ....
So we just set a flag and check it.
Fixes#7324.
Currently, completions have to be specified like
```fish
complete -c foo -l opt
```
while
```fish
complete foo -l opt
```
just complains about there being too many arguments.
That's kinda useless, so we just assume if there is one left-over
argument that it's meant to be the command.
Theoretically we could also use *all* the arguments as commands to
complete, but that seems unlikely to be what the user wants.
(I don't think multi-command completions really happen)
Currently only `complete` will list completions, and it will list all
of them.
That's a bit ridiculous, especially since `complete -c foo` just does nothing.
So just make `complete -c foo` list all the completions for `foo`.
Previously, when a command wasn't found, fish would emit the
"fish_command_not_found" *event*.
This was annoying as it was hard to override (the code ended up
checking for a function called `__fish_command_not_found_handler`
anyway!), the setup was ugly,
and it's useless - there is no use case for multiple command-not-found handlers.
Instead, let's just call a function `fish_command_not_found` if it
exists, or print the default message otherwise.
The event is completely removed, but because a missing event is not an error
(MEISNAE in C++-speak) this isn't an issue.
Note that, for backwards-compatibility, we still keep the default
handler function around even tho the new one is hard-coded in C++.
Also, if we detect a previous handler, the new handler just calls it.
This way, the backwards-compatible way to install a custom handler is:
```fish
function __fish_command_not_found_handler --on-event fish_command_not_found
# do a little dance, make a little love, get down tonight
end
```
and the new hotness is
```fish
function fish_command_not_found
# do the thing
end
```
Fixes#7293.
Now command, jobs, type, abbr, builtin, functions and set take `-q` to
query for existence, but the long option is inconsistent.
The first three use `--quiet`, the latter use `--query`. Add `--query`
to the first three, but keep `--quiet` around.
Fixes#7276.
Just as `math "bitand(5,3)"` and `math "bitor(6,2)"`.
These cast to long long before doing their thing,
so they truncate to an integer, producing weird results with floats.
That's to be expected because float representation is *very*
different, and performing bitwise operations on floats feels quite useless.
Fixes#7281.
Prior to this change, if we saw more than one repaint readline command in
a row, we would try to ignore the second one. However this was never the
right thing to do since sometimes we really do need to repaint twice in a
row (e.g. the user hits Ctrl+L twice). Previously we were saved by the
buginess of this mechanism but with the repainting refactoring we see
missing redraws.
Remove the coalescing logic and add a test. Fixes#7280.
Because TERM was set to something other than 'dumb', we were subject to
syntax highlighting and other interactive features that would affect the
output. In practice we were getting lucky timing-wise, but with upcoming
interactive changes syntax highlighting started to fail this test.
It could be nice to use a heuristic for this in future, but for now let's
stick to the old behavior so we can keep formatting scripts without occasional
bad formatting changes.
A heuristic could also be used to break lines after |, && or || but I don't
think there is much need for that at the moment.
Closes#7252
This concerns code like the following:
while true ; sleep 100; end
Here 'while' is a "simple block execution" and does not create a new job,
or get a pgid. Each 'sleep' however is an external command execution, and
is treated as a distinct job. (bash is the same way). So `while` and
`sleep` are always in different job groups.
The problem comes about if 'sleep' is cancelled through SIGINT or SIGQUIT.
Prior to 2a4c545b21, if *any* process got a SIGINT or SIGQUIT, then fish
would mark a global "stop executing" variable. This obviously prevents
background execution of fish functions.
In 2a4c545b21, this was changed so only the job's group gets marked as
cancelled. However in the case of one job group spawning another, we
weren't propagating the signal.
This adds a signal to parse_execution_context which the parser checks after
execution. It's not ideal since now we have three different places where
signals can be recorded. However it fixes this regression which is too
important to leave unfixed for long.
Fixes#7259
Might help figuring out where this times out on CI?
We're waiting *20 seconds* for the output to appear, there's no way
that's too slow. So maybe we're going too fast elsewhere?
This indents continuations after pipes and conjunctions if they contain
a newline.
Example:
cmd1 &&
cmd2
But it avoids the "double indent" if it indented unconditionally:
cmd1 | begin
cmd2
end
More work towards improving #7252
Prior to this change, when emitting gap text (comments, newlines, etc),
fish_indent would use the indentation of the text at the end of the gap.
But this has the wrong result for this case:
begin
command
# comment
end
as the comment would get the indent of the 'end'. Instead use the indent
computed for the gap text itself.
Addresses one case of #7252.
It's useless - `expect` has a timeout anyway, and it defaults to 5s,
so these 0.5s sleeps just mean it'll always take at least 0.5s.
Sometimes it is useful to let things settle before *sending* text, and
it would be nice to be able to set the timeout for each expect
separately, but just adding to the timeout isn't useful.
This one sometimes fails with a zombie detected, so I'm assuming it's
too fast for reaping to happen, so we add another 100ms sleep.
Yeah, this isn't great but...eh
This can be used to determine whether the previous command produced a real status, or just carried over the status from the command before it. Backgrounded commands and variable assignments will not increment status_generation, all other commands will.
This changes how fish attempts to protect itself from calling tcsetpgrp() too
aggressively. Recall that tcsetpgrp() will "force" itself, if SIGTTOU is
ignored (which it is in fish when job control is enabled).
Prior to this fix, we avoided SIGTTINs by only transferring the tty ownership
if fish was already the owner. This dated from a time before we had really
nailed down how pgroups should be assigned. Now we more deliberately assign a
job's pgroup so we don't need this conservative check.
However we still need logic to avoid transferring the tty if fish is not the
owner. The bad case is when job control is enabled while fish is running in the
background - here fish would transfer the tty and "steal" from the foreground
process.
So retain the checks of the current tty owner but migrate them to the point of
calling tcsetpgrp() itself.
Unfortunately this doesn't quite fix the issue with Pantheon
Terminal (#7913), as that somehow manages to re-set $VTE_VERSION by
the time littlecheck runs.
This switches fish_indent from parsing with parse_tree
to the new ast.
This is the most difficult transition because the new ast retains less
lexical information than the old parse tree. The strategy is:
1. Use parse_util_compute_indents to compute indenting for each token.
2. Compute the "gap text" between the text of significant tokens. This
contains whitespace, comments, etc.
3. "Fix up" the gap text while leaving the significant tokens alone.
I really kinda hate how insistent clang-format is to have line
breaks *IFF THE LINE IS TOO LONG*.
Like... lemme just add a break if it looks better, will you?
But it is the style at this time, so we shall tie an onion to our
belt.
A broken/missing optspec or `--` is a bug in the script using
argparse, an unknown option or invalid argument is a bug in using that script.
So in the former case print a stacktrace, because the person writing
the `argparse` call is at fault, in the latter don't.
Fixes#6703.
Note: This includes a super cheesy thing to print variable contents.
The expect version has one that's a bit more elaborate (featuring a
marker setup), but tbh that doesn't seem to be worth it.
If we do need it, we can add it, but it seems more likely we'd just do
`set -S`, or do it in a check instead.
With the new pexpect based framework, bind and pipeline expect tests can
be removed.
Amusingly the complete.fish check required the existence of bind.expect.
Fix the check at the same time.
Make it easier to use pexpect and to understand its error messages.
Switch to a style in tests using bound methods, which makes them
less noisy to write.
This adds a new interactive test framework based on Python's pexpect. This
is intended to supplant the TCL expect-based tests.
New tests go in `tests/pexpects/`. As a proof-of-concept, the
pipeline.expect test and the (gnarly) bind.expect test are ported to the
new framework.
There's a terrible number of fishscripts that start with
set path (dirname (status filename))
And that's really just a bit boring.
So let's let it be
set path (status dirname)
This is a function you can either execute once, interactively, or
stick in config.fish, and it will do the right thing.
Some options are included to choose some slightly different behavior,
like setting $PATH directly instead of $fish_user_paths, or moving
already existing components to the front/back instead of ignoring
them, or appending new components instead of prepending them.
The defaults were chosen because they are the most safe, and
especially because they allow it to be idempotent - running it again
and again and again won't change anything, it won't even run the
actual `set` because it skips that if all components are already in.
Fixes#6960.
Variables like $status and $history showed up in all scopes, including
universal, when querying with `set -q` or `set -S`.
This makes it so they all only count as set in global scope, because
we already only allow assignment to electric variables in global scope.
Fixes#7032
The default implementation will not print any output in that case, but this provides users with additional flexibility when it comes to customising the shell's behaviour.
This allows users to customise the behaviour of the shell by redefining the function. This is similar to how fish_title or fish_greeting behave, where the default implementation can be easily overridden.
The function receives as arguments the job id, command line, signal name and signal description.
Give string expansion an (optional) parent pgroup. This is threaded all
the way into eval(). This ensures that in a mixed pipeline like:
cmd | begin ; something (cmd2) ; end
that cmd2 and cmd have the same pgroup.
Add a test to ensure that command substitutions inherit pgroups
properly.
Fixes#6624
Changes it from
```
$fish_color_user: not set in local scope
$fish_color_user: set in global scope, unexported, with 1 elements
$fish_color_user[1]: length=3 value=|080|
$fish_color_user: set in universal scope, unexported, with 1 elements
$fish_color_user[1]: length=7 value=|brgreen|
```
(with the trailing empty line - not just a newline)
to
```
$fish_color_user: set in global scope, unexported, with 1 elements
$fish_color_user[1]: |080|
$fish_color_user: set in universal scope, unexported, with 1 elements
$fish_color_user[1]: |brgreen|
```
Prior to this fix, if job control is enabled but stdin is not a tty, we
would return an error from terminal_maybe_give_to_job which would cause us
to avoid waiting for the job. Instead just return notneeded.
Fixes#6573.
The description for an alias which already has escape sequences will
use backslash escapes for quoting; usually `string escape` can simply
quote it. Use a regex that accepts either escaping style.
Travis puts the commit message in an environment variable, so if it
contains the string `_flag` this would match TRAVIS_COMMIT_MESSAGE.
That happened in ca91c201c3, so the
tests failed.
We simply tighten the regex a little more, and make a commit message
that doesn't include the string.
This allows code of the form `if jobs -q $some_pid` in scripts to check whether a previously started job is still running. Previously this would return the correct value, but also print an error message.
The invalid argument errors will still be printed.
Added test cases for both.
Because `command ./somedir/somecommand` is okay.
Fixes test failure from aa304cbd3d.
Child directories in $PATH are still not suggested, as was the main
intention of the commit that introduced the tests:
8a3cf144f Don't include child directories of $PATH in completions.
We have now entirely switched the script tests to littlecheck.
Note: This adjusts the complete_directories test, because it removes a
directory that was created before by a .in test. There's no real
change in behavior.
This does require the test directory be cleaned, or the tests will fail.
test_util gets to stay for a while longer, because it sets up the
testing env (locale and such).
This, together with the other testX, really just tests some basic
syntax. So let's just call it "basic".
Note that this file uses escaped newlines on purpose, so restyling it
would currently break it. I'm not sure what the best thing to do here is.
Instead of invoking littlecheck.py independently for each file, pass
all files at once. This amortizes the Python startup cost, and reduces
the total test time by ~15 seconds (!).
This isn't quite the old-style test, but it checks some of the line
continuation stuff.
Note that littlecheck ignores leading whitespace, so testing the
actual indentation requires some more effort.
Things like
```fish
\
echo foo
```
or
```fish
echo foo; \
echo bar
```
are a formatting blunder and should be handled.
This makes it so the escaped newline is removed, and the
semicolon/token_type_end handling will then put the statements on
different lines.
One case this doesn't handle brilliantly is an escaped newline after a
pipe:
```fish
echo foo | \
cat
```
is turned into
```fish
echo foo | cat
```
which here works great, but in long pipelines can cause issues.
Pipes at the end of the line cause fish to continue parsing on the
next line, so this can just be written as
```fish
echo foo |
cat
```
for now.
This tries to see if quotes guard some expansion from happening. If it
detects a "weird" character it'll leave the quotes in place, even in
some cases where it might not trigger.
So
for i in 'c' 'color'
turns into
for i in c color
The rationale here is that these quotes are useless, wasting
space (and line length), but more importantly that they are
superstitions. They don't do anything, but look like they do.
The counter argument is that they can be kept in case of later
changes, or that they make the intent clear - "this is supposed to be
a string we pass".
The problem is that under TSAN, the timing of signals becomes very weird and
exposes some real race conditions. We will need to re-design how signal
event handlers work.
This test launches two background processes and is sensitive to
interleaving of output. Fix it so that newlines are not output by
the background process.
Hopefully this fixes the flakiness of this test.
f8ba0ac5bf introduced a bug where INT handlers would themselves be
cancelled, due to the signal. Defer processing handlers until the
parser is ready to execute more fish script.
Fixes the interactive case of #6649.
If a background process runs a fish function which launches another
background process, ensure that these background procs get different
pgroups. Add a test for it.
This executes `fish --no-execute` a whole bunch of times in order to
find syntax errors in our fish scripts.
tests/ is exempt because it contains syntax errors on purpose.
This is a great idea in principle, but it takes ~4s on my system.
It used to error out when a command wasn't known, even when it was a
function that would only be discovered via autoloading.
Now we just accept that a command doesn't exist when no-execute is
given - we're not gonna execute it anyway.
Also, in the same breath stop counting empty commands after expansion
and empty wildcard expansions as errors - these depend on runtime
values, so we can't verify them without executing.
Fixes#977.
(note that it still executes "time", but that's another commit)
Appending to an fd doesn't really make sense, but we allowed the
syntax previously and it was actually used.
It's not too harmful to allow it, so let's just do that again.
For the record: Zsh also allows it, bash doesn't.
Fixes#6614
Glob ordering is used in a variety of places, including figuring out
conf.d and really needs to be stable.
Other ordering, like completions, is really just cosmetic and can
change if it makes for a nicer experience.
So we uncouple it by copying the wcsfilecmp from 3.0.2, which will
return the ordering to what it was in that release.
Fixes#6593
The `function --on-job-exit caller` feature allows a command substitution
to observe when the parent job exits. This has never worked very well - in
particular it is based on job IDs, so a function that observes this will
run multiple times. Implement it properly.
Do this by having a not-recycled "internal job id".
This is only used by psub, but ensure it works properly none-the-less.
This one tests a bunch of separate stuff, so we put it into a few
different files.
The main, new one is "slices.fish", which tests various index expressions.
This makes two changes:
1. Remove the 'brace_text_start' idea. The idea of 'brace_text_start' was
to prevent emitting `BRACE_SPACE` at the beginning or end of an item. But
we later strip these off anyways, so there is no apparent benefit. If we
are not doing brace expansion, this prevented emitting whitespace at the
beginning or end of an item, leading to #6564.
2. When performing brace expansion, only stomp the space character with
`BRACE_SPACE`; do not stomp newlines and tabs. This is because the fix in
came from a newline or tab literal, then we would have effectively
replaced a newline or tab with a space, so this is important for #6564 as
well. Moreover, it is not easy to place a literal newline or tab inside a
brace expansion, and users who do probably do not mean for it to be
stripped, so I believe this is a good change in general.
Fixes#6564
Just another version of the error. We still want to get a bug if it
ever triggers a *wrong* error, so we still list all the options
instead of going for `.*option:.*Z.*`.
Fixes#6554
Solaris/OpenIndiana/Illumos `rm` checks that and errors out.
In these cases we don't actually need it to be a part of $PWD as
it's just for cleanup, so we `cd` out before.
See #5472
See 1ee57e9244Fixes#6555Fixes#6558
Prior to this fix, fish was rather inconsistent in when $status gets set
in response to an error. For example, a failed expansion like "$foo["
would not modify $status.
This makes the following inter-related changes:
1. String expansion now directly returns the value to set for $status on
error. The value is always used.
2. parser_t::eval() now directly returns the proc_status_t, which cleans
up a lot of call sites.
3. We expose a new function exec_subshell_for_expand() which ignores
$status but returns errors specifically related to subshell expansion.
4. We reify the notion of "expansion breaking" errors. These include
command-not-found, expand syntax errors, and others.
The upshot is we are more consistent about always setting $status on
errors.
macOS `mktemp -d` likes to return symlinks. Guard against that possibility.
That allows the test to succeed when run directly, instead of through the
build target.
It was possible to start the new job and execute `jobs` again before
the job died (or we noticed it did), so the test would fail.
To properly test, we need to ensure the job has been removed. `wait`
should do it.
complete -C'echo $HOM ' would complete $HOM instead of a new token.
Fixes another regression introduced in
6fb7f9b6b - Fix completion for builtins with subcommands
It's now good enough to do so.
We don't allow grid-alignment:
```fish
complete -c foo -s b -l barnanana -a '(something)'
complete -c foo -s z -a '(something)'
```
becomes
```fish
complete -c foo -s b -l barnanana -a '(something)'
complete -c foo -s z -a '(something)'
```
It's just more trouble than it is worth.
The one part I'd change:
We align and/or'd parts of an if-condition with the in-block code:
```fish
if true
and false
dosomething
end
```
becomes
```fish
if true
and false
dosomething
end
```
but it's not used terribly much and if we ever fix it we can just
reindent.
for-loops that were not inside a function could overwrite global
and universal variables with the loop variable. Avoid this by making
for-loop-variables local variables in their enclosing scope.
This means that if someone does:
set a global
for a in local; end
echo $a
The local $a will shadow the global one (but not be visible in child
scopes). Which is surprising, but less dangerous than the previous
behavior.
The detection whether the loop is running inside a function was failing
inside command substitutions. Remove this special handling of functions
alltogether, it's not needed anymore.
Fixes#6480
Store the entire function declaration, not just its job list.
This allows us to extract the body of the function complete with any
leading comments and indents.
Fixes#5285
In particular, this allows `true && time true`, or `true; and time true`,
and both `time not true` as well as `not time true` (like bash).
time is valid only as job _prefix_, so `true | time true` could call
`/bin/time` (same in bash)
See discussion in #6442
Extend the commit 8e17d29e04 to block processes, for example:
begin ; stuff ; end
or if/while blocks as well.
Note there's an existing optimization where we do not create a job for a
block if it has no redirections.
job_promote attempts to bring the most recently "touched" job to the front
of the job list. It did this via:
std::rotate(begin, job, end)
However this has the effect of pushing job-1 to the end. That is,
promoting '2' in [1, 2, 3] would result in [2, 3, 1].
Correct this by replacing it with:
std::rotate(begin, job, job+1);
now we get the desired [2, 1, 3].
Also add a test.
It looks like the last status already contains the signal that cancelled
execution.
Also make `fish -c something` always return the last exit status of
"something", instead of hardcoded 127 if exited or signalled.
Fixes#6444
This was previously required so that, if there was a redirection to a
file, we would fork a process to create the file even if there was no
output. For example `echo -n >/tmp/file.txt` would have to create
file.txt even though it would be empty.
However now we open the file before fork, so we no longer need special
logic around this.
Do this only when splitting on IFS characters which usually contains
whitespace characters --- read --delimiter is unchanged; it still
consumes no more than one delimiter per variable. This seems better,
because it allows arbitrary delimiters in the last field.
Fixes#6406
This adds a test for the obscure case where an fd is redirected to
itself. This is tricky because the dup2 will not clear the CLO_EXEC bit.
So do it manually; also posix_spawn can't be used in this case.
The IO cleanup left file redirections open in the child. For example,
/bin/cmd < file.txt would redirect stdin but also leave the file open.
Ensure these get closed properly.
Prior to this fix, a job would hold onto any IO redirections from its
parent. For example:
begin
echo a
end < file.txt
The "echo a" job would hold a reference to the I/O redirection.
The problem is that jobs then extend the life of pipes until the job is
cleaned up. This can prevent pipes from closing, leading to hangs.
Fix this by not storing the block IO; this ensures that jobs do not
prolong the life of pipes.
Fixes#6397
(command pwd) uses the system's implementation of pwd. At least the GNU
coreutils implementation defaults to -P, which resulted in symlinks being
expanded when switching between directories with nextd/prevd.
This did some weird unescaping to try to extract the first word.
So we're now more likely to be *correct*, and the alias benchmark is
about 20% *faster*.
Call it a win-win.
This splits a string into variables according to the shell's
tokenization rules, considering quoting, escaping etc.
This runs an automatic `unescape` on the string so it's presented like
it would be passed to the command. E.g.
printf '%s\n' a\ b
returns the tokens
printf
%s\n
a b
It might be useful to add another mode "--tokenize-raw" that doesn't
do that, but this seems to be the more useful of the two.
Fixes#3823.
This added the function offset *again*, but it's already included in
the line for the current file.
And yes, I have explicitly tested a function file with a function
defined at a later line.
Fixes#6350
Since #6287, bare variable assignments do not parse, which broke
the "Unsupported use of '='" error message.
This commit catches parse errors that occur on bare variable assignments.
When a statement node fails to parse, then we check if there is at least one
prefixing variable assignment. If so, we emit the old error message.
See also #6347
This adds initial support for statements with prefixed variable assignments.
Statments like this are supported:
a=1 b=$a echo $b # outputs 1
Just like in other shells, the left-hand side of each assignment must
be a valid variable identifier (no quoting/escaping). Array indexing
(PATH[1]=/bin ls $PATH) is *not* yet supported, but can be added fairly
easily.
The right hand side may be any valid string token, like a command
substitution, or a brace expansion.
Since `a=* foo` is equivalent to `begin set -lx a *; foo; end`,
the assignment, like `set`, uses nullglob behavior, e.g. below command
can safely be used to check if a directory is empty.
x=/nothing/{,.}* test (count $x) -eq 0
Generic file completion is done after the equal sign, so for example
pressing tab after something like `HOME=/` completes files in the
root directory
Subcommand completion works, so something like
`GIT_DIR=repo.git and command git ` correctly calls git completions
(but the git completion does not use the variable as of now).
The variable assignment is highlighted like an argument.
Closes#6048
Presently the completion engine ignores builtins that are part of the
fish syntax. This can be a problem when completing a string that was
based on the output of `commandline -p`. This changes completions to
treat these builtins like any other command.
This also disables generic (filename) completion inside comments and
after strings that do not tokenize.
Additionally, comments are stripped off the output of `commandline -p`.
Fixes#5415Fixes#2705
PATH and CDPATH have special behavior around empty elements. Express this
directly in env_stack_t::set rather than via variable dispatch; this is
cleaner.
This adds support for `fish_trace`, a new variable intended to serve the
same purpose as `set -x` as in bash. Setting this variable to anything
non-empty causes execution to be traced. In the future we may give more
specific meaning to the value of the variable.
The user's prompt is not traced unless you run it explicitly. Events are
also not traced because it is noisy; however autoloading is.
Fixes#3427
Until now, something like
`math '7 = 2'`
would complain about a "missing" operator.
Now we print an error about logical operators not being supported and
point the user towards `test`.
Fixes#6096
The `--entire` would enable output even though the `--quiet` should
have silenced it. These two don't make any sense together so print an
error, because the user could have just left off the `-q`.
This spewed errors because the `math` invocation got no second
operand:
Testing file checks/sigint.fish ... math: Error: Too few arguments
'1571487730 -'
but only if the `date` didn't do milliseconds, which is the case on
FreeBSD and NetBSD.
(also force the variable to be global - we don't want to have a
universal causing trouble here)
Universal exported variables (created by `set -xU`) used to show up
both as universal and global variable in child instances of fish.
As a result, when changing an exported universal variable, the
new value would only be visible after a new login (or deleting the
variable from global scope in each fish instance).
Additionally, something like `set -xU EDITOR vim -g` would be imported
into the global scope as a single word resulting in failures to
execute $EDITOR in fish.
We cannot simply give precedence to universal variables, because
another process might have exported the same variable. Instead, we
only skip importing a variable when it is equivalent to an exported
universal variable with the same name. We compare their values after
joining with spaces, hence skipping those imports does not change the
environment fish passes to its children. Only the representation in
fish is changed from `"vim -g"` to `vim -g`.
Closes#5258.
This eliminates the issue #5348 for universal variables.
Consider a group of short options, like -xzPARAM, where x and z are options and z takes an argument.
This commit enables completion of the argument to the last option (z), both within the same
token (-xzP) or in the next one (-xz P).
complete -C'-xz' will complete only parameters to z.
complete -C'-xz ' will complete only parameters to z if z requires a parameter
otherwise, it will also complete non-option parameters
To do so this implements a heuristic to differentiate such strings from single long options. To
detect whether our token contains some short options, we only require the first character after the
dash (here x) to be an option. Previously, all characters had to be short options. The last option
in our example is z. Everything after the last option is assumed to be a parameter to the last
option.
Assume there is also a single long option -x-foo, then complete -C'-x' will suggest both -x-foo and
-xy. However, when the single option x requires an argument, this will not suggest -x-foo.
However, I assume this will almost never happen in practise since completions very rarely mix
short and single long options.
Fixes#332
This stops reading argument names after another option appears. It does not break any previous uses and in fact fixes uses like
```fish
function foo --argument-names bar --description baz
```
* `function` command handles options after argument names (Fixes#6186)
* Removed unneccesary test
I got tired of seeing ' ... ok (0 sec)' so now with GNU date/gdate
installed there is millisecond output shown. One can get rough
nanoseconds from gdate.
This sequence can be generatd by control-spacebar. Allow it to be bound
properly.
To do this we must be sure that we never round-trip the key sequence
through a C string.
Meaning empty variables, command substitutions that don't print
anything.
A switch without an argument
```fish
switch
case ...
end
```
is still a syntax error, and more than one argument is still a runtime
error.
The none-argument matches either an empty-string `case ''` or a
catch-all `case '*'`.
Fixes#5677.
Fixes#4943.
This test uses universal variables, and so it can fail when run
multiple times.
It might be a good idea to do this in general, but for now let's just
try it here.
Previously when propagating explicitly separated output, we would early-out
if the buffer was empty, where empty meant contains no characters. However
it may contain one or more empty strings, in which case we should propagate
those strings.
Remove this footgun "empty" function and handle this properly.
Fixes#5987
I tested this manually (`littlecheck.py -s fish=fish tests/checks/eval.fish`) from the base directory, which means I got
"tests/checks/eval", while the real test gets "checks/eval".
I then reran `make test_fishscript`, but that didn't pull in the
updated test - we should really handle that better.
I'm gonna add more tests to this and I don't want to touch the old stuff.
Notice that this needs to have the output of the complete_directories
test adjusted because this one now runs later.
That's something we should take into account in future.
history now often writes to the history file asynchronously, but the history
test expects to find the text in the file immediately after running the
command. Hack a bit in history to make this test more reliable.
This required a bit of thinking.
What we do is we have one test that fakes $HOME, and then we do the
various config tests there.
The fake config we have is reused and we exercise all of the same codepaths.
This prints a green "ok" with the duration, just like the rest of the
tests.
Note that this clashes a bit with
https://github.com/ridiculousfish/littlecheck/pull/3.
(also don't check for python again and again and again)
This is a bit weird sometimes, e.g. to test the return status (that
fish actually *returns $status*), we use a #RUN line with %fish
invoking %fish, so we can use the substitution.
Still much nicer.
The missing scripts are those that rely on config.
Especially as, in this case, the documentation is quite massive.
Caught by porting string's test to littlecheck.
See #3404 - this was already supposed to be included.
This is a nice test (ha!) for how this works and what littlecheck can
do for us.
1. Input is now the actual file, not "Standard Input" anymore. So
any errors mentioning that now include the filename.
2. Regex are really nice for filenames, but especially for line
numbers
3. It's much nicer to have the output where it's created, instead of
needing to follow three files at the same time.
Instead of requiring a flag to enable newline trimming, invert it so the
flag (now `--no-trim-newlines`) disables newline trimming. This way our
default behavior matches that of sh's `"$(cmd)"`.
Also change newline trimming to trim all newlines instead of just one,
again to match sh's behavior.
The `string collect` subcommand behaves quite similarly in practice to
`string split0 -m 0` in that it doesn't split its output, but it also
takes an optional `--trim-newline` flag to trim a single trailing
newline off of the output.
See issue #159.
This adds support for .check files inside the tests directory. .check
files are tests designed to be run with littlecheck.
Port printf test to littlecheck and remove the printf.in test.
It's always a bit annoying that `*` requires quoting.
So we allow "x" as an alternative, only it needs to be followed by
whitespace to distinguish it from "0x" hexadecimal notation.
This makes the following changes:
1. Events in background threads are executed in those threads, instead of
being silently dropped
2. Blocked events are now per-parser instead of global
3. Events are posted in builtin_set instead of within the environment stack
The last one means that we no longer support event handlers for implicit
sets like (example) argv. Instead only the `set` builtin (and also `cd`)
post variable-change events.
Events from universal variable changes are still not fully rationalized.
When setting a variable without a specified scope, we should give priority
to an existing local or global above an existing universal variable with
the same name.
In 16fd780484 there was a regression that
made universal variables have priority.
Fixes#5883
Brace expansion with single words in it is quite useless - `HEAD@{0}`
expanding to `HEAD@0` breaks git.
So we complicate the rule slightly - if there is no variable expansion
or "," inside of braces, they are just treated as literal braces.
Note that this is technically backwards-incompatible, because
echo foo{0}
will now print `foo{0}` instead of `foo0`. However that's a
technicality because the braces were literally useless in that case.
Our tests needed to be adjusted, but that's because they are meant to
exercise this in weird ways.
I don't believe this will break any code in practice.
Fixes#5869.
This read something like `o=!_validate_int`, and the flag modifier
reading kept the pointer after the `!`, so it created a long flag
called `_validate_int`, which meant it would not only error out form
```fish
argparse 'i=!_validate_int' 'o=!_validate_int' -- $argv
```
with "Long flag '_validate_int' already defined", but also set
$_flag_validate_int.
Fixes#5864.
As mentioned in #2900, something like
```fish
test -n "$var"; and set -l foo $var
```
is sufficiently idiomatic that it should be allowable.
Also fixes some additional weirdness with semicolons.
This removes semicolons at the end of the line and collapses
consecutive ones, while replacing meaningful semicolons with newlines.
I.e.
```fish
echo;
```
becomes
```fish
echo
```
but
```fish
echo; echo
```
becomes
```fish
echo
echo
```
Fixes#5859.
This keeps all unknown options in $argv, so
```fish
argparse -i a/alpha -- -a banana -o val -w
```
results in $_flag_a set to banana, and $argv set to `-o val -w`.
This allows users to use multiple argparse passes, or to simply avoid
specifying all options e.g. in completions - `systemctl` has 46 of
them, most not having any effect on the completions.
Fixes#5367.