From 8eab3115654f7a799f5805c91c54e087d5d28e7b Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Sat, 23 Apr 2022 19:53:12 -0500 Subject: [PATCH] consolidate shell integration behind config setting (#5302) * consolidate shell integration behind config setting * write output differently --- crates/nu-cli/src/prompt.rs | 7 +++++-- crates/nu-cli/src/prompt_update.rs | 2 +- crates/nu-cli/src/repl.rs | 27 +++++++++++++++++++++------ crates/nu-protocol/src/config.rs | 10 ++++++++++ docs/sample_config/default_config.nu | 1 + 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/crates/nu-cli/src/prompt.rs b/crates/nu-cli/src/prompt.rs index 361baec682..487d2a4243 100644 --- a/crates/nu-cli/src/prompt.rs +++ b/crates/nu-cli/src/prompt.rs @@ -7,6 +7,9 @@ use { std::borrow::Cow, }; +const PROMPT_MARKER_BEFORE_PS1: &str = "\x1b]133;A\x1b\\"; // OSC 133;A ST +const PROMPT_MARKER_BEFORE_PS2: &str = "\x1b]133;A;k=s\x1b\\"; // OSC 133;A;k=s ST + /// Nushell prompt definition #[derive(Clone)] pub struct NushellPrompt { @@ -95,7 +98,7 @@ impl Prompt for NushellPrompt { // 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\\") + String::from(PROMPT_MARKER_BEFORE_PS1) } else { String::new() }; @@ -155,7 +158,7 @@ impl Prompt for NushellPrompt { // 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\\") + String::from(PROMPT_MARKER_BEFORE_PS2) } else { String::new() }; diff --git a/crates/nu-cli/src/prompt_update.rs b/crates/nu-cli/src/prompt_update.rs index ecaafdf543..1b10cffae4 100644 --- a/crates/nu-cli/src/prompt_update.rs +++ b/crates/nu-cli/src/prompt_update.rs @@ -147,7 +147,7 @@ pub(crate) fn update_prompt<'prompt>( (prompt_vi_insert_string, prompt_vi_normal_string), ); - if config.use_ansi_coloring { + if config.shell_integration { nu_prompt.enable_shell_integration(); } diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index d45b6fb4c1..8a86aba86c 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -18,9 +18,13 @@ use nu_protocol::{ ShellError, Span, Value, }; use reedline::{DefaultHinter, Emacs, Vi}; +use std::io::{self, Write}; use std::path::PathBuf; use std::{sync::atomic::Ordering, time::Instant}; +const PROMPT_MARKER_BEFORE_CMD: &str = "\x1b]133;C\x1b\\"; // OSC 133;C ST +const RESET_APPLICATION_MODE: &str = "\x1b[?1l"; + pub fn evaluate_repl( engine_state: &mut EngineState, stack: &mut Stack, @@ -209,12 +213,7 @@ 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\\"); - } + let use_shell_integration = config.shell_integration; match input { Ok(Signal::Success(s)) => { @@ -305,6 +304,22 @@ pub fn evaluate_repl( let _ = std::env::set_current_dir(path); engine_state.env_vars.insert("PWD".into(), cwd); } + + if use_shell_integration { + // Just before running a command/program, send the escape code (see + // https://sw.kovidgoyal.net/kitty/shell-integration/#notes-for-shell-developers) + let mut ansi_escapes = String::from(PROMPT_MARKER_BEFORE_CMD); + ansi_escapes.push_str(RESET_APPLICATION_MODE); + if let Some(cwd) = stack.get_env_var(engine_state, "PWD") { + let path = cwd.as_string()?; + ansi_escapes.push_str(&format!("\x1b]2;{}\x07", path)); + } + // print!("{}", ansi_escapes); + match io::stdout().write_all(ansi_escapes.as_bytes()) { + Ok(it) => it, + Err(err) => print!("error: {}", err), + }; + } } Ok(Signal::CtrlC) => { // `Reedline` clears the line content. New prompt is shown diff --git a/crates/nu-protocol/src/config.rs b/crates/nu-protocol/src/config.rs index 1c115669a5..d2cff3ff08 100644 --- a/crates/nu-protocol/src/config.rs +++ b/crates/nu-protocol/src/config.rs @@ -45,6 +45,7 @@ pub struct Config { pub keybindings: Vec, pub menus: Vec, pub rm_always_trash: bool, + pub shell_integration: bool, } impl Default for Config { @@ -69,6 +70,7 @@ impl Default for Config { keybindings: Vec::new(), menus: Vec::new(), rm_always_trash: false, + shell_integration: false, } } } @@ -236,6 +238,14 @@ impl Value { eprintln!("{:?}", e); } }, + "shell_integration" => { + if let Ok(b) = value.as_bool() { + config.shell_integration = b; + } else { + eprintln!("$config.shell_integration is not a bool") + } + } + x => { eprintln!("$config.{} is an unknown config setting", x) } diff --git a/docs/sample_config/default_config.nu b/docs/sample_config/default_config.nu index f4c681cabc..0d5b9bacf0 100644 --- a/docs/sample_config/default_config.nu +++ b/docs/sample_config/default_config.nu @@ -194,6 +194,7 @@ let-env config = { edit_mode: emacs # emacs, vi max_history_size: 10000 # Session has to be reloaded for this to take effect sync_history_on_enter: true # Enable to share the history between multiple sessions, else you have to close the session to persist history to file + shell_integration: true # enables terminal markers and a workaround to arrow keys stop working issue menus: [ # Configuration for default nushell menus # Note the lack of souce parameter