Prior to this fix, fish would attempt to react if a local fish_complete_path
or fish_function_path were set. However this has never been very well tested
and will become impossible with concurrent execution. Always use the global
values.
Soon we will have more complicated logic around whether to call tcsetpgrp.
Prepare to centralize the logic by passing in the new term owner pgrp,
instead of having child_setup_process perform the decision.
This exitted if the cursor was at the end of the line as well (i.e. if
delete-char failed). That's a bit too eager.
Also documentation, which should have already been included.
We used to have a global notion of "is the shell interactive" but soon we
will want to have multiple independent execution threads, only some of
which may be interactive. Start tracking this data per-parser.
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.
Prior to this diff, fish had different signal handling functions for
different signals. However it was hard to coordinate when a signal needed
to be the default handler, and when it was custom. In #5962 we overwrote
fish's custom WINCH handler with the default_handler when fish script asked
for WINCH to be handled.
Just have a single big signal handler function. That way it can never be
set to the wrong thing.
Fixes#5969
When executing a job, if the first process is fish internal, then have
fish claim the job's pgroup.
The idea here is that the terminal must be owned by a pgroup containing
the process reading from the terminal. If the first process is fish
internal (a function or builtin) then the pgroup must contain the fish
process.
This is a bit of a workaround of the behavior where the first process that
executes in a job becomes the process group leader. If there's a deferred
process, then we will execute processes out of order so the pgroup can be
wrong. Fix this by setting the process group leader explicitly as fish
when necessary.
Fixes#5855
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.
25afc9b377 made this unnecessary by
having child processes wait for a signal after fork(), but this change
was later reverted. If we artificially slow down fish (e.g. with a sleep)
after the fork call, we see commands getting backgrounded by mistake.
Put back the tcsetgrp() call.
* Prevent not-yet-loaded functions from loaded when erased
Today, `functions --erase $function` does nothing if the function
hasn't been autoloaded yet.
E.g. run, in an interactive session
> functions --erase ls
> type ls
and be amazed that it still shows our default `ls --color=auto`
wrapper function.
This seems counter-intuitive - removing a function ought to remove it,
whether it had been executed before or not.
* doc/changelog
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.
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.
To support distinct parsers having different working directories, we need
to keep the working directory alive, and also retain a non-path reference
to it.
Because an exported universal variable must be exported in all variable
stacks, explicit invalidation is infeasible. Switch the universal variables
to a generation count.
Prior to this fix, fish would invalidate the exported variable list
whenever an exported variable changes. However we soon will not have a
single "exported variable list." If a global variable changes, it is
infeasible to find all exported variable lists and invalidate them.
Switch to a new model where we store a list of generation counts. Every
time an exported variable changes, the node gets a new generation. If the
current generation list does not match the cached one, then we know that
our exported variable list is stale.
This was undocumented, not all that useful and potentially unwanted.
In particular it means that things like
mysql -p(read)
will still keep the password in history.
Also it allows us to simply implement asking for the history deletion
term.
See #5791.
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.
This cuts down on the wcs2string here by ~25%.
The better solution would be to cache narrow versions of $PATH, since
we compute that over and over and over and over again, while it rarely changes.
Or we could add a full path-cache (where which command is), but that's
much harder to invalidate.
See #5905.
This sets the explicit path to the default one, which should be okay,
since the default path never changes (not even if $XDG_CONFIG_HOME
does).
Then it saves a narrow version of that, which saves most of the time
needed to `sync` in most cases.
Fixes#5905.
Note that this isn't technically *w*util, but the differences between
the functions are basically just whether they do the wcs2string
themselves or not.
This fixes a race condition in the topic monitor. A thread may decide to
enter the wait queue, but before it does the generation list changes, and
so our thread will wait forever, resulting in a hang.
It also simplifies the implementation of the topic monitor considerably;
on reflection the whole "metagen" thing isn't providing any value and we
should just compare generations directly.
In the new design, we have a lock-protected list of current generations,
along with a boolean as to whether someone is reading from the pipe. The
reader (only one at a time) is responsible for broadcasting notifications
via a condition variable.
The enum starts at 0 (defined to be!), so we can eliminate this one.
That allows us to remove a reliance on the position of
beginning_of_line, and it would trigger a "type-limits" warning.
Also leave a comment because I actually hit that.
Someone has hit the 10MiB limit (and of course it's the number of
javascript packages), and we don't handle it fantastically currently.
And even though you can't pass a variable of that size in one go, it's
plausible that someone might do it in multiple passes.
See #5267.
This widens the remaining ones that don't take a char
anywhere.
The rest either use a char _variable_ or __FUNCTION__, which from my
reading is narrow and needs to be widened manually. I've been unable
to test it, though.
See #5900.
This solves the main part of (careful linebreak)
issue #5900.
I'm betting all the errors that do use narrow IO are broken, including
a bunch of asserts.
This adds a new mechanism for logging, intended to replace debug().
The entry points are FLOG and FLOGF. FLOG can be used to log a sequence of
arguments, FLOGF is for printf-style formatted strings.
Each call to FLOG and FLOGF requires a category. If logging for a category
is not enabled, there is no effect (and arguments are not evaluated).
Categories may be enabled on the command line via the -d option.
Now that our interactive signal handlers are a strict superset of
non-interactive ones, there is no reason to "reset" signals or take action
when becoming non-interactive. Clean up how signal handlers get installed.
The signal handlers for interactive and non-interactive SIGINT were distinct
and talked to the reader. This wasn't really justified and will complicate
having multiple threads. Unify these into a single signal handler.
is_interactive_read is a suspicious flag which prevents a call to
parser_t::skip_all_blocks from a ^C signal handler. However we end
up skipping the blocks later when we exit the read loop.
This flag seems unnecessary. Bravely remove it.
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
Otherwise we'd undo the history search when you press e.g. execute,
which means you'd execute the search term.
Only `cancel` should walk it back, like it previously did hardcoded to
escape.
Fixes#5891.
These were inadvertently disabled by a bug which was introduced in
cd7e8f4103 . Fix the bug so the tests run
again.
They don't all pass yet; they regressed during the period they were
disabled.
This mainly is conceptually a bit simpler. The comment about making it
cheaper is entirely misplaced since this is quite far away from being
important.
Even expanding 1000 abbrs, it doesn't show up in the profile.
This was, under some circumstances, apparently off by one.
If a suggestion was really long, like
```fish
infocmp | string split , | string trim | string match -re . | while read -d = -l key val; test -z "$val"; and continue; string match -q '*%*' -- $val; and continue; test (string replace -ra '\e([\[\]]|\(B).*[\comJKsu]' '' -- a(tput $key)b) = ab; or echo $key $val; end > xterm
```
(I'm assuming longer than $COLUMNS), it would staircase like with a wrong wcwidth.
This reverts commit 15a5c0ed5f.
I noticed my debug output for 24bit color mode was garbled due to
this being wrong. I spent a little time trying to get the compiler
to tell us about these, but -Wformat doesn't do anything for wchar
printf functions, and __attribute__((format(printf, n, m))) will
cause an error with wchar_t's, so I gave up and decided to manually
check out every '%s' in the entire project. I found (only) one
more.
debug(0, "%s", wchars) will report warnings for incorrect
specifiers but debug(0, L"%s", wchars) is unable. Thus there may
be reason to prefer not using L"..." as an argument if all else
is equal and it's not necessary.
Allows `fish_indent -w **.fish` to restyle all fish files under the
current directory.
(This also has the sideeffect of reducing style.fish time by ~10s, as
we only need to invoke `fish_indent` once, instead of once per-file)
Blocks will soon need to be shared across parsers. Migrate the loop status
(like break or continue) from the block into the libdata. It turns out we
only ever need one, we don't need to track this per-block.
Make it an enum class.
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.
Prior to this fix, a function_block stored a process_t, which was only used
when printing backtraces. Switch this to an array of arguments, and make
various other cleanups around null terminated argument arrays.
We previously checked if fish_mode_prompt existed as a function, but
that's a bad change for those who already set it to an empty function
to have a mode display elsewhere.
Updated widechar_width takes care of it.
Technically, this does ~3 comparisons more per-character (because it
checks variation selectors and such), but that shouldn't really matter.
get_current_winsize() is intended to be lazy. It does the following:
1. Gets the termsize from the kernel
2. Compares it against the current value
3. If changed, sets COLUMNS and LINES variables
Upon setting these variables, we notice that the termsize has changed
and invalidate the termsize. Thus we were doing this work multiple times
on every screen repaint.
Put back an old hack that just marked the termsize as valid at the end
of get_current_winsize().
This just sets some special characters that we use in the reader, so
it only needs to be done before the reader is set up.
Which, as it stands, is in env_init().
This stops trying to see if the previous line is wider if it is a
prefix of the current one.
Which turns out to be true often enough that it's a net benefit.
This passes character width as an argument for a few functions.
In particular, it hardcodes a width of "1" for a space literal.
There's no reason to compute wcwidth for the length of the prompt.
This measured *all* the characters on the commandline, and saved all
of them in another wcstring_list_t, just to then do... nothing with
that info.
Also, it did wcslen for something that we already have as wcstring,
reserved a vector and did a bunch of work for autosuggestions that
isn't necessary if we have more than one line.
Instead, we do what we need, which is to figure out if we are
multiline and how wide the first line is.
Fixes#5866.
line_shared_prefix explains in its comment that
> If the prefix ends on a combining character, do not include the
previous character in the prefix.
But that's not what it does.
Instead, what it appears to do is to return idx for *every* combining
mark. This seems wrong to begin with, and it also requires checking
wcwidth for *every* character.
So instead we don't do that. If we find the mismatch, we check if it's
a combining mark, and then go back to the previous character (i.e. the
one before the one that the combining mark is for).
My tests found no issues with this, other than a 20% reduction in
pasting time.
The old commit #3f820f0 "Disable ONLCR mapping of NL output to CR-NL"
incorrectly used c_iflag instead of c_oflag, and I copied that error
in my patch. Fixed that. However, there seems to be other problems
trying to use "\x1B[A", which I have not tried to debug, so comment that out.
(However, #3f820f0 seems to mostly work if we fix it to use c_oflag.)
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 runs build_tools/style.fish, which runs clang-format on C++, fish_indent on fish and (new) black on python.
If anything is wrong with the formatting, we should fix the tools, but automated formatting is worth it.
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 was a sort of side channel that was only used to propagate redraws
after universal variable changes. We can eliminate it and handle these
more directly.
tsan does funny things to signals, preventing signals from being delivered
in a blocking read. Switch the topic monitor to non-blocking reads under
tsan.
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.
This cleans up how functions are stored and autoloaded. It eliminates the
recursive lock. Instead there is a single normal owning_lock that protects
the entirety of the function data. Autoloading is re-implemented via the
new autoloader_t.
autoloader_t will be the reimplementation of autoloading. Crucically it no
longer manages any locking or loading itself; instead all locking and loading
is performed by clients. This makes it easier to test and helps limit its
responsibilities.
autoloading has a "feature" where functions are removed in an LRU-fashion.
But there's hardly any benefit in removing autoloaded functions. Just stop
doing it.
This is a long-standing issue with how `complete --do-complete` does
its argument parsing: It takes an optional argument, so it has to be
attached to the token like `complete --do-complete=foo` or (worse)
`complete -Cfoo`.
But since `complete` doesn't take any bare arguments otherwise (it
would error with "too many arguments" if you did `complete -C foo`) we
can just take one free argument as the argument to `--do-complete`.
It's more of a command than an option anyway, since it entirely
changes what the `complete` call _does_.
* Some comment fixes and renaming of is_iterm2_escape_seq.
The comment for is_iterm2_escape_seq incorrectly says "CSI followed by ]".
This is wrong, because CSI is ESC followed by [ (or the seldom-used 0x9b).
The procedure actually matches Operating System Command (OSC) escape codes.
Since there is nothing iterm2-specific about OSC, is_osc_escape_seq
would be a better name.
Also s_desired_append_char documents a non-existent parameter.
* Update broken iterm2 url in comment.
This was added in 04a96f6 but not strictly required to fix#5803
(verified), with the intention of hiding invisible background jobs
(created by invoking a function within a pipeline) from the user, but
that also broke intentionally created jobs from displaying as well.
I'm thinking it can't be done without keeping track of caller context vs
job context.
Closes#5824.
env_scoped_t lives between environment_t and env_stack_t.
It represents the read-only logic of env_stack_t and will be used to back
the new environment snapshot implementation.
These tests used raw, unescaped parentheses to perform `test` logical
grouping, but the test failures weren't caught because the parser
evaluation errors were not being propagated (fixed in bdbd173e).
It was unconditionally returning `parse_execution_success`. This was
causing certain parser errors to incorrectly return after evaluation
with `$status` equal to `0`, as reported after `eval`, `source`, or
sub-`fish` execution.
Prior to this change, fish used a global flag to decide if we should check
for changes to universal variables. This flag was then checked at arbitrary
locations, potentially triggering variable updates and event handlers for
those updates; this was very hard to reason about.
Switch to triggering a universal variable update at a fixed location,
after running an external command. The common case is that the variable
file has not changed, which we can identify with just a stat() call, so
this is pretty cheap.
This reverts commit cdce8511a1.
This change was unsafe. The prior version (now restored) took the lock and
then copied the data. By returning a reference, the caller holds a
reference to data outside of the lock.
This function isn't worth optimizing. Hardly any functions use this
facility, and for those that do, they typically just capture one or two
variables.
* Convert `function_get_inherit_vars()` to return a reference to the
(possibly) existing map, rather than a copy;
* Preallocate and reuse a static (read-only) map for the (very) common
case of no inherited vars;
* Pass references to the inherit vars map around thereafter, never
triggering the map copy (or even move) constructor.
NB: If it turns out the reference is unsafe, we can switch the inherit vars
to be a shared_ptr and return that instead.
I did not realize builtins could safely call into the parser and inject
jobs during execution. This is much cleaner than hacking around the
required shape of a plain_statement.
- fix the carat position expanding e.g. `command $,`
- improve the error reporting for not-allowed command subtitutions
by figuring out where the expansion failed instead of using
SOURCE_LOCATION_UNKNOWN
- allow nullptr for parse_util_licate_brackets_range() out_string
argument if we don't need it to do any work.
Fixes#5812
`eval` has always been implemented as a function, which was always a bit
of a hack that caused some issues such as triggering the creation of a
new scope. This turns `eval` into a decorator.
The scoping issues with eval prevented it from being usable to actually
implement other shell components in fish script, such as the problems
described in #4442, which should now no longer be the case.
Closes#4443.
While `eval` is still a function, this paves the way for changing that
in the future, and lets the proc/exec functions detect when an eval is
used to allow/disallow certain behaviors and optimizations.
This adds an option --print-rusage-self to the fish executable. When set,
this option prints some getrusage stats to the console in a human-readable
way. This will be used by upcoming benchmarking support.
Followup to 394623b.
Doing it in the parser meant only top-level jobs would be reaped after
being `disown`ed, as subjobs aren't directly handled by the parser.
This is also much cleaner, as now job removal is centralized in
`process_clean_after_marking()`.
Closes#5803.
This prevents the `disown` builtin from directly removing jobs out of
the jobs list to prevent sanity issues, as `disown` may be called within
the context of a subjob (e.g. in a function or block) in which case the
parent job might not yet be done with the reference to the child job.
Instead, a flag is set and the parser removes the job from the list only
after the entire execution chain has completed.
Closes#5720.
When popping a scope from the environment stack, we currently do a lot of
nonsense like looking for changed curses variables. We want to centralize
this in env_stack_t so that it can be migrated to the env_dispatch logic.
Move this logic up one level in preparation for doing that.
This new file is supposed to encapsulate all of the logic around
reacting to variable changes, as opposed to the environment core.
This is to help break up the env.cpp monolith.
Prior to this fix, a job would only inherit a pgrp from its parent if the
first command were external. There seems to be no reason for this
restriction and this causes tcsetgrp() churn, potentially cuasing SIGTTIN.
Switch to unconditionally inheriting a pgrp from parents.
This should fix most of #5765, the only remaining question is
tcsetpgrp from builtins.
Prior to this fix, in every call to job_continue, fish would reclaim the
foreground pgrp. This would cause other jobs in the pipeline (which may
have another pgrp) to receive SIGTTIN / SIGTTOU.
Only reclaim the foreground pgrp if it was held at the point of job_continue.
This partially addresses #5765
In tests we would like to arrange for an executable to invoke certain
system calls, e.g. to claim or relinquish control of the terminal. This is
annoying to do portably via e.g. perl. fish_test_helper is a little
program where we can add custom commands to make it act in certain ways.
This set the term modes to the shell-modes, including disabling
ICRNL (translating \cm to \cj) and echo.
The rationale given was that `reader_interactive_init()` would only be
called >= 250ms later, which I _highly_ doubt considering fish's total
startup time is 8ms for me.
The main idea was that this would stop programs like tmuxinator that
send shortcuts early from failing _iff_ the shortcut was \cj, which
also seems quite unusual.
This works both with `rm -i` and `read` in config.fish, because `read`
explicitly calls `reader_push`, which then initializes the shell modes.
The real fix would involve reordering our init so we set up the
modesetting first, but that's quite involved and the remaining issue
should barely happen, while it's fairly common to have issues with a
prompt in config.fish, and the workaround for the former is simpler, so let's leave it for now.
Partially reverts #2578.
Fixes#2980.
Putting larger members before smaller ones will reduce structure
sizes. bools are 1 byte. on 64bit systems I think they reduced:
wgetopt.h:46: 64 to 56 bytes
builtin_history.cpp:30: 48 to 32 bytes
builtin_status.cpp:91: 32 to 24 bytes
tinyexpr.cpp:69: 40 to 32 bytes
The data stored in these containers is small enough that it is worth
creating distinct sets for each lookup.
In a microbenchmark of these changes, the single-lookup version of the
function with lookups gated on the length of input (bypassed entirely if
the input is longer than the longest key in the container) provided a
1.5x-3.5x speedup over the previous implementation.
Additionally, as the collections are static and their contents are never
modified after startup, it makes no sense to continously calculate the
location of and allocate an iterator for the `!= foo.end()` comparison;
the end iterator is now statically cached.
I'm not expecting massive speed gains out of this change, but the parser
does perform enough of these to make it worth optimizing in this way.
This reverts commit 7a74198aa3.
Believe it or not this commit actually increased copying. When accepting
a value you know you're going to take ownership of, just accept it by
value; then temporaries can invoke the move ctor and blah blah blah.
We really need a lightweight refcounted pass-by-value string to make this
less error prone.
If we switch the bind mode, we add a "force-repaint" there just to
redraw the mode indicator.
That's quite wasteful and annoying, considering that sometimes the prompt can take
half a second.
So we add a "repaint-mode" function that just reexecutes the
mode-prompt and uses the cached values for the others.
Fixes#5783.
As it turns out it didn't work much better, and it fell behind in
support when it comes to things that wcwidth traditionally can't
express like variation selectors and hangul combining characters, but
also simply $fish_*_width.
I've had to tell a few people now to rebuild with widecharwidth after
sending them on a fool's errand to set X variable.
So keeping this option is doing our users a disservice.
* Add "expand-abbr" bind function
This can be used to explictly allow expanding abbreviations.
* Make expanding abbr explicit
NOTE: This accepts them for space only, we currently also do it for \n
and \r.
* Remove now dead code
We no longer trigger an abbr implicitly, so we can remove the code
that does it.
* Fix comment
[ci skip]