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 =
get_prompt_string(TRANSIENT_PROMPT_COMMAND, config, engine_state, &mut stack);
// Now that we have the prompt string lets ansify it.
// <133 A><prompt><133 B><command><133 C><command output>
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( impl Prompt for TransientPrompt {
fn render_prompt_left(&self) -> Cow<str> {
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<str> {
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, TRANSIENT_PROMPT_COMMAND_RIGHT,
PROMPT_COMMAND_RIGHT,
config, config,
engine_state, &self.engine_state,
&mut stack, &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, config.render_right_prompt_on_last_line,
); );
nu_prompt.render_prompt_right().to_string().into()
trace!( }
"make_transient_prompt {}:{}:{}",
file!(), fn render_prompt_indicator(&self, prompt_mode: reedline::PromptEditMode) -> Cow<str> {
line!(), let mut nu_prompt = NushellPrompt::new();
column!() let config = &self.engine_state.get_config().clone();
); let mut stack = self.stack.clone();
nu_prompt.update_prompt_indicator(get_transient_prompt_string(
Box::new(nu_prompt) 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<str> {
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<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 {