Commit 29f2da8d1 (Toggle terminal protocols lazily, 2024-05-16) made it so
the wildcard expansion in "echo **" (in a large directory tree) can't be
canceled with ctrl-c. Fix this by disabling terminal protocols already at
expansion time (not waiting until execution).
Using
SHELL=$(command -v fish) mc
Midnight Commander will spawn a fish child with
"function fish_prompt;"
"echo \"$PWD\">&%d; fish_prompt_mc; kill -STOP %%self; end\n",
So fish_prompt will SIGSTOP itself using an uncatchable signal.
On ctrl-o, mc will send SIGCONT to give back control to the shell.
Another ctrl-o will be intercepted by mc to put the shell back to sleep.
Since mc wants to intercept at least ctrl-o -- also while fish is in control
-- we can't use the CSI u encoding until mc either understands that, or uses
a different way of passing control between mc and fish.
Let's disable it for now.
Note that mc still uses %self but we've added a feature flag
to disable that. So if you use "set fish_features all"
you'll want to add a " no-remove-percent-self". A patch
to make mc use $fish_pid has been submitted upstream at
https://lists.midnight-commander.org/pipermail/mc-devel/2024-July/011226.html.
Closes#10640
When applying a wildcard, it's important to keep track of the files that have
been visited, to avoid symlink loops. Previously fish used a FileId for the
purpose. However FileId also includes richer information like modification time;
thus if a file is modified during wildcard expansion then fish may believe that
the file is different and visit it twice.
The richer information like modification time is important for atomic file
writes but should be ignored for wildcard expansion; just use the (dev, inode)
pair instead.
This also somewhat reduces our reliance on struct stat, but we still need it for
fstatat which Rust does not expose.
Returns 0 (true) in case an autosuggestion is currently being displayed.
This was first requested in #5000 then again in #10580 after the existing
workaround for this missing functionality was broken as part of a change to the
overall behavior of `commandline` (for the better).
Since we have a mix of both 0-based and 1-based line numbers in the code base,
we can now distinguish between them by type alone. Also stop using 0 as a
placeholder value for "no line number available" except in explicit helper
functions such as `get_lineno_for_display()`.
I've often needed a way to get the last bit of performance out of unwieldy
completions that involve a lot of string processing (apt completions come to
mind, and I ran into it just now with parsing man pages for kldload
completions).
Since many times we are looking for just one exact string in the haystack, an
easy optimization here is to introduce a way for `string match` or `string
replace` to early exit after a specific number of matches (typically one) have
been found.
Depending on the size of the input, this can be a huge boon. For example,
parsing the description from FreeBSD kernel module man pages with
zcat /usr/share/man/man4/zfs.4.gz | string match -m1 '.Nd *'
runs 35% faster with -m1 than without, while processing all files under
/usr/share/man/man4/*.4.gz in a loop (so a mix of files ranging from very short
to moderately long) runs about 10% faster overall with -m1.
Part of #1842
It's like jump-to-matching-bracket, but jumps right before the bracket
I will use it to mimic vi 'ab' and 'ib' text objects in the next commit
Given complicated semantics of jump-till-matching-bracket, an alternative name
could be 'jump-inside-matching-brackets'. But that would make names non-symmetrical.
I'm not sure what is worse.
Part of #1842
Split to:
- jump_and_remember_last_jump. What previously was called jump, now called
jump_and_remember_last_jump
- jump. Only jump, don't remember last jump. Now it's also possible to pass
vector of targets
The commit is pure refactoring, no functional changes are introduced.
The refactoring is needed for the next commits
Command completion descriptions were not being generated from `apropos`. Well,
they were being generated but that was not being correctly used by fish core.
Not sure when this was broken, but there's a possibility it was during the rust
port.
In addition to simply not working, it seems the old code tried to avoid
allocations but String::split_at_mut() allocates a new string (since one
allocation from the global allocator can't be split into two allocations to be
freed separately). Use `String::as_mut_utfstr()` before splitting the &wstr
instead of splitting the &str to actually do this alloc-free.
The "principal" parser is the one and only today; in the future we hope to
have multiple parsers to execute fish script in parallel.
Having a globally accessible "principle" parser is suspicious; now we can
get rid of it.
The "principal" environment stack was the one that was associated with the
"principal" parser and would dispatch changes like to TZ, etc.
This was always very suspicious, as a global; now we can remove it.
Prior to this commit, there was a stack of ReaderDatas, each one has a
reference to a Parser (same Parser in each, for now). However, the current
ReaderData is globally accessible. Because it holds a Parser, effectively
anything can run fish script; this also prevents us from making the Parser
&mut.
Split these up. Create ReaderData, which holds the data portion of the
reader machinery, and then create Reader which holds a ReaderData and a
Parser. Now `reader_current_data()` can only return the data itself; it
cannot execute fish script.
This results in some other nice simplifications.
This is a start on untangling input. Prior to this, a ReaderData and an
Inputter would communicate with each other; this is natural in C++ but
difficult in Rust because the Reader would own an Inputter and therefore
the Inputter could not easily reference the Reader. This was previously
"resolved" via unsafe code.
Fix this by collapsing Inputter into Reader. Now they're the same object!
Migrate Inputter's logic into a trait, so we get some modularity, and then
directly implement the remaining input methods on ReaderData.
Add round options, but I think can also add floor, ceiling, etc. And
the default mode is trunc.
Closes#9117
Co-authored-by: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
The special input functions self-insert, self-insert-not-first, and
and or used to be handled by inputter_t::readch, but they aren't
anymore with `commandline -f`.
I am unsure if these *would* have worked, I can't come up with a use.
So, for now, do nothing instead of panicking.
This would crash if you ran `commandline -f backward-jump`.
The C++ version would read a char (but badly), this doesn't anymore.
So, at least instead of crashing, just do nothing.
This doesn't pull its weight. Block size is not a particularly big
problem,
and this both complicates the code a bit and would arbitrarily cause issues
if a fish script exceeded 65k lines.
This reverts commit edd6533a14.
This doesn't have any effect on the size of the struct (due to alignment
requirements and padding) but reduces the complexity by turning
Block::wants_pop_env into an emergent property dependent on the type rather than
something we have to manually manage.
We only increment it and check if it's non-zero, we never decrement or check the
actual count. As such, change it to a bool and bring the size of `Block` down
from 32 to 24 bytes.
We almost never access any of this and having it stored directly in the `Block`
struct increases its size (reducing how many we can fit in L1 and L2, and
increasing memory copy traffic).
Gets rid of BlockData::None so we can avoid allocating a Box at all when we have
no data (at the cost of yet-another-wrapper-type), which is the usual case.
This has a few advantages,
* We now statically assert that all fields used by a particular block type are
correctly initialized (i.e. you can't assign the function name but forget to
assign its arguments),
* Conversely, we can match directly on `BlockData` and be guaranteed that the
fields we want to access are initialized and present,
* We reduce the number of assertions, effectively "unwrapping" only once based
off the block type instead of each time we try to access a conditional field,
* We reduce the size of the `Block` struct by coalescing fields that cannot
co-exist, bringing it down from 104 bytes to 88 bytes.
It would be nice to make all of `Block` itself an enum, but it currently
requires `Copy` and we take advantage of that to copy it around everywhere.
Putting these fields directly in `Block` directly would mean a lot more memory
traffic just checking block types.
There's no need for two separate block types when one is merely a variant of the
other. This may have been required under C++ but thanks to sum types (rust's
enums) we don't need to do that any more.
If the backgrounded/stopped job was using the tty, sending it SIGCONT first
might cause it to immediately wake and try to use the tty (which fish still has
control over), causing it to immediately stop again after receiving a SIGTTOU.
We are supposed to send SIGHUP first so that when the process resumes it sees
the queued SIGHUP and executes its registered handler!
There's no guarantee that a condition variable is stateful. The docs for
`Condvar::notify_one()` actually say the opposite:
> If there is a blocked thread on this condition variable, then it will be woken
> up from its call to wait or wait_timeout. Calls to notify_one are not buffered
> in any way.
This test was relying on the main loop obtaining the lock and entering the
condition variable sleep before the thread was scheduled and got around to
notifying the condition variable. If this non-deterministic behavior was not
upheld, the test would time out since it would obtain the lock (either before or
after the variable were updated) then call `condvar.wait()` *after* the variable
had been updated and the condvar signalled, but without (atomically or even at
all) checking to see if the desired wake precondition was fulfilled. As the
child thread had already run and the wake notification was NOT buffered, there
was nothing to wake the running thread.
There really wasn't any way to salvage the test as originally written, since the
write to `ctx.val` was not in any way linked to the acquire/release of the mutex
so regardless of whether or not the main thread obtained the mutex and checked
the value precondition before calling `condvar.wait()`, the child thread's write
could have happened after the check but before the wait() call. As such, the
test has been rewritten to use `wait_while()` but then also updated to bail in
case of a timeout instead of hanging indefinitely (since neither the `ctest`
runner nor the `cargo test` harness was timing out; `cargo test` would only
report that the test had exceeded 60 seconds but as long as it was not executed
with `cargo test -- -Z --ensure-time` (which is only available under nightly),
the test would not halt.
If this test were *intentionally* written to test the scenario that was timing
out, it should be written deterministically in such a way that the main loop
did not run until after it was guaranteed that the variable had been updated
(i.e. by looping until val became 5 or waiting for an AtomicBool indicating the
update had completed to be set), but I'm not sure what the benefit in that would
be since the docs actually guarantee the opposite behavior (the notified state
is explicitly not cached/buffered).
If we have fish code written with the assumption that condvar notifications
prior to *any* call to `Condvar::wait()` *are* buffered, then that code should
of course be revisited in light of this.