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
#[allow(clippy::wildcard_imports)]
use super::*;
/// The `tix template` management tree (`contracts/cli-surface.md`).
///
/// `list`/`show` are read-only; the four mutations call one service that
/// validates the complete candidate registry before a single atomic
/// `tix.toml` save, so a refused operation leaves the file byte-identical.
/// Identity is the immutable stable ID: `update` changes a display name
/// without touching scope, defaults, prompts, references, or preserved
/// unknown metadata.
#[derive(Subcommand)]
pub enum TemplateAction {
/// List templates: one `id<TAB>name<TAB>scope` row each, in declaration order
List,
/// Show one template by stable ID (or a unique display name)
Show {
/// Stable ID, or a display name that names exactly one template
reference: String,
},
/// Create a template under a new stable ID
Create {
/// The new stable ID: ASCII letters, digits, `-` or `_`
#[arg(long, value_name = "ID")]
id: String,
/// Display name; omitted means the ID is shown in its place
#[arg(long, value_name = "NAME")]
name: Option<String>,
/// Scope: `repository` (default) | `board:<name>` | `team:<label>`
#[arg(long, value_name = "SCOPE")]
scope: Option<String>,
/// A normal create default, `FIELD=VALUE` (repeatable). Supplying any
/// `--default` replaces the whole defaults block.
#[arg(long = "default", value_name = "FIELD=VALUE")]
defaults: Vec<String>,
/// A structured prompt,
/// `key=<field>[,kind=text|select|multi-select|date][,required=true|false][,default=<v>][,label=<l>][,options_ref=<source>]`
/// (repeatable). Supplying any `--prompt` replaces the whole prompt list.
#[arg(long = "prompt", value_name = "KEY,ATTR=VALUE...")]
prompts: Vec<String>,
/// A typed reference,
/// `kind=label|assignee|file|cycle|milestone|relationship,value=<v>[,required=true|false]`
/// (repeatable). Supplying any `--reference` replaces the whole list.
#[arg(long = "reference", value_name = "KIND=VALUE,ATTR=VALUE...")]
references: Vec<String>,
},
/// Update the flags supplied, leaving every other stored field as it was
Update {
/// Stable ID, or a display name that names exactly one template
reference: String,
/// New display name (the stable ID never changes)
#[arg(long, value_name = "NAME")]
name: Option<String>,
/// New scope: `repository` | `board:<name>` | `team:<label>`
#[arg(long, value_name = "SCOPE")]
scope: Option<String>,
/// Replacement defaults, `FIELD=VALUE` (repeatable)
#[arg(long = "default", value_name = "FIELD=VALUE")]
defaults: Vec<String>,
/// Replacement prompts (repeatable; same grammar as `create`)
#[arg(long = "prompt", value_name = "KEY,ATTR=VALUE...")]
prompts: Vec<String>,
/// Replacement references (repeatable; same grammar as `create`)
#[arg(long = "reference", value_name = "KIND=VALUE,ATTR=VALUE...")]
references: Vec<String>,
},
/// Copy a template to a new stable ID, leaving the source untouched
Duplicate {
/// Stable ID, or a display name that names exactly one template
reference: String,
/// The new stable ID; omitted allocates `<source>-copy`, `-copy-2`, …
#[arg(long, value_name = "ID")]
id: Option<String>,
/// Display name for the copy; omitted keeps the source's label
#[arg(long, value_name = "NAME")]
name: Option<String>,
},
/// Delete a template definition (never the issues created from it)
Delete {
/// Stable ID, or a display name that names exactly one template
reference: String,
/// Confirm without prompting
#[arg(long)]
yes: bool,
},
}