diff --git a/crates/nu-cli/src/prompt_update.rs b/crates/nu-cli/src/prompt_update.rs index 1df120bd96..e691a3e32c 100644 --- a/crates/nu-cli/src/prompt_update.rs +++ b/crates/nu-cli/src/prompt_update.rs @@ -8,7 +8,7 @@ use nu_protocol::{ }; use reedline::Prompt; use std::borrow::Cow; -use std::sync::Arc; +use std::sync::{Arc, RwLock}; // Name of environment variable where the prompt could be stored pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND"; @@ -98,12 +98,12 @@ fn get_prompt_string( }) } -pub(crate) fn update_prompt<'prompt>( +pub(crate) fn update_prompt( config: &Config, engine_state: &EngineState, stack: &Stack, - nu_prompt: &'prompt mut NushellPrompt, -) -> &'prompt dyn Prompt { + nu_prompt: Arc>, +) { let mut stack = stack.clone(); let left_prompt_string = get_prompt_string(PROMPT_COMMAND, config, engine_state, &mut stack); @@ -138,95 +138,96 @@ pub(crate) fn update_prompt<'prompt>( get_prompt_string(PROMPT_INDICATOR_VI_NORMAL, config, engine_state, &mut stack); // apply the other indicators - nu_prompt.update_all_prompt_strings( - left_prompt_string, - right_prompt_string, - prompt_indicator_string, - prompt_multiline_string, - (prompt_vi_insert_string, prompt_vi_normal_string), - config.render_right_prompt_on_last_line, - ); + nu_prompt + .write() + .expect("Could not lock on nu_prompt to update") + .update_all_prompt_strings( + left_prompt_string, + right_prompt_string, + prompt_indicator_string, + prompt_multiline_string, + (prompt_vi_insert_string, prompt_vi_normal_string), + config.render_right_prompt_on_last_line, + ); - let ret_val = nu_prompt as &dyn Prompt; trace!("update_prompt {}:{}:{}", file!(), line!(), column!()); - - ret_val } struct TransientPrompt { + prompt_lock: Arc>, engine_state: Arc, stack: Stack, } -/// Try getting `$env.TRANSIENT_PROMPT_`, and get `$env.PROMPT_` if that fails -fn get_transient_prompt_string( - transient_prompt: &str, - prompt: &str, - config: &Config, - engine_state: &EngineState, - stack: &mut Stack, -) -> Option { - get_prompt_string(transient_prompt, config, engine_state, stack) - .or_else(|| get_prompt_string(prompt, config, engine_state, stack)) +impl TransientPrompt { + fn new_prompt(&self) -> NushellPrompt { + if let Ok(prompt) = self.prompt_lock.read() { + prompt.clone() + } else { + NushellPrompt::new() + } + } } impl Prompt for TransientPrompt { fn render_prompt_left(&self) -> Cow { - let mut nu_prompt = NushellPrompt::new(); + let mut nu_prompt = self.new_prompt(); let config = &self.engine_state.get_config().clone(); let mut stack = self.stack.clone(); - nu_prompt.update_prompt_left(get_transient_prompt_string( + if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_COMMAND, - PROMPT_COMMAND, config, &self.engine_state, &mut stack, - )); + ) { + nu_prompt.update_prompt_left(Some(s)) + } nu_prompt.render_prompt_left().to_string().into() } fn render_prompt_right(&self) -> Cow { - let mut nu_prompt = NushellPrompt::new(); + let mut nu_prompt = self.new_prompt(); let config = &self.engine_state.get_config().clone(); let mut stack = self.stack.clone(); - nu_prompt.update_prompt_right( - get_transient_prompt_string( - TRANSIENT_PROMPT_COMMAND_RIGHT, - PROMPT_COMMAND_RIGHT, - config, - &self.engine_state, - &mut stack, - ), - config.render_right_prompt_on_last_line, - ); + if let Some(s) = get_prompt_string( + TRANSIENT_PROMPT_COMMAND_RIGHT, + config, + &self.engine_state, + &mut stack, + ) { + nu_prompt.update_prompt_right(Some(s), config.render_right_prompt_on_last_line) + } nu_prompt.render_prompt_right().to_string().into() } fn render_prompt_indicator(&self, prompt_mode: reedline::PromptEditMode) -> Cow { - let mut nu_prompt = NushellPrompt::new(); + let mut nu_prompt = self.new_prompt(); let config = &self.engine_state.get_config().clone(); let mut stack = self.stack.clone(); - nu_prompt.update_prompt_indicator(get_transient_prompt_string( + if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_INDICATOR, - PROMPT_INDICATOR, config, &self.engine_state, &mut stack, - )); - nu_prompt.update_prompt_vi_insert(get_transient_prompt_string( + ) { + nu_prompt.update_prompt_indicator(Some(s)) + } + if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_INDICATOR_VI_INSERT, - PROMPT_INDICATOR_VI_INSERT, config, &self.engine_state, &mut stack, - )); - nu_prompt.update_prompt_vi_normal(get_transient_prompt_string( + ) { + nu_prompt.update_prompt_vi_insert(Some(s)) + } + if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_INDICATOR_VI_NORMAL, - PROMPT_INDICATOR_VI_NORMAL, config, &self.engine_state, &mut stack, - )); + ) { + nu_prompt.update_prompt_vi_normal(Some(s)) + } nu_prompt .render_prompt_indicator(prompt_mode) .to_string() @@ -234,16 +235,17 @@ impl Prompt for TransientPrompt { } fn render_prompt_multiline_indicator(&self) -> Cow { - let mut nu_prompt = NushellPrompt::new(); + let mut nu_prompt = self.new_prompt(); let config = &self.engine_state.get_config().clone(); let mut stack = self.stack.clone(); - nu_prompt.update_prompt_multiline(get_transient_prompt_string( + if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_MULTILINE_INDICATOR, - PROMPT_MULTILINE_INDICATOR, config, &self.engine_state, &mut stack, - )); + ) { + nu_prompt.update_prompt_multiline(Some(s)) + } nu_prompt .render_prompt_multiline_indicator() .to_string() @@ -262,8 +264,13 @@ impl Prompt for TransientPrompt { } /// Construct the transient prompt -pub(crate) fn transient_prompt(engine_state: Arc, stack: &Stack) -> Box { +pub(crate) fn transient_prompt( + prompt_lock: Arc>, + engine_state: Arc, + stack: &Stack, +) -> Box { Box::new(TransientPrompt { + prompt_lock, engine_state, stack: stack.clone(), }) diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 65425d4306..25f1e60926 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -29,7 +29,7 @@ use std::{ env::temp_dir, io::{self, IsTerminal, Write}, path::Path, - sync::atomic::Ordering, + sync::{atomic::Ordering, Arc, RwLock}, time::Instant, }; use sysinfo::SystemExt; @@ -68,7 +68,7 @@ pub fn evaluate_repl( let mut entry_num = 0; - let mut nu_prompt = NushellPrompt::new(); + let nu_prompt = Arc::new(RwLock::new(NushellPrompt::new())); let start_time = std::time::Instant::now(); // Translate environment variables from Strings to Values @@ -269,6 +269,7 @@ pub fn evaluate_repl( .with_ansi_colors(config.use_ansi_coloring) .with_cursor_config(cursor_config) .with_transient_prompt(prompt_update::transient_prompt( + Arc::clone(&nu_prompt), engine_reference.clone(), stack, )); @@ -424,7 +425,7 @@ pub fn evaluate_repl( start_time = std::time::Instant::now(); let config = &engine_state.get_config().clone(); - let prompt = prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt); + prompt_update::update_prompt(config, engine_state, stack, Arc::clone(&nu_prompt)); perf( "update_prompt", start_time, @@ -437,7 +438,14 @@ pub fn evaluate_repl( entry_num += 1; start_time = std::time::Instant::now(); - let input = line_editor.read_line(prompt); + let input = { + line_editor.read_line( + &nu_prompt + .read() + .expect("Could not lock on prompt to pass to read_line") + .to_owned(), + ) + }; let shell_integration = config.shell_integration; match input {