diff options
| author | Aram Drevekenin <aram@poor.dev> | 2023-08-24 13:36:24 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-24 13:36:24 +0200 |
| commit | bc628abc1266cdc0dbce4f19a89727527a3e39a8 (patch) | |
| tree | 6a0fcac6ec35c71a237bca0128a57a5b40afb0e3 /default-plugins/session-manager/src/main.rs | |
| parent | docs(changelog): permission system (diff) | |
| download | sl0ppij-bc628abc1266cdc0dbce4f19a89727527a3e39a8.tar.gz sl0ppij-bc628abc1266cdc0dbce4f19a89727527a3e39a8.tar.xz sl0ppij-bc628abc1266cdc0dbce4f19a89727527a3e39a8.zip | |
feat(sessions): add a session manager to switch between sessions, tabs and panes and create new ones (#2721)
* write/read session metadata to disk for all sessions
* switch session client side
* fix tests
* various adjustments
* fix full screen focus bug in tiled panes
* fix tests
* fix permission sorting issue
* cleanups
* add session manager
* fix tests
* various cleanups
* style(fmt): rustfmt
* clear screen before switching sessions
* I hate you clippy
* truncate controls line to width
* version session cache
* attempt to fix plugin tests
* style(fmt): rustfmt
* another attempt to fix the tests in the ci
Diffstat (limited to 'default-plugins/session-manager/src/main.rs')
| -rw-r--r-- | default-plugins/session-manager/src/main.rs | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/default-plugins/session-manager/src/main.rs b/default-plugins/session-manager/src/main.rs new file mode 100644 index 00000000..66ff54c4 --- /dev/null +++ b/default-plugins/session-manager/src/main.rs @@ -0,0 +1,208 @@ +mod session_list; +mod ui; +use zellij_tile::prelude::*; + +use std::collections::BTreeMap; + +use ui::{ + components::{render_controls_line, render_new_session_line, render_prompt, Colors}, + SessionUiInfo, +}; + +use session_list::SessionList; + +#[derive(Default)] +struct State { + session_name: Option<String>, + sessions: SessionList, + selected_index: Option<usize>, + search_term: String, + new_session_name: Option<String>, + colors: Colors, +} + +register_plugin!(State); + +impl ZellijPlugin for State { + fn load(&mut self, _configuration: BTreeMap<String, String>) { + subscribe(&[ + EventType::ModeUpdate, + EventType::SessionUpdate, + EventType::Key, + ]); + } + + fn update(&mut self, event: Event) -> bool { + let mut should_render = false; + match event { + Event::ModeUpdate(mode_info) => { + self.colors = Colors::new(mode_info.style.colors); + should_render = true; + }, + Event::Key(key) => { + should_render = self.handle_key(key); + }, + Event::PermissionRequestResult(_result) => { + should_render = true; + }, + Event::SessionUpdate(session_infos) => { + self.update_session_infos(session_infos); + should_render = true; + }, + _ => (), + }; + should_render + } + + fn render(&mut self, rows: usize, cols: usize) { + render_prompt( + self.new_session_name.is_some(), + &self.search_term, + self.colors, + ); + let room_for_list = rows.saturating_sub(5); // search line and controls + self.sessions.update_rows(room_for_list); + let list = self + .sessions + .render(room_for_list, cols.saturating_sub(7), self.colors); // 7 for various ui + for line in list { + println!("{}", line.render()); + } + render_new_session_line( + &self.new_session_name, + self.sessions.is_searching, + self.colors, + ); + render_controls_line(self.sessions.is_searching, rows, cols, self.colors); + } +} + +impl State { + fn reset_selected_index(&mut self) { + self.selected_index = None; + } + fn handle_key(&mut self, key: Key) -> bool { + let mut should_render = false; + if let Key::Right = key { + if self.new_session_name.is_none() { + self.sessions.result_expand(); + } + should_render = true; + } else if let Key::Left = key { + if self.new_session_name.is_none() { + self.sessions.result_shrink(); + } + should_render = true; + } else if let Key::Down = key { + if self.new_session_name.is_none() { + self.sessions.move_selection_down(); + } + should_render = true; + } else if let Key::Up = key { + if self.new_session_name.is_none() { + self.sessions.move_selection_up(); + } + should_render = true; + } else if let Key::Char(character) = key { + if character == '\n' { + self.handle_selection(); + } else if let Some(new_session_name) = self.new_session_name.as_mut() { + new_session_name.push(character); + } else { + self.search_term.push(character); + self.sessions + .update_search_term(&self.search_term, &self.colors); + } + should_render = true; + } else if let Key::Backspace = key { + if let Some(new_session_name) = self.new_session_name.as_mut() { + if new_session_name.is_empty() { + self.new_session_name = None; + } else { + new_session_name.pop(); + } + } else { + self.search_term.pop(); + self.sessions + .update_search_term(&self.search_term, &self.colors); + } + should_render = true; + } else if let Key::Ctrl('w') = key { + if self.sessions.is_searching { + // no-op + } else if self.new_session_name.is_some() { + self.new_session_name = None; + } else { + self.new_session_name = Some(String::new()); + } + should_render = true; + } else if let Key::Ctrl('c') = key { + if let Some(new_session_name) = self.new_session_name.as_mut() { + if new_session_name.is_empty() { + self.new_session_name = None; + } else { + new_session_name.clear() + } + } else if !self.search_term.is_empty() { + self.search_term.clear(); + self.sessions + .update_search_term(&self.search_term, &self.colors); + self.reset_selected_index(); + } else { + self.reset_selected_index(); + hide_self(); + } + should_render = true; + } else if let Key::Esc = key { + hide_self(); + } + should_render + } + fn handle_selection(&mut self) { + if let Some(new_session_name) = &self.new_session_name { + if new_session_name.is_empty() { + switch_session(None); + } else if self.session_name.as_ref() == Some(new_session_name) { + // noop - we're already here! + self.new_session_name = None; + } else { + switch_session(Some(new_session_name)); + } + } else if let Some(selected_session_name) = self.sessions.get_selected_session_name() { + let selected_tab = self.sessions.get_selected_tab_position(); + let selected_pane = self.sessions.get_selected_pane_id(); + let is_current_session = self.sessions.selected_is_current_session(); + if is_current_session { + if let Some((pane_id, is_plugin)) = selected_pane { + if is_plugin { + focus_plugin_pane(pane_id, true); + } else { + focus_terminal_pane(pane_id, true); + } + } else if let Some(tab_position) = selected_tab { + go_to_tab(tab_position as u32); + } + } else { + switch_session_with_focus(&selected_session_name, selected_tab, selected_pane); + } + } + hide_self(); + } + fn update_session_infos(&mut self, session_infos: Vec<SessionInfo>) { + let session_infos: Vec<SessionUiInfo> = session_infos + .iter() + .map(|s| SessionUiInfo::from_session_info(s)) + .collect(); + let current_session_name = session_infos.iter().find_map(|s| { + if s.is_current_session { + Some(s.name.clone()) + } else { + None + } + }); + if let Some(current_session_name) = current_session_name { + self.session_name = Some(current_session_name); + } + self.sessions.set_sessions(session_infos); + } +} |
