use anyhow::Result;
use clap::Parser;
#[derive(Parser)]
#[command(name = "pidge")]
#[command(author, version, about)]
#[command(long_about = "A fast CLI for e-mail and calendar.\n\n\
Foundation release — AI configuration, shell completions, and version info only. \
E-mail and calendar feature commands ship in future releases.")]
#[command(propagate_version = true)]
pub struct Cli {
#[arg(short, long, action = clap::ArgAction::Count, global = true)]
pub verbose: u8,
#[arg(short, long, global = true)]
pub quiet: bool,
#[arg(long, global = true)]
pub no_color: bool,
#[arg(long, global = true)]
pub json: bool,
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(clap::Subcommand)]
pub enum Commands {
Ai {
#[command(subcommand)]
command: Option<AiCommands>,
},
Auth {
#[command(subcommand)]
command: AuthCommands,
},
Inbox {
#[command(subcommand)]
command: InboxCommands,
},
Trust {
#[command(subcommand)]
command: TrustCommands,
},
Completion {
#[arg(value_enum)]
shell: Shell,
},
Version,
}
#[derive(clap::Subcommand)]
pub enum AiCommands {
Test {
message: Option<String>,
},
Enable,
Disable,
Config,
Status,
Skill {
#[arg(long)]
emit: bool,
#[arg(long)]
reference: bool,
},
}
#[derive(clap::Subcommand)]
pub enum AuthCommands {
Login {
#[arg(long, value_enum, default_value_t = StorageBackendArg::Keychain)]
store: StorageBackendArg,
},
List,
Status,
Logout {
#[arg(long)]
account: Option<String>,
#[arg(long, conflicts_with = "account")]
all: bool,
#[arg(short = 'y', long)]
yes: bool,
},
Default {
#[arg(long)]
send: Option<String>,
#[arg(long)]
calendar: Option<String>,
},
MigrateStorage {
email: String,
#[arg(long = "to", value_enum)]
to: StorageBackendArg,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
pub enum StorageBackendArg {
Keychain,
File,
}
impl From<StorageBackendArg> for pidge_core::TokenStorage {
fn from(v: StorageBackendArg) -> Self {
match v {
StorageBackendArg::Keychain => Self::Keychain,
StorageBackendArg::File => Self::File,
}
}
}
#[derive(clap::Subcommand)]
pub enum InboxCommands {
List {
#[arg(long)]
account: Vec<String>,
#[arg(short = 'n', long, default_value = "25")]
limit: usize,
#[arg(long)]
unread: bool,
#[arg(short = 'c', long)]
compact: bool,
},
Show {
fragment: String,
#[arg(short = 'r', long)]
mark_read: bool,
#[arg(long)]
show_images: bool,
#[arg(long, hide = true)]
raw_html: bool,
},
}
#[derive(clap::Subcommand)]
pub enum TrustCommands {
List,
Add {
email: String,
},
Remove {
email: String,
},
}
#[derive(Clone, clap::ValueEnum)]
pub enum Shell {
Bash,
Zsh,
Fish,
Powershell,
}
impl Cli {
pub async fn run(self) -> Result<()> {
match self.command {
Some(Commands::Ai { command }) => crate::commands::ai::run(command).await,
Some(Commands::Auth { command }) => {
crate::commands::auth::run(command, self.json).await
}
Some(Commands::Inbox { command }) => {
crate::commands::inbox::run(command, self.json).await
}
Some(Commands::Trust { command }) => {
crate::commands::trust::run(command, self.json).await
}
Some(Commands::Completion { shell }) => {
crate::commands::completion::generate_completions(shell);
Ok(())
}
Some(Commands::Version) => {
crate::banner::print_banner_with_version();
Ok(())
}
None => {
use clap::CommandFactory;
let mut cmd = Self::command();
cmd.print_help()?;
println!();
Ok(())
}
}
}
}