diff options
| author | Jonah Caplan <jonahcaplan@gmail.com> | 2021-02-20 18:19:05 -0500 |
|---|---|---|
| committer | Jonah Caplan <jonahcaplan@gmail.com> | 2021-02-25 01:44:10 -0500 |
| commit | ce54127d7de314e683ed0fefd8be987bbc47e369 (patch) | |
| tree | 0fd91434af3477f9b7c16a61b822537a18abcca2 /src | |
| parent | Make fullscreen panes not override the status bar and strider (#209) (diff) | |
| download | sl0ppij-ce54127d7de314e683ed0fefd8be987bbc47e369.tar.gz sl0ppij-ce54127d7de314e683ed0fefd8be987bbc47e369.tar.xz sl0ppij-ce54127d7de314e683ed0fefd8be987bbc47e369.zip | |
add basic tab bar #166
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/tab.rs | 3 | ||||
| -rw-r--r-- | src/common/errors.rs | 4 | ||||
| -rw-r--r-- | src/common/input/actions.rs | 1 | ||||
| -rw-r--r-- | src/common/input/handler.rs | 5 | ||||
| -rw-r--r-- | src/common/input/keybinds.rs | 3 | ||||
| -rw-r--r-- | src/common/mod.rs | 14 | ||||
| -rw-r--r-- | src/common/screen.rs | 79 | ||||
| -rw-r--r-- | src/common/wasm_vm.rs | 1 | ||||
| -rw-r--r-- | src/main.rs | 1 |
9 files changed, 93 insertions, 18 deletions
diff --git a/src/client/tab.rs b/src/client/tab.rs index bdbf7db1..bf096367 100644 --- a/src/client/tab.rs +++ b/src/client/tab.rs @@ -50,6 +50,7 @@ fn split_horizontally_with_gap(rect: &PositionAndSize) -> (PositionAndSize, Posi pub struct Tab { pub index: usize, + pub position: usize, panes: BTreeMap<PaneId, Box<dyn Pane>>, panes_to_hide: HashSet<PaneId>, active_terminal: Option<PaneId>, @@ -168,6 +169,7 @@ impl Tab { // FIXME: Too many arguments here! Maybe bundle all of the senders for the whole program in a struct? pub fn new( index: usize, + position: usize, full_screen_ws: &PositionAndSize, mut os_api: Box<dyn OsApi>, send_pty_instructions: SenderWithContext<PtyInstruction>, @@ -191,6 +193,7 @@ impl Tab { }; Tab { index, + position, panes, max_panes, panes_to_hide: HashSet::new(), diff --git a/src/common/errors.rs b/src/common/errors.rs index 3d105dbc..03aec714 100644 --- a/src/common/errors.rs +++ b/src/common/errors.rs @@ -197,6 +197,7 @@ pub enum ScreenContext { SwitchTabNext, SwitchTabPrev, CloseTab, + GoToTab, } impl From<&ScreenInstruction> for ScreenContext { @@ -234,6 +235,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::SwitchTabNext => ScreenContext::SwitchTabNext, ScreenInstruction::SwitchTabPrev => ScreenContext::SwitchTabPrev, ScreenInstruction::CloseTab => ScreenContext::CloseTab, + ScreenInstruction::GoToTab(_) => ScreenContext::GoToTab, } } } @@ -277,6 +279,7 @@ pub enum PluginContext { GlobalInput, Unload, Quit, + Tabs, } impl From<&PluginInstruction> for PluginContext { @@ -288,6 +291,7 @@ impl From<&PluginInstruction> for PluginContext { PluginInstruction::GlobalInput(_) => PluginContext::GlobalInput, PluginInstruction::Unload(_) => PluginContext::Unload, PluginInstruction::Quit => PluginContext::Quit, + PluginInstruction::UpdateTabs(..) => PluginContext::Tabs, } } } diff --git a/src/common/input/actions.rs b/src/common/input/actions.rs index eee8b1b6..fe5e2dad 100644 --- a/src/common/input/actions.rs +++ b/src/common/input/actions.rs @@ -47,4 +47,5 @@ pub enum Action { GoToPreviousTab, /// Close the current tab. CloseTab, + GoToTab(u32), } diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs index 2a8c3bfa..5c4f1971 100644 --- a/src/common/input/handler.rs +++ b/src/common/input/handler.rs @@ -227,6 +227,11 @@ impl InputHandler { .unwrap(); self.command_is_executing.wait_until_pane_is_closed(); } + Action::GoToTab(i) => { + self.send_screen_instructions + .send(ScreenInstruction::GoToTab(i)) + .unwrap(); + } Action::NoOp => {} } diff --git a/src/common/input/keybinds.rs b/src/common/input/keybinds.rs index c573a557..e56488b4 100644 --- a/src/common/input/keybinds.rs +++ b/src/common/input/keybinds.rs @@ -133,6 +133,9 @@ fn get_defaults_for_mode(mode: &InputMode) -> Result<ModeKeybinds, String> { 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::Esc, vec![Action::SwitchToMode(InputMode::Command)]); } InputMode::Scroll => { diff --git a/src/common/mod.rs b/src/common/mod.rs index 8f37994f..f78303ea 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -416,6 +416,9 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) { screen.apply_layout(layout, new_pane_pids); command_is_executing.done_opening_new_pane(); } + ScreenInstruction::GoToTab(tab_index) => { + screen.go_to_tab(tab_index as usize) + } ScreenInstruction::Quit => { break; } @@ -511,6 +514,17 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) { buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap(); } + PluginInstruction::UpdateTabs(active_tab_index, num_tabs) => { + for (instance, _) in plugin_map.values() { + let handler = instance.exports.get_function("update_tabs").unwrap(); + handler + .call(&[ + Value::I32(active_tab_index as i32), + Value::I32(num_tabs as i32), + ]) + .unwrap(); + } + } // FIXME: Deduplicate this with the callback below! PluginInstruction::Input(pid, input_bytes) => { let (instance, plugin_env) = plugin_map.get(&pid).unwrap(); diff --git a/src/common/screen.rs b/src/common/screen.rs index 1e04e231..7747b43b 100644 --- a/src/common/screen.rs +++ b/src/common/screen.rs @@ -45,6 +45,7 @@ pub enum ScreenInstruction { SwitchTabNext, SwitchTabPrev, CloseTab, + GoToTab(u32), } /// A [`Screen`] holds multiple [`Tab`]s, each one holding multiple [`panes`](crate::client::panes). @@ -98,8 +99,10 @@ impl Screen { /// [pane](crate::client::panes) with PTY file descriptor `pane_id`. pub fn new_tab(&mut self, pane_id: RawFd) { let tab_index = self.get_new_tab_index(); + let position = self.tabs.len(); let tab = Tab::new( tab_index, + position, &self.full_screen_ws, self.os_api.clone(), self.send_pty_instructions.clone(), @@ -110,6 +113,7 @@ impl Screen { ); self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); + self.update_tabs(); self.render(); } @@ -126,34 +130,52 @@ impl Screen { /// Sets this [`Screen`]'s active [`Tab`] to the next tab. pub fn switch_tab_next(&mut self) { - let active_tab_id = self.get_active_tab().unwrap().index; - let tab_ids: Vec<usize> = self.tabs.keys().copied().collect(); - let first_tab = tab_ids.get(0).unwrap(); - let active_tab_id_position = tab_ids.iter().position(|id| id == &active_tab_id).unwrap(); - if let Some(next_tab) = tab_ids.get(active_tab_id_position + 1) { - self.active_tab_index = Some(*next_tab); - } else { - self.active_tab_index = Some(*first_tab); + let active_tab_pos = self.get_active_tab().unwrap().position; + let new_tab_pos = (active_tab_pos + 1) % self.tabs.len(); + + for tab in self.tabs.values() { + if tab.position == new_tab_pos { + self.active_tab_index = Some(tab.index); + break; + } } + self.update_tabs(); self.render(); } /// Sets this [`Screen`]'s active [`Tab`] to the previous tab. pub fn switch_tab_prev(&mut self) { - let active_tab_id = self.get_active_tab().unwrap().index; - let tab_ids: Vec<usize> = self.tabs.keys().copied().collect(); - let first_tab = tab_ids.get(0).unwrap(); - let last_tab = tab_ids.last().unwrap(); - - let active_tab_id_position = tab_ids.iter().position(|id| id == &active_tab_id).unwrap(); - if active_tab_id == *first_tab { - self.active_tab_index = Some(*last_tab) - } else if let Some(prev_tab) = tab_ids.get(active_tab_id_position - 1) { - self.active_tab_index = Some(*prev_tab) + let active_tab_pos = self.get_active_tab().unwrap().position; + let new_tab_pos = if active_tab_pos == 0 { + self.tabs.len() - 1 + } else { + active_tab_pos - 1 + }; + for tab in self.tabs.values() { + if tab.position == new_tab_pos { + self.active_tab_index = Some(tab.index); + break; + } } + self.update_tabs(); self.render(); } + pub fn go_to_tab(&mut self, mut tab_index: usize) { + tab_index -= 1; + let active_tab = self.get_active_tab().unwrap(); + match self.tabs.values().find(|t| t.position == tab_index) { + Some(t) => { + if t.index != active_tab.index { + self.active_tab_index = Some(t.index); + self.update_tabs(); + self.render(); + } + } + None => {} + } + } + /// Closes this [`Screen`]'s active [`Tab`], exiting the application if it happens /// to be the last tab. pub fn close_tab(&mut self) { @@ -174,6 +196,13 @@ impl Screen { self.send_app_instructions .send(AppInstruction::Exit) .unwrap(); + } else { + for t in self.tabs.values_mut() { + if t.position > active_tab.position { + t.position -= 1; + } + } + self.update_tabs(); } } @@ -213,8 +242,10 @@ impl Screen { /// and switching to it. pub fn apply_layout(&mut self, layout: Layout, new_pids: Vec<RawFd>) { let tab_index = self.get_new_tab_index(); + let position = self.tabs.len(); let mut tab = Tab::new( tab_index, + position, &self.full_screen_ws, self.os_api.clone(), self.send_pty_instructions.clone(), @@ -226,5 +257,17 @@ impl Screen { tab.apply_layout(layout, new_pids); self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); + self.update_tabs(); + } + + fn update_tabs(&self) { + if let Some(active_tab) = self.get_active_tab() { + self.send_plugin_instructions + .send(PluginInstruction::UpdateTabs( + active_tab.position, + self.tabs.len(), + )) + .unwrap(); + } } } diff --git a/src/common/wasm_vm.rs b/src/common/wasm_vm.rs index 70808b5d..5d4b1e30 100644 --- a/src/common/wasm_vm.rs +++ b/src/common/wasm_vm.rs @@ -18,6 +18,7 @@ pub enum PluginInstruction { Input(u32, Vec<u8>), // plugin id, input bytes GlobalInput(Vec<u8>), // input bytes Unload(u32), + UpdateTabs(usize, usize), // num tabs, active tab Quit, } diff --git a/src/main.rs b/src/main.rs index 91a7b422..c4123e55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,7 @@ pub fn main() { let data_dir = project_dirs.data_dir(); let assets = asset_map! { "target/status-bar.wasm" => "plugins/status-bar.wasm", + "target/tab-bar.wasm" => "plugins/tab-bar.wasm", "target/strider.wasm" => "plugins/strider.wasm", "assets/layouts/default.yaml" => "layouts/default.yaml", "assets/layouts/strider.yaml" => "layouts/strider.yaml", |
