radicle_cli/commands/inbox/
args.rs1use std::{fmt::Display, str::FromStr};
2
3use clap::{Parser, Subcommand, ValueEnum};
4use radicle::{node::notifications::NotificationId, prelude::RepoId};
5
6const ABOUT: &str = "Manage your Radicle notifications";
7
8const LONG_ABOUT: &str = r#"
9By default, this command lists all items in your inbox.
10If your working directory is a Radicle repository, it only shows items
11belonging to this repository, unless `--all` is used.
12
13The `show` subcommand takes a notification ID (which can be found in
14the output of the `list` subcommand) and displays the information related to that
15notification. This will mark the notification as read.
16
17The `clear` subcommand will clear all notifications with given IDs,
18or all notifications if no IDs are given. Cleared notifications are
19deleted and cannot be restored.
20"#;
21
22#[derive(Clone, Debug, Parser)]
23#[command(about = ABOUT, long_about = LONG_ABOUT, disable_version_flag = true)]
24pub struct Args {
25 #[command(subcommand)]
26 pub(super) command: Option<Command>,
27
28 #[clap(flatten)]
29 pub(super) empty: EmptyArgs,
30}
31
32#[derive(Subcommand, Clone, Debug)]
33pub(super) enum Command {
34 List(ListArgs),
36 Show {
42 #[arg(value_name = "NOTIFICATION_ID")]
44 id: NotificationId,
45 },
46 Clear(ClearArgs),
52}
53
54#[derive(Parser, Clone, Copy, Debug)]
55pub(super) struct EmptyArgs {
56 #[arg(long, value_enum, default_value_t, hide = true)]
58 sort_by: SortBy,
59
60 #[arg(short, long, hide = true)]
62 reverse: bool,
63
64 #[arg(long, hide = true)]
66 show_unknown: bool,
67
68 #[arg(value_name = "RID")]
70 #[arg(long, hide = true)]
71 repo: Option<RepoId>,
72
73 #[arg(short, long, conflicts_with = "repo", hide = true)]
75 all: bool,
76}
77
78#[derive(Parser, Clone, Copy, Debug)]
79pub(super) struct ListArgs {
80 #[arg(long, value_enum, default_value_t)]
82 pub(super) sort_by: SortBy,
83
84 #[arg(short, long)]
86 pub(super) reverse: bool,
87
88 #[arg(long)]
90 pub(super) show_unknown: bool,
91
92 #[arg(long, value_name = "RID")]
94 pub(super) repo: Option<RepoId>,
95
96 #[arg(short, long, conflicts_with = "repo")]
98 pub(super) all: bool,
99}
100
101impl From<ListArgs> for ListMode {
102 fn from(args: ListArgs) -> Self {
103 if args.all {
104 assert!(args.repo.is_none());
105 return Self::All;
106 }
107
108 if let Some(repo) = args.repo {
109 return Self::ByRepo(repo);
110 }
111
112 Self::Contextual
113 }
114}
115
116impl From<EmptyArgs> for ListArgs {
117 fn from(
118 EmptyArgs {
119 sort_by,
120 reverse,
121 show_unknown,
122 repo,
123 all,
124 }: EmptyArgs,
125 ) -> Self {
126 Self {
127 sort_by,
128 reverse,
129 show_unknown,
130 repo,
131 all,
132 }
133 }
134}
135
136#[derive(Parser, Clone, Debug)]
137pub(super) struct ClearArgs {
138 #[arg(long, value_name = "RID")]
140 repo: Option<RepoId>,
141
142 #[arg(short, long, conflicts_with = "repo")]
144 all: bool,
145
146 #[arg(value_name = "NOTIFICATION_ID")]
151 ids: Option<Vec<NotificationId>>,
152}
153
154impl From<ClearArgs> for ClearMode {
155 fn from(ClearArgs { repo, all, ids }: ClearArgs) -> Self {
156 if let Some(ids) = ids {
157 return Self::ByNotifications(ids);
158 }
159
160 if all {
161 assert!(repo.is_none());
162 return Self::All;
163 }
164
165 if let Some(repo) = repo {
166 return Self::ByRepo(repo);
167 }
168
169 Self::Contextual
170 }
171}
172
173#[derive(ValueEnum, Clone, Copy, Default, Debug)]
174pub enum SortBy {
175 Id,
176 #[default]
177 Timestamp,
178}
179
180impl Display for SortBy {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 match self {
183 Self::Id => write!(f, "rowid"),
184 Self::Timestamp => write!(f, "timestamp"),
185 }
186 }
187}
188
189impl FromStr for SortBy {
190 type Err = String;
191
192 fn from_str(s: &str) -> Result<Self, Self::Err> {
193 match s {
194 "id" => Ok(Self::Id),
195 "timestamp" => Ok(Self::Timestamp),
196 _ => Err(format!("'{s}' is not a valid sort by column")),
197 }
198 }
199}
200
201pub(super) enum ListMode {
202 Contextual,
205 All,
207 ByRepo(RepoId),
209}
210
211pub(super) enum ClearMode {
212 ByNotifications(Vec<NotificationId>),
217 ByRepo(RepoId),
219 All,
221 Contextual,
224}