use std::{fmt::Display, str::FromStr};
use clap::{Args, Subcommand};
#[derive(Debug, clap::Parser)]
#[clap(
name = "sesh",
version = "0.1.0",
author = "Will Hopkins <willothyh@gmail.com>"
)]
#[group(required = false, multiple = true)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Command>,
#[command(flatten)]
pub args: CliArgs,
}
#[derive(Debug, Clone, Args)]
pub struct CliArgs {
pub program: Option<String>,
pub args: Vec<String>,
#[arg(short, long)]
pub name: Option<String>,
#[arg(short, long)]
pub detached: bool,
}
#[derive(Debug, Subcommand)]
pub enum Command {
#[command(alias = "r")]
Resume {
#[arg(short, long)]
create: bool,
},
#[command(alias = "s")]
Start {
#[arg(short, long)]
name: Option<String>,
program: Option<String>,
args: Vec<String>,
#[arg(short, long)]
detached: bool,
},
#[command(alias = "a")]
Attach {
session: SessionSelector,
#[arg(short, long)]
create: bool,
},
#[command(alias = "f")]
Select,
#[command(alias = "d")]
Detach {
session: Option<SessionSelector>,
},
#[command(alias = "k")]
Kill {
session: SessionSelector,
},
#[command(alias = "ls")]
List {
#[arg(short, long)]
info: bool,
},
Shutdown,
}
#[derive(Debug, Clone)]
pub enum SessionSelector {
Id(usize),
Name(String),
}
impl SessionSelector {
pub fn name(self) -> Option<String> {
match self {
SessionSelector::Id(_) => None,
SessionSelector::Name(name) => Some(name),
}
}
}
impl Display for SessionSelector {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SessionSelector::Id(id) => write!(f, "{}", id),
SessionSelector::Name(name) => write!(f, "{}", name),
}
}
}
impl FromStr for SessionSelector {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(id) = s.parse::<usize>() {
Ok(SessionSelector::Id(id))
} else {
Ok(SessionSelector::Name(s.to_owned()))
}
}
}