add osc633e (#13625)

# Description

This PR adds OSC 633E for vscode users to enable `Terminal: Run Recent
Command` with ctrl-shift-p.


![image](https://github.com/user-attachments/assets/21b92206-3c44-4060-aa0b-78718c099336)
This commit is contained in:
Darren Schroeder 2024-08-15 00:40:34 -05:00 committed by GitHub
parent 31b3104af7
commit 04746b8e2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 70 additions and 11 deletions

View File

@ -46,7 +46,10 @@ pub(crate) const VSCODE_POST_EXECUTION_MARKER_PREFIX: &str = "\x1b]633;D;";
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) const VSCODE_POST_EXECUTION_MARKER_SUFFIX: &str = "\x1b\\"; pub(crate) const VSCODE_POST_EXECUTION_MARKER_SUFFIX: &str = "\x1b\\";
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) const VSCODE_COMMANDLINE_MARKER: &str = "\x1b]633;E\x1b\\"; //"\x1b]633;E;{}\x1b\\"
pub(crate) const VSCODE_COMMANDLINE_MARKER_PREFIX: &str = "\x1b]633;E;";
#[allow(dead_code)]
pub(crate) const VSCODE_COMMANDLINE_MARKER_SUFFIX: &str = "\x1b\\";
#[allow(dead_code)] #[allow(dead_code)]
// "\x1b]633;P;Cwd={}\x1b\\" // "\x1b]633;P;Cwd={}\x1b\\"
pub(crate) const VSCODE_CWD_PROPERTY_MARKER_PREFIX: &str = "\x1b]633;P;Cwd="; pub(crate) const VSCODE_CWD_PROPERTY_MARKER_PREFIX: &str = "\x1b]633;P;Cwd=";

View File

@ -1,6 +1,7 @@
use crate::prompt_update::{ use crate::prompt_update::{
POST_EXECUTION_MARKER_PREFIX, POST_EXECUTION_MARKER_SUFFIX, PRE_EXECUTION_MARKER, POST_EXECUTION_MARKER_PREFIX, POST_EXECUTION_MARKER_SUFFIX, PRE_EXECUTION_MARKER,
RESET_APPLICATION_MODE, VSCODE_CWD_PROPERTY_MARKER_PREFIX, VSCODE_CWD_PROPERTY_MARKER_SUFFIX, RESET_APPLICATION_MODE, VSCODE_COMMANDLINE_MARKER_PREFIX, VSCODE_COMMANDLINE_MARKER_SUFFIX,
VSCODE_CWD_PROPERTY_MARKER_PREFIX, VSCODE_CWD_PROPERTY_MARKER_SUFFIX,
VSCODE_POST_EXECUTION_MARKER_PREFIX, VSCODE_POST_EXECUTION_MARKER_SUFFIX, VSCODE_POST_EXECUTION_MARKER_PREFIX, VSCODE_POST_EXECUTION_MARKER_SUFFIX,
VSCODE_PRE_EXECUTION_MARKER, VSCODE_PRE_EXECUTION_MARKER,
}; };
@ -131,7 +132,26 @@ pub fn evaluate_repl(
run_shell_integration_osc9_9(engine_state, &mut unique_stack, use_color); run_shell_integration_osc9_9(engine_state, &mut unique_stack, use_color);
} }
if shell_integration_osc633 { if shell_integration_osc633 {
run_shell_integration_osc633(engine_state, &mut unique_stack, use_color); // escape a few things because this says so
// https://code.visualstudio.com/docs/terminal/shell-integration#_vs-code-custom-sequences-osc-633-st
let cmd_text = line_editor.current_buffer_contents().to_string();
let replaced_cmd_text = cmd_text
.chars()
.map(|c| match c {
'\n' => '\x0a',
'\r' => '\x0d',
'\x1b' => '\x1b',
_ => c,
})
.collect();
run_shell_integration_osc633(
engine_state,
&mut unique_stack,
use_color,
replaced_cmd_text,
);
} }
engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64); engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64);
@ -452,14 +472,19 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
let line_editor_input_time = std::time::Instant::now(); let line_editor_input_time = std::time::Instant::now();
match input { match input {
Ok(Signal::Success(s)) => { Ok(Signal::Success(repl_cmd_line_text)) => {
let history_supports_meta = matches!( let history_supports_meta = matches!(
engine_state.history_config().map(|h| h.file_format), engine_state.history_config().map(|h| h.file_format),
Some(HistoryFileFormat::Sqlite) Some(HistoryFileFormat::Sqlite)
); );
if history_supports_meta { if history_supports_meta {
prepare_history_metadata(&s, hostname, engine_state, &mut line_editor); prepare_history_metadata(
&repl_cmd_line_text,
hostname,
engine_state,
&mut line_editor,
);
} }
// For pre_exec_hook // For pre_exec_hook
@ -470,7 +495,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
if let Some(hook) = config.hooks.pre_execution.clone() { if let Some(hook) = config.hooks.pre_execution.clone() {
// Set the REPL buffer to the current command for the "pre_execution" hook // Set the REPL buffer to the current command for the "pre_execution" hook
let mut repl = engine_state.repl_state.lock().expect("repl state mutex"); let mut repl = engine_state.repl_state.lock().expect("repl state mutex");
repl.buffer = s.to_string(); repl.buffer = repl_cmd_line_text.to_string();
drop(repl); drop(repl);
if let Err(err) = eval_hook( if let Err(err) = eval_hook(
@ -531,7 +556,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
// Actual command execution logic starts from here // Actual command execution logic starts from here
let cmd_execution_start_time = Instant::now(); let cmd_execution_start_time = Instant::now();
match parse_operation(s.clone(), engine_state, &stack) { match parse_operation(repl_cmd_line_text.clone(), engine_state, &stack) {
Ok(operation) => match operation { Ok(operation) => match operation {
ReplOperation::AutoCd { cwd, target, span } => { ReplOperation::AutoCd { cwd, target, span } => {
do_auto_cd(target, cwd, &mut stack, engine_state, span); do_auto_cd(target, cwd, &mut stack, engine_state, span);
@ -577,7 +602,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
if history_supports_meta { if history_supports_meta {
if let Err(e) = fill_in_result_related_history_metadata( if let Err(e) = fill_in_result_related_history_metadata(
&s, &repl_cmd_line_text,
engine_state, engine_state,
cmd_duration, cmd_duration,
&mut stack, &mut stack,
@ -597,7 +622,12 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
run_shell_integration_osc9_9(engine_state, &mut stack, use_color); run_shell_integration_osc9_9(engine_state, &mut stack, use_color);
} }
if shell_integration_osc633 { if shell_integration_osc633 {
run_shell_integration_osc633(engine_state, &mut stack, use_color); run_shell_integration_osc633(
engine_state,
&mut stack,
use_color,
repl_cmd_line_text,
);
} }
if shell_integration_reset_application_mode { if shell_integration_reset_application_mode {
run_shell_integration_reset_application_mode(); run_shell_integration_reset_application_mode();
@ -993,7 +1023,12 @@ fn run_shell_integration_osc9_9(engine_state: &EngineState, stack: &mut Stack, u
} }
} }
fn run_shell_integration_osc633(engine_state: &EngineState, stack: &mut Stack, use_color: bool) { fn run_shell_integration_osc633(
engine_state: &EngineState,
stack: &mut Stack,
use_color: bool,
repl_cmd_line_text: String,
) {
#[allow(deprecated)] #[allow(deprecated)]
if let Ok(path) = current_dir_str(engine_state, stack) { if let Ok(path) = current_dir_str(engine_state, stack) {
// Supported escape sequences of Microsoft's Visual Studio Code (vscode) // Supported escape sequences of Microsoft's Visual Studio Code (vscode)
@ -1013,6 +1048,27 @@ fn run_shell_integration_osc633(engine_state: &EngineState, stack: &mut Stack, u
start_time, start_time,
use_color use_color
); );
// escape a few things because this says so
// https://code.visualstudio.com/docs/terminal/shell-integration#_vs-code-custom-sequences-osc-633-st
let replaced_cmd_text: String = repl_cmd_line_text
.chars()
.map(|c| match c {
'\n' => '\x0a',
'\r' => '\x0d',
'\x1b' => '\x1b',
_ => c,
})
.collect();
//OSC 633 ; E ; <commandline> [; <nonce] ST - Explicitly set the command line with an optional nonce.
run_ansi_sequence(&format!(
"{}{}{}",
VSCODE_COMMANDLINE_MARKER_PREFIX,
replaced_cmd_text,
VSCODE_COMMANDLINE_MARKER_SUFFIX
));
} }
} }
} }

View File

@ -255,7 +255,7 @@ $env.config = {
# 633;B - Mark prompt end # 633;B - Mark prompt end
# 633;C - Mark pre-execution # 633;C - Mark pre-execution
# 633;D;exit - Mark execution finished with exit code # 633;D;exit - Mark execution finished with exit code
# 633;E - NOT IMPLEMENTED - Explicitly set the command line with an optional nonce # 633;E - Explicitly set the command line with an optional nonce
# 633;P;Cwd=<path> - Mark the current working directory and communicate it to the terminal # 633;P;Cwd=<path> - Mark the current working directory and communicate it to the terminal
# and also helps with the run recent menu in vscode # and also helps with the run recent menu in vscode
osc633: true osc633: true