The commandline "and fis" rightly gets command autosuggestions whereas
"'and' fis" wrongly gets file autosuggestions. The former works via
a hack. Extend it to quoted keywords.
StatementVariant needs an indirection because for example NotStatement
may contain another whole statement (error[E0072]: recursive type
has infinite size).
This is dealt with by putting each StatementVariant in a Box.
This Box was also used by the AST walk implementation to implement
tagged dispatched for all variant AST nodes (see "visit_union_field").
Because of this, all other variant AST are boxed the same way, even
though they may not by cyclic themselves.
Reduce confusion by boxing only around the nodes that are actually
recursive types, and use a different tag for static dispatch.
This means that simple nodes like most normal commands and arguments
need one fewer allocation.
This is allowed
time a=b echo 123
but -- due to an oversight in 3de95038b0 (Make "time" a job prefix,
2019-12-21) -- this is not allowed:
not time a=b echo 123
Instead, this one one works:
not a=b time echo 123
which is weird because without the "not" this would run "/bin/time".
It seems wrong that "not" is not like the others. Swap the order
for consistency.
Note that unlike "not", "time" currently needs to come before variable
assignments, so "a=b time true" is disallowed. This matches zsh. POSIX
shells call "/bin/time" here. Since it's ambiguous, erroring out seems
fine. It's weird that we're inconsistent with not here but I guess
"command not" is not expected to have subtly different behavior.
Closes#10890
This was added accidentally in 971d257e67 (Port AST to Rust,
2023-04-02). It does not seem to be causing an observable effect
(although I didn't try hard).
On a command with multiline quoted string like
begin
echo "line1
line2"
end
we actually indent line2 which seeems misleading because the indentation
changes the behavior when typed into a script.
This has become more prominent since commits
- a37629f86 (fish_clipboard_copy: indent multiline commands, 2024-04-13)
- 611a0572b (builtins type/functions: indent interactively-defined functions, 2024-04-12)
- 222673f33 (edit_command_buffer: send indented commandline to editor, 2024-04-12)
which add indentation to an exported commandline.
Never indent quoted strings, to make sure the rendering matches the semantics.
Note that we do need to indent the opening quote which is fine because
it's on the same line.
While at it, indent command substitutions recursively. That feature should
also be added to fish_indent's formatting mode (which is the default).
Fortunately the formatting mode already works fine with quoted strings;
it does not indent them. Not sure how that's done and whether indentation
can use the same logic.
IfStatement is 680 bytes, much larger than the other
variants (SwitchStatement is next at 232). An enum is as large as its
largest variant, so this saves a bunch, especially since
DecoratedStatement is much more likely than IfStatement.
This will speed up the no-execute benchmark by 1.07x.
This reserved 64, which is *gigantic*.
Over all of share/**.fish, 75% of lists are empty, 99.97% are 16
elements or fewer.
Reducing this to 16 reduces memory usage for a gigantic example
script (git.fish pasted a bunch of times for a total of almost 100k
lines) by ~10% and speeds up "--no-execute" time by the same amount.
For smaller scripts it's less noticeable simply because parse time
matters less.
There are other options, like creating the vec ::with_capacity, or
using 8 instead of 16, or even letting the vec just grow
naturally (rust's vec currently grows from 0 to 4 and then doubles,
which isn't terrible for this use), but the point is that 64 is
wasteful and never comes out on top, always in the last two places
comparing a bunch of choices.