feat(panes): Add an option to press <ESC> and drop to shell in command panes (#2872)

* feat(panes): ESC to drop to default shell on command panes

* style(fmt): rustfmt
This commit is contained in:
Aram Drevekenin 2023-10-17 11:55:38 +02:00 committed by GitHub
parent 8378f146c1
commit 69eb904426
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 194 additions and 82 deletions

View file

@ -2070,7 +2070,7 @@ pub fn send_command_through_the_cli() {
// so when we press "Enter", it will run again and we'll see two "foo"s one after the other, // so when we press "Enter", it will run again and we'll see two "foo"s one after the other,
// that's how we know the whole flow is working // that's how we know the whole flow is working
let fake_win_size = Size { let fake_win_size = Size {
cols: 120, cols: 150,
rows: 24, rows: 24,
}; };
let mut test_attempts = 10; let mut test_attempts = 10;
@ -2118,7 +2118,7 @@ pub fn send_command_through_the_cli() {
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.snapshot_contains("<Ctrl-c>") if remote_terminal.snapshot_contains("<Ctrl-c>")
&& remote_terminal.cursor_position_is(61, 3) && remote_terminal.cursor_position_is(76, 3)
{ {
remote_terminal.send_key(&SPACE); // re-run script - here we use SPACE remote_terminal.send_key(&SPACE); // re-run script - here we use SPACE
// instead of the default ENTER because // instead of the default ENTER because
@ -2135,7 +2135,7 @@ pub fn send_command_through_the_cli() {
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.snapshot_contains("<Ctrl-c>") if remote_terminal.snapshot_contains("<Ctrl-c>")
&& remote_terminal.cursor_position_is(61, 4) && remote_terminal.cursor_position_is(76, 4)
{ {
step_is_complete = true step_is_complete = true
} }
@ -2149,7 +2149,7 @@ pub fn send_command_through_the_cli() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.snapshot_contains("foo") if remote_terminal.snapshot_contains("foo")
&& remote_terminal.cursor_position_is(61, 4) && remote_terminal.cursor_position_is(76, 4)
{ {
step_is_complete = true step_is_complete = true
} }

View file

@ -17,10 +17,10 @@ expression: last_snapshot
│ │ │ │ │────────────────────────────┘ │ │ │ │ │────────────────────────────┘
│ │ │ Waiting to run: top │ │────────────────────────────┐ │ │ │ Waiting to run: top │ │────────────────────────────┐
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │ <ENTER> to run, <Ctrl-c> to exit │ │ │ │ │ │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │ │
│ └─│ │ │ │ │ └─│ │ │ │
│ │ │ │ │ │ │ │ │ │
│ └─ <ENTER> to run, <Ctrl-c> to exit ─────────────────────┘ │ │ │ └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ──────┘ │ │
│ │ │ │ │ │ │ │
│ └────────────────────────────────────────────────────────┘ │ │ └────────────────────────────────────────────────────────┘ │
│ ││ │ │ ││ │

View file

@ -17,10 +17,10 @@ expression: last_snapshot
│ │ │ │ │────────────────────────────┘ │ │ │ │ │────────────────────────────┘
│ │ │ Waiting to run: top │ │────────────────────────────┐ │ │ │ Waiting to run: top │ │────────────────────────────┐
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │ <ENTER> to run, <Ctrl-c> to exit │ │ │ │ │ │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │ │
│ └─│ │ │ │ │ └─│ │ │ │
│ │ │ │ │ │ │ │ │ │
│ └─ <ENTER> to run, <Ctrl-c> to exit ─────────────────────┘ │ │ │ └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ──────┘ │ │
│ │ │ │ │ │ │ │
│ └────────────────────────────────────────────────────────┘ │ │ └────────────────────────────────────────────────────────┘ │
│ ││ │ │ ││ │

View file

@ -1,29 +1,29 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 2031 assertion_line: 2175
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
┌ Pane #1 ─────────────────────────────────────────────────┐┌ /usr/src/zellij/fixtures/append-echo-script.sh ──────────┐ ┌ Pane #1 ────────────────────────────────────────────────────────────────┐┌ /usr/src/zellij/fixtures/append-echo-script.sh ─────────────────────────┐
│$ /usr/src/zellij/x86_64-unknown-linux-musl/release/zellij││foo │$ /usr/src/zellij/x86_64-unknown-linux-musl/release/zellij run -s -- "/us││foo
run -s -- "/usr/src/zellij/fixtures/append-echo-script.sh││foo r/src/zellij/fixtures/append-echo-script.sh" ││foo
" ││█ │ $ ││█
$ ││ │ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
││ ││
└──────────────────────────────────────────────────────────┘└ [ EXIT CODE: 0 ] <ENTER> to re-run, <Ctrl-c> to exit ────┘ └─────────────────────────────────────────────────────────────────────────┘└ [ EXIT CODE: 0 ] <ENTER> re-run, <ESC> drop to shell, <Ctrl-c> exit ────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt + <[]>  VERTICAL 
Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane. Tip: Alt + <n> => open new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate between panes. Alt + <+|-> => increase/decrease pane size.

View file

@ -31,7 +31,7 @@ use zellij_utils::{
}; };
use std::{ use std::{
collections::{BTreeMap, HashMap, HashSet}, collections::{BTreeMap, BTreeSet, HashMap},
env, env,
fs::File, fs::File,
io::Write, io::Write,
@ -581,7 +581,7 @@ impl ServerOsApi for ServerOsInputOutput {
.with_context(err_context)?; .with_context(err_context)?;
let mut terminal_id = None; let mut terminal_id = None;
{ {
let current_ids: HashSet<u32> = self let current_ids: BTreeSet<u32> = self
.terminal_id_to_raw_fd .terminal_id_to_raw_fd
.lock() .lock()
.to_anyhow() .to_anyhow()
@ -589,13 +589,7 @@ impl ServerOsApi for ServerOsInputOutput {
.keys() .keys()
.copied() .copied()
.collect(); .collect();
for i in 0..u32::MAX { terminal_id = current_ids.last().map(|l| l + 1).or(Some(0));
let i = i as u32;
if !current_ids.contains(&i) {
terminal_id = Some(i);
break;
}
}
} }
match terminal_id { match terminal_id {
Some(terminal_id) => { Some(terminal_id) => {
@ -628,7 +622,7 @@ impl ServerOsApi for ServerOsInputOutput {
let mut terminal_id = None; let mut terminal_id = None;
{ {
let current_ids: HashSet<u32> = self let current_ids: BTreeSet<u32> = self
.terminal_id_to_raw_fd .terminal_id_to_raw_fd
.lock() .lock()
.to_anyhow() .to_anyhow()
@ -636,13 +630,7 @@ impl ServerOsApi for ServerOsInputOutput {
.keys() .keys()
.copied() .copied()
.collect(); .collect();
for i in 0..u32::MAX { terminal_id = current_ids.last().map(|l| l + 1).or(Some(0));
let i = i as u32;
if !current_ids.contains(&i) {
terminal_id = Some(i);
break;
}
}
} }
match terminal_id { match terminal_id {
Some(terminal_id) => { Some(terminal_id) => {

View file

@ -773,21 +773,25 @@ pub fn render_first_run_banner(
let controls_bare_text_first_part = "<"; let controls_bare_text_first_part = "<";
let enter_bare_text = "ENTER"; let enter_bare_text = "ENTER";
let controls_bare_text_second_part = "> to run, <"; let controls_bare_text_second_part = "> run, <";
let esc_bare_text = "ESC";
let controls_bare_text_third_part = "> drop to shell, <";
let ctrl_c_bare_text = "Ctrl-c"; let ctrl_c_bare_text = "Ctrl-c";
let controls_bare_text_third_part = "> to exit"; let controls_bare_text_fourth_part = "> exit";
let controls_color = RESET_STYLES let controls_color = RESET_STYLES
.foreground(Some(AnsiCode::from(style.colors.orange))) .foreground(Some(AnsiCode::from(style.colors.orange)))
.bold(Some(AnsiCode::On)); .bold(Some(AnsiCode::On));
let controls_line_length = controls_bare_text_first_part.len() let controls_line_length = controls_bare_text_first_part.len()
+ enter_bare_text.len() + enter_bare_text.len()
+ controls_bare_text_second_part.len() + controls_bare_text_second_part.len()
+ esc_bare_text.len()
+ controls_bare_text_third_part.len()
+ ctrl_c_bare_text.len() + ctrl_c_bare_text.len()
+ controls_bare_text_third_part.len(); + controls_bare_text_fourth_part.len();
let controls_column_start_position = let controls_column_start_position =
middle_column.saturating_sub(controls_line_length / 2); middle_column.saturating_sub(controls_line_length / 2);
let controls_line = format!( let controls_line = format!(
"\u{1b}[{};{}H{}<{}{}{}{}> to run, <{}{}{}{}> to exit", "\u{1b}[{};{}H{}<{}{}{}{}> run, <{}{}{}{}> drop to shell, <{}{}{}{}> exit",
middle_row + 2, middle_row + 2,
controls_column_start_position, controls_column_start_position,
bold_text, bold_text,
@ -796,6 +800,10 @@ pub fn render_first_run_banner(
RESET_STYLES, RESET_STYLES,
bold_text, bold_text,
controls_color, controls_color,
esc_bare_text,
RESET_STYLES,
bold_text,
controls_color,
ctrl_c_bare_text, ctrl_c_bare_text,
RESET_STYLES, RESET_STYLES,
bold_text bold_text
@ -817,21 +825,25 @@ pub fn render_first_run_banner(
let controls_bare_text_first_part = "<"; let controls_bare_text_first_part = "<";
let enter_bare_text = "ENTER"; let enter_bare_text = "ENTER";
let controls_bare_text_second_part = "> to run, <"; let controls_bare_text_second_part = "> run, <";
let esc_bare_text = "ESC";
let controls_bare_text_third_part = "> drop to shell, <";
let ctrl_c_bare_text = "Ctrl-c"; let ctrl_c_bare_text = "Ctrl-c";
let controls_bare_text_third_part = "> to exit"; let controls_bare_text_fourth_part = "> exit";
let controls_color = RESET_STYLES let controls_color = RESET_STYLES
.foreground(Some(AnsiCode::from(style.colors.orange))) .foreground(Some(AnsiCode::from(style.colors.orange)))
.bold(Some(AnsiCode::On)); .bold(Some(AnsiCode::On));
let controls_line_length = controls_bare_text_first_part.len() let controls_line_length = controls_bare_text_first_part.len()
+ enter_bare_text.len() + enter_bare_text.len()
+ controls_bare_text_second_part.len() + controls_bare_text_second_part.len()
+ esc_bare_text.len()
+ controls_bare_text_third_part.len()
+ ctrl_c_bare_text.len() + ctrl_c_bare_text.len()
+ controls_bare_text_third_part.len(); + controls_bare_text_fourth_part.len();
let controls_column_start_position = let controls_column_start_position =
middle_column.saturating_sub(controls_line_length / 2); middle_column.saturating_sub(controls_line_length / 2);
let controls_line = format!( let controls_line = format!(
"\u{1b}[{};{}H{}<{}{}{}{}> to run, <{}{}{}{}> to exit", "\u{1b}[{};{}H{}<{}{}{}{}> run, <{}{}{}{}> drop to shell, <{}{}{}{}> exit",
middle_row + 2, middle_row + 2,
controls_column_start_position, controls_column_start_position,
bold_text, bold_text,
@ -840,6 +852,10 @@ pub fn render_first_run_banner(
RESET_STYLES, RESET_STYLES,
bold_text, bold_text,
controls_color, controls_color,
esc_bare_text,
RESET_STYLES,
bold_text,
controls_color,
ctrl_c_bare_text, ctrl_c_bare_text,
RESET_STYLES, RESET_STYLES,
bold_text bold_text

View file

@ -40,6 +40,7 @@ const END_KEY: &[u8] = &[27, 91, 70];
const BRACKETED_PASTE_BEGIN: &[u8] = &[27, 91, 50, 48, 48, 126]; const BRACKETED_PASTE_BEGIN: &[u8] = &[27, 91, 50, 48, 48, 126];
const BRACKETED_PASTE_END: &[u8] = &[27, 91, 50, 48, 49, 126]; const BRACKETED_PASTE_END: &[u8] = &[27, 91, 50, 48, 49, 126];
const ENTER_NEWLINE: &[u8] = &[10]; const ENTER_NEWLINE: &[u8] = &[10];
const ESC: &[u8] = &[27];
const ENTER_CARRIAGE_RETURN: &[u8] = &[13]; const ENTER_CARRIAGE_RETURN: &[u8] = &[13];
const SPACE: &[u8] = &[32]; const SPACE: &[u8] = &[32];
const CTRL_C: &[u8] = &[3]; // TODO: check this to be sure it fits all types of CTRL_C (with mac, etc) const CTRL_C: &[u8] = &[3]; // TODO: check this to be sure it fits all types of CTRL_C (with mac, etc)
@ -192,6 +193,13 @@ impl Pane for TerminalPane {
self.remove_banner(); self.remove_banner();
Some(AdjustedInput::ReRunCommandInThisPane(run_command)) Some(AdjustedInput::ReRunCommandInThisPane(run_command))
}, },
ESC => {
self.is_held = None;
self.grid.reset_terminal_state();
self.set_should_render(true);
self.remove_banner();
Some(AdjustedInput::DropToShellInThisPane)
},
CTRL_C => Some(AdjustedInput::CloseThisPane), CTRL_C => Some(AdjustedInput::CloseThisPane),
_ => None, _ => None,
} }

View file

@ -66,6 +66,7 @@ pub enum PtyInstruction {
ClosePane(PaneId), ClosePane(PaneId),
CloseTab(Vec<PaneId>), CloseTab(Vec<PaneId>),
ReRunCommandInPane(PaneId, RunCommand), ReRunCommandInPane(PaneId, RunCommand),
DropToShellInPane(PaneId, Option<PathBuf>), // Option<PathBuf> - default shell
SpawnInPlaceTerminal( SpawnInPlaceTerminal(
Option<TerminalAction>, Option<TerminalAction>,
Option<String>, Option<String>,
@ -89,6 +90,7 @@ impl From<&PtyInstruction> for PtyContext {
PtyInstruction::CloseTab(_) => PtyContext::CloseTab, PtyInstruction::CloseTab(_) => PtyContext::CloseTab,
PtyInstruction::NewTab(..) => PtyContext::NewTab, PtyInstruction::NewTab(..) => PtyContext::NewTab,
PtyInstruction::ReRunCommandInPane(..) => PtyContext::ReRunCommandInPane, PtyInstruction::ReRunCommandInPane(..) => PtyContext::ReRunCommandInPane,
PtyInstruction::DropToShellInPane(..) => PtyContext::DropToShellInPane,
PtyInstruction::SpawnInPlaceTerminal(..) => PtyContext::SpawnInPlaceTerminal, PtyInstruction::SpawnInPlaceTerminal(..) => PtyContext::SpawnInPlaceTerminal,
PtyInstruction::DumpLayout(..) => PtyContext::DumpLayout, PtyInstruction::DumpLayout(..) => PtyContext::DumpLayout,
PtyInstruction::LogLayoutToHd(..) => PtyContext::LogLayoutToHd, PtyInstruction::LogLayoutToHd(..) => PtyContext::LogLayoutToHd,
@ -532,6 +534,55 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
}, },
} }
}, },
PtyInstruction::DropToShellInPane(pane_id, default_shell) => {
let err_context = || format!("failed to rerun command in pane {:?}", pane_id);
// TODO: get configured default_shell from screen/tab as an option and default to
// this otherwise (also look for a place that turns get_default_shell into a
// RunCommand, we might have done this before)
let run_command = RunCommand {
command: default_shell.unwrap_or_else(|| get_default_shell()),
hold_on_close: false,
hold_on_start: false,
// TODO: cwd
..Default::default()
};
match pty
.rerun_command_in_pane(pane_id, run_command.clone())
.with_context(err_context)
{
Ok(..) => {},
Err(err) => match err.downcast_ref::<ZellijError>() {
Some(ZellijError::CommandNotFound { terminal_id, .. }) => {
if run_command.hold_on_close {
pty.bus
.senders
.send_to_screen(ScreenInstruction::PtyBytes(
*terminal_id,
format!(
"Command not found: {}",
run_command.command.display()
)
.as_bytes()
.to_vec(),
))
.with_context(err_context)?;
pty.bus
.senders
.send_to_screen(ScreenInstruction::HoldPane(
PaneId::Terminal(*terminal_id),
Some(2), // exit status
run_command,
None,
None,
))
.with_context(err_context)?;
}
},
_ => Err::<(), _>(err).non_fatal(),
},
}
},
PtyInstruction::DumpLayout(mut session_layout_metadata, client_id) => { PtyInstruction::DumpLayout(mut session_layout_metadata, client_id) => {
let err_context = || format!("Failed to dump layout"); let err_context = || format!("Failed to dump layout");
pty.populate_session_layout_metadata(&mut session_layout_metadata); pty.populate_session_layout_metadata(&mut session_layout_metadata);

View file

@ -1149,6 +1149,7 @@ impl Screen {
self.terminal_emulator_colors.clone(), self.terminal_emulator_colors.clone(),
self.terminal_emulator_color_codes.clone(), self.terminal_emulator_color_codes.clone(),
swap_layouts, swap_layouts,
self.default_shell.clone(),
self.debug, self.debug,
); );
self.tabs.insert(tab_index, tab); self.tabs.insert(tab_index, tab);

View file

@ -8,6 +8,7 @@ mod swap_layouts;
use copy_command::CopyCommand; use copy_command::CopyCommand;
use std::env::temp_dir; use std::env::temp_dir;
use std::path::PathBuf;
use uuid::Uuid; use uuid::Uuid;
use zellij_utils::data::{ use zellij_utils::data::{
Direction, PaneInfo, PermissionStatus, PermissionType, PluginPermission, ResizeStrategy, Direction, PaneInfo, PermissionStatus, PermissionType, PluginPermission, ResizeStrategy,
@ -182,6 +183,7 @@ pub(crate) struct Tab {
pending_instructions: Vec<BufferedTabInstruction>, // instructions that came while the tab was pending_instructions: Vec<BufferedTabInstruction>, // instructions that came while the tab was
// pending and need to be re-applied // pending and need to be re-applied
swap_layouts: SwapLayouts, swap_layouts: SwapLayouts,
default_shell: Option<PathBuf>,
debug: bool, debug: bool,
} }
@ -482,6 +484,7 @@ pub enum AdjustedInput {
ReRunCommandInThisPane(RunCommand), ReRunCommandInThisPane(RunCommand),
PermissionRequestResult(Vec<PermissionType>, PermissionStatus), PermissionRequestResult(Vec<PermissionType>, PermissionStatus),
CloseThisPane, CloseThisPane,
DropToShellInThisPane,
} }
pub fn get_next_terminal_position( pub fn get_next_terminal_position(
tiled_panes: &TiledPanes, tiled_panes: &TiledPanes,
@ -528,6 +531,7 @@ impl Tab {
terminal_emulator_colors: Rc<RefCell<Palette>>, terminal_emulator_colors: Rc<RefCell<Palette>>,
terminal_emulator_color_codes: Rc<RefCell<HashMap<usize, String>>>, terminal_emulator_color_codes: Rc<RefCell<HashMap<usize, String>>>,
swap_layouts: (Vec<SwapTiledLayout>, Vec<SwapFloatingLayout>), swap_layouts: (Vec<SwapTiledLayout>, Vec<SwapFloatingLayout>),
default_shell: Option<PathBuf>,
debug: bool, debug: bool,
) -> Self { ) -> Self {
let name = if name.is_empty() { let name = if name.is_empty() {
@ -615,6 +619,7 @@ impl Tab {
is_pending: true, // will be switched to false once the layout is applied is_pending: true, // will be switched to false once the layout is applied
pending_instructions: vec![], pending_instructions: vec![],
swap_layouts, swap_layouts,
default_shell,
debug, debug,
} }
} }
@ -1695,6 +1700,16 @@ impl Tab {
self.close_pane(PaneId::Terminal(active_terminal_id), false, None); self.close_pane(PaneId::Terminal(active_terminal_id), false, None);
should_update_ui = true; should_update_ui = true;
}, },
Some(AdjustedInput::DropToShellInThisPane) => {
self.pids_waiting_resize.insert(active_terminal_id);
self.senders
.send_to_pty(PtyInstruction::DropToShellInPane(
PaneId::Terminal(active_terminal_id),
self.default_shell.clone(),
))
.with_context(err_context)?;
should_update_ui = true;
},
Some(_) => {}, Some(_) => {},
None => {}, None => {},
} }

View file

@ -1,6 +1,6 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5472 assertion_line: 6071
expression: snapshot expression: snapshot
--- ---
00 (C): ┌ tab-bar ────────────────────────────────────────┌ status-bar ──────────────────────────────────────────────┐──────────┐ 00 (C): ┌ tab-bar ────────────────────────────────────────┌ status-bar ──────────────────────────────────────────────┐──────────┐
@ -19,7 +19,7 @@ expression: snapshot
13 (C): │ │ │ │ │ 13 (C): │ │ │ │ │
14 (C): │ Waiting to ru└───────────────────│ Waiting to run: command2 │ │ 14 (C): │ Waiting to ru└───────────────────│ Waiting to run: command2 │ │
15 (C): │ │ │ │ 15 (C): │ │ │ │
16 (C): │ <ENTER> to run, <Ctrl-c> to exit │ <ENTER> to run, <Ctrl-c> to exit │ │ 16 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> e│ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │
17 (C): │ │ │ │ 17 (C): │ │ │ │
18 (C): │ │ │ │ 18 (C): │ │ │ │
19 (C): └─────────────────────────────────────────────────└──────────────────────────────────────────────────────────┘──────────┘ 19 (C): └─────────────────────────────────────────────────└──────────────────────────────────────────────────────────┘──────────┘

View file

@ -1,5 +1,6 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5109
expression: snapshot expression: snapshot
--- ---
00 (C): I am a tab bar 00 (C): I am a tab bar
@ -12,14 +13,14 @@ expression: snapshot
07 (C): │ ││ ││ │ 07 (C): │ ││ ││ │
08 (C): │ Waiting to run: command2 ││ ││ Waiting to run: command1 │ 08 (C): │ Waiting to run: command2 ││ ││ Waiting to run: command1 │
09 (C): │ ││ ││ │ 09 (C): │ ││ ││ │
10 (C): │ <ENTER> to run, <Ctrl-c> to exit ││ ││ <ENTER> to run, <Ctrl-c> to exit 10 (C): │<ENTER> run, <ESC> drop to shell, <Ctrl││ ││<ENTER> run, <ESC> drop to shell, <Ctr
11 (C): │ ││ ││ 11 (C): │-c> exit ││ ││l-c> exit
12 (C): │ ││ ││ │ 12 (C): │ ││ ││ │
13 (C): │ ││ ││ │ 13 (C): │ ││ ││ │
14 (C): │ ││ ││ │ 14 (C): │ ││ ││ │
15 (C): │ ││ ││ │ 15 (C): │ ││ ││ │
16 (C): │ ││ ││ │ 16 (C): │ ││ ││ │
17 (C): └───────────────────────────────────────┘└──────────────────────────────────────┘└─ <ENTER> to run, <Ctrl-c> to exit ───┘ 17 (C): └───────────────────────────────────────┘└──────────────────────────────────────┘└──────────────────────────────────────┘
18 (C): I am a 18 (C): I am a
19 (C): status bar 19 (C): status bar

View file

@ -1,6 +1,6 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5926 assertion_line: 5971
expression: snapshot expression: snapshot
--- ---
00 (C): ┌ status-bar ──────────────────────────────────────────────┐─────────────────────────────────────────────────┐──────────┐ 00 (C): ┌ status-bar ──────────────────────────────────────────────┐─────────────────────────────────────────────────┐──────────┐
@ -19,7 +19,7 @@ expression: snapshot
13 (C): │ │ │ │ │ 13 (C): │ │ │ │ │
14 (C): │ Waiting to ru└───────────────────│ Waiting to run: command2 │ │ 14 (C): │ Waiting to ru└───────────────────│ Waiting to run: command2 │ │
15 (C): │ │ │ │ 15 (C): │ │ │ │
16 (C): │ <ENTER> to run, <Ctrl-c> to exit │ <ENTER> to run, <Ctrl-c> to exit │ │ 16 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> e│ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │
17 (C): │ │ │ │ 17 (C): │ │ │ │
18 (C): │ │ │ │ 18 (C): │ │ │ │
19 (C): └─────────────────────────────────────────────────└──────────────────────────────────────────────────────────┘──────────┘ 19 (C): └─────────────────────────────────────────────────└──────────────────────────────────────────────────────────┘──────────┘

View file

@ -1,5 +1,6 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5007
expression: snapshot expression: snapshot
--- ---
00 (C): I am a 00 (C): I am a
@ -8,13 +9,13 @@ expression: snapshot
03 (C): │ │ 03 (C): │ │
04 (C): │ Waiting to run: command1 │ 04 (C): │ Waiting to run: command1 │
05 (C): │ │ 05 (C): │ │
06 (C): │ <ENTER> to run, <Ctrl-c> to exit 06 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
07 (C): └─ <ENTER> to run, <Ctrl-c> to exit ────────────────────────────────────────────────────────────────────────────────────┘ 07 (C): └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ─────────────────────────────────────────────────────────────────────┘
08 (C): ┌ command2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 08 (C): ┌ command2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
09 (C): │ │ 09 (C): │ │
10 (C): │ Waiting to run: command2 │ 10 (C): │ Waiting to run: command2 │
11 (C): │ │ 11 (C): │ │
12 (C): │ <ENTER> to run, <Ctrl-c> to exit 12 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
13 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 13 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
14 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 14 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
15 (C): │ │ 15 (C): │ │

View file

@ -1,15 +1,15 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5614 assertion_line: 6269
expression: snapshot expression: snapshot
--- ---
00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
01 (C): │ │ 01 (C): │ │
02 (C): │ ┌ command2 ────────────────────────────┐ │ 02 (C): │ ┌ command2 ────────────── SCROLL: 0/1 ┐ │
03 (C): │ │ │ │ 03 (C): │ │ Waiting to run: command2 │ │
04 (C): │ │ ┌ tab-bar ─────────────────────────────┐ │ 04 (C): │ │ ┌ tab-bar ─────────────────────────────┐ │
05 (C): │ │ │I am a tab bar ┌ status-bar ──────────────────────────────────────────────┐ │ 05 (C): │ │<│I am a tab bar ┌ status-bar ──────────────────────────────────────────────┐ │
06 (C): │ │ │ │I am a │ │ 06 (C): │ │l│ │I am a │ │
07 (C): │ └─│ │status bar │─┐ │ 07 (C): │ └─│ │status bar │─┐ │
08 (C): │ │ │ │ │ │ 08 (C): │ │ │ │ │ │
09 (C): │ └─────────────────────────│ │───┐ │ 09 (C): │ └─────────────────────────│ │───┐ │
@ -18,7 +18,7 @@ expression: snapshot
12 (C): │ │ │ │ │ 12 (C): │ │ │ │ │
13 (C): │ │ │ │ │ 13 (C): │ │ │ │ │
14 (C): │ └──────────────────────────────────────────────────────────┘ │ │ 14 (C): │ └──────────────────────────────────────────────────────────┘ │ │
15 (C): │ │ │ <ENTER> to run, <Ctrl-c> to exit │ │ 15 (C): │ │ │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │
16 (C): │ └─│ │ │ 16 (C): │ └─│ │ │
17 (C): │ │ │ │ 17 (C): │ │ │ │
18 (C): │ └──────────────────────────────────────────────────────────┘ │ 18 (C): │ └──────────────────────────────────────────────────────────┘ │

View file

@ -1,5 +1,6 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5307
expression: snapshot expression: snapshot
--- ---
00 (C): I am a 00 (C): I am a
@ -14,12 +15,12 @@ expression: snapshot
09 (C): │ │ 09 (C): │ │
10 (C): │ Waiting to run: command1 │ 10 (C): │ Waiting to run: command1 │
11 (C): │ │ 11 (C): │ │
12 (C): │ <ENTER> to run, <Ctrl-c> to exit 12 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
13 (C): └─ <ENTER> to run, <Ctrl-c> to exit ────────────────────────────────────────────────────────────────────────────────────┘ 13 (C): └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ─────────────────────────────────────────────────────────────────────┘
14 (C): ┌ command2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 14 (C): ┌ command2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
15 (C): │ Waiting to run: command2 │ 15 (C): │ Waiting to run: command2 │
16 (C): │ │ 16 (C): │ │
17 (C): │ <ENTER> to run, <Ctrl-c> to exit 17 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
18 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 18 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
19 (C): I am a tab bar 19 (C): I am a tab bar

View file

@ -1,5 +1,6 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5481
expression: snapshot expression: snapshot
--- ---
00 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 00 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
@ -8,13 +9,13 @@ expression: snapshot
03 (C): │ │ 03 (C): │ │
04 (C): │ Waiting to run: command1 │ 04 (C): │ Waiting to run: command1 │
05 (C): │ │ 05 (C): │ │
06 (C): │ <ENTER> to run, <Ctrl-c> to exit 06 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
07 (C): └─ <ENTER> to run, <Ctrl-c> to exit ────────────────────────────────────────────────────────────────────────────────────┘ 07 (C): └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ─────────────────────────────────────────────────────────────────────┘
08 (C): ┌ command2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 08 (C): ┌ command2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
09 (C): │ │ 09 (C): │ │
10 (C): │ Waiting to run: command2 │ 10 (C): │ Waiting to run: command2 │
11 (C): │ │ 11 (C): │ │
12 (C): │ <ENTER> to run, <Ctrl-c> to exit 12 (C): │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │
13 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 13 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
14 (C): ┌ status-bar ───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 14 (C): ┌ status-bar ───────────────────────────────────────────────────────────────────────────────────────────────────────────┐
15 (C): │I am a │ 15 (C): │I am a │

View file

@ -245,6 +245,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab {
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), (vec![], vec![]),
None,
debug, debug,
); );
tab.apply_layout( tab.apply_layout(
@ -317,6 +318,7 @@ fn create_new_tab_with_swap_layouts(
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
swap_layouts, swap_layouts,
None,
debug, debug,
); );
let ( let (
@ -391,6 +393,7 @@ fn create_new_tab_with_os_api(
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), // swap layouts (vec![], vec![]), // swap layouts
None,
debug, debug,
); );
tab.apply_layout( tab.apply_layout(
@ -451,6 +454,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str)
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), // swap layouts (vec![], vec![]), // swap layouts
None,
debug, debug,
); );
let pane_ids = tab_layout let pane_ids = tab_layout
@ -525,6 +529,7 @@ fn create_new_tab_with_mock_pty_writer(
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), // swap layouts (vec![], vec![]), // swap layouts
None,
debug, debug,
); );
tab.apply_layout( tab.apply_layout(
@ -590,6 +595,7 @@ fn create_new_tab_with_sixel_support(
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), // swap layouts (vec![], vec![]), // swap layouts
None,
debug, debug,
); );
tab.apply_layout( tab.apply_layout(

View file

@ -186,6 +186,7 @@ fn create_new_tab(size: Size) -> Tab {
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), // swap layouts (vec![], vec![]), // swap layouts
None,
debug, debug,
); );
tab.apply_layout( tab.apply_layout(
@ -243,6 +244,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab {
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), // swap layouts (vec![], vec![]), // swap layouts
None,
debug, debug,
); );
let mut new_terminal_ids = vec![]; let mut new_terminal_ids = vec![];
@ -306,6 +308,7 @@ fn create_new_tab_with_cell_size(
terminal_emulator_colors, terminal_emulator_colors,
terminal_emulator_color_codes, terminal_emulator_color_codes,
(vec![], vec![]), // swap layouts (vec![], vec![]), // swap layouts
None,
debug, debug,
); );
tab.apply_layout( tab.apply_layout(

View file

@ -837,14 +837,20 @@ impl PaneFrame {
let enter_text = "ENTER"; let enter_text = "ENTER";
let right_enter_bracket = ">"; let right_enter_bracket = ">";
let enter_tip = if self.is_first_run { let enter_tip = if self.is_first_run {
" to run, " " run, "
} else { } else {
" to re-run, " " re-run, "
}; };
let left_esc_bracket = "<";
let esc_text = "ESC";
let right_esc_bracket = ">";
let esc_tip = " drop to shell, ";
let left_break_bracket = "<"; let left_break_bracket = "<";
let break_text = "Ctrl-c"; let break_text = "Ctrl-c";
let right_break_bracket = ">"; let right_break_bracket = ">";
let break_tip = " to exit "; let break_tip = " exit ";
second_part.append(&mut foreground_color(left_enter_bracket, self.color)); second_part.append(&mut foreground_color(left_enter_bracket, self.color));
second_part.append(&mut foreground_color( second_part.append(&mut foreground_color(
enter_text, enter_text,
@ -852,6 +858,15 @@ impl PaneFrame {
)); ));
second_part.append(&mut foreground_color(right_enter_bracket, self.color)); second_part.append(&mut foreground_color(right_enter_bracket, self.color));
second_part.append(&mut foreground_color(enter_tip, self.color)); second_part.append(&mut foreground_color(enter_tip, self.color));
second_part.append(&mut foreground_color(left_esc_bracket, self.color));
second_part.append(&mut foreground_color(
esc_text,
Some(self.style.colors.orange),
));
second_part.append(&mut foreground_color(right_esc_bracket, self.color));
second_part.append(&mut foreground_color(esc_tip, self.color));
second_part.append(&mut foreground_color(left_break_bracket, self.color)); second_part.append(&mut foreground_color(left_break_bracket, self.color));
second_part.append(&mut foreground_color( second_part.append(&mut foreground_color(
break_text, break_text,
@ -865,6 +880,10 @@ impl PaneFrame {
+ enter_text.len() + enter_text.len()
+ right_enter_bracket.len() + right_enter_bracket.len()
+ enter_tip.len() + enter_tip.len()
+ left_esc_bracket.len()
+ esc_text.len()
+ right_esc_bracket.len()
+ esc_tip.len()
+ left_break_bracket.len() + left_break_bracket.len()
+ break_text.len() + break_text.len()
+ right_break_bracket.len() + right_break_bracket.len()

View file

@ -362,6 +362,7 @@ pub enum PtyContext {
ClosePane, ClosePane,
CloseTab, CloseTab,
ReRunCommandInPane, ReRunCommandInPane,
DropToShellInPane,
SpawnInPlaceTerminal, SpawnInPlaceTerminal,
DumpLayout, DumpLayout,
LogLayoutToHd, LogLayoutToHd,