Shell Integration (#5162)

This commit renders ANSI chars in order to provide shell integrations
such Kitty's opening feature that captures the output of the last
command in a pager such as less.

Fixes #5138
This commit is contained in:
Marc Schreiber 2022-04-17 05:03:02 +02:00 committed by GitHub
parent 6e85b04923
commit a35b975d84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 13 deletions

View File

@ -16,6 +16,7 @@ pub struct NushellPrompt {
default_vi_insert_prompt_indicator: Option<String>,
default_vi_normal_prompt_indicator: Option<String>,
default_multiline_indicator: Option<String>,
shell_integration: bool,
}
impl Default for NushellPrompt {
@ -33,6 +34,7 @@ impl NushellPrompt {
default_vi_insert_prompt_indicator: None,
default_vi_normal_prompt_indicator: None,
default_multiline_indicator: None,
shell_integration: false,
}
}
@ -82,20 +84,34 @@ impl NushellPrompt {
fn default_wrapped_custom_string(&self, str: String) -> String {
format!("({})", str)
}
pub(crate) fn enable_shell_integration(&mut self) {
self.shell_integration = true
}
}
impl Prompt for NushellPrompt {
fn render_prompt_left(&self) -> Cow<str> {
if let Some(prompt_string) = &self.left_prompt_string {
prompt_string.replace('\n', "\r\n").into()
// Just before starting to draw the PS1 prompt send the escape code (see
// https://sw.kovidgoyal.net/kitty/shell-integration/#notes-for-shell-developers)
let mut prompt = if self.shell_integration {
String::from("\x1b]133;A\x1b\\")
} else {
let default = DefaultPrompt::new();
default
.render_prompt_left()
.to_string()
.replace('\n', "\r\n")
.into()
}
String::new()
};
prompt.push_str(&match &self.left_prompt_string {
Some(prompt_string) => prompt_string.replace('\n', "\r\n"),
None => {
let default = DefaultPrompt::new();
default
.render_prompt_left()
.to_string()
.replace('\n', "\r\n")
}
});
prompt.into()
}
fn render_prompt_right(&self) -> Cow<str> {
@ -136,10 +152,21 @@ impl Prompt for NushellPrompt {
}
fn render_prompt_multiline_indicator(&self) -> Cow<str> {
match &self.default_multiline_indicator {
Some(indicator) => indicator.as_str().into(),
None => "::: ".into(),
}
// Just before starting to draw the PS1 prompt send the escape code (see
// https://sw.kovidgoyal.net/kitty/shell-integration/#notes-for-shell-developers)
let mut prompt = if self.shell_integration {
String::from("\x1b]133;A;k=s\x1b\\")
} else {
String::new()
};
prompt.push_str(
self.default_multiline_indicator
.as_ref()
.unwrap_or(&String::from("::: ")),
);
prompt.into()
}
fn render_prompt_history_search_indicator(

View File

@ -147,6 +147,10 @@ pub(crate) fn update_prompt<'prompt>(
(prompt_vi_insert_string, prompt_vi_normal_string),
);
if config.use_ansi_coloring {
nu_prompt.enable_shell_integration();
}
let ret_val = nu_prompt as &dyn Prompt;
if is_perf_true {
info!("update_prompt {}:{}:{}", file!(), line!(), column!());

View File

@ -231,6 +231,13 @@ pub fn evaluate_repl(
}
let input = line_editor.read_line(prompt);
if config.use_ansi_coloring {
// Just before running a command/program, send the escape code (see
// https://sw.kovidgoyal.net/kitty/shell-integration/#notes-for-shell-developers)
print!("\x1b]133;C\x1b\\");
}
match input {
Ok(Signal::Success(s)) => {
let start_time = Instant::now();