mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-29 06:01:16 -03:00
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.
52 lines
1.7 KiB
Rust
52 lines
1.7 KiB
Rust
use crate::flog::log_extra_to_flog_file;
|
|
use crate::parser::Parser;
|
|
use crate::{common::escape, global_safety::RelaxedAtomicBool, wchar::prelude::*};
|
|
|
|
static DO_TRACE: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
|
|
|
pub fn trace_set_enabled(do_enable: bool) {
|
|
DO_TRACE.store(do_enable);
|
|
}
|
|
|
|
/// return whether tracing is enabled.
|
|
pub fn trace_enabled(parser: &Parser) -> bool {
|
|
if parser.scope().suppress_fish_trace {
|
|
return false;
|
|
}
|
|
DO_TRACE.load()
|
|
}
|
|
|
|
/// Trace an "argv": a list of arguments where the first is the command.
|
|
// Allow the `&Vec` parameter as this function only exists temporarily for the FFI
|
|
pub fn trace_argv<S: AsRef<wstr>>(parser: &Parser, command: &wstr, args: &[S]) {
|
|
// Format into a string to prevent interleaving with flog in other threads.
|
|
// Add the + prefix.
|
|
let mut trace_text = L!("-").repeat(parser.blocks_size() - 1);
|
|
trace_text.push('>');
|
|
|
|
if !command.is_empty() {
|
|
trace_text.push(' ');
|
|
trace_text.push_utfstr(command);
|
|
}
|
|
for arg in args {
|
|
trace_text.push(' ');
|
|
trace_text.push_utfstr(&escape(arg.as_ref()));
|
|
}
|
|
trace_text.push('\n');
|
|
log_extra_to_flog_file(&trace_text);
|
|
}
|
|
|
|
/// Convenience helper to trace a single command if tracing is enabled.
|
|
pub fn trace_if_enabled(parser: &Parser, command: &wstr) {
|
|
if trace_enabled(parser) {
|
|
let argv: &[&'static wstr] = &[];
|
|
trace_argv(parser, command, argv);
|
|
}
|
|
}
|
|
/// Convenience helper to trace a single command and arguments if tracing is enabled.
|
|
pub fn trace_if_enabled_with_args<S: AsRef<wstr>>(parser: &Parser, command: &wstr, args: &[S]) {
|
|
if trace_enabled(parser) {
|
|
trace_argv(parser, command, args);
|
|
}
|
|
}
|