From bfcebbcd38d7bbf2aa4cce2e446fdb781bc0c4f0 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 13 Jul 2023 11:46:25 +0400 Subject: [PATCH] Add bindings for macOS tabs This doesn't represnet the movement to add tabs on any other platform, unless winit could add a similar API for them. --- CHANGELOG.md | 1 + alacritty/src/cli.rs | 5 +++ alacritty/src/config/bindings.rs | 68 ++++++++++++++++++++++++++++++ alacritty/src/display/window.rs | 46 +++++++++++++++++++- alacritty/src/event.rs | 7 ++- alacritty/src/input.rs | 37 +++++++++++++++- alacritty/src/window_context.rs | 4 ++ extra/man/alacritty-bindings.5.scd | 56 ++++++++++++++++++++++++ extra/man/alacritty.5.scd | 26 ++++++++++++ 9 files changed, 246 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef262f2a..85dd5f0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Support for keybindings with dead keys - `Back`/`Forward` mouse buttons support in bindings - Copy global IPC options (`-w -1`) for new windows +- Bindings to create and navigate tabs on macOS ### Changed diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index 7eb281d9..d2982bde 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -297,6 +297,11 @@ pub struct WindowOptions { #[clap(flatten)] /// Window options which could be passed via IPC. pub window_identity: WindowIdentity, + + #[clap(skip)] + #[cfg(target_os = "macos")] + /// The window tabbing identifier to use when building a window. + pub window_tabbing_id: Option, } /// Parameters to the `config` IPC subcommand. diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs index 5a2ca7ec..6e25ac9d 100644 --- a/alacritty/src/config/bindings.rs +++ b/alacritty/src/config/bindings.rs @@ -182,9 +182,61 @@ pub enum Action { /// Spawn a new instance of Alacritty. SpawnNewInstance, + #[cfg(target_os = "macos")] + /// Select next tab. + SelectNextTab, + + #[cfg(target_os = "macos")] + /// Select previous tab. + SelectPreviousTab, + + #[cfg(target_os = "macos")] + /// Select the first tab. + SelectTab1, + + #[cfg(target_os = "macos")] + /// Select the second tab. + SelectTab2, + + #[cfg(target_os = "macos")] + /// Select the third tab. + SelectTab3, + + #[cfg(target_os = "macos")] + /// Select the fourth tab. + SelectTab4, + + #[cfg(target_os = "macos")] + /// Select the fifth tab. + SelectTab5, + + #[cfg(target_os = "macos")] + /// Select the sixth tab. + SelectTab6, + + #[cfg(target_os = "macos")] + /// Select the seventh tab. + SelectTab7, + + #[cfg(target_os = "macos")] + /// Select the eighth tab. + SelectTab8, + + #[cfg(target_os = "macos")] + /// Select the nineth tab. + SelectTab9, + + #[cfg(target_os = "macos")] + /// Select the last tab. + SelectLastTab, + /// Create a new Alacritty window. CreateNewWindow, + #[cfg(target_os = "macos")] + /// Create new window in a tab. + CreateNewTab, + /// Toggle fullscreen. ToggleFullscreen, @@ -600,6 +652,22 @@ pub fn platform_key_bindings() -> Vec { KeyBinding; "c", ModifiersState::SUPER, +BindingMode::VI, ~BindingMode::SEARCH; Action::ClearSelection; Insert, ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[2;2~".into()); + // Tabbing api. + "t", ModifiersState::SUPER; Action::CreateNewTab; + "]", ModifiersState::SUPER | ModifiersState::SHIFT; Action::SelectNextTab; + "[", ModifiersState::SUPER | ModifiersState::SHIFT; Action::SelectPreviousTab; + Tab, ModifiersState::SUPER; Action::SelectNextTab; + Tab, ModifiersState::SUPER | ModifiersState::SHIFT; Action::SelectPreviousTab; + "1", ModifiersState::SUPER; Action::SelectTab1; + "2", ModifiersState::SUPER; Action::SelectTab2; + "3", ModifiersState::SUPER; Action::SelectTab3; + "4", ModifiersState::SUPER; Action::SelectTab4; + "5", ModifiersState::SUPER; Action::SelectTab5; + "6", ModifiersState::SUPER; Action::SelectTab6; + "7", ModifiersState::SUPER; Action::SelectTab7; + "8", ModifiersState::SUPER; Action::SelectTab8; + "9", ModifiersState::SUPER; Action::SelectLastTab; + "0", ModifiersState::SUPER; Action::ResetFontSize; "=", ModifiersState::SUPER; Action::IncreaseFontSize; "+", ModifiersState::SUPER; Action::IncreaseFontSize; diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 942b28ee..c7ad37c8 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -122,6 +122,9 @@ impl Window { config: &UiConfig, identity: &Identity, #[rustfmt::skip] + #[cfg(target_os = "macos")] + tabbing_id: &Option, + #[rustfmt::skip] #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] x11_visual: Option, ) -> Result { @@ -131,6 +134,8 @@ impl Window { &config.window, #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] x11_visual, + #[cfg(target_os = "macos")] + tabbing_id, ); if let Some(position) = config.window.position { @@ -284,8 +289,16 @@ impl Window { } #[cfg(target_os = "macos")] - pub fn get_platform_window(_: &Identity, window_config: &WindowConfig) -> WindowBuilder { - let window = WindowBuilder::new().with_option_as_alt(window_config.option_as_alt()); + pub fn get_platform_window( + _: &Identity, + window_config: &WindowConfig, + tabbing_id: &Option, + ) -> WindowBuilder { + let mut window = WindowBuilder::new().with_option_as_alt(window_config.option_as_alt()); + + if let Some(tabbing_id) = tabbing_id { + window = window.with_tabbing_identifier(tabbing_id); + } match window_config.decorations { Decorations::Full => window, @@ -406,6 +419,35 @@ impl Window { let _: id = msg_send![raw_window, setHasShadow: value]; } } + + /// Select tab at the given `index`. + #[cfg(target_os = "macos")] + pub fn select_tab_at_index(&self, index: usize) { + self.window.select_tab_at_index(index); + } + + /// Select the last tab. + #[cfg(target_os = "macos")] + pub fn select_last_tab(&self) { + self.window.select_tab_at_index(self.window.num_tabs() - 1); + } + + /// Select next tab. + #[cfg(target_os = "macos")] + pub fn select_next_tab(&self) { + self.window.select_next_tab(); + } + + /// Select previous tab. + #[cfg(target_os = "macos")] + pub fn select_previous_tab(&self) { + self.window.select_previous_tab(); + } + + #[cfg(target_os = "macos")] + pub fn tabbing_id(&self) -> String { + self.window.tabbing_identifier() + } } #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 6717e0ab..387e768e 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -392,12 +392,17 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon } #[cfg(not(windows))] - fn create_new_window(&mut self) { + fn create_new_window(&mut self, #[cfg(target_os = "macos")] tabbing_id: Option) { let mut options = WindowOptions::default(); if let Ok(working_directory) = foreground_process_path(self.master_fd, self.shell_pid) { options.terminal_options.working_directory = Some(working_directory); } + #[cfg(target_os = "macos")] + { + options.window_tabbing_id = tabbing_id; + } + let _ = self.event_proxy.send_event(Event::new(EventType::CreateWindow(options), None)); } diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index 54580fa6..14413f75 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -98,6 +98,9 @@ pub trait ActionContext { fn terminal(&self) -> &Term; fn terminal_mut(&mut self) -> &mut Term; fn spawn_new_instance(&mut self) {} + #[cfg(target_os = "macos")] + fn create_new_window(&mut self, _tabbing_id: Option) {} + #[cfg(not(target_os = "macos"))] fn create_new_window(&mut self) {} fn change_font_size(&mut self, _delta: f32) {} fn reset_font_size(&mut self) {} @@ -363,8 +366,40 @@ impl Execute for Action { }, Action::ClearHistory => ctx.terminal_mut().clear_screen(ClearMode::Saved), Action::ClearLogNotice => ctx.pop_message(), - Action::SpawnNewInstance => ctx.spawn_new_instance(), + #[cfg(not(target_os = "macos"))] Action::CreateNewWindow => ctx.create_new_window(), + Action::SpawnNewInstance => ctx.spawn_new_instance(), + #[cfg(target_os = "macos")] + Action::CreateNewWindow => ctx.create_new_window(None), + #[cfg(target_os = "macos")] + Action::CreateNewTab => { + let tabbing_id = Some(ctx.window().tabbing_id()); + ctx.create_new_window(tabbing_id); + }, + #[cfg(target_os = "macos")] + Action::SelectNextTab => ctx.window().select_next_tab(), + #[cfg(target_os = "macos")] + Action::SelectPreviousTab => ctx.window().select_previous_tab(), + #[cfg(target_os = "macos")] + Action::SelectTab1 => ctx.window().select_tab_at_index(0), + #[cfg(target_os = "macos")] + Action::SelectTab2 => ctx.window().select_tab_at_index(1), + #[cfg(target_os = "macos")] + Action::SelectTab3 => ctx.window().select_tab_at_index(2), + #[cfg(target_os = "macos")] + Action::SelectTab4 => ctx.window().select_tab_at_index(3), + #[cfg(target_os = "macos")] + Action::SelectTab5 => ctx.window().select_tab_at_index(4), + #[cfg(target_os = "macos")] + Action::SelectTab6 => ctx.window().select_tab_at_index(5), + #[cfg(target_os = "macos")] + Action::SelectTab7 => ctx.window().select_tab_at_index(6), + #[cfg(target_os = "macos")] + Action::SelectTab8 => ctx.window().select_tab_at_index(7), + #[cfg(target_os = "macos")] + Action::SelectTab9 => ctx.window().select_tab_at_index(8), + #[cfg(target_os = "macos")] + Action::SelectLastTab => ctx.window().select_last_tab(), Action::ReceiveChar | Action::None => (), } } diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index 0dd4b4bb..84ce4457 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -103,6 +103,8 @@ impl WindowContext { &identity, #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] gl_config.x11_visual(), + #[cfg(target_os = "macos")] + &options.window_tabbing_id, )?; // Create context. @@ -135,6 +137,8 @@ impl WindowContext { &identity, #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] gl_config.x11_visual(), + #[cfg(target_os = "macos")] + &options.window_tabbing_id, )?; // Create context. diff --git a/extra/man/alacritty-bindings.5.scd b/extra/man/alacritty-bindings.5.scd index 6ad98680..a8f8dfe0 100644 --- a/extra/man/alacritty-bindings.5.scd +++ b/extra/man/alacritty-bindings.5.scd @@ -450,6 +450,10 @@ configuration. See *alacritty*(5) for full configuration format documentation. : _"Command"_ :[ : _"CreateNewWindow"_ +| _"T"_ +: _"Command"_ +:[ +: _"CreateNewTab"_ | _"F"_ : _"Command|Control"_ :[ @@ -462,6 +466,58 @@ configuration. See *alacritty*(5) for full configuration format documentation. : _"Command"_ : _"~Search"_ : _"SearchBackward"_ +| _"]"_ +: _"Command|Shift"_ +:[ +: _"SelectNextTab"_ +| _"["_ +: _"Command|Shift"_ +:[ +: _"SelectPreviousTab"_ +| _"Tab"_ +: _"Command"_ +:[ +: _"SelectNextTab"_ +| _"Tab"_ +: _"Command|Shift"_ +:[ +: _"SelectPreviousTab"_ +| _"1"_ +: _"Command"_ +:[ +: _"SelectTab1"_ +| _"2"_ +: _"Command"_ +:[ +: _"SelectTab2"_ +| _"3"_ +: _"Command"_ +:[ +: _"SelectTab3"_ +| _"4"_ +: _"Command"_ +:[ +: _"SelectTab4"_ +| _"5"_ +: _"Command"_ +:[ +: _"SelectTab5"_ +| _"6"_ +: _"Command"_ +:[ +: _"SelectTab6"_ +| _"7"_ +: _"Command"_ +:[ +: _"SelectTab7"_ +| _"8"_ +: _"Command"_ +:[ +: _"SelectTab8"_ +| _"2 9"_ +: _"Command"_ +:[ +: _"SelectLastTab"_ # SEE ALSO diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index f3cff4ed..8d44e019 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -843,6 +843,32 @@ https://docs.rs/winit/\*/winit/keyboard/enum.Key.html Enter fullscreen without occupying another space. *HideOtherApplications* Hide all windows other than Alacritty. + *CreateNewTab* + Create new window in a tab. + *SelectNextTab* + Select next tab. + *SelectPreviousTab* + Select previous tab. + *SelectTab1* + Select the first tab. + *SelectTab2* + Select the second tab. + *SelectTab3* + Select the third tab. + *SelectTab4* + Select the fourth tab. + *SelectTab5* + Select the fifth tab. + *SelectTab6* + Select the sixth tab. + *SelectTab7* + Select the seventh tab. + *SelectTab8* + Select the eighth tab. + *SelectTab9* + Select the nineth tab. + *SelectLastTab* + Select the last tab. _Linux/BSD exclusive:_