Commit Graph

84 Commits

Author SHA1 Message Date
Peter Ammon
2104f8a18a Remove Rc from Parser's vars
This will help enable Parser to be Send, which will be important for
concurrent execution.
2025-06-14 13:59:17 -07:00
Peter Ammon
ef2e30cdc1 Clean up pids
Use OnceLock more often in place of atomics. Tighten up async signal safety.
2025-06-14 10:34:27 -07:00
Peter Ammon
e598010020 Clean up some Node representations
Use NodeRef more pervasively, leading to simplifications.
2025-06-14 10:33:53 -07:00
Daniel Rainer
80033adcf5 Use LocalizableString for gettext
This new wrapper type can be constructed via macros which invoke the
`gettext_extract` proc macro to extract the string literals for PO file
generation.

The type checking enabled by this wrapper should prevent trying to obtain
translations for a string for which none exist.

Because some strings (e.g. for completions) are not defined in Rust, but rather
in fish scripts, the `LocalizableString` type can also be constructed from
non-literals, in which case no extraction happens.
In such cases, it is the programmer's responsibility to only construct the type
for strings which are available for localization.

This approach is a replacement for the `cargo-expand`-based extraction.

When building with the `FISH_GETTEXT_EXTRACTION_FILE` environment variable set,
the `gettext_extract` proc macro will write the messages marked for extraction
to a file in the directory specified by the variable.

Updates to the po files:
- This is the result of running the `update_translations.fish` script using the
  new proc_macro extraction. It finds additional messages compared to the
  `cargo-expand` based approach.
- Messages IDs corresponding to paths are removed. The do not have localizations
  in any language and localizing paths would not make sense. I have not
  investigated how they made it into the po files in the first place.
- Some messages are reordered due to `msguniq` sorting differing from `sort`.

Remove docs about installing `cargo-expand`
These are no longer needed due to the switch to our extraction macro.
2025-06-07 00:10:05 +02:00
Daniel Rainer
02ccf25443 Prettify profiling for multi-line commands
The old version just prints the entire command being profiled as-is.
If such a command consists of more than one line, these lines do not have any
padding, and thus visually interfere with the timings.

This commit adds padding, such that all lines but the first one have padding
prepended, such that the original line content starts at the column in which the
first line starts.

This does not work perfectly for subcommands (in the profiling sense,
where the command starts with (regex) '-+>' instead of just '>').
In such cases, even if the command string is indented in the source, the command
will not start with whitespace. However, subsequent lines are not trimmed, so
the might be indented farther than they should be relative to the first line of
the command.
2025-05-13 00:11:33 +02:00
Peter Ammon
ccfe949514 ast: make Ast generic
We can parse two different things via Ast:

1. A regular job list
2. A freestanding argument list, as used in `complete --arguments ...`

This second case is specific to one use.

Prior to this commit, we parsed the Ast and then "forgot" what we parsed,
storing a &dyn Node. Then we had to cast it to the right type, and assert,
and etc.

Make Ast generic over the Node type it parsed, and default the Node type to
JobList. This simplifies call sites.
2025-05-04 18:59:13 -07:00
Peter Ammon
dfac66082a ast: adopt Kind in yet more places 2025-05-04 18:59:05 -07:00
Peter Ammon
e05ecd6c7d ast: clean up lists
Make working with lists more natural
2025-05-04 18:28:25 -07:00
Johannes Altmanninger
d18cb6ce27 Use OnceCell for terminal query state initialization
This object is initialized once just before we start reading from the terminal.
Once seems to be the appropriate type for this.  This gets rid of an awkward
enum variant.
2025-04-29 13:51:18 +02:00
Johannes Altmanninger
9b44a59b80 Rename terminal-query-state data structure
While at it, extract a function for initialization.  This looks pretty ugly
but it will get better with the next commit.
2025-04-29 13:51:18 +02:00
Johannes Altmanninger
788eddd0e8 Make terminal query data state a RefCell instead of mutex
We never need to access this from other threads, so a Mutex is overkill.
Leave behind stale variable names like "wait_guard" to be cleaned up by the
next commit.

Since TestInputEventQueuer is used concurrently in tests,
give it its own private object, to avoid borrowing conflicts.

Same for fish_key_reader; this fixes the issue that fish_key_reader potentially
reads keyboard input before a query is finished.
2025-04-29 13:50:15 +02:00
Johannes Altmanninger
e7c9f6d47e Move terminal query state data structure into the parser
Whenever config.fish runs (interactive) builtin read, we push and pop a
top-level, before the main shell's reader.

The terminal state outlives all readers, so its scope should reflect that
to avoid redundant initialization. Move it into the parser.

This is also used by a following commit that wants to access the query state
from a builtin. This should work even if no reader is active.

Note that Mutex doesn't really make sense here - the next commit will fix that.
2025-04-29 13:31:13 +02:00
Daniel Rainer
9d904e1113 Improve profiling output
Indicate the units of the durations (microseconds).

Right-align the durations for better readability.

Use `format!` instead of `fprintf` for more flexible formatting.

Write to `File` instead of raw fd.

Closes #11396
2025-04-18 20:22:30 +02:00
Daniel Rainer
aa01f984b7 Use File as arg to print_profile 2025-04-17 11:46:35 +02:00
Fabian Boehm
66d7c00ba3 Let parser eval string directly
This gets the reader out of asting the source and is needed for
autoloader to get it to read a source string directly

Also add an "eval_file_wstr" method as a convenience to run a wstr as if it is a *file*, with a block and stuff
2025-04-11 17:29:22 +02:00
Johannes Altmanninger
11c7310f17 Prevent commandline modification inside abbreviation callbacks
Consider command line modifications triggered from fish script via abbreviation
expansion:

	function my-abbr-func
	    commandline -r ""
	    echo expanded
	end
	abbr -a foo --function my-abbr-func

Prior to commit 8386088b3d (Update commandline state changes eagerly as well,
2024-04-11), we'd silently ignore the command line modification.
This is because the abbreviation machinery runs something similar to

	if my-abbr-func
	    commandline -rt expanded
	end

except without running "apply_commandline_state_changes()" after
"my-abbr-func", so the «commandline -r ""» update is lost.

Commit 8386088b3d applies the commandline change immediately in the abbrevation
function callback, invalidating abbrevation-expansion state.

The abbreviation design does not tell us what should happen here.  Let's ignore
commandline modifications for now. This mostly matches historical behavior.

Unlike historical behavior we also ignore modifications if the callback fails:

	function my-abbr-func
	    commandline -r ""
	    false
	end

Remove the resulting dead code in editable_line.

See #11324
2025-03-28 12:58:15 +01:00
Peter Ammon
a0a6edd303 Remove Rc from line_counter
We no longer need this.
2025-03-15 16:43:17 -07:00
Peter Ammon
7f8e773b4d Use the new scoped machinery for the current filename 2025-03-15 16:43:17 -07:00
Peter Ammon
e0953cac41 Use new scoped types for line_counter and caller_id 2025-03-15 16:43:17 -07:00
Peter Ammon
adde79259b Move the eval_level into the Parser scoped data
Clean up some ugly atomic stuff.
2025-03-15 16:43:17 -07:00
Peter Ammon
29ae571afa Make scoped_push nicer
In C++ it's easy to make an RAII-type object like "increment a counter for
the duration of this function." Such an object might accept a pointer or
reference, increment the value, and then restore it in its destructor. We
do this all the time - for example to mark a region of code as
non-interactive, etc.

Rust makes this more awkward, because now the reference is tracked by the
borrow checker: it "owns" the object for the duration of the function. This
leads to approaches like "zelf" where the object that marks the parser as
non-interactive itself becomes the new parser, but we can't call it "self"
and it's just yucky.

In this commit we introduce a notion of the "scoped data" of the Parser,
factored out of the library data. This is data which is typically set in a
scoped fashion: whether we are a subshell, are interactive, emit fish_trace
debugging info, etc. Crucially we set this as Rc: this allow the scope
itself to share data with the Parser and we can get rid of lots of "zelf"s.

Introduce a new function `Parser::push_scope` which creates a new scope and
allows modifying these variables associated with the scope. This ends up as
a nice simplification.
2025-03-15 16:43:16 -07:00
Peter Ammon
0113db3ff7 Make parser.libdata.is_event a bool instead of an int
Contrary to the comment, this can and should be a bool.
2025-03-15 16:40:31 -07:00
Peter Ammon
7cc72f1306 Make the transient command line a single value, not a stack
This concerns completions which wrap other completions. For example, if 'tig'
wraps 'git' then for the duration of the git completions, we need to make a fake
("transient") command line which contains "git" and not "tig".

Previously we had a stack of such command lines, but we never inspected anything
except the last element. Make this a single value.
2025-03-15 16:40:31 -07:00
Sander Machado
f4a8368c9e builtins: idiomatic error code passing
Remaining code smells:
- exec_subshell_internal needs to convert a number to a result

Closes #10948
2025-03-15 21:30:49 +01:00
Peter Ammon
b97598fa6c Clean up some logic around handling the parser blocks
Fix a todo. Enforce reverse iteration order.
2024-12-27 16:42:38 -08:00
Peter Ammon
0b68fbfd85 Clean up some stale comments 2024-12-07 10:37:53 -08:00
Johannes Altmanninger
b89619330b Disable terminal protocols before cancellable operations
The [disambiguate flag](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#disambiguate) means that:

> In particular, ctrl+c will no longer generate the SIGINT signal,
> but instead be delivered as a CSI u escape code.

so cancellation only works while we turn off disambiguation.

Today we turn it off while running external commands that want to
claim the TTY.  Also we do it (only as a workaround for this issue)
while expanding wildcards or while running builtin wait.

However there are other cases where we don't have a workaround,
like in trivial infinite loops or when opening a fifo.

Before we run "while true; end", we put the terminal back in ICANON
mode. This means it's line-buffered, so we won't be able to detect
if the user pressed ctrl-c.

Commit 8164855b7 (Disable terminal protocols throughout evaluation,
2024-04-02) had the right solution: simply disable terminal protocols
whenever we do computations that might take a long time.
eval_node() covers most of that; there are a few others.

As pointed out in #10494, the logic was fairly unsophisticated then:
it toggled terminal protocols many times.  The fix in 29f2da8d1
(Toggle terminal protocols lazily, 2024-05-16) went to the extreme
other end of only toggling protocols when absolutely necessary.

Back out part of that commit by toggling in eval_node() again,
fixing cancellation.  Fortunately, we can keep most of the benefits
of the lazy approach from 29f2da8d1: we toggle only 2 times instead
of 8 times for an empty prompt.

There are only two places left where we call signal_check_cancel()
without necessarily disabling the disambiguate flag
1. open_cloexec() we assume that the files we open outside eval_node()
   are never blocking fifos.
2. fire_delayed(). Judging by commit history, this check is not
   relevant for interactive sessions; we'll soon end up calling
   eval_node() anyway.

In future, we can leave bracketed paste, modifyOtherKeys and
application keypad mode turned on again, until we actually run an
external command.  We really only want to turn off the disambiguate
flag.

Since this is approach is overly complex, I plan to go with either
of these two alternatives in future:
- extend the kitty keyboard protocol to optionally support VINTR,
  VSTOP and friends.  Then we can drop most of these changes.
- poll stdin for ctrl-c. This promises a great simplification,
  because it implies that terminal ownership (term_steal/term_donate)
  will be perfectly synced with us enabling kitty keyboard protocol.
  This is because polling requires us to turn off ICANON.
  I started working on this change; I'm convinced it must work,
  but it's not finished yet. Note that this will also want to
  add stdin polling to builtin wait.

Closes #10864
2024-11-24 16:11:57 +01:00
Mahmoud Al-Qudsi
fc47d9fa1d Use strongly typed Pid for job control 2024-11-14 13:02:03 -06:00
Mahmoud Al-Qudsi
3307672998 Use type safety for pid values
The previous approach of "treat this field as an `Option<NonZeroU32>` and
remember to check `p.has_pid()` before accessing it" was a mix of C++ and rust
conventions and led to some bugs or incorrect behaviors.

* `jobs -p` would previously print both the (correct) external pid and the
  (incorrect) internal value of `0` if a backgrounded command contained a
  fish function (e.g. `function foo; end; cat | foo &; jobs`)
* Updating/calculating job cpu time and usage was incorrectly including all of
  fish's cpu usage/time for each function/builtin member of the job pipeline.

Closes #10832
2024-11-14 13:02:03 -06:00
Mahmoud Al-Qudsi
d1a2923d72 Fix doc comments for CancelBehavior 2024-11-04 15:49:33 -06:00
Johannes Altmanninger
2dbaf10c36 Also refresh TTY timestamps after external commands from bindings
Commit ba67d20b7 (Refresh TTY timestamps after nextd/prevd, 2024-10-13)
wasn't quite right because it also needs to fix it for arbitrary commands.

While at it, do this only when needed:
1. It seems to be only relevant for multiline prompts.
   Note that we can wait until after evaluation to check if the prompt is
   multiline, because repaint events go through the queue, see 5ba21cd29
   (Send repaint requests through the input queue again, 2024-04-19).
2. When the binding doesn't execute any external command, we probably don't
   need to fix up whatever the user printed. If they actually wanted to show
   output and print another prompt, they should currently use  "__fish_echo",
   to properly support multiline prompts. Bindings should produce no other
   output. What distinguishes external programs is that they can trigger this
   issue even if they don't  produce any output that remains visible in fish,
   namely by using the terminal's alternate screen.
   Would be nice if we could get rid of __fish_echo; I'm not yet sure how.

Fixes #10800
2024-10-21 12:13:00 +02:00
Johannes Altmanninger
cd541575b4 Fix completion failing on unclosed brace with wildcard
Completion on ": {*," used to work but nowadays our attempt to wildcard-expand
it fails with a syntax error and we do nothing.  This behavior probably only
makes sense for the overflow case, so do that.
2024-10-19 22:04:54 +02:00
Peter Ammon
974ad882fa Clean up fish-printf in preparation for publishing
Make fish-printf no longer depend on the widestring crate, as other clients
won't use it; instead this is an optional feature.

Make format strings a generic type, so that both narrow and wide strings can
serve. This removes a lot of the complexity around converting from narrow to
wide.

Add a README.md to this crate.
2024-09-21 17:52:11 -07:00
Fabian Boehm
8612d34996 Remove useless osttr->cstr->osstr roundtrip 2024-08-16 15:30:57 +02:00
hdhoang
7682abb703 Import portable_atomic::AtomicU64 when std does not provide it
Restores support for 32-bit powerpc and mips. Fixes #10415.

Signed-off-by: Hoang Duc Hieu <code@hdhoang.space>
2024-08-11 14:50:39 +02:00
Mahmoud Al-Qudsi
4730a04f25 Use NonZero types for 1-based line numbers
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()`.
2024-07-07 20:58:09 -05:00
Mahmoud Al-Qudsi
92cae9b576 Reduce size of Block to 32 bytes
Using a 32-bit integer to store the line number, as previously discussed.
2024-07-07 20:37:04 -05:00
Peter Ammon
1ed256d328 Remove RefCells from ExecutionContext and just make it mut
No more storing these in Parser; big simplification.
2024-06-29 18:03:52 -07:00
Peter Ammon
c212ac95e9 Thread a reference to a line counter into parse execution
Simplify Parser by removing the reference to the execution context
2024-06-29 18:03:52 -07:00
Peter Ammon
3aa12c1be9 Rename ParseExecutionContext to ExecutionContext 2024-06-29 18:03:52 -07:00
Peter Ammon
6163999ec7 Remove the ParserRef type
No need to pass around Rc any more.
2024-06-23 16:49:11 -07:00
Peter Ammon
4557d9fc09 Remove the notion of principal parser
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.
2024-06-23 16:49:11 -07:00
Peter Ammon
631516398e Remove the notion of the "principal" environment stack
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.
2024-06-23 16:49:11 -07:00
Peter Ammon
d2d2d8cb45 Remove the shared_from_this for Parser
We no longer need this.
2024-06-23 16:39:39 -07:00
ridiculousfish
c9a76bd634 Make OperationContext not hold a Parser via Rc
Exploit Rust's lifetimes. This will lead to simplifications.
2024-06-23 16:39:39 -07:00
Peter Ammon
5a45b189da Make EnvStackSetResult use Rust naming conventions 2024-06-15 15:57:28 -07:00
ridiculousfish
838ff86ae7 Rename printf crate to fish-printf
Preparing to publish to crates.io
2024-06-09 12:29:09 -07:00
Mahmoud Al-Qudsi
d90d924c8c Remove parser library_data_pod_t ffi workaround
We don't need to separate POD fields from the main parser libdata any more.
2024-06-02 20:27:44 -05:00
Fabian Boehm
94644e88fb Revert "Reduce size of Block to 32 bytes"
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.
2024-06-02 10:44:15 +02:00
Mahmoud Al-Qudsi
ac40807309 Reduce explicit Block state
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.
2024-06-01 13:16:24 -05:00