1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use clap::{Parser, Subcommand};
use crate::models::common::Priority;
#[derive(Parser)]
#[command(name = "tally")]
#[command(about = "A task management tool for TODO.md files")]
#[command(version)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
/// Add a new task to TODO.md.
Add {
/// Task text to add.
#[arg(required = true, num_args = 1..)]
description: Vec<String>,
/// Priority for the new task.
#[arg(short, long, value_enum, default_value_t = Priority::Medium)]
priority: Priority,
/// Comma-separated tags to attach.
#[arg(short, long, value_delimiter = ',')]
tags: Option<Vec<String>>,
/// Show what would be added without writing TODO.md.
#[arg(long, default_value_t = false)]
dry_run: bool,
/// Auto-commit updated files after adding.
#[arg(long, default_value_t = false)]
auto: bool,
},
/// Mark a task as completed using fuzzy description matching.
Done {
/// Task text to match.
#[arg(required = true, num_args = 1..)]
description: Vec<String>,
/// Commit hash to associate with completion.
#[arg(short, long)]
commit: Option<String>,
/// Release version to attach at completion time.
#[arg(short, long)]
version: Option<String>,
/// Show what would be changed without writing TODO.md.
#[arg(long, default_value_t = false)]
dry_run: bool,
/// Auto-commit updated files after completion.
#[arg(long, default_value_t = false)]
auto: bool,
},
/// List tasks with optional filters.
List {
/// Filter by one or more comma-separated tags.
#[arg(short, long, value_delimiter = ',')]
tags: Option<Vec<String>>,
/// Filter by priority.
#[arg(short, long, value_enum)]
priority: Option<Priority>,
/// Show only completed tasks.
#[arg(long, default_value_t = false)]
done: bool,
/// List released tasks from CHANGELOG.md; optionally filter by tag.
#[arg(short = 'r', long, num_args = 0..=1, default_missing_value = "__all__")]
released: Option<String>,
/// Output results as JSON.
#[arg(long, default_value_t = false)]
json: bool,
},
/// Move completed unversioned tasks into CHANGELOG.md under a version.
Semver {
/// Version to assign (for example: 1.2.3 or v1.2.3).
version: String,
/// Show what would be moved without writing files.
#[arg(long, default_value_t = false)]
dry_run: bool,
/// Print a summary of tasks moved for this version.
#[arg(long, default_value_t = false)]
summary: bool,
/// Auto-commit updated files after semver move.
#[arg(long, default_value_t = false)]
auto: bool,
},
/// Remove a task by fuzzy description match.
Remove {
/// Task text to match.
#[arg(required = true, num_args = 1..)]
description: Vec<String>,
/// Remove from CHANGELOG.md instead of TODO.md; optionally filter by tag.
#[arg(short = 'r', long, num_args = 0..=1, default_missing_value = "__all__")]
released: Option<String>,
/// Show what would be removed without writing TODO.md.
#[arg(long, default_value_t = false)]
dry_run: bool,
/// Auto-commit updated files after removal.
#[arg(long, default_value_t = false)]
auto: bool,
},
/// Yank a changelog entry back into TODO as completed and unversioned.
Yank {
/// Released task text to match.
#[arg(required = true, num_args = 1..)]
description: Vec<String>,
/// Optional tag filter to narrow released-task matching.
#[arg(short, long)]
tag: Option<String>,
/// Show what would be yanked without writing files.
#[arg(long, default_value_t = false)]
dry_run: bool,
/// Auto-commit updated files after yank.
#[arg(long, default_value_t = false)]
auto: bool,
},
/// Scan for task updates from git commits and/or source TODO markers.
Scan {
/// Auto-accept git-based done matches without prompting.
#[arg(long, default_value_t = false)]
auto: bool,
/// Show what would change without writing files.
#[arg(long, default_value_t = false)]
dry_run: bool,
/// Run only git commit scanning.
#[arg(long, default_value_t = false)]
git: bool,
/// Run only source TODO scanning.
#[arg(long, default_value_t = false)]
source: bool,
},
}