diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-02-24 13:10:40 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-24 13:10:40 +0100 |
| commit | 8cd6286c3ffc10d14fdafd5005fa89b0f7fdcd44 (patch) | |
| tree | c6341f5e3e251ae17db0c3427ddaf1e54d4fa91c /default-plugins/sequence/src/state | |
| parent | Allow closing replaced panes when opening panes in place (#4760) (diff) | |
| download | sl0ppij-8cd6286c3ffc10d14fdafd5005fa89b0f7fdcd44.tar.gz sl0ppij-8cd6286c3ffc10d14fdafd5005fa89b0f7fdcd44.tar.xz sl0ppij-8cd6286c3ffc10d14fdafd5005fa89b0f7fdcd44.zip | |
remove sequence plugin (#4761)
Diffstat (limited to 'default-plugins/sequence/src/state')
| -rw-r--r-- | default-plugins/sequence/src/state/chain_type.rs | 45 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/command_entry.rs | 76 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/command_parser.rs | 370 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/command_status.rs | 26 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/execution.rs | 87 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/layout.rs | 19 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/mod.rs | 231 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/selection.rs | 47 | ||||
| -rw-r--r-- | default-plugins/sequence/src/state/sequence_mode.rs | 6 |
9 files changed, 0 insertions, 907 deletions
diff --git a/default-plugins/sequence/src/state/chain_type.rs b/default-plugins/sequence/src/state/chain_type.rs deleted file mode 100644 index 3da3316c..00000000 --- a/default-plugins/sequence/src/state/chain_type.rs +++ /dev/null @@ -1,45 +0,0 @@ -use serde::{Deserialize, Serialize}; -use zellij_tile::prelude::*; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum ChainType { - And, - Or, - Then, - None, -} - -impl Default for ChainType { - fn default() -> Self { - ChainType::None - } -} - -impl ChainType { - pub fn to_unblock_condition(&self) -> Option<UnblockCondition> { - match self { - ChainType::And => Some(UnblockCondition::OnExitSuccess), - ChainType::Or => Some(UnblockCondition::OnExitFailure), - ChainType::Then => Some(UnblockCondition::OnAnyExit), - ChainType::None => None, - } - } - - pub fn as_str(&self) -> &str { - match self { - ChainType::And => "&&", - ChainType::Or => "||", - ChainType::Then => ";", - ChainType::None => "", - } - } - - pub fn cycle_next(&mut self) { - *self = match self { - ChainType::And => ChainType::Or, - ChainType::Or => ChainType::Then, - ChainType::Then => ChainType::And, - ChainType::None => ChainType::And, - }; - } -} diff --git a/default-plugins/sequence/src/state/command_entry.rs b/default-plugins/sequence/src/state/command_entry.rs deleted file mode 100644 index 4ca9350a..00000000 --- a/default-plugins/sequence/src/state/command_entry.rs +++ /dev/null @@ -1,76 +0,0 @@ -use super::{ChainType, CommandStatus}; -use std::path::PathBuf; -use zellij_tile::prelude::PaneId; - -#[derive(Debug, Clone)] -pub struct CommandEntry { - text: String, - cwd: Option<PathBuf>, - pub(super) chain_type: ChainType, - pub(super) status: CommandStatus, -} - -impl Default for CommandEntry { - fn default() -> Self { - CommandEntry { - text: String::default(), - cwd: None, - chain_type: ChainType::default(), - status: CommandStatus::default(), - } - } -} - -impl CommandEntry { - pub fn new(text: &str, cwd: Option<PathBuf>) -> Self { - CommandEntry { - text: text.to_owned(), - cwd, - ..Default::default() - } - } - pub fn get_text(&self) -> String { - self.text.clone() - } - pub fn set_text(&mut self, text: String) { - self.text = text; - } - pub fn clear_text(&mut self) { - self.text.clear(); - } - pub fn get_chain_type(&self) -> ChainType { - self.chain_type - } - pub fn set_chain_type(&mut self, chain_type: ChainType) { - self.chain_type = chain_type; - } - pub fn get_status(&self) -> CommandStatus { - self.status.clone() - } - pub fn set_status(&mut self, status: CommandStatus) { - self.status = status; - } - pub fn get_pane_id(&self) -> Option<PaneId> { - self.status.get_pane_id() - } - pub fn is_empty(&self) -> bool { - self.text.trim().is_empty() - } - pub fn fill_chain_type_if_empty(&mut self) { - if let ChainType::None = self.chain_type { - self.chain_type = ChainType::And; - } - } - pub fn clear_chain_type(&mut self) { - self.chain_type = ChainType::None; - } - pub fn clear_status(&mut self) { - self.status = CommandStatus::Pending; - } - pub fn get_cwd(&self) -> Option<PathBuf> { - self.cwd.clone() - } - pub fn set_cwd(&mut self, cwd: Option<PathBuf>) { - self.cwd = cwd; - } -} diff --git a/default-plugins/sequence/src/state/command_parser.rs b/default-plugins/sequence/src/state/command_parser.rs deleted file mode 100644 index 35935cd3..00000000 --- a/default-plugins/sequence/src/state/command_parser.rs +++ /dev/null @@ -1,370 +0,0 @@ -use super::{ChainType, CommandEntry}; - -#[derive(Debug, Clone, Copy, PartialEq)] -enum ParseState { - Normal, - InSingleQuote, - InDoubleQuote, - Escaped(EscapeContext), -} - -#[derive(Debug, Clone, Copy, PartialEq)] -enum EscapeContext { - Normal, - DoubleQuote, -} - -pub fn split_by_chain_operators(text: &str) -> Vec<(String, Option<ChainType>)> { - let mut segments = Vec::new(); - let mut current_segment = String::new(); - let mut state = ParseState::Normal; - let chars: Vec<char> = text.chars().collect(); - let mut i = 0; - - while i < chars.len() { - let ch = chars[i]; - - match state { - ParseState::Normal => { - if ch == '\\' { - state = ParseState::Escaped(EscapeContext::Normal); - current_segment.push(ch); - i += 1; - } else if ch == '\'' { - state = ParseState::InSingleQuote; - current_segment.push(ch); - i += 1; - } else if ch == '"' { - state = ParseState::InDoubleQuote; - current_segment.push(ch); - i += 1; - } else if ch == '&' && i + 1 < chars.len() && chars[i + 1] == '&' { - let segment_text = current_segment.trim().to_string(); - if !segment_text.is_empty() { - segments.push((segment_text, Some(ChainType::And))); - } - current_segment.clear(); - i += 2; - } else if ch == '|' && i + 1 < chars.len() && chars[i + 1] == '|' { - let segment_text = current_segment.trim().to_string(); - if !segment_text.is_empty() { - segments.push((segment_text, Some(ChainType::Or))); - } - current_segment.clear(); - i += 2; - } else if ch == ';' { - let segment_text = current_segment.trim().to_string(); - if !segment_text.is_empty() { - segments.push((segment_text, Some(ChainType::Then))); - } - current_segment.clear(); - i += 1; - } else { - current_segment.push(ch); - i += 1; - } - }, - ParseState::InSingleQuote => { - current_segment.push(ch); - if ch == '\'' { - state = ParseState::Normal; - } - i += 1; - }, - ParseState::InDoubleQuote => { - if ch == '\\' { - state = ParseState::Escaped(EscapeContext::DoubleQuote); - current_segment.push(ch); - i += 1; - } else if ch == '"' { - current_segment.push(ch); - state = ParseState::Normal; - i += 1; - } else { - current_segment.push(ch); - i += 1; - } - }, - ParseState::Escaped(context) => { - current_segment.push(ch); - state = match context { - EscapeContext::Normal => ParseState::Normal, - EscapeContext::DoubleQuote => ParseState::InDoubleQuote, - }; - i += 1; - }, - } - } - - let final_segment = current_segment.trim().to_string(); - if !final_segment.is_empty() { - segments.push((final_segment, None)); - } - - segments -} - -pub fn detect_cd_command(text: &str) -> Option<String> { - let trimmed = text.trim(); - - if trimmed == "cd" { - return Some("~".to_string()); - } - - if trimmed.starts_with("cd ") { - let path = trimmed[3..].trim(); - return Some(path.to_string()); - } - - None -} - -/// Serialize a sequence of commands to editor format. -/// CWD changes are emitted as `cd <path>` lines; chain type as trailing ` &&`, ` ||`, ` ;`. -pub fn serialize_sequence_to_editor(commands: &[CommandEntry]) -> String { - let mut result = String::new(); - - result.push_str("# One cmd per line. Use && || ; to chain. cd <path> sets cwd.\n"); - result.push_str("\n"); - - let mut prev_cwd: Option<std::path::PathBuf> = None; - - for cmd in commands { - if cmd.get_text().trim().is_empty() { - continue; - } - - let cmd_cwd = cmd.get_cwd(); - if cmd_cwd != prev_cwd && cmd_cwd.is_some() { - let path = cmd_cwd.as_ref().unwrap(); - result.push_str(&format!("cd {}\n", path.display())); - } - prev_cwd = cmd_cwd; - - let op_suffix = match cmd.get_chain_type() { - ChainType::And => " &&", - ChainType::Or => " ||", - ChainType::Then => " ;", - ChainType::None => "", - }; - - result.push_str(&format!("{}{}\n", cmd.get_text(), op_suffix)); - } - - result -} - -/// Parse command text into a Vec<CommandEntry>. -/// `cd <path>` lines set the cwd for subsequent commands. -/// Blank lines and `#` comment lines are ignored. -pub fn parse_commands( - contents: &str, - initial_cwd: Option<std::path::PathBuf>, -) -> Vec<CommandEntry> { - use crate::path_formatting; - let mut commands = Vec::new(); - let mut current_cwd = initial_cwd; - - for line in contents.lines() { - let trimmed = line.trim(); - if trimmed.is_empty() || trimmed.starts_with('#') { - continue; - } - - // Split by chain operators first so that "cd /path &&" doesn't absorb the operator - // into the path. Each resulting segment is then checked for cd independently. - let segments = split_by_chain_operators(trimmed); - for (text, chain_type_opt) in segments { - let text = text.trim().to_string(); - if text.is_empty() { - continue; - } - if let Some(path) = detect_cd_command(&text) { - if let Some(new_cwd) = path_formatting::resolve_path(current_cwd.as_ref(), &path) { - current_cwd = Some(new_cwd); - } - // cd segments are not added as command entries; their chain type is discarded - } else { - let mut entry = CommandEntry::new(&text, current_cwd.clone()); - if let Some(chain_type) = chain_type_opt { - entry.set_chain_type(chain_type); - } - commands.push(entry); - } - } - } - - // Commands with no explicit operator default to && - if !commands.is_empty() { - let last_idx = commands.len() - 1; - for cmd in &mut commands[..last_idx] { - cmd.fill_chain_type_if_empty(); - } - } - - commands -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_single_command_no_operator() { - let result = split_by_chain_operators("ls"); - assert_eq!(result, vec![("ls".to_string(), None)]); - } - - #[test] - fn test_two_commands_with_and() { - let result = split_by_chain_operators("ls && pwd"); - assert_eq!( - result, - vec![ - ("ls".to_string(), Some(ChainType::And)), - ("pwd".to_string(), None) - ] - ); - } - - #[test] - fn test_two_commands_with_or() { - let result = split_by_chain_operators("cmd1 || cmd2"); - assert_eq!( - result, - vec![ - ("cmd1".to_string(), Some(ChainType::Or)), - ("cmd2".to_string(), None) - ] - ); - } - - #[test] - fn test_two_commands_with_semicolon() { - let result = split_by_chain_operators("echo hi ; ls"); - assert_eq!( - result, - vec![ - ("echo hi".to_string(), Some(ChainType::Then)), - ("ls".to_string(), None) - ] - ); - } - - #[test] - fn test_three_commands_mixed() { - let result = split_by_chain_operators("a && b || c"); - assert_eq!( - result, - vec![ - ("a".to_string(), Some(ChainType::And)), - ("b".to_string(), Some(ChainType::Or)), - ("c".to_string(), None) - ] - ); - } - - #[test] - fn test_operator_in_single_quotes() { - let result = split_by_chain_operators("echo '&&' && ls"); - assert_eq!( - result, - vec![ - ("echo '&&'".to_string(), Some(ChainType::And)), - ("ls".to_string(), None) - ] - ); - } - - #[test] - fn test_operator_in_double_quotes() { - let result = split_by_chain_operators("echo \"||\" || pwd"); - assert_eq!( - result, - vec![ - ("echo \"||\"".to_string(), Some(ChainType::Or)), - ("pwd".to_string(), None) - ] - ); - } - - #[test] - fn test_escaped_operator() { - let result = split_by_chain_operators("echo \\&& test"); - assert_eq!(result, vec![("echo \\&& test".to_string(), None)]); - } - - #[test] - fn test_complex_quoting() { - let result = split_by_chain_operators("cmd1 && echo \"a || b\" && cmd2"); - assert_eq!( - result, - vec![ - ("cmd1".to_string(), Some(ChainType::And)), - ("echo \"a || b\"".to_string(), Some(ChainType::And)), - ("cmd2".to_string(), None) - ] - ); - } - - #[test] - fn test_empty_segments_filtered() { - let result = split_by_chain_operators("cmd1 && && cmd2"); - assert_eq!( - result, - vec![ - ("cmd1".to_string(), Some(ChainType::And)), - ("cmd2".to_string(), None) - ] - ); - } - - #[test] - fn test_whitespace_trimming() { - let result = split_by_chain_operators(" cmd1 && cmd2 "); - assert_eq!( - result, - vec![ - ("cmd1".to_string(), Some(ChainType::And)), - ("cmd2".to_string(), None) - ] - ); - } - - #[test] - fn test_trailing_operator_with_space() { - let result = split_by_chain_operators("ls && "); - assert_eq!(result, vec![("ls".to_string(), Some(ChainType::And))]); - } - - #[test] - fn test_editor_file_no_operator_defaults_to_and() { - let contents = "cmd1\ncmd2\ncmd3"; - let result = parse_commands(contents, None); - assert_eq!(result.len(), 3); - assert_eq!(result[0].get_chain_type(), ChainType::And); - assert_eq!(result[1].get_chain_type(), ChainType::And); - assert_eq!(result[2].get_chain_type(), ChainType::None); - } - - #[test] - fn test_editor_file_explicit_operator_preserved() { - let contents = "cmd1 ||\ncmd2"; - let result = parse_commands(contents, None); - assert_eq!(result.len(), 2); - assert_eq!(result[0].get_chain_type(), ChainType::Or); - assert_eq!(result[1].get_chain_type(), ChainType::None); - } - - #[test] - fn test_cd_with_chain_operator_does_not_absorb_operator_into_path() { - use super::super::CommandEntry; - use std::path::PathBuf; - - let contents = "cd /some/path && cargo build"; - let result = parse_commands(contents, None); - assert_eq!(result.len(), 1); - assert_eq!(result[0].get_text(), "cargo build"); - assert_eq!(result[0].get_cwd(), Some(PathBuf::from("/some/path"))); - } -} diff --git a/default-plugins/sequence/src/state/command_status.rs b/default-plugins/sequence/src/state/command_status.rs deleted file mode 100644 index 39717e8b..00000000 --- a/default-plugins/sequence/src/state/command_status.rs +++ /dev/null @@ -1,26 +0,0 @@ -use zellij_tile::prelude::*; - -#[derive(Debug, Clone)] -pub enum CommandStatus { - Exited(Option<i32>, Option<PaneId>), - Running(Option<PaneId>), - Pending, - Interrupted(Option<PaneId>), -} - -impl CommandStatus { - pub fn get_pane_id(&self) -> Option<PaneId> { - match self { - CommandStatus::Exited(_, pane_id) => *pane_id, - CommandStatus::Running(pane_id) => *pane_id, - CommandStatus::Pending => None, - CommandStatus::Interrupted(pane_id) => *pane_id, - } - } -} - -impl Default for CommandStatus { - fn default() -> Self { - CommandStatus::Pending - } -} diff --git a/default-plugins/sequence/src/state/execution.rs b/default-plugins/sequence/src/state/execution.rs deleted file mode 100644 index 42d4112a..00000000 --- a/default-plugins/sequence/src/state/execution.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::path_formatting::format_cwd; -use crate::state::{CommandEntry, CommandStatus}; -use std::path::PathBuf; -use zellij_tile::prelude::*; - -pub struct Execution { - pub all_commands: Vec<CommandEntry>, - pub current_running_command_index: usize, - pub is_running: bool, - pub displayed_pane_id: Option<PaneId>, -} - -impl Execution { - pub fn new() -> Self { - Self { - all_commands: vec![CommandEntry::default()], - current_running_command_index: 0, - is_running: false, - displayed_pane_id: None, - } - } - - pub fn longest_cwd_display(&self, global_cwd: &Option<PathBuf>) -> String { - self.all_commands - .iter() - .map(|cmd| { - let cwd = cmd.get_cwd().or_else(|| global_cwd.clone()); - if let Some(cwd) = &cwd { - format_cwd(cwd) - } else { - "~".to_string() - } - }) - .max_by_key(|s| s.len()) - .unwrap_or_else(|| "~".to_string()) - } - - pub fn remove_empty_commands(&mut self) { - if self.all_commands.iter().len() > 1 { - self.all_commands.retain(|c| !c.get_text().is_empty()); - } - } - - pub fn get_first_command(&self) -> Option<CommandEntry> { - self.all_commands.iter().next().cloned() - } - - pub fn set_command_status(&mut self, command_index: usize, status: CommandStatus) { - self.all_commands - .get_mut(command_index) - .map(|c| c.set_status(status)); - } - - pub fn set_current_running_command_status(&mut self, status: CommandStatus) { - self.all_commands - .get_mut(self.current_running_command_index) - .map(|c| c.set_status(status)); - } - - pub fn get_current_running_command_status(&self) -> Option<CommandStatus> { - self.all_commands - .get(self.current_running_command_index) - .map(|c| c.get_status()) - } - - pub fn can_run_sequence(&self) -> bool { - self.all_commands.iter().any(|command| !command.is_empty()) - } - - pub fn copy_to_clipboard(&self) { - let text_to_copy = self - .all_commands - .iter() - .map(|c| format!("{}", c.get_text())) - .collect::<Vec<_>>() - .join("\n"); - if !text_to_copy.is_empty() { - copy_to_clipboard(text_to_copy); - } - } -} - -impl Default for Execution { - fn default() -> Self { - Self::new() - } -} diff --git a/default-plugins/sequence/src/state/layout.rs b/default-plugins/sequence/src/state/layout.rs deleted file mode 100644 index 6b070778..00000000 --- a/default-plugins/sequence/src/state/layout.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub struct Layout { - pub spinner_frame: usize, - pub spinner_timer_scheduled: bool, -} - -impl Layout { - pub fn new() -> Self { - Self { - spinner_frame: 0, - spinner_timer_scheduled: false, - } - } -} - -impl Default for Layout { - fn default() -> Self { - Self::new() - } -} diff --git a/default-plugins/sequence/src/state/mod.rs b/default-plugins/sequence/src/state/mod.rs deleted file mode 100644 index 148e6702..00000000 --- a/default-plugins/sequence/src/state/mod.rs +++ /dev/null @@ -1,231 +0,0 @@ -mod chain_type; -mod command_entry; -mod command_parser; -mod command_status; -mod execution; -mod layout; -mod selection; -mod sequence_mode; - -pub use chain_type::ChainType; -pub use command_entry::CommandEntry; -pub use command_parser::{parse_commands, serialize_sequence_to_editor}; -pub use command_status::CommandStatus; -pub use execution::Execution; -pub use layout::Layout; -pub use selection::Selection; -pub use sequence_mode::SequenceMode; - -use std::collections::BTreeMap; -use std::path::PathBuf; -use zellij_tile::prelude::*; - -#[derive(Default)] -pub struct State { - pub shell: Option<PathBuf>, - pub plugin_id: Option<u32>, - pub client_id: Option<u16>, - pub own_rows: Option<usize>, - pub own_columns: Option<usize>, - pub cwd: Option<PathBuf>, - pub total_viewport_columns: Option<usize>, - pub total_viewport_rows: Option<usize>, - pub selection: Selection, - pub execution: Execution, - pub layout: Layout, - pub current_position: Option<FloatingPaneCoordinates>, - pub mode: SequenceMode, - pub editor_pane_id: Option<PaneId>, - pub editor_temp_file: Option<PathBuf>, - pub sequence_tab_id: Option<usize>, - pub blocking_pipe_id: Option<String>, -} - -impl State { - pub fn set_plugin_id(&mut self, plugin_id: u32) { - self.plugin_id = Some(plugin_id); - } - - pub fn move_selection_up(&mut self) { - self.selection.move_up(&self.execution.all_commands); - self.show_selected_pane(); - } - - pub fn move_selection_down(&mut self) { - self.selection.move_down(&self.execution.all_commands); - self.show_selected_pane(); - } - - pub fn show_selected_pane(&mut self) { - if self.mode == SequenceMode::Spread { - let all_pane_ids: Vec<PaneId> = self - .execution - .all_commands - .iter() - .filter_map(|c| c.get_pane_id()) - .collect(); - let selected_pane_id = self - .current_selected_command() - .and_then(|c| c.get_pane_id()); - if let Some(selected) = selected_pane_id { - let to_unhighlight: Vec<PaneId> = all_pane_ids - .into_iter() - .filter(|&p| p != selected) - .collect(); - highlight_and_unhighlight_panes(vec![selected], to_unhighlight); - } - return; - } - let target_pane_id = self - .current_selected_command() - .and_then(|c| c.get_pane_id()); - if let (Some(displayed), Some(target)) = (self.execution.displayed_pane_id, target_pane_id) - { - if displayed != target { - replace_pane_with_existing_pane(displayed, target, true); - self.execution.displayed_pane_id = Some(target); - } - } - } - - pub fn remove_empty_commands(&mut self) { - self.execution.remove_empty_commands(); - } - - pub fn clear_all_commands(&mut self) { - self.execution.all_commands = vec![CommandEntry::new("", self.cwd.clone())]; - self.selection.current_selected_command_index = None; - self.execution.current_running_command_index = 0; - } - - pub fn load_commands(&mut self, command_string: &str, cwd_override: Option<PathBuf>) { - let effective_cwd = cwd_override.or_else(|| self.cwd.clone()); - let commands = parse_commands(command_string, effective_cwd); - if commands.is_empty() { - return; - } - self.execution.all_commands = commands; - self.execution.current_running_command_index = 0; - self.selection.current_selected_command_index = None; - } - - pub fn can_run_sequence(&self) -> bool { - self.execution.can_run_sequence() - } - - pub fn copy_to_clipboard(&mut self) { - self.execution.copy_to_clipboard(); - } - - pub fn current_selected_command_mut(&mut self) -> Option<&mut CommandEntry> { - let Some(i) = self.selection.current_selected_command_index else { - return None; - }; - self.execution.all_commands.get_mut(i) - } - - /// Serialize current sequence to a temp file and open it in the user's $EDITOR. - /// Stores the editor pane id and temp file path for later retrieval. - pub fn open_editor(&mut self) { - if self.execution.is_running { - return; - } - let Some(plugin_id) = self.plugin_id else { - return; - }; - - let serialized = serialize_sequence_to_editor(&self.execution.all_commands); - let temp_path = PathBuf::from(format!("/tmp/zellij-sequence-{}.sh", plugin_id)); - - if let Err(e) = std::fs::write(&temp_path, &serialized) { - eprintln!("Failed to write sequence to temp file: {}", e); - return; - } - - let file_to_open = FileToOpen::new(temp_path.clone()); - let editor_pane_id = open_file_in_place_of_plugin(file_to_open, false, BTreeMap::new()); - self.editor_pane_id = editor_pane_id; - self.editor_temp_file = Some(temp_path); - } - - pub fn reposition_plugin(&mut self) -> bool { - let mut repositioned = false; - let Some(plugin_id) = self.plugin_id else { - return repositioned; - }; - let Some(total_viewport_rows) = self.total_viewport_rows else { - return repositioned; - }; - let Some(total_viewport_columns) = self.total_viewport_columns else { - return repositioned; - }; - if self.all_commands_are_pending() { - return false; - } - - let total_commands = std::cmp::max(self.execution.all_commands.iter().len(), 1); - let height_padding = 7; - - // Calculate longest table row width - let longest_cwd_display = self.execution.longest_cwd_display(&self.cwd); - let longest_command = self - .execution - .all_commands - .iter() - .map(|cmd| cmd.get_text().chars().count()) - .max() - .unwrap_or(1); - - let (max_chain_width, max_status_width) = crate::ui::components::calculate_max_widths( - &self.execution.all_commands, - self.layout.spinner_frame, - ); - - let longest_line = crate::ui::components::calculate_longest_line( - &longest_cwd_display, - longest_command, - max_chain_width, - max_status_width, - ); - - let ui_width = std::cmp::max(longest_line, 50) + 4; // 2 for ui-padding, 2 for pane frame - let width = std::cmp::min(ui_width, total_viewport_columns.saturating_sub(2)); - - let height = (height_padding + total_commands).min((total_viewport_rows * 50) / 100); - - // Position: top-right with 1-space margins - let x = total_viewport_columns.saturating_sub(width); - let y = 1; - - let coordinates = FloatingPaneCoordinates::new( - Some(x.to_string()), - Some(y.to_string()), - Some(width.to_string()), - Some(height.to_string()), - Some(true), // should be pinned for sequence - Some(false), - ); - coordinates.map(|coordinates| { - if Some(&coordinates) != self.current_position.as_ref() { - self.current_position = Some(coordinates.clone()); - repositioned = true; - change_floating_panes_coordinates(vec![(PaneId::Plugin(plugin_id), coordinates)]); - } - }); - repositioned - } - - pub fn all_commands_are_pending(&self) -> bool { - self.execution - .all_commands - .iter() - .all(|command| matches!(command.get_status(), CommandStatus::Pending)) - } - - fn current_selected_command(&self) -> Option<&CommandEntry> { - let Some(i) = self.selection.current_selected_command_index else { - return None; - }; - self.execution.all_commands.get(i) - } -} diff --git a/default-plugins/sequence/src/state/selection.rs b/default-plugins/sequence/src/state/selection.rs deleted file mode 100644 index 2137f47d..00000000 --- a/default-plugins/sequence/src/state/selection.rs +++ /dev/null @@ -1,47 +0,0 @@ -use super::CommandEntry; - -pub struct Selection { - pub current_selected_command_index: Option<usize>, -} - -impl Selection { - pub fn new() -> Self { - Self { - current_selected_command_index: None, - } - } - - pub fn move_up(&mut self, all_commands: &[CommandEntry]) { - match self.current_selected_command_index.as_mut() { - Some(i) if *i > 0 => { - *i -= 1; - }, - None => { - self.current_selected_command_index = Some(all_commands.len().saturating_sub(1)); - }, - _ => { - self.current_selected_command_index = None; - }, - } - } - - pub fn move_down(&mut self, all_commands: &[CommandEntry]) { - match self.current_selected_command_index.as_mut() { - Some(i) if *i < all_commands.len().saturating_sub(1) => { - *i += 1; - }, - None => { - self.current_selected_command_index = Some(0); - }, - _ => { - self.current_selected_command_index = None; - }, - } - } -} - -impl Default for Selection { - fn default() -> Self { - Self::new() - } -} diff --git a/default-plugins/sequence/src/state/sequence_mode.rs b/default-plugins/sequence/src/state/sequence_mode.rs deleted file mode 100644 index 3d079d70..00000000 --- a/default-plugins/sequence/src/state/sequence_mode.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[derive(Default, Debug, Clone, PartialEq)] -pub enum SequenceMode { - #[default] - SinglePane, - Spread, -} |
