mirror of
https://github.com/nushell/nushell
synced 2024-12-29 06:23:11 +00:00
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
3 changed files with 102 additions and 146 deletions
|
@ -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(
|
pub fn update_all_prompt_strings(
|
||||||
&mut self,
|
&mut self,
|
||||||
left_prompt_string: Option<String>,
|
left_prompt_string: Option<String>,
|
||||||
|
@ -90,6 +61,32 @@ 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})")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,6 @@ 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";
|
||||||
|
@ -153,118 +151,79 @@ pub(crate) fn update_prompt<'prompt>(
|
||||||
ret_val
|
ret_val
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TransientPrompt {
|
pub(crate) fn make_transient_prompt(
|
||||||
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: &mut Stack,
|
stack: &Stack,
|
||||||
) -> Option<String> {
|
nu_prompt: &NushellPrompt,
|
||||||
get_prompt_string(transient_prompt, config, engine_state, stack)
|
) -> Box<dyn Prompt> {
|
||||||
.or_else(|| get_prompt_string(prompt, config, engine_state, stack))
|
let mut stack = stack.clone();
|
||||||
}
|
let mut nu_prompt = nu_prompt.clone();
|
||||||
|
|
||||||
impl Prompt for TransientPrompt {
|
let left_prompt_string =
|
||||||
fn render_prompt_left(&self) -> Cow<str> {
|
get_prompt_string(TRANSIENT_PROMPT_COMMAND, config, engine_state, &mut stack);
|
||||||
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> {
|
// Now that we have the prompt string lets ansify it.
|
||||||
let mut nu_prompt = NushellPrompt::new();
|
// <133 A><prompt><133 B><command><133 C><command output>
|
||||||
let config = &self.engine_state.get_config().clone();
|
let left_prompt_string = if config.shell_integration {
|
||||||
let mut stack = self.stack.clone();
|
if let Some(prompt_string) = left_prompt_string {
|
||||||
nu_prompt.update_prompt_right(
|
Some(format!(
|
||||||
get_transient_prompt_string(
|
"{PRE_PROMPT_MARKER}{prompt_string}{POST_PROMPT_MARKER}"
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
left_prompt_string
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
left_prompt_string
|
||||||
|
};
|
||||||
|
|
||||||
|
let right_prompt_string = get_prompt_string(
|
||||||
TRANSIENT_PROMPT_COMMAND_RIGHT,
|
TRANSIENT_PROMPT_COMMAND_RIGHT,
|
||||||
PROMPT_COMMAND_RIGHT,
|
|
||||||
config,
|
config,
|
||||||
&self.engine_state,
|
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_prompt_indicator(&self, prompt_mode: reedline::PromptEditMode) -> Cow<str> {
|
trace!(
|
||||||
let mut nu_prompt = NushellPrompt::new();
|
"make_transient_prompt {}:{}:{}",
|
||||||
let config = &self.engine_state.get_config().clone();
|
file!(),
|
||||||
let mut stack = self.stack.clone();
|
line!(),
|
||||||
nu_prompt.update_prompt_indicator(get_transient_prompt_string(
|
column!()
|
||||||
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> {
|
Box::new(nu_prompt)
|
||||||
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(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,11 +267,7 @@ 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,
|
||||||
|
@ -423,8 +419,11 @@ 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();
|
||||||
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(
|
perf(
|
||||||
"update_prompt",
|
"update_prompt",
|
||||||
start_time,
|
start_time,
|
||||||
|
@ -437,7 +436,8 @@ pub fn evaluate_repl(
|
||||||
entry_num += 1;
|
entry_num += 1;
|
||||||
|
|
||||||
start_time = std::time::Instant::now();
|
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;
|
let shell_integration = config.shell_integration;
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
|
|
Loading…
Reference in a new issue