aboutsummaryrefslogtreecommitdiffstats
path: root/default-plugins/sequence/src/state
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2026-02-24 13:10:40 +0100
committerGitHub <noreply@github.com>2026-02-24 13:10:40 +0100
commit8cd6286c3ffc10d14fdafd5005fa89b0f7fdcd44 (patch)
treec6341f5e3e251ae17db0c3427ddaf1e54d4fa91c /default-plugins/sequence/src/state
parentAllow closing replaced panes when opening panes in place (#4760) (diff)
downloadsl0ppij-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.rs45
-rw-r--r--default-plugins/sequence/src/state/command_entry.rs76
-rw-r--r--default-plugins/sequence/src/state/command_parser.rs370
-rw-r--r--default-plugins/sequence/src/state/command_status.rs26
-rw-r--r--default-plugins/sequence/src/state/execution.rs87
-rw-r--r--default-plugins/sequence/src/state/layout.rs19
-rw-r--r--default-plugins/sequence/src/state/mod.rs231
-rw-r--r--default-plugins/sequence/src/state/selection.rs47
-rw-r--r--default-plugins/sequence/src/state/sequence_mode.rs6
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,
-}