From 2264682443dcf926b2b5d0caee513bf12e501956 Mon Sep 17 00:00:00 2001 From: Steven Date: Sat, 16 Dec 2023 18:12:34 -0800 Subject: [PATCH] fix shell integration markers (#11352) Fixes #11260 # Description Note: my issue description was a bit wrong. Issue one can't be reproduced without a config (`shell_integration` isn't on by default, so..), however the issue itself is still valid For issue 1, the default prompt needs to know about the `shell_integration` config, and the markers are added around the default prompt when that's on. For issue 2, this is actually related to transient prompts. When rendering, the markers weren't added like for normal prompts. After the fix the output do now contain the proper markers: Reproducing the minimum config here for convenience: ```nu $env.config = { show_banner: false shell_integration: true } # $env.PROMPT_COMMAND = {|| "> " } ``` For issue 1, the output looks like: ``` [2.3490236,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\/home/steven\u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:31:58 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h"] [2.5676293,"o","\u001b[6n"] [2.571353,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\\u001b]133;A\u001b\\/home/steven\u001b]133;B\u001b\\\u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:31:59 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h\u001b[21;1H\r\n\u001b[21;1H"] [2.571436,"o","\u001b[?2004l"] [2.5714657,"o","\u001b]133;C\u001b\\"] ``` in line 3, where enter is pressed, `133 A` and `B` are present. Same for issue 2 (uncomment the `PROMPT_COMMAND` line in the config): ``` [1.9585224,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\> \u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:32:15 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h"] [2.453972,"o","\u001b[6n"] [2.4585786,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\\u001b]133;A\u001b\\> \u001b]133;B\u001b\\\u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:32:15 PM\u001b8\u001b[0m\u001b[0m\u001b[1;36mecho\u001b[0m\u001b7\u001b8\u001b[?25h\u001b[21;1H\r\n\u001b[21;1H\u001b[?2004l\u001b]133;C\u001b\\\r\n\u001b]133;D;0\u001b\\\u001b]7;file://Aostro-5468/home/steven\u001b\\\u001b]2;~\u0007\u001b[?1l"] [2.4669976,"o","\u001b[?2004h\u001b[6n"] [2.4703515,"o","\u001b[6n"] [2.4736586,"o","\u001b[?25l\u001b[21;1H\u001b[21;1H\u001b[J\u001b[38;5;10m\u001b]133;A\u001b\\> \u001b]133;B\u001b\\\u001b[38;5;14m\u001b[38;5;5m\u001b7\u001b[21;84H12/16/2023 03:32:15 PM\u001b8\u001b[0m\u001b[0m\u001b7\u001b8\u001b[?25h"] ``` # User-Facing Changes None user facing changes other than that prompt markers are working # Tests + Formatting # After Submitting --- crates/nu-cli/src/prompt.rs | 17 +++++++-------- crates/nu-cli/src/prompt_update.rs | 33 +++++++++++++++++------------- crates/nu-cli/src/repl.rs | 5 +++-- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/crates/nu-cli/src/prompt.rs b/crates/nu-cli/src/prompt.rs index 9264c1b64..4ec0e677f 100644 --- a/crates/nu-cli/src/prompt.rs +++ b/crates/nu-cli/src/prompt.rs @@ -1,3 +1,4 @@ +use crate::prompt_update::{POST_PROMPT_MARKER, PRE_PROMPT_MARKER}; #[cfg(windows)] use nu_utils::enable_vt_processing; use reedline::DefaultPrompt; @@ -11,6 +12,7 @@ use { /// Nushell prompt definition #[derive(Clone)] pub struct NushellPrompt { + shell_integration: bool, left_prompt_string: Option, right_prompt_string: Option, default_prompt_indicator: Option, @@ -20,15 +22,10 @@ pub struct NushellPrompt { render_right_prompt_on_last_line: bool, } -impl Default for NushellPrompt { - fn default() -> Self { - NushellPrompt::new() - } -} - impl NushellPrompt { - pub fn new() -> NushellPrompt { + pub fn new(shell_integration: bool) -> NushellPrompt { NushellPrompt { + shell_integration, left_prompt_string: None, right_prompt_string: None, default_prompt_indicator: None, @@ -111,7 +108,11 @@ impl Prompt for NushellPrompt { .to_string() .replace('\n', "\r\n"); - prompt.into() + if self.shell_integration { + format!("{PRE_PROMPT_MARKER}{prompt}{POST_PROMPT_MARKER}").into() + } else { + prompt.into() + } } } diff --git a/crates/nu-cli/src/prompt_update.rs b/crates/nu-cli/src/prompt_update.rs index e691a3e32..bacb1167a 100644 --- a/crates/nu-cli/src/prompt_update.rs +++ b/crates/nu-cli/src/prompt_update.rs @@ -28,8 +28,8 @@ pub(crate) const TRANSIENT_PROMPT_MULTILINE_INDICATOR: &str = "TRANSIENT_PROMPT_MULTILINE_INDICATOR"; // According to Daniel Imms @Tyriar, we need to do these this way: // <133 A><133 B><133 C> -const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\"; -const POST_PROMPT_MARKER: &str = "\x1b]133;B\x1b\\"; +pub(crate) const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\"; +pub(crate) const POST_PROMPT_MARKER: &str = "\x1b]133;B\x1b\\"; fn get_prompt_string( prompt: &str, @@ -160,19 +160,19 @@ struct TransientPrompt { } impl TransientPrompt { - fn new_prompt(&self) -> NushellPrompt { + fn new_prompt(&self, shell_integration: bool) -> NushellPrompt { if let Ok(prompt) = self.prompt_lock.read() { prompt.clone() } else { - NushellPrompt::new() + NushellPrompt::new(shell_integration) } } } impl Prompt for TransientPrompt { fn render_prompt_left(&self) -> Cow { - let mut nu_prompt = self.new_prompt(); - let config = &self.engine_state.get_config().clone(); + let config = self.engine_state.get_config(); + let mut nu_prompt = self.new_prompt(config.shell_integration); let mut stack = self.stack.clone(); if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_COMMAND, @@ -182,12 +182,17 @@ impl Prompt for TransientPrompt { ) { nu_prompt.update_prompt_left(Some(s)) } - nu_prompt.render_prompt_left().to_string().into() + let left_prompt = nu_prompt.render_prompt_left(); + if config.shell_integration { + format!("{PRE_PROMPT_MARKER}{left_prompt}{POST_PROMPT_MARKER}").into() + } else { + left_prompt.to_string().into() + } } fn render_prompt_right(&self) -> Cow { - let mut nu_prompt = self.new_prompt(); - let config = &self.engine_state.get_config().clone(); + let config = self.engine_state.get_config(); + let mut nu_prompt = self.new_prompt(config.shell_integration); let mut stack = self.stack.clone(); if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_COMMAND_RIGHT, @@ -201,8 +206,8 @@ impl Prompt for TransientPrompt { } fn render_prompt_indicator(&self, prompt_mode: reedline::PromptEditMode) -> Cow { - let mut nu_prompt = self.new_prompt(); - let config = &self.engine_state.get_config().clone(); + let config = self.engine_state.get_config(); + let mut nu_prompt = self.new_prompt(config.shell_integration); let mut stack = self.stack.clone(); if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_INDICATOR, @@ -235,8 +240,8 @@ impl Prompt for TransientPrompt { } fn render_prompt_multiline_indicator(&self) -> Cow { - let mut nu_prompt = self.new_prompt(); - let config = &self.engine_state.get_config().clone(); + let config = self.engine_state.get_config(); + let mut nu_prompt = self.new_prompt(config.shell_integration); let mut stack = self.stack.clone(); if let Some(s) = get_prompt_string( TRANSIENT_PROMPT_MULTILINE_INDICATOR, @@ -256,7 +261,7 @@ impl Prompt for TransientPrompt { &self, history_search: reedline::PromptHistorySearch, ) -> Cow { - NushellPrompt::new() + NushellPrompt::new(self.engine_state.get_config().shell_integration) .render_prompt_history_search_indicator(history_search) .to_string() .into() diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 25f1e6092..48014e68e 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -54,7 +54,8 @@ pub fn evaluate_repl( ) -> Result<()> { use nu_cmd_base::hook; use reedline::Signal; - let use_color = engine_state.get_config().use_ansi_coloring; + let config = engine_state.get_config(); + let use_color = config.use_ansi_coloring; // Guard against invocation without a connected terminal. // reedline / crossterm event polling will fail without a connected tty @@ -68,7 +69,7 @@ pub fn evaluate_repl( let mut entry_num = 0; - let nu_prompt = Arc::new(RwLock::new(NushellPrompt::new())); + let nu_prompt = Arc::new(RwLock::new(NushellPrompt::new(config.shell_integration))); let start_time = std::time::Instant::now(); // Translate environment variables from Strings to Values