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.
This commit is contained in:
Darren Schroeder 2023-12-15 11:58:32 -06:00 committed by GitHub
parent 5b557a888e
commit 9092fc1b12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 150 additions and 106 deletions

View File

@ -39,6 +39,35 @@ impl NushellPrompt {
} }
} }
pub fn update_prompt_left(&mut self, prompt_string: Option<String>) {
self.left_prompt_string = prompt_string;
}
pub fn update_prompt_right(
&mut self,
prompt_string: Option<String>,
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<String>) {
self.default_prompt_indicator = prompt_indicator_string;
}
pub fn update_prompt_vi_insert(&mut self, prompt_vi_insert_string: Option<String>) {
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
}
pub fn update_prompt_vi_normal(&mut self, prompt_vi_normal_string: Option<String>) {
self.default_vi_normal_prompt_indicator = prompt_vi_normal_string;
}
pub fn update_prompt_multiline(&mut self, prompt_multiline_indicator_string: Option<String>) {
self.default_multiline_indicator = prompt_multiline_indicator_string;
}
pub fn update_all_prompt_strings( pub fn update_all_prompt_strings(
&mut self, &mut self,
left_prompt_string: Option<String>, left_prompt_string: Option<String>,
@ -61,32 +90,6 @@ impl NushellPrompt {
self.render_right_prompt_on_last_line = render_right_prompt_on_last_line; 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<String>,
right_prompt_string: Option<String>,
prompt_indicator_string: Option<String>,
prompt_multiline_indicator_string: Option<String>,
prompt_vi: (Option<String>, Option<String>),
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 { fn default_wrapped_custom_string(&self, str: String) -> String {
format!("({str})") format!("({str})")
} }

View File

@ -7,6 +7,8 @@ use nu_protocol::{
Config, PipelineData, Value, Config, PipelineData, Value,
}; };
use reedline::Prompt; use reedline::Prompt;
use std::borrow::Cow;
use std::sync::Arc;
// Name of environment variable where the prompt could be stored // Name of environment variable where the prompt could be stored
pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND"; pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
@ -151,79 +153,118 @@ pub(crate) fn update_prompt<'prompt>(
ret_val ret_val
} }
pub(crate) fn make_transient_prompt( struct TransientPrompt {
engine_state: Arc<EngineState>,
stack: Stack,
}
/// Try getting `$env.TRANSIENT_PROMPT_<X>`, and get `$env.PROMPT_<X>` if that fails
fn get_transient_prompt_string(
transient_prompt: &str,
prompt: &str,
config: &Config, config: &Config,
engine_state: &EngineState, engine_state: &EngineState,
stack: &Stack, stack: &mut Stack,
nu_prompt: &NushellPrompt, ) -> Option<String> {
) -> Box<dyn Prompt> { get_prompt_string(transient_prompt, config, engine_state, stack)
let mut stack = stack.clone(); .or_else(|| get_prompt_string(prompt, config, engine_state, stack))
let mut nu_prompt = nu_prompt.clone(); }
let left_prompt_string = impl Prompt for TransientPrompt {
get_prompt_string(TRANSIENT_PROMPT_COMMAND, config, engine_state, &mut stack); fn render_prompt_left(&self) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
// Now that we have the prompt string lets ansify it. let config = &self.engine_state.get_config().clone();
// <133 A><prompt><133 B><command><133 C><command output> let mut stack = self.stack.clone();
let left_prompt_string = if config.shell_integration { nu_prompt.update_prompt_left(get_transient_prompt_string(
if let Some(prompt_string) = left_prompt_string { TRANSIENT_PROMPT_COMMAND,
Some(format!( PROMPT_COMMAND,
"{PRE_PROMPT_MARKER}{prompt_string}{POST_PROMPT_MARKER}" config,
)) &self.engine_state,
} else { &mut stack,
left_prompt_string ));
} nu_prompt.render_prompt_left().to_string().into()
} else { }
left_prompt_string
}; fn render_prompt_right(&self) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
let right_prompt_string = get_prompt_string( let config = &self.engine_state.get_config().clone();
TRANSIENT_PROMPT_COMMAND_RIGHT, let mut stack = self.stack.clone();
config, nu_prompt.update_prompt_right(
engine_state, get_transient_prompt_string(
&mut stack, TRANSIENT_PROMPT_COMMAND_RIGHT,
); PROMPT_COMMAND_RIGHT,
config,
let prompt_indicator_string = &self.engine_state,
get_prompt_string(TRANSIENT_PROMPT_INDICATOR, config, engine_state, &mut stack); &mut stack,
),
let prompt_multiline_string = get_prompt_string( config.render_right_prompt_on_last_line,
TRANSIENT_PROMPT_MULTILINE_INDICATOR, );
config, nu_prompt.render_prompt_right().to_string().into()
engine_state, }
&mut stack,
); fn render_prompt_indicator(&self, prompt_mode: reedline::PromptEditMode) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
let prompt_vi_insert_string = get_prompt_string( let config = &self.engine_state.get_config().clone();
TRANSIENT_PROMPT_INDICATOR_VI_INSERT, let mut stack = self.stack.clone();
config, nu_prompt.update_prompt_indicator(get_transient_prompt_string(
engine_state, TRANSIENT_PROMPT_INDICATOR,
&mut stack, PROMPT_INDICATOR,
); config,
&self.engine_state,
let prompt_vi_normal_string = get_prompt_string( &mut stack,
TRANSIENT_PROMPT_INDICATOR_VI_NORMAL, ));
config, nu_prompt.update_prompt_vi_insert(get_transient_prompt_string(
engine_state, TRANSIENT_PROMPT_INDICATOR_VI_INSERT,
&mut stack, PROMPT_INDICATOR_VI_INSERT,
); config,
&self.engine_state,
// apply the other indicators &mut stack,
nu_prompt.overlay_all_prompt_strings( ));
left_prompt_string, nu_prompt.update_prompt_vi_normal(get_transient_prompt_string(
right_prompt_string, TRANSIENT_PROMPT_INDICATOR_VI_NORMAL,
prompt_indicator_string, PROMPT_INDICATOR_VI_NORMAL,
prompt_multiline_string, config,
(prompt_vi_insert_string, prompt_vi_normal_string), &self.engine_state,
config.render_right_prompt_on_last_line, &mut stack,
); ));
nu_prompt
trace!( .render_prompt_indicator(prompt_mode)
"make_transient_prompt {}:{}:{}", .to_string()
file!(), .into()
line!(), }
column!()
); fn render_prompt_multiline_indicator(&self) -> Cow<str> {
let mut nu_prompt = NushellPrompt::new();
Box::new(nu_prompt) 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<str> {
NushellPrompt::new()
.render_prompt_history_search_indicator(history_search)
.to_string()
.into()
}
}
/// Construct the transient prompt
pub(crate) fn transient_prompt(engine_state: Arc<EngineState>, stack: &Stack) -> Box<dyn Prompt> {
Box::new(TransientPrompt {
engine_state,
stack: stack.clone(),
})
} }

View File

@ -267,7 +267,11 @@ pub fn evaluate_repl(
.with_quick_completions(config.quick_completions) .with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions) .with_partial_completions(config.partial_completions)
.with_ansi_colors(config.use_ansi_coloring) .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( perf(
"reedline builder", "reedline builder",
start_time, start_time,
@ -419,11 +423,8 @@ pub fn evaluate_repl(
); );
start_time = std::time::Instant::now(); start_time = std::time::Instant::now();
// Now we compute the prompt after running the hooks
let config = &engine_state.get_config().clone(); let config = &engine_state.get_config().clone();
prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt); let prompt = 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);
perf( perf(
"update_prompt", "update_prompt",
start_time, start_time,
@ -436,8 +437,7 @@ pub fn evaluate_repl(
entry_num += 1; entry_num += 1;
start_time = std::time::Instant::now(); start_time = std::time::Instant::now();
line_editor = line_editor.with_transient_prompt(transient_prompt); let input = line_editor.read_line(prompt);
let input = line_editor.read_line(&nu_prompt);
let shell_integration = config.shell_integration; let shell_integration = config.shell_integration;
match input { match input {