Skip to main content

things3_cloud/commands/
mod.rs

1pub mod anytime;
2pub mod area;
3pub mod areas;
4pub mod completions;
5pub mod delete;
6pub mod edit;
7pub mod find;
8pub mod inbox;
9pub mod logbook;
10pub mod mark;
11pub mod new;
12pub mod project;
13pub mod projects;
14pub mod reorder;
15pub mod schedule;
16pub mod set_auth;
17pub mod someday;
18pub mod tags;
19pub mod today;
20pub mod upcoming;
21
22use anyhow::Result;
23use clap::{Args, Subcommand};
24use serde::Serialize;
25
26use crate::{
27    app::Cli,
28    cmd_ctx::{CmdCtx, DefaultCmdCtx},
29};
30
31pub trait Command {
32    fn run_with_ctx(
33        &self,
34        cli: &Cli,
35        out: &mut dyn std::io::Write,
36        ctx: &mut dyn CmdCtx,
37    ) -> Result<()>;
38
39    fn run(&self, cli: &Cli, out: &mut dyn std::io::Write) -> Result<()> {
40        let mut ctx = DefaultCmdCtx::from_cli(cli);
41        self.run_with_ctx(cli, out, &mut ctx)
42    }
43}
44
45pub(crate) fn detailed_json_conflict(json: bool, detailed: bool) -> bool {
46    if json && detailed {
47        eprintln!("--detailed is not supported with --json.");
48        true
49    } else {
50        false
51    }
52}
53
54pub(crate) fn write_json<T: Serialize>(out: &mut dyn std::io::Write, value: &T) -> Result<()> {
55    serde_json::to_writer_pretty(&mut *out, value)?;
56    writeln!(out)?;
57    Ok(())
58}
59
60#[derive(Debug, Default, Clone, Args)]
61pub struct DetailedArgs {
62    /// Show notes beneath each task
63    #[arg(long, short = 'd')]
64    pub detailed: bool,
65}
66
67#[derive(Debug, Default, Clone, Args)]
68pub struct TagDeltaArgs {
69    #[arg(
70        long = "add-tags",
71        short = 'a',
72        help = "Comma-separated tags to add (titles or UUID prefixes)"
73    )]
74    pub add_tags: Option<String>,
75    #[arg(
76        long = "remove-tags",
77        short = 'r',
78        help = "Comma-separated tags to remove (titles or UUID prefixes)"
79    )]
80    pub remove_tags: Option<String>,
81}
82
83#[derive(Debug, Subcommand)]
84pub enum Commands {
85    #[command(about = "Show the Inbox")]
86    Inbox(inbox::InboxArgs),
87    #[command(about = "Show the Today view (default)")]
88    Today(today::TodayArgs),
89    #[command(about = "Show tasks scheduled for the future")]
90    Upcoming(upcoming::UpcomingArgs),
91    #[command(about = "Show the Anytime view")]
92    Anytime(anytime::AnytimeArgs),
93    #[command(about = "Show the Someday view")]
94    Someday(someday::SomedayArgs),
95    #[command(about = "Show the Logbook")]
96    Logbook(logbook::LogbookArgs),
97    #[command(about = "Show, create, or edit projects")]
98    Projects(projects::ProjectsArgs),
99    #[command(about = "Show all tasks in a project")]
100    Project(project::ProjectArgs),
101    #[command(about = "Show or create areas")]
102    Areas(areas::AreasArgs),
103    #[command(about = "Show projects and tasks in an area")]
104    Area(area::AreaArgs),
105    #[command(about = "Show or edit tags")]
106    Tags(tags::TagsArgs),
107    #[command(about = "Create a new task")]
108    New(new::NewArgs),
109    #[command(about = "Edit a task title, container, notes, tags, or checklist items")]
110    Edit(edit::EditArgs),
111    #[command(about = "Mark a task done, incomplete, or canceled")]
112    Mark(mark::MarkArgs),
113    #[command(about = "Set when and deadline")]
114    Schedule(schedule::ScheduleArgs),
115    #[command(about = "Reorder item relative to another item")]
116    Reorder(reorder::ReorderArgs),
117    #[command(about = "Delete tasks/projects/headings/areas")]
118    Delete(delete::DeleteArgs),
119    #[command(about = "Configure Things Cloud credentials")]
120    SetAuth(set_auth::SetAuthArgs),
121    #[command(about = "Search and filter tasks")]
122    Find(find::FindArgs),
123    #[command(hide = true, about = "Generate shell completion scripts")]
124    Completions(completions::CompletionsArgs),
125}
126
127impl Command for Commands {
128    fn run_with_ctx(
129        &self,
130        cli: &Cli,
131        out: &mut dyn std::io::Write,
132        ctx: &mut dyn CmdCtx,
133    ) -> Result<()> {
134        match self {
135            Commands::Inbox(args) => args.run_with_ctx(cli, out, ctx),
136            Commands::Today(args) => args.run_with_ctx(cli, out, ctx),
137            Commands::Upcoming(args) => args.run_with_ctx(cli, out, ctx),
138            Commands::Anytime(args) => args.run_with_ctx(cli, out, ctx),
139            Commands::Someday(args) => args.run_with_ctx(cli, out, ctx),
140            Commands::Logbook(args) => args.run_with_ctx(cli, out, ctx),
141            Commands::Projects(args) => args.run_with_ctx(cli, out, ctx),
142            Commands::Project(args) => args.run_with_ctx(cli, out, ctx),
143            Commands::Areas(args) => args.run_with_ctx(cli, out, ctx),
144            Commands::Area(args) => args.run_with_ctx(cli, out, ctx),
145            Commands::Tags(args) => args.run_with_ctx(cli, out, ctx),
146            Commands::New(args) => args.run_with_ctx(cli, out, ctx),
147            Commands::Edit(args) => args.run_with_ctx(cli, out, ctx),
148            Commands::Mark(args) => args.run_with_ctx(cli, out, ctx),
149            Commands::Schedule(args) => args.run_with_ctx(cli, out, ctx),
150            Commands::Reorder(args) => args.run_with_ctx(cli, out, ctx),
151            Commands::Delete(args) => args.run_with_ctx(cli, out, ctx),
152            Commands::SetAuth(args) => args.run_with_ctx(cli, out, ctx),
153            Commands::Find(args) => args.run_with_ctx(cli, out, ctx),
154            Commands::Completions(args) => args.run_with_ctx(cli, out, ctx),
155        }
156    }
157}