According to the discussion in #2315, we adopt TTY modes for external commands
mainly for "stty". If our child process crashes (or SSH disconnect), we
might get weird modes. Let's ignore the modes in the failure case.
Co-authored-by: Johannes Altmanninger <aclopte@gmail.com>
Part of #10603
Run
printf \Xf6 | wl-copy # ö in ISO-8859-1
LANG=de_DE LC_ALL=$LANG gnome-terminal -- build/fish
and press ctrl-v. The pasted data looks like this:
$ set data (wl-paste -n 2>/dev/null | string collect -N)
$ set -S data
$data: set in local scope, unexported, with 1 elements
$data[1]: |\Xf6|
we pass $data directly to "commandline -i", which is supposed to insert it
into the commandline verbatim. What's actually inserted is "�".
This is because of all of:
1. We never decode "\Xf6 -> ö" in this scenario. Decoding it -- like we do
for non-pasted keyboard input -- would fix the issue.
2. We've switched to using Rust's char, which, for better or worse, disallows
code points that are not valid in Unicode (see b77d1d0e2 (Stop crashing
on invalid Unicode input, 2024-02-27)). This means that we don't simply
store \Xf6 as '\u{00f6}'. Instead we use our PUA encoding trick, making it
\u{f6f6} internally.
3. Finally, b77d1d0e2 renders reserved codepoints (which includes PUA chars)
using the replacement character � (sic). This was deemed more
user-friendly than printing an invalid character (which is probably not
mapped to a glyph). Yet it causes problems here: since we think that
\u{f6f6} is garbage, we try to render the replacement character. Apparently
that one is not defined(?) in ISO-8859-1; we get "�".
Fix this regression by removing the replacement character feature.
In future we should maybe decode pasted input instead. We could do that
lazily in "commandline -i", or eagerly in "set data (wl-paste ...)".
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()`.
Both are plenty fast enough, but this way the output of fish_trace isn't
completely taken over by the loops (seems fair since fish_trace probably gets
used rather heavily for completions).
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.