forked from extern/nushell
Only run $env.PROMPT_COMMAND once per prompt (#10986)
# Description If `$env.TRANSIENT_PROMPT_COMMAND` is not set, use the prompt created by `$env.PROMPT_COMMAND` instead of running the command a second time. As a side effect, `$env.TRANSIENT_PROMPT_COMMAND` now runs after the hooks `pre_prompt` and `env_change`, instead of before. # User-Facing Changes - `$env.PROMPT_COMMAND` gets run only once per prompt instead of twice - `$env.TRANSIENT_PROMPT_COMMAND` now sees any environment set in a `pre_prompt` or `env_change` hook, like `$env.PROMPT_COMMAND` does
This commit is contained in:
parent
84742275a1
commit
533c1a89af
@ -39,35 +39,6 @@ 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(
|
||||
&mut self,
|
||||
left_prompt_string: Option<String>,
|
||||
@ -90,6 +61,32 @@ 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<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 {
|
||||
format!("({str})")
|
||||
}
|
||||
|
@ -7,8 +7,6 @@ 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";
|
||||
@ -153,118 +151,79 @@ pub(crate) fn update_prompt<'prompt>(
|
||||
ret_val
|
||||
}
|
||||
|
||||
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,
|
||||
pub(crate) fn make_transient_prompt(
|
||||
config: &Config,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
) -> Option<String> {
|
||||
get_prompt_string(transient_prompt, config, engine_state, stack)
|
||||
.or_else(|| get_prompt_string(prompt, config, engine_state, stack))
|
||||
}
|
||||
stack: &Stack,
|
||||
nu_prompt: &NushellPrompt,
|
||||
) -> Box<dyn Prompt> {
|
||||
let mut stack = stack.clone();
|
||||
let mut nu_prompt = nu_prompt.clone();
|
||||
|
||||
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()
|
||||
}
|
||||
let left_prompt_string =
|
||||
get_prompt_string(TRANSIENT_PROMPT_COMMAND, config, engine_state, &mut stack);
|
||||
|
||||
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,
|
||||
PROMPT_COMMAND_RIGHT,
|
||||
config,
|
||||
&self.engine_state,
|
||||
&mut stack,
|
||||
),
|
||||
config.render_right_prompt_on_last_line,
|
||||
);
|
||||
nu_prompt.render_prompt_right().to_string().into()
|
||||
}
|
||||
// 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
|
||||
};
|
||||
|
||||
fn render_prompt_indicator(&self, prompt_mode: reedline::PromptEditMode) -> 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_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<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 {
|
||||
let right_prompt_string = get_prompt_string(
|
||||
TRANSIENT_PROMPT_COMMAND_RIGHT,
|
||||
config,
|
||||
engine_state,
|
||||
stack: stack.clone(),
|
||||
})
|
||||
&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)
|
||||
}
|
||||
|
@ -267,11 +267,7 @@ 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_transient_prompt(prompt_update::transient_prompt(
|
||||
engine_reference.clone(),
|
||||
stack,
|
||||
));
|
||||
.with_cursor_config(cursor_config);
|
||||
perf(
|
||||
"reedline builder",
|
||||
start_time,
|
||||
@ -423,8 +419,11 @@ 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();
|
||||
let prompt = prompt_update::update_prompt(config, engine_state, stack, &mut nu_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(
|
||||
"update_prompt",
|
||||
start_time,
|
||||
@ -437,7 +436,8 @@ pub fn evaluate_repl(
|
||||
entry_num += 1;
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
let input = line_editor.read_line(prompt);
|
||||
line_editor = line_editor.with_transient_prompt(transient_prompt);
|
||||
let input = line_editor.read_line(&nu_prompt);
|
||||
let shell_integration = config.shell_integration;
|
||||
|
||||
match input {
|
||||
|
Loading…
Reference in New Issue
Block a user