Skip to main content

ralph/cli/task/args/
batch.rs

1//! CLI arguments for task batch operations.
2//!
3//! Responsibilities:
4//! - Define BatchSelectArgs for task selection and filtering.
5//! - Define BatchOperation enum and all batch operation argument structs.
6//! - Define TaskBatchArgs for the batch command.
7//!
8//! Not handled here:
9//! - Command execution (see batch handler).
10//!
11//! Invariants/assumptions:
12//! - All types must be Clone where needed for clap flattening.
13
14use clap::{Args, Subcommand};
15
16use crate::cli::task::args::types::{TaskEditFieldArg, TaskPriorityArg, TaskStatusArg};
17
18/// Shared task selection + filters for batch operations.
19#[derive(Args, Clone, Debug, Default)]
20pub struct BatchSelectArgs {
21    /// Task IDs to target (conflicts with --tag-filter).
22    #[arg(value_name = "TASK_ID...", conflicts_with = "tag_filter")]
23    pub task_ids: Vec<String>,
24
25    /// Filter tasks by tag (case-insensitive, repeatable; OR logic).
26    #[arg(long, value_name = "TAG", conflicts_with = "task_ids")]
27    pub tag_filter: Vec<String>,
28
29    /// Filter selected tasks by status (repeatable; OR logic).
30    #[arg(long, value_enum, value_name = "STATUS")]
31    pub status_filter: Vec<TaskStatusArg>,
32
33    /// Filter selected tasks by priority (repeatable; OR logic).
34    #[arg(long, value_enum, value_name = "PRIORITY")]
35    pub priority_filter: Vec<TaskPriorityArg>,
36
37    /// Filter selected tasks by scope substring (repeatable; OR logic; case-insensitive).
38    #[arg(long, value_name = "PATTERN")]
39    pub scope_filter: Vec<String>,
40
41    /// Filter selected tasks whose updated_at is older than this cutoff.
42    /// Supported forms: "7d", "1w", "2026-01-01", RFC3339
43    #[arg(long, value_name = "WHEN")]
44    pub older_than: Option<String>,
45}
46
47/// Batch operation type.
48#[derive(Subcommand)]
49pub enum BatchOperation {
50    /// Update status for multiple tasks.
51    Status(BatchStatusArgs),
52    /// Set a custom field on multiple tasks.
53    Field(BatchFieldArgs),
54    /// Edit any field on multiple tasks.
55    Edit(BatchEditArgs),
56
57    /// Delete multiple tasks from the active queue.
58    Delete(BatchDeleteArgs),
59
60    /// Archive terminal tasks (Done/Rejected) from active queue into done archive.
61    Archive(BatchArchiveArgs),
62
63    /// Clone multiple tasks.
64    Clone(BatchCloneArgs),
65
66    /// Split multiple tasks into child tasks.
67    Split(BatchSplitArgs),
68
69    /// Append plan items to multiple tasks.
70    #[command(name = "plan-append")]
71    PlanAppend(BatchPlanAppendArgs),
72
73    /// Prepend plan items to multiple tasks.
74    #[command(name = "plan-prepend")]
75    PlanPrepend(BatchPlanPrependArgs),
76}
77
78/// Arguments for batch status operation.
79#[derive(Args)]
80pub struct BatchStatusArgs {
81    /// New status.
82    #[arg(value_enum)]
83    pub status: TaskStatusArg,
84
85    /// Optional note to append to all affected tasks.
86    #[arg(long)]
87    pub note: Option<String>,
88
89    #[command(flatten)]
90    pub select: BatchSelectArgs,
91}
92
93/// Arguments for batch field operation.
94#[derive(Args)]
95pub struct BatchFieldArgs {
96    /// Custom field key.
97    pub key: String,
98
99    /// Custom field value.
100    pub value: String,
101
102    #[command(flatten)]
103    pub select: BatchSelectArgs,
104}
105
106/// Arguments for batch edit operation.
107#[derive(Args)]
108pub struct BatchEditArgs {
109    /// Task field to update.
110    #[arg(value_enum)]
111    pub field: TaskEditFieldArg,
112
113    /// New field value.
114    pub value: String,
115
116    #[command(flatten)]
117    pub select: BatchSelectArgs,
118}
119
120/// Arguments for batch delete operation.
121#[derive(Args)]
122pub struct BatchDeleteArgs {
123    #[command(flatten)]
124    pub select: BatchSelectArgs,
125}
126
127/// Arguments for batch archive operation.
128#[derive(Args)]
129pub struct BatchArchiveArgs {
130    #[command(flatten)]
131    pub select: BatchSelectArgs,
132}
133
134/// Arguments for batch clone operation.
135#[derive(Args)]
136pub struct BatchCloneArgs {
137    /// Status for the cloned tasks (default: draft).
138    #[arg(long, value_enum)]
139    pub status: Option<TaskStatusArg>,
140
141    /// Prefix to add to the cloned task titles.
142    #[arg(long)]
143    pub title_prefix: Option<String>,
144
145    #[command(flatten)]
146    pub select: BatchSelectArgs,
147}
148
149/// Arguments for batch split operation.
150#[derive(Args)]
151pub struct BatchSplitArgs {
152    /// Number of child tasks to create per source task (default: 2, minimum: 2).
153    #[arg(short = 'n', long, default_value = "2")]
154    pub number: usize,
155
156    /// Status for child tasks (default: draft).
157    #[arg(long, value_enum)]
158    pub status: Option<TaskStatusArg>,
159
160    /// Prefix to add to child task titles.
161    #[arg(long)]
162    pub title_prefix: Option<String>,
163
164    /// Distribute plan items across child tasks.
165    #[arg(long)]
166    pub distribute_plan: bool,
167
168    #[command(flatten)]
169    pub select: BatchSelectArgs,
170}
171
172/// Arguments for batch plan-append operation.
173#[derive(Args)]
174pub struct BatchPlanAppendArgs {
175    /// Plan items to append (repeatable).
176    #[arg(long = "plan-item", value_name = "ITEM", required = true)]
177    pub plan_items: Vec<String>,
178
179    #[command(flatten)]
180    pub select: BatchSelectArgs,
181}
182
183/// Arguments for batch plan-prepend operation.
184#[derive(Args)]
185pub struct BatchPlanPrependArgs {
186    /// Plan items to prepend (repeatable).
187    #[arg(long = "plan-item", value_name = "ITEM", required = true)]
188    pub plan_items: Vec<String>,
189
190    #[command(flatten)]
191    pub select: BatchSelectArgs,
192}
193
194/// Arguments for the batch command.
195#[derive(Args)]
196pub struct TaskBatchArgs {
197    /// Batch operation type.
198    #[command(subcommand)]
199    pub operation: BatchOperation,
200
201    /// Preview changes without modifying the queue.
202    #[arg(long)]
203    pub dry_run: bool,
204
205    /// Continue on individual task failures (default: atomic/all-or-nothing).
206    #[arg(long)]
207    pub continue_on_error: bool,
208}