diff --git a/crates/nu-cli/src/prompt_update.rs b/crates/nu-cli/src/prompt_update.rs index 127c02458..d212ab2de 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"; @@ -15,6 +17,15 @@ pub(crate) const PROMPT_INDICATOR: &str = "PROMPT_INDICATOR"; pub(crate) const PROMPT_INDICATOR_VI_INSERT: &str = "PROMPT_INDICATOR_VI_INSERT"; pub(crate) const PROMPT_INDICATOR_VI_NORMAL: &str = "PROMPT_INDICATOR_VI_NORMAL"; pub(crate) const PROMPT_MULTILINE_INDICATOR: &str = "PROMPT_MULTILINE_INDICATOR"; +pub(crate) const TRANSIENT_PROMPT_COMMAND: &str = "TRANSIENT_PROMPT_COMMAND"; +pub(crate) const TRANSIENT_PROMPT_COMMAND_RIGHT: &str = "TRANSIENT_PROMPT_COMMAND_RIGHT"; +pub(crate) const TRANSIENT_PROMPT_INDICATOR: &str = "TRANSIENT_PROMPT_INDICATOR"; +pub(crate) const TRANSIENT_PROMPT_INDICATOR_VI_INSERT: &str = + "TRANSIENT_PROMPT_INDICATOR_VI_INSERT"; +pub(crate) const TRANSIENT_PROMPT_INDICATOR_VI_NORMAL: &str = + "TRANSIENT_PROMPT_INDICATOR_VI_NORMAL"; +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\\"; @@ -145,3 +156,119 @@ pub(crate) fn update_prompt<'prompt>( ret_val } + +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: &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 7898285bb..9341a1b33 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -271,7 +271,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, diff --git a/crates/nu-utils/src/sample_config/default_env.nu b/crates/nu-utils/src/sample_config/default_env.nu index 12a24ade1..9935859be 100644 --- a/crates/nu-utils/src/sample_config/default_env.nu +++ b/crates/nu-utils/src/sample_config/default_env.nu @@ -47,6 +47,18 @@ $env.PROMPT_INDICATOR_VI_INSERT = {|| ": " } $env.PROMPT_INDICATOR_VI_NORMAL = {|| "> " } $env.PROMPT_MULTILINE_INDICATOR = {|| "::: " } +# If you want previously entered commands to have a different prompt from the usual one, +# you can uncomment one or more of the following lines. +# This can be useful if you have a 2-line prompt and it's taking up a lot of space +# because every command entered takes up 2 lines instead of 1. You can then uncomment +# the line below so that previously entered commands show with a single `🚀`. +# $env.TRANSIENT_PROMPT_COMMAND = {|| "🚀 " } +# $env.TRANSIENT_PROMPT_INDICATOR = {|| "" } +# $env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = {|| "" } +# $env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = {|| "" } +# $env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = {|| "" } +# $env.TRANSIENT_PROMPT_COMMAND_RIGHT = {|| "" } + # Specifies how environment variables are: # - converted from a string to a value on Nushell startup (from_string) # - converted from a value back to a string when running external commands (to_string)