From 1a84c5f4ecdb119068d39864191c69608ab5ac29 Mon Sep 17 00:00:00 2001 From: Dante Pippi <6619666+dantepippi@users.noreply.github.com> Date: Tue, 27 Apr 2021 14:03:41 -0300 Subject: [PATCH 1/4] New feature: Synchronize text sent to panes --- src/client/tab.rs | 27 ++++ src/common/errors.rs | 2 + src/common/input/actions.rs | 2 + src/common/input/handler.rs | 7 + src/common/input/keybinds.rs | 273 +++++++++++++++++++++++++++++++++++ src/common/mod.rs | 17 ++- src/common/screen.rs | 1 + 7 files changed, 325 insertions(+), 4 deletions(-) diff --git a/src/client/tab.rs b/src/client/tab.rs index af48d3fe..23146eba 100644 --- a/src/client/tab.rs +++ b/src/client/tab.rs @@ -68,6 +68,7 @@ pub struct Tab { max_panes: Option, full_screen_ws: PositionAndSize, fullscreen_is_active: bool, + synchronize_is_active: bool, os_api: Box, pub send_pty_instructions: SenderWithContext, pub send_plugin_instructions: SenderWithContext, @@ -249,6 +250,7 @@ impl Tab { active_terminal: pane_id, full_screen_ws: *full_screen_ws, fullscreen_is_active: false, + synchronize_is_active: false, os_api, send_app_instructions, send_pty_instructions, @@ -592,6 +594,25 @@ impl Tab { terminal_output.handle_pty_bytes(bytes); } } + pub fn write_to_terminals_on_current_tab(&mut self, input_bytes: Vec) { + let pane_ids = self.get_pane_ids(); + pane_ids.iter().for_each(|pane_id| { + match pane_id { + PaneId::Terminal(pid) => { + self.write_to_pane_id(input_bytes.clone(), *pid); + } + PaneId::Plugin(_) => {} + } + }); + } + pub fn write_to_pane_id(&mut self, mut input_bytes: Vec, pid:RawFd) { + self.os_api + .write_to_tty_stdin(pid, &mut input_bytes) + .expect("failed to write to terminal"); + self.os_api + .tcdrain(pid) + .expect("failed to drain terminal"); + } pub fn write_to_active_terminal(&mut self, input_bytes: Vec) { match self.get_active_pane_id() { Some(PaneId::Terminal(active_terminal_id)) => { @@ -677,6 +698,12 @@ impl Tab { pub fn toggle_fullscreen_is_active(&mut self) { self.fullscreen_is_active = !self.fullscreen_is_active; } + pub fn is_sync_panes_active(&self) -> bool { + self.synchronize_is_active + } + pub fn toggle_sync_panes_is_active(&mut self) { + self.synchronize_is_active = !self.synchronize_is_active; + } pub fn render(&mut self) { if self.active_terminal.is_none() { // we might not have an active terminal if we closed the last pane diff --git a/src/common/errors.rs b/src/common/errors.rs index dd675738..c1c6753f 100644 --- a/src/common/errors.rs +++ b/src/common/errors.rs @@ -200,6 +200,7 @@ pub enum ScreenContext { PageScrollDown, ClearScroll, CloseFocusedPane, + ToggleActiveSyncPanes, ToggleActiveTerminalFullscreen, SetSelectable, SetInvisibleBorders, @@ -260,6 +261,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::UpdateTabName(_) => ScreenContext::UpdateTabName, ScreenInstruction::TerminalResize => ScreenContext::TerminalResize, ScreenInstruction::ChangeMode(_) => ScreenContext::ChangeMode, + ScreenInstruction::ToggleActiveSyncPanes => ScreenContext::ToggleActiveSyncPanes, } } } diff --git a/src/common/input/actions.rs b/src/common/input/actions.rs index 3bcadf15..46a8e1d6 100644 --- a/src/common/input/actions.rs +++ b/src/common/input/actions.rs @@ -39,6 +39,8 @@ pub enum Action { PageScrollDown, /// Toggle between fullscreen focus pane and normal layout. ToggleFocusFullscreen, + /// Toggle between sending text commands to all panes and normal mode. + ToggleActiveSyncPanes, /// Open a new pane in the specified direction (relative to focus). /// If no direction is specified, will try to use the biggest available space. NewPane(Option), diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs index 197f8315..fa5268bd 100644 --- a/src/common/input/handler.rs +++ b/src/common/input/handler.rs @@ -244,6 +244,12 @@ impl InputHandler { .send(ScreenInstruction::SwitchTabPrev) .unwrap(); } + Action::ToggleActiveSyncPanes => { + self.send_screen_instructions + .send(ScreenInstruction::ToggleActiveSyncPanes) + .unwrap(); + + } Action::CloseTab => { self.command_is_executing.closing_pane(); self.send_screen_instructions @@ -293,6 +299,7 @@ pub fn get_mode_info(mode: InputMode) -> ModeInfo { keybinds.push(("d".to_string(), "Down split".to_string())); keybinds.push(("r".to_string(), "Right split".to_string())); keybinds.push(("x".to_string(), "Close".to_string())); + keybinds.push(("s".to_string(), "Sync".to_string())); keybinds.push(("f".to_string(), "Fullscreen".to_string())); } InputMode::Tab => { diff --git a/src/common/input/keybinds.rs b/src/common/input/keybinds.rs index 9842fbe2..a3b710cf 100644 --- a/src/common/input/keybinds.rs +++ b/src/common/input/keybinds.rs @@ -105,6 +105,279 @@ impl Keybinds { keybinds } + /// Returns the default keybinds for a given [`InputMode`]. + fn get_defaults_for_mode(mode: &InputMode) -> ModeKeybinds { + let mut defaults = HashMap::new(); + + match *mode { + InputMode::Normal => { + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Locked)], + ); + defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); + defaults.insert( + Key::Ctrl('r'), + vec![Action::SwitchToMode(InputMode::Resize)], + ); + defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); + defaults.insert( + Key::Ctrl('s'), + vec![Action::SwitchToMode(InputMode::Scroll)], + ); + defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); + + defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); + defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); + defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); + defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); + } + InputMode::Locked => { + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + } + InputMode::Resize => { + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Locked)], + ); + defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); + defaults.insert( + Key::Ctrl('r'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); + defaults.insert( + Key::Ctrl('s'), + vec![Action::SwitchToMode(InputMode::Scroll)], + ); + defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); + defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); + defaults.insert( + Key::Char('\n'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert( + Key::Char(' '), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + + defaults.insert(Key::Char('h'), vec![Action::Resize(Direction::Left)]); + defaults.insert(Key::Char('j'), vec![Action::Resize(Direction::Down)]); + defaults.insert(Key::Char('k'), vec![Action::Resize(Direction::Up)]); + defaults.insert(Key::Char('l'), vec![Action::Resize(Direction::Right)]); + + defaults.insert(Key::Left, vec![Action::Resize(Direction::Left)]); + defaults.insert(Key::Down, vec![Action::Resize(Direction::Down)]); + defaults.insert(Key::Up, vec![Action::Resize(Direction::Up)]); + defaults.insert(Key::Right, vec![Action::Resize(Direction::Right)]); + + defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); + defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); + defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); + defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); + } + InputMode::Pane => { + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Locked)], + ); + defaults.insert( + Key::Ctrl('p'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert( + Key::Ctrl('r'), + vec![Action::SwitchToMode(InputMode::Resize)], + ); + defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); + defaults.insert( + Key::Ctrl('s'), + vec![Action::SwitchToMode(InputMode::Scroll)], + ); + defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); + defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); + defaults.insert( + Key::Char('\n'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert( + Key::Char(' '), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + + defaults.insert(Key::Char('h'), vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Char('j'), vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Char('k'), vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Char('l'), vec![Action::MoveFocus(Direction::Right)]); + + defaults.insert(Key::Left, vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Down, vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Up, vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Right, vec![Action::MoveFocus(Direction::Right)]); + + defaults.insert(Key::Char('p'), vec![Action::SwitchFocus]); + defaults.insert(Key::Char('n'), vec![Action::NewPane(None)]); + defaults.insert(Key::Char('d'), vec![Action::NewPane(Some(Direction::Down))]); + defaults.insert( + Key::Char('r'), + vec![Action::NewPane(Some(Direction::Right))], + ); + defaults.insert(Key::Char('x'), vec![Action::CloseFocus]); + defaults.insert(Key::Char('s'), vec![Action::ToggleActiveSyncPanes]); + defaults.insert(Key::Char('f'), vec![Action::ToggleFocusFullscreen]); + + defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); + defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); + defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); + defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); + } + InputMode::Tab => { + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Locked)], + ); + defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); + defaults.insert( + Key::Ctrl('r'), + vec![Action::SwitchToMode(InputMode::Resize)], + ); + defaults.insert( + Key::Ctrl('t'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert( + Key::Ctrl('s'), + vec![Action::SwitchToMode(InputMode::Scroll)], + ); + defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); + defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); + defaults.insert( + Key::Char('\n'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert( + Key::Char(' '), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + + defaults.insert(Key::Char('h'), vec![Action::GoToPreviousTab]); + defaults.insert(Key::Char('j'), vec![Action::GoToNextTab]); + defaults.insert(Key::Char('k'), vec![Action::GoToPreviousTab]); + defaults.insert(Key::Char('l'), vec![Action::GoToNextTab]); + + defaults.insert(Key::Left, vec![Action::GoToPreviousTab]); + defaults.insert(Key::Down, vec![Action::GoToNextTab]); + defaults.insert(Key::Up, vec![Action::GoToPreviousTab]); + defaults.insert(Key::Right, vec![Action::GoToNextTab]); + + defaults.insert(Key::Char('n'), vec![Action::NewTab]); + defaults.insert(Key::Char('x'), vec![Action::CloseTab]); + + defaults.insert( + Key::Char('r'), + vec![ + Action::SwitchToMode(InputMode::RenameTab), + Action::TabNameInput(vec![0]), + ], + ); + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + for i in '1'..='9' { + defaults.insert(Key::Char(i), vec![Action::GoToTab(i.to_digit(10).unwrap())]); + } + defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); + defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); + defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); + defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); + } + InputMode::Scroll => { + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Locked)], + ); + defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); + defaults.insert( + Key::Ctrl('r'), + vec![Action::SwitchToMode(InputMode::Resize)], + ); + defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); + defaults.insert( + Key::Ctrl('s'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); + defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); + defaults.insert( + Key::Char('\n'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert( + Key::Char(' '), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + + defaults.insert(Key::Char('j'), vec![Action::ScrollDown]); + defaults.insert(Key::Char('k'), vec![Action::ScrollUp]); + + defaults.insert(Key::Ctrl('f'), vec![Action::PageScrollDown]); + defaults.insert(Key::Ctrl('b'), vec![Action::PageScrollUp]); + defaults.insert(Key::PageDown, vec![Action::PageScrollDown]); + defaults.insert(Key::PageUp, vec![Action::PageScrollUp]); + + defaults.insert(Key::Down, vec![Action::ScrollDown]); + defaults.insert(Key::Up, vec![Action::ScrollUp]); + + defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); + defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); + defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); + defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); + } + InputMode::RenameTab => { + defaults.insert(Key::Char('\n'), vec![Action::SwitchToMode(InputMode::Tab)]); + defaults.insert( + Key::Ctrl('g'), + vec![Action::SwitchToMode(InputMode::Normal)], + ); + defaults.insert( + Key::Esc, + vec![ + Action::TabNameInput(vec![0x1b]), + Action::SwitchToMode(InputMode::Tab), + ], + ); + + defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); + defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); + defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); + defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); + defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); + defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); + defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); + } + } + ModeKeybinds(defaults) + } + /// Converts a [`Key`] terminal event to a sequence of [`Action`]s according to the current /// [`InputMode`] and [`Keybinds`]. pub fn key_to_actions( diff --git a/src/common/mod.rs b/src/common/mod.rs index ec2efe58..f56a1c91 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -320,10 +320,12 @@ pub fn start(mut os_input: Box, opts: CliArgs) { command_is_executing.done_opening_new_pane(); } ScreenInstruction::WriteCharacter(bytes) => { - screen - .get_active_tab_mut() - .unwrap() - .write_to_active_terminal(bytes); + let active_tab = screen.get_active_tab_mut().unwrap(); + match active_tab.is_sync_panes_active() { + true => active_tab.write_to_terminals_on_current_tab(bytes), + false => active_tab + .write_to_active_terminal(bytes), + } } ScreenInstruction::ResizeLeft => { screen.get_active_tab_mut().unwrap().resize_left(); @@ -444,9 +446,16 @@ pub fn start(mut os_input: Box, opts: CliArgs) { ScreenInstruction::ChangeMode(mode_info) => { screen.change_mode(mode_info); } + ScreenInstruction::ToggleActiveSyncPanes => { + screen + .get_active_tab_mut() + .unwrap() + .toggle_sync_panes_is_active(); + } ScreenInstruction::Quit => { break; } + } } } diff --git a/src/common/screen.rs b/src/common/screen.rs index a2f41574..75c0a805 100644 --- a/src/common/screen.rs +++ b/src/common/screen.rs @@ -51,6 +51,7 @@ pub enum ScreenInstruction { NewTab(RawFd), SwitchTabNext, SwitchTabPrev, + ToggleActiveSyncPanes, CloseTab, GoToTab(u32), UpdateTabName(Vec), From 6769627c3677e22a69b9059b1d85b00bd0d29bbb Mon Sep 17 00:00:00 2001 From: Dante Pippi <6619666+dantepippi@users.noreply.github.com> Date: Tue, 27 Apr 2021 14:44:09 -0300 Subject: [PATCH 2/4] cargo fmt --- src/client/tab.rs | 22 +++++++++------------- src/common/input/handler.rs | 5 ++--- src/common/mod.rs | 4 +--- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/client/tab.rs b/src/client/tab.rs index 23146eba..f9d98ace 100644 --- a/src/client/tab.rs +++ b/src/client/tab.rs @@ -596,22 +596,18 @@ impl Tab { } pub fn write_to_terminals_on_current_tab(&mut self, input_bytes: Vec) { let pane_ids = self.get_pane_ids(); - pane_ids.iter().for_each(|pane_id| { - match pane_id { - PaneId::Terminal(pid) => { - self.write_to_pane_id(input_bytes.clone(), *pid); - } - PaneId::Plugin(_) => {} + pane_ids.iter().for_each(|pane_id| match pane_id { + PaneId::Terminal(pid) => { + self.write_to_pane_id(input_bytes.clone(), *pid); } - }); + PaneId::Plugin(_) => {} + }); } - pub fn write_to_pane_id(&mut self, mut input_bytes: Vec, pid:RawFd) { + pub fn write_to_pane_id(&mut self, mut input_bytes: Vec, pid: RawFd) { self.os_api - .write_to_tty_stdin(pid, &mut input_bytes) - .expect("failed to write to terminal"); - self.os_api - .tcdrain(pid) - .expect("failed to drain terminal"); + .write_to_tty_stdin(pid, &mut input_bytes) + .expect("failed to write to terminal"); + self.os_api.tcdrain(pid).expect("failed to drain terminal"); } pub fn write_to_active_terminal(&mut self, input_bytes: Vec) { match self.get_active_pane_id() { diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs index fa5268bd..62118722 100644 --- a/src/common/input/handler.rs +++ b/src/common/input/handler.rs @@ -246,9 +246,8 @@ impl InputHandler { } Action::ToggleActiveSyncPanes => { self.send_screen_instructions - .send(ScreenInstruction::ToggleActiveSyncPanes) - .unwrap(); - + .send(ScreenInstruction::ToggleActiveSyncPanes) + .unwrap(); } Action::CloseTab => { self.command_is_executing.closing_pane(); diff --git a/src/common/mod.rs b/src/common/mod.rs index f56a1c91..d829451e 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -323,8 +323,7 @@ pub fn start(mut os_input: Box, opts: CliArgs) { let active_tab = screen.get_active_tab_mut().unwrap(); match active_tab.is_sync_panes_active() { true => active_tab.write_to_terminals_on_current_tab(bytes), - false => active_tab - .write_to_active_terminal(bytes), + false => active_tab.write_to_active_terminal(bytes), } } ScreenInstruction::ResizeLeft => { @@ -455,7 +454,6 @@ pub fn start(mut os_input: Box, opts: CliArgs) { ScreenInstruction::Quit => { break; } - } } } From 62662464e3814bde666ec826850c9d87d4af2639 Mon Sep 17 00:00:00 2001 From: Dante Pippi <6619666+dantepippi@users.noreply.github.com> Date: Tue, 27 Apr 2021 15:56:42 -0300 Subject: [PATCH 3/4] Including text on tab name to let users know sync is on. --- default-plugins/tab-bar/src/main.rs | 2 +- default-plugins/tab-bar/src/tab.rs | 13 +++++++++++-- src/common/mod.rs | 1 + src/common/screen.rs | 3 ++- zellij-tile/src/data.rs | 1 + 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/default-plugins/tab-bar/src/main.rs b/default-plugins/tab-bar/src/main.rs index 5a77ebac..f059d20e 100644 --- a/default-plugins/tab-bar/src/main.rs +++ b/default-plugins/tab-bar/src/main.rs @@ -65,7 +65,7 @@ impl ZellijPlugin for State { } else if t.active { active_tab_index = t.position; } - let tab = tab_style(tabname, t.active, t.position); + let tab = tab_style(tabname, t.active, t.position, t.is_sync_panes_active); all_tabs.push(tab); } let tab_line = tab_line(all_tabs, active_tab_index, cols); diff --git a/default-plugins/tab-bar/src/tab.rs b/default-plugins/tab-bar/src/tab.rs index a4c7c376..0bc143b7 100644 --- a/default-plugins/tab-bar/src/tab.rs +++ b/default-plugins/tab-bar/src/tab.rs @@ -40,9 +40,18 @@ pub fn non_active_tab(text: String) -> LinePart { } } -pub fn tab_style(text: String, is_active_tab: bool, position: usize) -> LinePart { +pub fn tab_style( + text: String, + is_active_tab: bool, + position: usize, + is_sync_panes_active: bool, +) -> LinePart { + let sync_text = match is_sync_panes_active { + true => " (Sync)".to_string(), + false => "".to_string(), + }; let tab_text = if text.is_empty() { - format!("Tab #{}", position + 1) + format!("Tab #{}{}", position + 1, sync_text) } else { text }; diff --git a/src/common/mod.rs b/src/common/mod.rs index d829451e..0a04e3ff 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -450,6 +450,7 @@ pub fn start(mut os_input: Box, opts: CliArgs) { .get_active_tab_mut() .unwrap() .toggle_sync_panes_is_active(); + screen.update_tabs(); } ScreenInstruction::Quit => { break; diff --git a/src/common/screen.rs b/src/common/screen.rs index 75c0a805..bc68f2ea 100644 --- a/src/common/screen.rs +++ b/src/common/screen.rs @@ -286,7 +286,7 @@ impl Screen { self.update_tabs(); } - fn update_tabs(&self) { + pub fn update_tabs(&self) { let mut tab_data = vec![]; let active_tab_index = self.active_tab_index.unwrap(); for tab in self.tabs.values() { @@ -294,6 +294,7 @@ impl Screen { position: tab.position, name: tab.name.clone(), active: active_tab_index == tab.index, + is_sync_panes_active: tab.is_sync_panes_active(), }); } self.send_plugin_instructions diff --git a/zellij-tile/src/data.rs b/zellij-tile/src/data.rs index fec37b17..713282cb 100644 --- a/zellij-tile/src/data.rs +++ b/zellij-tile/src/data.rs @@ -83,6 +83,7 @@ pub struct TabInfo { pub position: usize, pub name: String, pub active: bool, + pub is_sync_panes_active: bool, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] From f6df6e9dc890b129dbf05a0bb9f4dfe2b5a8f408 Mon Sep 17 00:00:00 2001 From: Dante Pippi <6619666+dantepippi@users.noreply.github.com> Date: Wed, 28 Apr 2021 11:41:48 -0300 Subject: [PATCH 4/4] Defining sync keybind using default.yaml --- assets/config/default.yaml | 2 + src/common/input/keybinds.rs | 273 ----------------------------------- 2 files changed, 2 insertions(+), 273 deletions(-) diff --git a/assets/config/default.yaml b/assets/config/default.yaml index a3a0242f..d7360c58 100644 --- a/assets/config/default.yaml +++ b/assets/config/default.yaml @@ -97,6 +97,8 @@ keybinds: key: [Char: 'r',] - action: [CloseFocus,] key: [Char: 'x',] + - action: [ToggleActiveSyncPanes] + key: [Char: 's'] - action: [ToggleFocusFullscreen,] key: [Char: 'f',] - action: [FocusPreviousPane,] diff --git a/src/common/input/keybinds.rs b/src/common/input/keybinds.rs index a3b710cf..9842fbe2 100644 --- a/src/common/input/keybinds.rs +++ b/src/common/input/keybinds.rs @@ -105,279 +105,6 @@ impl Keybinds { keybinds } - /// Returns the default keybinds for a given [`InputMode`]. - fn get_defaults_for_mode(mode: &InputMode) -> ModeKeybinds { - let mut defaults = HashMap::new(); - - match *mode { - InputMode::Normal => { - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Locked)], - ); - defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); - defaults.insert( - Key::Ctrl('r'), - vec![Action::SwitchToMode(InputMode::Resize)], - ); - defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); - defaults.insert( - Key::Ctrl('s'), - vec![Action::SwitchToMode(InputMode::Scroll)], - ); - defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); - - defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); - defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); - defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); - defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); - } - InputMode::Locked => { - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - } - InputMode::Resize => { - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Locked)], - ); - defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); - defaults.insert( - Key::Ctrl('r'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); - defaults.insert( - Key::Ctrl('s'), - vec![Action::SwitchToMode(InputMode::Scroll)], - ); - defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); - defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); - defaults.insert( - Key::Char('\n'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert( - Key::Char(' '), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - - defaults.insert(Key::Char('h'), vec![Action::Resize(Direction::Left)]); - defaults.insert(Key::Char('j'), vec![Action::Resize(Direction::Down)]); - defaults.insert(Key::Char('k'), vec![Action::Resize(Direction::Up)]); - defaults.insert(Key::Char('l'), vec![Action::Resize(Direction::Right)]); - - defaults.insert(Key::Left, vec![Action::Resize(Direction::Left)]); - defaults.insert(Key::Down, vec![Action::Resize(Direction::Down)]); - defaults.insert(Key::Up, vec![Action::Resize(Direction::Up)]); - defaults.insert(Key::Right, vec![Action::Resize(Direction::Right)]); - - defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); - defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); - defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); - defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); - } - InputMode::Pane => { - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Locked)], - ); - defaults.insert( - Key::Ctrl('p'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert( - Key::Ctrl('r'), - vec![Action::SwitchToMode(InputMode::Resize)], - ); - defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); - defaults.insert( - Key::Ctrl('s'), - vec![Action::SwitchToMode(InputMode::Scroll)], - ); - defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); - defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); - defaults.insert( - Key::Char('\n'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert( - Key::Char(' '), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - - defaults.insert(Key::Char('h'), vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Char('j'), vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Char('k'), vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Char('l'), vec![Action::MoveFocus(Direction::Right)]); - - defaults.insert(Key::Left, vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Down, vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Up, vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Right, vec![Action::MoveFocus(Direction::Right)]); - - defaults.insert(Key::Char('p'), vec![Action::SwitchFocus]); - defaults.insert(Key::Char('n'), vec![Action::NewPane(None)]); - defaults.insert(Key::Char('d'), vec![Action::NewPane(Some(Direction::Down))]); - defaults.insert( - Key::Char('r'), - vec![Action::NewPane(Some(Direction::Right))], - ); - defaults.insert(Key::Char('x'), vec![Action::CloseFocus]); - defaults.insert(Key::Char('s'), vec![Action::ToggleActiveSyncPanes]); - defaults.insert(Key::Char('f'), vec![Action::ToggleFocusFullscreen]); - - defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); - defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); - defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); - defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); - } - InputMode::Tab => { - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Locked)], - ); - defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); - defaults.insert( - Key::Ctrl('r'), - vec![Action::SwitchToMode(InputMode::Resize)], - ); - defaults.insert( - Key::Ctrl('t'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert( - Key::Ctrl('s'), - vec![Action::SwitchToMode(InputMode::Scroll)], - ); - defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); - defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); - defaults.insert( - Key::Char('\n'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert( - Key::Char(' '), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - - defaults.insert(Key::Char('h'), vec![Action::GoToPreviousTab]); - defaults.insert(Key::Char('j'), vec![Action::GoToNextTab]); - defaults.insert(Key::Char('k'), vec![Action::GoToPreviousTab]); - defaults.insert(Key::Char('l'), vec![Action::GoToNextTab]); - - defaults.insert(Key::Left, vec![Action::GoToPreviousTab]); - defaults.insert(Key::Down, vec![Action::GoToNextTab]); - defaults.insert(Key::Up, vec![Action::GoToPreviousTab]); - defaults.insert(Key::Right, vec![Action::GoToNextTab]); - - defaults.insert(Key::Char('n'), vec![Action::NewTab]); - defaults.insert(Key::Char('x'), vec![Action::CloseTab]); - - defaults.insert( - Key::Char('r'), - vec![ - Action::SwitchToMode(InputMode::RenameTab), - Action::TabNameInput(vec![0]), - ], - ); - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - for i in '1'..='9' { - defaults.insert(Key::Char(i), vec![Action::GoToTab(i.to_digit(10).unwrap())]); - } - defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); - defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); - defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); - defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); - } - InputMode::Scroll => { - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Locked)], - ); - defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]); - defaults.insert( - Key::Ctrl('r'), - vec![Action::SwitchToMode(InputMode::Resize)], - ); - defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]); - defaults.insert( - Key::Ctrl('s'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert(Key::Ctrl('q'), vec![Action::Quit]); - defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]); - defaults.insert( - Key::Char('\n'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert( - Key::Char(' '), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - - defaults.insert(Key::Char('j'), vec![Action::ScrollDown]); - defaults.insert(Key::Char('k'), vec![Action::ScrollUp]); - - defaults.insert(Key::Ctrl('f'), vec![Action::PageScrollDown]); - defaults.insert(Key::Ctrl('b'), vec![Action::PageScrollUp]); - defaults.insert(Key::PageDown, vec![Action::PageScrollDown]); - defaults.insert(Key::PageUp, vec![Action::PageScrollUp]); - - defaults.insert(Key::Down, vec![Action::ScrollDown]); - defaults.insert(Key::Up, vec![Action::ScrollUp]); - - defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); - defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); - defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); - defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); - } - InputMode::RenameTab => { - defaults.insert(Key::Char('\n'), vec![Action::SwitchToMode(InputMode::Tab)]); - defaults.insert( - Key::Ctrl('g'), - vec![Action::SwitchToMode(InputMode::Normal)], - ); - defaults.insert( - Key::Esc, - vec![ - Action::TabNameInput(vec![0x1b]), - Action::SwitchToMode(InputMode::Tab), - ], - ); - - defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]); - defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]); - defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]); - defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]); - defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]); - defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]); - defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]); - } - } - ModeKeybinds(defaults) - } - /// Converts a [`Key`] terminal event to a sequence of [`Action`]s according to the current /// [`InputMode`] and [`Keybinds`]. pub fn key_to_actions(