This ports some signal setup and handling bits to Rust.
The signal handling machinery requires walking over the list of known signals;
that's not supported by the Signal type. Rather than duplicate the list of
signals yet again, switch back to a table, as we had in C++.
This also adds two further pieces which were neglected by the Signal struct:
1. Localize signal descriptions
2. Support for integers as the signal name
This allows the rust code to free up C++ resources allocated for a callback even
when the callback isn't executed (as opposed to requiring the callback to run
and at the end of the callback cleaning up all allocated resources).
Also add type-erased destructor registration to callback_t. This allows for
freeing variables allocated by the callback for debounce_t's
perform_with_callback() that don't end up having their completion called due to
a timeout.
Largely routine but for the trampolines in iothread.h and iothread.cpp which
were a real PITA to get correct w/ all their variants.
Integration is complete with all old code ripped out and the tests using the
rust version of the code.
Like the WSL check, this was incorrectly assuming WSL implies
cfg(windows) when it's actually picked up as Linux.
Also, improve over the C++ code by not relying on the build-time WSL
status to determine if we are running on WSL at runtime since it's often
the case that the fish binaries are built on a non-WSL host (for
packaging) then executed on a WSL only at runtime.
(But it's ok to assume if fish has been built for Windows or not Linux
that it will either be run or not run on top of a Win32 character device
system.)
Also, port of the comment and relevant WSL and fish issue links over
from the CPP codebase for posterity.
* Since we already have an allocation of length wstr.len(), it's
probably better to allocate the result (which is strictly less than or
equal to the input length) up-front rather than risk thrashing the Vec
allocation,
* There's no need to compare c2 against '\0' since that will just cause
to_digit(16) to return None anyway,
* Our convert_hex() specialization of to_digit(16) that only checks
capital letters A-F without also checking lowercase a-f isn't
significantly faster than just use to_digit(16), and we already assert
that the input *wasn't* a lowercase a-f before making the call, so
there's no point in using a special function to handle that.
Prior to this change, wstr::split had two weird behaviors:
1. Splitting an empty string would yield nothing, rather than an empty
string.
2. Splitting a string with the separator character as last character
would not yield an empty string.
For example L!("x:y:").split(':') would return ["x", "y"] instead of
what it does in C++, which is ["x", "y", ""].
Fix these.
This reverts commit 76dc849fca.
The warning added in that commit is incorrect. The functions
unescape_string_url and unescape_string_var will not panic, because
char_at() return 0 if the index is equal to its length.
This reverts commit f9c92753c4.
This commit attempted to replace exit_without_destructors() with
std::process::exit; however this is wrong for two reasons:
1. std::process::exit() runs Rust runtime cleanup stuff we don't want
2. std::process::exit() invokes destructors, meaning atexit handlers,
which we don't want.
The type system no longer guarantees that the input string is nul-terminated,
meaning accessing beyond the range-checked `i` a char-at-a-time is no longer
safe. (In C++, we would either be using a plain C string which is always
nul-terminated or we would be using (w)string::cstr() which similarly grants
access to its nul-terminated buffer.)
Aside from that, there's no need to explicitly check `if c2 == '\0'` because
'\0' is not a valid hex digit so the `?` tacked on to `convert_hex_digit(c2)?`
will abort and return `None` anyway.
convert_hex_digit() is not appreciably faster than char::to_digit(16) and makes
the code less maintainable since it encodes certain assumptions; since it's also
not used consistently just drop it in favor of the std fn.
Since the output string (per the decode logic) is always shorter than or equal
to the input string, just reserve the input string size upfront to prevent vec
reallocations.
* Add rpm-ostree completion
Add basic command completion for rpm-ostree. This should improve the
user experience for fish users using rpm-ostree.
* Shorten rpm-ostree descriptions
---------
Co-authored-by: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
* completions: updated jq completions
* completions: added completions for gojq
* Shorten jq completion descriptions
* Update gojq.fish
Capitalize first letter of descriptions to match other completions.
---------
Co-authored-by: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Somewhat counter-intuitively, this code is active when compiling under *Linux*
and is always false when compiling under Windows. The logic was incorrectly
reversed before (it's easier to reason about when you realize that fish doesn't
even compile under Windows because it uses tons of libc functions).
As the code was actually never compiled, it wasn't actually tested for validity
either and there were some issues that prevented it from compiling that have
since been fixed. The logic has also been adjusted a bit to make it possible to
use the rust-native int parsing instead of `libc::strtod()`.
The code has been changed to use `once_cell::race::OnceBool` instead of
`once_cell::sync::Lazy<T>` which imposes a greater runtime burden with locking
and other overhead. We don't care if the code runs more than once on init (if
calls were to race, though they probably don't) - just that the code isn't
subsequently executed on each call. The `once_cell::race` module is a better fit
here, though it doesn't expose the ergonomic `Lazy<T>` façade around its types.
is_main_thread() and co were previously ported to threads.rs, so remove the
duplicate code and move everything else related to threads there as well. No
need for common.rs to be as long as our old common.cpp!
I left #[deprecated] stubs in common.rs to help redirect anyone porting code
over that we can remove after the port has finished.
Additionally, the fork guards had previously been left as a todo!() item but I
ported that over. They're all called from the now-central threads::init()
function so there isn't a need to call each individual thread-management-fn
manually.
The decision was made a while back to try and embrace/use the native rust thread
functionality and utilities so the manual thread management code has been ripped
out and was replaced with code that marshals the native rust values instead. The
values won't line up with what the C++ code sees, but it never lined up anyway
since each was using a separate counter to keep track of the values.
There are many places where we want to treat a missing variable the same as
a variable with an empty value.
In C++ we handle this by branching on maybe_t<env_var_t>::missing_or_empty().
If it returns false, we go on to access maybe_t<env_var_t>::value() aka
operator*.
In Rust, Environment::get() will return an Option<EnvVar>.
We could define a MissingOrEmpty trait and implement it for Option<EnvVar>.
However that will still leave us with ugly calls to Option::unwrap()
(by convention Rust does use shorthands like *).
Let's add a variable getter that returns none for empty variables.