Skip to main content

zj/
main.rs

1//! Interactive Zellij session management.
2//!
3//! # Errors
4//! - Zellij CLI invocation or user interaction fails.
5
6use core::fmt::Display;
7
8use owo_colors::OwoColorize;
9use rootcause::prelude::ResultExt;
10use strum::EnumIter;
11use strum::IntoEnumIterator;
12use ytil_sys::cli::Args;
13
14struct DisplaySession(ytil_zellij::Session);
15
16impl Display for DisplaySession {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        write!(f, "{}", self.0.display)
19    }
20}
21
22#[derive(Debug, EnumIter)]
23enum Op {
24    Attach,
25    Restart,
26    Kill,
27    Delete,
28}
29
30impl Display for Op {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        match self {
33            Self::Attach => write!(f, "{}", "Attach".green().bold()),
34            Self::Restart => write!(f, "{}", "Restart".cyan().bold()),
35            Self::Kill => write!(f, "{}", "Kill".yellow().bold()),
36            Self::Delete => write!(f, "{}", "Delete".red().bold()),
37        }
38    }
39}
40
41#[ytil_sys::main]
42fn main() -> rootcause::Result<()> {
43    let args = ytil_sys::cli::get();
44
45    let is_zj_help = (args.len() == 1 && args.has_help()) || args.first().is_some_and(|a| a == "help");
46    if is_zj_help {
47        ytil_zellij::help()?;
48        println!();
49        println!("{}", include_str!("../help.txt"));
50        return Ok(());
51    }
52
53    if !args.is_empty() {
54        return ytil_zellij::forward(&args);
55    }
56
57    let sessions: Vec<DisplaySession> = ytil_zellij::list_sessions()?.into_iter().map(DisplaySession).collect();
58    if sessions.is_empty() {
59        println!("No sessions");
60        return Ok(());
61    }
62
63    let Some(selected) = ytil_tui::minimal_multi_select(sessions)? else {
64        println!("\n\nNo sessions selected");
65        return Ok(());
66    };
67
68    let Some(op) = ytil_tui::minimal_select::<Op>(Op::iter().collect())? else {
69        println!("\n\nNo action selected");
70        return Ok(());
71    };
72
73    match op {
74        Op::Attach => {
75            let session = ytil_tui::require_single(&selected, "sessions")?;
76            ytil_zellij::attach_session(&session.0.name)
77                .attach(format!("op={op:?}"))
78                .attach(format!("session={}", session.0.name))?;
79        }
80        Op::Restart => {
81            let session = ytil_tui::require_single(&selected, "sessions")?;
82            let name = &session.0.name;
83            ytil_zellij::kill_session(name)
84                .attach(format!("op={op:?}"))
85                .attach(format!("session={name}"))?;
86            ytil_zellij::attach_session(name)
87                .attach(format!("op={op:?}"))
88                .attach(format!("session={name}"))?;
89        }
90        Op::Kill => {
91            for session in &selected {
92                ytil_zellij::kill_session(&session.0.name)
93                    .attach(format!("op={op:?}"))
94                    .attach(format!("session={}", session.0.name))?;
95                println!("{} {}", "Killed".yellow().bold(), session.0.name);
96            }
97        }
98        Op::Delete => {
99            for session in &selected {
100                ytil_zellij::delete_session(&session.0.name)
101                    .attach(format!("op={op:?}"))
102                    .attach(format!("session={}", session.0.name))?;
103                println!("{} {}", "Deleted".red().bold(), session.0.name);
104            }
105        }
106    }
107
108    Ok(())
109}