diff options
author | Aram Drevekenin <aram@poor.dev> | 2022-11-01 09:07:25 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-01 09:07:25 +0100 |
commit | abc700fc4d10d61c969ad94fa520d7d9336dcf14 (patch) | |
tree | a2e6318c4fe3951236cfa758befce8b95393a26e | |
parent | 6d29c6951e4768cc6f2f3c7b1bbb708d79d860c9 (diff) |
feat(command-panes): allow to start suspended (#1887)
* feat(command-panes): allow panes to start suspended
* style(fmt): remove unused code
* style(fmt): rustfmt
52 files changed, 668 insertions, 172 deletions
diff --git a/src/main.rs b/src/main.rs index 3ed592c53..6203f0f16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,7 @@ fn main() { floating, name, close_on_exit, + start_suspended, })) = opts.command { let command_cli_action = CliAction::NewPane { @@ -35,6 +36,7 @@ fn main() { floating, name, close_on_exit, + start_suspended, }; commands::send_action_to_session(command_cli_action, opts.session); std::process::exit(0); diff --git a/src/tests/e2e/cases.rs b/src/tests/e2e/cases.rs index 44551d997..359d74162 100644 --- a/src/tests/e2e/cases.rs +++ b/src/tests/e2e/cases.rs @@ -1915,6 +1915,25 @@ pub fn send_command_through_the_cli() { }, }) .add_step(Step { + name: "Initial run of suspended command", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.snapshot_contains("<Ctrl-c>") + && remote_terminal.cursor_position_is(0, 0) + // cursor does not appear in + // suspend_start panes + { + remote_terminal.send_key(&SPACE); // run script - here we use SPACE + // instead of the default ENTER because + // sending ENTER over SSH can be a little + // problematic (read: I couldn't get it + // to pass consistently) + step_is_complete = true + } + step_is_complete + }, + }) + .add_step(Step { name: "Wait for command to run", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; diff --git a/src/tests/e2e/remote_runner.rs b/src/tests/e2e/remote_runner.rs index dd2c800da..9b007989c 100644 --- a/src/tests/e2e/remote_runner.rs +++ b/src/tests/e2e/remote_runner.rs @@ -346,7 +346,8 @@ impl RemoteTerminal { let mut channel = self.channel.lock().unwrap(); channel .write_all( - format!("{} run -- \"{}\"\n", ZELLIJ_EXECUTABLE_LOCATION, command).as_bytes(), + // note that this is run with the -s flag that suspends the command on startup + format!("{} run -s -- \"{}\"\n", ZELLIJ_EXECUTABLE_LOCATION, command).as_bytes(), ) .unwrap(); channel.flush().unwrap(); diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_command_through_the_cli.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_command_through_the_cli.snap index 84d33a037..0603ac26e 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_command_through_the_cli.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_command_through_the_cli.snap @@ -1,14 +1,14 @@ --- source: src/tests/e2e/cases.rs -assertion_line: 1968 +assertion_line: 1998 expression: last_snapshot --- Zellij (e2e-test) Tab #1 ┌ Pane #1 ─────────────────────────────────────────────────┐┌ /usr/src/zellij/fixtures/append-echo-script.sh ──────────┐ │$ /usr/src/zellij/x86_64-unknown-linux-musl/release/zellij││foo │ -│ run -- "/usr/src/zellij/fixtures/append-echo-script.sh" ││foo │ -│$ ││█ │ -│ ││ │ +│ run -s -- "/usr/src/zellij/fixtures/append-echo-script.sh││foo │ +│" ││█ │ +│$ ││ │ │ ││ │ │ ││ │ │ ││ │ diff --git a/zellij-server/src/os_input_output.rs b/zellij-server/src/os_input_output.rs index 9a8ce0088..02f53dbe5 100644 --- a/zellij-server/src/os_input_output.rs +++ b/zellij-server/src/os_input_output.rs @@ -280,6 +280,7 @@ fn spawn_terminal( args, cwd: None, hold_on_close: false, + hold_on_start: false, } }, TerminalAction::RunCommand(command) => command, @@ -381,6 +382,10 @@ pub trait ServerOsApi: Send + Sync { quit_cb: Box<dyn Fn(PaneId, Option<i32>, RunCommand) + Send>, // u32 is the exit status default_editor: Option<PathBuf>, ) -> Result<(u32, RawFd, RawFd), SpawnTerminalError>; + // reserves a terminal id without actually opening a terminal + fn reserve_terminal_id(&self) -> Result<u32, SpawnTerminalError> { + unimplemented!() + } /// Read bytes from the standard output of the virtual terminal referred to by `fd`. fn read_from_tty_stdout(&self, fd: RawFd, buf: &mut [u8]) -> Result<usize, nix::Error>; /// Creates an `AsyncReader` that can be used to read from `fd` in an async context @@ -484,6 +489,35 @@ impl ServerOsApi for ServerOsInputOutput { None => Err(SpawnTerminalError::NoMoreTerminalIds), } } + fn reserve_terminal_id(&self) -> Result<u32, SpawnTerminalError> { + let mut terminal_id = None; + { + let current_ids: HashSet<u32> = self + .terminal_id_to_raw_fd + .lock() + .unwrap() + .keys() + .copied() + .collect(); + for i in 0..u32::MAX { + let i = i as u32; + if !current_ids.contains(&i) { + terminal_id = Some(i); + break; + } + } + } + match terminal_id { + Some(terminal_id) => { + self.terminal_id_to_raw_fd + .lock() + .unwrap() + .insert(terminal_id, None); + Ok(terminal_id) + }, + None => Err(SpawnTerminalError::NoMoreTerminalIds), + } + } fn read_from_tty_stdout(&self, fd: RawFd, buf: &mut [u8]) -> Result<usize, nix::Error> { unistd::read(fd, buf) } diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs index f686f40bb..d17be7557 100644 --- a/zellij-server/src/panes/floating_panes/mod.rs +++ b/zellij-server/src/panes/floating_panes/mod.rs @@ -156,11 +156,12 @@ impl FloatingPanes { &mut self, pane_id: PaneId, exit_status: Option<i32>, + is_first_run: bool, run_command: RunCommand, ) { self.panes .get_mut(&pane_id) - .map(|p| p.hold(exit_status, run_command)); + .map(|p| p.hold(exit_status, is_first_run, run_command)); } pub fn get(&self, pane_id: &PaneId) -> Option<&Box<dyn Pane>> { self.panes.get(pane_id) diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index 67a882fb4..d9d60fefe 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -1533,6 +1533,7 @@ impl Grid { self.sixel_scrolling = false; self.mouse_mode = MouseMode::NoEncoding; self.mouse_tracking = MouseTracking::Off; + self.cursor_is_hidden = false; if let Some(images_to_reap) = self.sixel_grid.clear() { self.sixel_grid.reap_images(images_to_reap); } diff --git a/zellij-server/src/panes/terminal_character.rs b/zellij-server/src/panes/terminal_character.rs index c6fa0adf1..68813e7a9 100644 --- a/zellij-server/src/panes/terminal_character.rs +++ b/zellij-server/src/panes/terminal_character.rs @@ -3,7 +3,12 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::ops::{Index, IndexMut}; use unicode_width::UnicodeWidthChar; -use zellij_utils::{data::PaletteColor, vte::ParamsIter}; +use unicode_width::UnicodeWidthStr; +use zellij_utils::input::command::RunCommand; +use zellij_utils::{ + data::{PaletteColor, Style}, + vte::ParamsIter, +}; use crate::panes::alacritty_functions::parse_sgr_color; @@ -736,3 +741,113 @@ impl ::std::fmt::Debug for TerminalCharacter { write!(f, "{}", self.character) } } + +pub fn render_first_run_banner( + columns: usize, + rows: usize, + style: &Style, + run_command: Option<&RunCommand>, +) -> String { + let middle_row = rows / 2; + let middle_column = columns / 2; + match run_command { + Some(run_command) => { + let bold_text = RESET_STYLES.bold(Some(AnsiCode::On)); + let command_color_text = RESET_STYLES + .foreground(Some(AnsiCode::from(style.colors.green))) + .bold(Some(AnsiCode::On)); + let waiting_to_run_text = "Waiting to run: "; + let command_text = run_command.to_string(); + let waiting_to_run_text_width = waiting_to_run_text.width() + command_text.width(); + let column_start_postion = middle_column.saturating_sub(waiting_to_run_text_width / 2); + let waiting_to_run_line = format!( + "\u{1b}[{};{}H{}{}{}{}{}", + middle_row, + column_start_postion, + bold_text, + waiting_to_run_text, + command_color_text, + command_text, + RESET_STYLES + ); + + let controls_bare_text_first_part = "<"; + let enter_bare_text = "ENTER"; + let controls_bare_text_second_part = "> to run, <"; + let ctrl_c_bare_text = "Ctrl-c"; + let controls_bare_text_third_part = "> to exit"; + let controls_color = RESET_STYLES + .foreground(Some(AnsiCode::from(style.colors.orange))) + .bold(Some(AnsiCode::On)); + let controls_line_length = controls_bare_text_first_part.len() + + enter_bare_text.len() + + controls_bare_text_second_part.len() + + ctrl_c_bare_text.len() + + controls_bare_text_third_part.len(); |