♻️ refactor(cli): restructure cli commands for better organization

- rename `label_cli.rs` to `labels_cli.rs`
- rename `message_cli.rs` to `messages_cli.rs`
- move config related commands to `rules config` subcommand
- introduce `rules run` subcommand
This commit is contained in:
Jeremiah Russell
2025-10-15 10:55:32 +01:00
committed by Jeremiah Russell
parent 7c2bcd37b4
commit 3beab7d82d
14 changed files with 101 additions and 77 deletions

View File

@@ -0,0 +1,35 @@
use clap::{Parser, ValueEnum};
use cull_gmail::{Config, EolAction, Error, Result};
#[derive(Debug, Clone, Parser, ValueEnum)]
pub enum Action {
/// Set the action to trash
#[clap(name = "trash")]
Trash,
/// Set the action to
#[clap(name = "add")]
Delete,
}
#[derive(Debug, Parser)]
pub struct ActionCli {
/// Id of the rule on which action applies
#[clap(short, long)]
id: usize,
/// Configuration commands
#[command(subcommand)]
action: Action,
}
impl ActionCli {
pub fn run(&self, mut config: Config) -> Result<()> {
if config.get_rule(self.id).is_none() {
return Err(Error::RuleNotFound(self.id));
}
match self.action {
Action::Trash => config.set_action_on_rule(self.id, &EolAction::Trash),
Action::Delete => config.set_action_on_rule(self.id, &EolAction::Trash),
}
}
}

View File

@@ -0,0 +1,40 @@
use clap::{Parser, Subcommand};
use cull_gmail::{Config, Error};
mod add_cli;
mod list_cli;
mod remove_cli;
use add_cli::AddCli;
use list_cli::ListCli;
use remove_cli::RemoveCli;
#[derive(Debug, Subcommand)]
pub enum LabelCommands {
/// List the labels associated with a rule
#[clap(name = "list")]
List(ListCli),
/// Add label to rule
#[clap(name = "add")]
Add(AddCli),
/// Remove a label from a
#[clap(name = "remove", alias = "rm")]
Remove(RemoveCli),
}
#[derive(Debug, Parser)]
pub struct LabelCli {
/// Configuration commands
#[command(subcommand)]
command: LabelCommands,
}
impl LabelCli {
pub fn run(&self, config: Config) -> Result<(), Error> {
match &self.command {
LabelCommands::List(list_cli) => list_cli.run(config),
LabelCommands::Add(add_cli) => add_cli.run(config),
LabelCommands::Remove(rm_cli) => rm_cli.run(config),
}
}
}

View File

@@ -0,0 +1,23 @@
use clap::Parser;
use cull_gmail::{Config, Error, Result};
#[derive(Debug, Parser)]
pub struct AddCli {
/// Id of the rule on which action applies
#[clap(short, long)]
id: usize,
/// Label to add to the rule
#[clap(short, long)]
label: String,
}
impl AddCli {
pub fn run(&self, mut config: Config) -> Result<()> {
if config.get_rule(self.id).is_none() {
return Err(Error::RuleNotFound(self.id));
}
config.add_label_to_rule(self.id, &self.label)
}
}

View File

@@ -0,0 +1,29 @@
use clap::Parser;
use cull_gmail::{Config, Error, Result};
#[derive(Debug, Parser)]
pub struct ListCli {
/// Id of the rule on which action applies
#[clap(short, long)]
id: usize,
}
impl ListCli {
pub fn run(&self, config: Config) -> Result<()> {
let Some(rule) = config.get_rule(self.id) else {
return Err(Error::RuleNotFound(self.id));
};
print!("Labels in rule: ");
for (i, label) in rule.labels().iter().enumerate() {
if i != 0 {
print!(", {label}");
} else {
print!("`{label}");
}
}
println!("`");
Ok(())
}
}

View File

@@ -0,0 +1,23 @@
use clap::Parser;
use cull_gmail::{Config, Error, Result};
#[derive(Debug, Parser)]
pub struct RemoveCli {
/// Id of the rule on which action applies
#[clap(short, long)]
id: usize,
/// Label to remove from the rule
#[clap(short, long)]
label: String,
}
impl RemoveCli {
pub fn run(&self, mut config: Config) -> Result<()> {
if config.get_rule(self.id).is_none() {
return Err(Error::RuleNotFound(self.id));
}
config.remove_label_from_rule(self.id, &self.label)
}
}

View File

@@ -0,0 +1,38 @@
use clap::{Parser, Subcommand};
use cull_gmail::{Config, Error};
mod add_cli;
mod rm_cli;
use add_cli::AddCli;
use rm_cli::RmCli;
#[derive(Debug, Subcommand)]
pub enum RulesCommands {
/// List the rules configured and saved in the config file
#[clap(name = "list")]
List,
/// Add a rules to the config file
#[clap(name = "add")]
Add(AddCli),
/// Remove a rule from the config file
#[clap(name = "remove", alias = "rm")]
Remove(RmCli),
}
#[derive(Debug, Parser)]
pub struct RulesCli {
/// Configuration commands
#[command(subcommand)]
command: RulesCommands,
}
impl RulesCli {
pub fn run(&self, config: Config) -> Result<(), Error> {
match &self.command {
RulesCommands::List => config.list_rules(),
RulesCommands::Add(add_cli) => add_cli.run(config),
RulesCommands::Remove(rm_cli) => rm_cli.run(config),
}
}
}

View File

@@ -0,0 +1,50 @@
use std::fmt;
use clap::{Parser, ValueEnum};
use cull_gmail::{Config, Error, MessageAge, Retention};
#[derive(Debug, Clone, Parser, ValueEnum)]
pub enum Period {
Days,
Weeks,
Months,
Years,
}
impl fmt::Display for Period {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Period::Days => write!(f, "days"),
Period::Weeks => write!(f, "weeks"),
Period::Months => write!(f, "months"),
Period::Years => write!(f, "years"),
}
}
}
#[derive(Debug, Parser)]
pub struct AddCli {
/// Period for the rule
#[arg(short, long)]
period: Period,
/// Count of the period
#[arg(short, long, default_value = "1")]
count: i64,
/// Optional specific label; if not specified one will be generated
#[arg(short, long)]
label: Option<String>,
/// Immediate delete instead of move to trash
#[arg(long)]
delete: bool,
}
impl AddCli {
pub fn run(&self, mut config: Config) -> Result<(), Error> {
let generate = self.label.is_none();
let message_age = MessageAge::new(self.period.to_string().as_str(), self.count);
let retention = Retention::new(message_age, generate);
config.add_rule(retention, self.label.as_ref(), self.delete);
config.save()
}
}

View File

@@ -0,0 +1,32 @@
use clap::Parser;
use cull_gmail::{Config, Error};
#[derive(Debug, Parser)]
pub struct RmCli {
/// Id of the rule to remove
#[clap(short, long)]
id: Option<usize>,
/// Label in the rule to remove (the rule will be removed)
#[clap(short, long)]
label: Option<String>,
}
impl RmCli {
pub fn run(&self, mut config: Config) -> Result<(), Error> {
if self.id.is_none() && self.label.is_none() {
return Err(Error::NoRuleSelector);
}
if let Some(id) = self.id {
config.remove_rule_by_id(id)?;
config.save()?;
}
if let Some(label) = &self.label {
config.remove_rule_by_label(label)?;
config.save()?;
}
Ok(())
}
}