From 4e78f3649b7288576e8d13e7217702b7190132c6 Mon Sep 17 00:00:00 2001 From: Antoine Stevan <44101798+amtoine@users.noreply.github.com> Date: Thu, 9 Mar 2023 21:18:58 +0100 Subject: [PATCH] FEATURE: add the startup time to `$nu` (#8353) # Description in https://github.com/nushell/nushell/issues/8311 and the discord server, the idea of moving the default banner from the `rust` source to the `nushell` standar library has emerged :yum: however, in order to do this, one need to have access to all the variables used in the default banner => all of them are accessible because known constants, except for the startup time of the shell, which is not anywhere in the shell... #### this PR adds exactly this, i.e. the new `startup_time` to the `$nu` variable, which is computed to have the exact same value as the value shown in the banner. ## the changes in order to achieve this, i had to - add `startup_time` as an `i64` to the `EngineState` => this is, to the best of my knowledge, the easiest way to pass such an information around down to where the banner startup time is computed and where the `$nu` variable is evaluated - add `startup-time` to the `$nu` variable and use the `EngineState` getter for `startup_time` to show it as a `Value::Duration` - pass `engine_state` as a `&mut`able argument from `main.rs` down to `repl.rs` to allow the setter to change the value of `startup_time` => without this, the value would not change and would show `-1ns` as the default value... - the value of the startup time is computed in `evaluate_repl` in `repl.rs`, only once at the beginning, and the same value is used in the default banner :ok_hand: # User-Facing Changes one can now access to the same time as shown in the default banner with ```bash $nu.startup-time ``` # Tests + Formatting - :green_circle: `cargo fmt --all` - :green_circle: `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` - :green_circle: `cargo test --workspace` # After Submitting ``` $nothing ``` --- crates/nu-cli/src/repl.rs | 15 +++++++++------ crates/nu-cli/tests/completions.rs | 3 ++- crates/nu-engine/src/nu_variable.rs | 5 +++++ crates/nu-protocol/src/engine/engine_state.rs | 10 ++++++++++ src/main.rs | 2 +- src/run.rs | 6 +++--- 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 7ea22265ea..22af1fba8d 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -414,7 +414,7 @@ pub fn evaluate_repl( ); start_time = std::time::Instant::now(); - let config = engine_state.get_config(); + let config = &engine_state.get_config().clone(); let prompt = prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt); perf( "update_prompt", @@ -427,11 +427,14 @@ pub fn evaluate_repl( entry_num += 1; - if entry_num == 1 && show_banner { - println!( - "Startup Time: {}", - format_duration(entire_start_time.elapsed().as_nanos() as i64) - ); + if entry_num == 1 { + engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64); + if show_banner { + println!( + "Startup Time: {}", + format_duration(engine_state.get_startup_time()) + ); + } } start_time = std::time::Instant::now(); diff --git a/crates/nu-cli/tests/completions.rs b/crates/nu-cli/tests/completions.rs index bbb56cb303..78c3b07143 100644 --- a/crates/nu-cli/tests/completions.rs +++ b/crates/nu-cli/tests/completions.rs @@ -524,7 +524,7 @@ fn variables_completions() { // Test completions for $nu let suggestions = completer.complete("$nu.", 4); - assert_eq!(11, suggestions.len()); + assert_eq!(12, suggestions.len()); let expected: Vec = vec![ "config-path".into(), @@ -537,6 +537,7 @@ fn variables_completions() { "os-info".into(), "pid".into(), "scope".into(), + "startup-time".into(), "temp-path".into(), ]; diff --git a/crates/nu-engine/src/nu_variable.rs b/crates/nu-engine/src/nu_variable.rs index dc6677064d..ec39413794 100644 --- a/crates/nu-engine/src/nu_variable.rs +++ b/crates/nu-engine/src/nu_variable.rs @@ -36,6 +36,7 @@ impl LazyRecord for NuVariable { cols.push("temp-path"); cols.push("pid"); cols.push("os-info"); + cols.push("startup-time"); cols.push("is-interactive"); cols.push("is-login"); @@ -188,6 +189,10 @@ impl LazyRecord for NuVariable { val: self.engine_state.is_login, span: self.span, }), + "startup-time" => Ok(Value::Duration { + val: self.engine_state.get_startup_time(), + span: self.span(), + }), _ => err(&format!("Could not find column '{column}'")), } } diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 6a1666743d..4b65113541 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -147,6 +147,7 @@ pub struct EngineState { pub regex_cache: Arc>>, pub is_interactive: bool, pub is_login: bool, + startup_time: i64, } // The max number of compiled regexes to keep around in a LRU cache, arbitrarily chosen @@ -199,6 +200,7 @@ impl EngineState { ))), is_interactive: false, is_login: false, + startup_time: -1, } } @@ -1015,6 +1017,14 @@ impl EngineState { pub fn get_file_contents(&self) -> &Vec<(Vec, usize, usize)> { &self.file_contents } + + pub fn get_startup_time(&self) -> i64 { + self.startup_time + } + + pub fn set_startup_time(&mut self, startup_time: i64) { + self.startup_time = startup_time; + } } /// A temporary extension to the global state. This handles bridging between the global state and the diff --git a/src/main.rs b/src/main.rs index ce0dda9842..d62ba568db 100644 --- a/src/main.rs +++ b/src/main.rs @@ -245,6 +245,6 @@ fn main() -> Result<()> { ) } else { engine_state.is_interactive = true; - run_repl(engine_state, parsed_nu_cli_args, entire_start_time) + run_repl(&mut engine_state, parsed_nu_cli_args, entire_start_time) } } diff --git a/src/run.rs b/src/run.rs index 7aeafbff7f..99eaf4f602 100644 --- a/src/run.rs +++ b/src/run.rs @@ -194,7 +194,7 @@ pub(crate) fn run_file( } pub(crate) fn run_repl( - mut engine_state: nu_protocol::engine::EngineState, + engine_state: &mut nu_protocol::engine::EngineState, parsed_nu_cli_args: command::NushellCliArgs, entire_start_time: std::time::Instant, ) -> Result<(), miette::ErrReport> { @@ -203,7 +203,7 @@ pub(crate) fn run_repl( if parsed_nu_cli_args.no_config_file.is_none() { setup_config( - &mut engine_state, + engine_state, &mut stack, #[cfg(feature = "plugin")] parsed_nu_cli_args.plugin_file, @@ -226,7 +226,7 @@ pub(crate) fn run_repl( let start_time = std::time::Instant::now(); let ret_val = evaluate_repl( - &mut engine_state, + engine_state, &mut stack, config_files::NUSHELL_FOLDER, parsed_nu_cli_args.execute,