From 9092fc1b125b30c81fb3452c6ba4e47f3a90760d Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:58:32 -0600 Subject: [PATCH] Revert "Only run $env.PROMPT_COMMAND once per prompt" (#11340) Reverts nushell/nushell#10986 @CAD97 This isn't working right. I have a 2 line prompt with a transient prompt. on enter, you see the transient prompt drawn and then the normal prompt overwrites it. --- crates/nu-cli/src/prompt.rs | 55 +++++---- crates/nu-cli/src/prompt_update.rs | 187 ++++++++++++++++++----------- crates/nu-cli/src/repl.rs | 14 +-- 3 files changed, 150 insertions(+), 106 deletions(-) diff --git a/crates/nu-cli/src/prompt.rs b/crates/nu-cli/src/prompt.rs index 081de2b7f5..9264c1b646 100644 --- a/crates/nu-cli/src/prompt.rs +++ b/crates/nu-cli/src/prompt.rs @@ -39,6 +39,35 @@ impl NushellPrompt { } } + pub fn update_prompt_left(&mut self, prompt_string: Option) { + self.left_prompt_string = prompt_string; + } + + pub fn update_prompt_right( + &mut self, + prompt_string: Option, + render_right_prompt_on_last_line: bool, + ) { + self.right_prompt_string = prompt_string; + self.render_right_prompt_on_last_line = render_right_prompt_on_last_line; + } + + pub fn update_prompt_indicator(&mut self, prompt_indicator_string: Option) { + self.default_prompt_indicator = prompt_indicator_string; + } + + pub fn update_prompt_vi_insert(&mut self, prompt_vi_insert_string: Option) { + self.default_vi_insert_prompt_indicator = prompt_vi_insert_string; + } + + pub fn update_prompt_vi_normal(&mut self, prompt_vi_normal_string: Option) { + self.default_vi_normal_prompt_indicator = prompt_vi_normal_string; + } + + pub fn update_prompt_multiline(&mut self, prompt_multiline_indicator_string: Option) { + self.default_multiline_indicator = prompt_multiline_indicator_string; + } + pub fn update_all_prompt_strings( &mut self, left_prompt_string: Option, @@ -61,32 +90,6 @@ impl NushellPrompt { self.render_right_prompt_on_last_line = render_right_prompt_on_last_line; } - pub fn overlay_all_prompt_strings( - &mut self, - left_prompt_string: Option, - right_prompt_string: Option, - prompt_indicator_string: Option, - prompt_multiline_indicator_string: Option, - prompt_vi: (Option, Option), - render_right_prompt_on_last_line: bool, - ) { - let (prompt_vi_insert_string, prompt_vi_normal_string) = prompt_vi; - - self.left_prompt_string = left_prompt_string.or(self.left_prompt_string.take()); - self.right_prompt_string = right_prompt_string.or(self.right_prompt_string.take()); - self.default_prompt_indicator = - prompt_indicator_string.or(self.default_prompt_indicator.take()); - self.default_multiline_indicator = - prompt_multiline_indicator_string.or(self.default_multiline_indicator.take()); - - self.default_vi_insert_prompt_indicator = - prompt_vi_insert_string.or(self.default_vi_insert_prompt_indicator.take()); - self.default_vi_normal_prompt_indicator = - prompt_vi_normal_string.or(self.default_vi_normal_prompt_indicator.take()); - - self.render_right_prompt_on_last_line = render_right_prompt_on_last_line; - } - fn default_wrapped_custom_string(&self, str: String) -> String { format!("({str})") } diff --git a/crates/nu-cli/src/prompt_update.rs b/crates/nu-cli/src/prompt_update.rs index a12bb0b6af..1df120bd96 100644 --- a/crates/nu-cli/src/prompt_update.rs +++ b/crates/nu-cli/src/prompt_update.rs @@ -7,6 +7,8 @@ use nu_protocol::{ Config, PipelineData, Value, }; use reedline::Prompt; +use std::borrow::Cow; +use std::sync::Arc; // Name of environment variable where the prompt could be stored pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND"; @@ -151,79 +153,118 @@ pub(crate) fn update_prompt<'prompt>( ret_val } -pub(crate) fn make_transient_prompt( +struct TransientPrompt { + 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: &Stack, - nu_prompt: &NushellPrompt, -) -> Box { - let mut stack = stack.clone(); - let mut nu_prompt = nu_prompt.clone(); - - let left_prompt_string = - get_prompt_string(TRANSIENT_PROMPT_COMMAND, config, engine_state, &mut stack); - - // Now that we have the prompt string lets ansify it. - // <133 A><133 B><133 C> - let left_prompt_string = if config.shell_integration { - if let Some(prompt_string) = left_prompt_string { - Some(format!( - "{PRE_PROMPT_MARKER}{prompt_string}{POST_PROMPT_MARKER}" - )) - } else { - left_prompt_string - } - } else { - left_prompt_string - }; - - let right_prompt_string = get_prompt_string( - TRANSIENT_PROMPT_COMMAND_RIGHT, - config, - engine_state, - &mut stack, - ); - - let prompt_indicator_string = - get_prompt_string(TRANSIENT_PROMPT_INDICATOR, config, engine_state, &mut stack); - - let prompt_multiline_string = get_prompt_string( - TRANSIENT_PROMPT_MULTILINE_INDICATOR, - config, - engine_state, - &mut stack, - ); - - let prompt_vi_insert_string = get_prompt_string( - TRANSIENT_PROMPT_INDICATOR_VI_INSERT, - config, - engine_state, - &mut stack, - ); - - let prompt_vi_normal_string = get_prompt_string( - TRANSIENT_PROMPT_INDICATOR_VI_NORMAL, - config, - engine_state, - &mut stack, - ); - - // apply the other indicators - nu_prompt.overlay_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, - ); - - trace!( - "make_transient_prompt {}:{}:{}", - file!(), - line!(), - column!() - ); - - Box::new(nu_prompt) + stack: &mut Stack, +) -> Option { + get_prompt_string(transient_prompt, config, engine_state, stack) + .or_else(|| get_prompt_string(prompt, config, engine_state, stack)) +} + +impl Prompt for TransientPrompt { + fn render_prompt_left(&self) -> Cow { + let mut nu_prompt = NushellPrompt::new(); + let config = &self.engine_state.get_config().clone(); + let mut stack = self.stack.clone(); + nu_prompt.update_prompt_left(get_transient_prompt_string( + TRANSIENT_PROMPT_COMMAND, + PROMPT_COMMAND, + config, + &self.engine_state, + &mut stack, + )); + nu_prompt.render_prompt_left().to_string().into() + } + + fn render_prompt_right(&self) -> Cow { + let mut nu_prompt = NushellPrompt::new(); + 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, + ); + 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 config = &self.engine_state.get_config().clone(); + let mut stack = self.stack.clone(); + nu_prompt.update_prompt_indicator(get_transient_prompt_string( + TRANSIENT_PROMPT_INDICATOR, + PROMPT_INDICATOR, + config, + &self.engine_state, + &mut stack, + )); + nu_prompt.update_prompt_vi_insert(get_transient_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( + TRANSIENT_PROMPT_INDICATOR_VI_NORMAL, + PROMPT_INDICATOR_VI_NORMAL, + config, + &self.engine_state, + &mut stack, + )); + nu_prompt + .render_prompt_indicator(prompt_mode) + .to_string() + .into() + } + + fn render_prompt_multiline_indicator(&self) -> Cow { + let mut nu_prompt = NushellPrompt::new(); + let config = &self.engine_state.get_config().clone(); + let mut stack = self.stack.clone(); + nu_prompt.update_prompt_multiline(get_transient_prompt_string( + TRANSIENT_PROMPT_MULTILINE_INDICATOR, + PROMPT_MULTILINE_INDICATOR, + config, + &self.engine_state, + &mut stack, + )); + nu_prompt + .render_prompt_multiline_indicator() + .to_string() + .into() + } + + fn render_prompt_history_search_indicator( + &self, + history_search: reedline::PromptHistorySearch, + ) -> Cow { + NushellPrompt::new() + .render_prompt_history_search_indicator(history_search) + .to_string() + .into() + } +} + +/// Construct the transient prompt +pub(crate) fn transient_prompt(engine_state: Arc, stack: &Stack) -> Box { + Box::new(TransientPrompt { + engine_state, + stack: stack.clone(), + }) } diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 09f190251b..65425d4306 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -267,7 +267,11 @@ pub fn evaluate_repl( .with_quick_completions(config.quick_completions) .with_partial_completions(config.partial_completions) .with_ansi_colors(config.use_ansi_coloring) - .with_cursor_config(cursor_config); + .with_cursor_config(cursor_config) + .with_transient_prompt(prompt_update::transient_prompt( + engine_reference.clone(), + stack, + )); perf( "reedline builder", start_time, @@ -419,11 +423,8 @@ pub fn evaluate_repl( ); start_time = std::time::Instant::now(); - // Now we compute the prompt after running the hooks let config = &engine_state.get_config().clone(); - prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt); - let transient_prompt = - prompt_update::make_transient_prompt(config, engine_state, stack, &nu_prompt); + let prompt = prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt); perf( "update_prompt", start_time, @@ -436,8 +437,7 @@ pub fn evaluate_repl( entry_num += 1; start_time = std::time::Instant::now(); - line_editor = line_editor.with_transient_prompt(transient_prompt); - let input = line_editor.read_line(&nu_prompt); + let input = line_editor.read_line(prompt); let shell_integration = config.shell_integration; match input {