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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
use clap::{crate_authors, crate_description, crate_version, Args, Parser, Subcommand};
#[derive(Parser)]
#[clap(author=crate_authors!(), version=crate_version!(), about=crate_description!(), long_about = None)]
pub struct CliArgs {
/// Database url
#[arg(long, env = "DATABASE_URL", default_value = "./research.sqlite")]
pub db: String,
/// Turn debugging information on
#[arg(short, long, action = clap::ArgAction::Count)]
pub debug: u8,
#[command(subcommand)]
pub subcommand: Option<Subcommands>,
}
#[derive(Subcommand)]
pub enum Subcommands {
/// Pocket related actions
Pocket {
#[clap(subcommand)]
command: PocketCommands,
},
/// Add a new item to the database stored locally
Local {
#[clap(subcommand)]
command: LocalCommands,
},
/// Gets all data from authenticated providers
Fetch {
/// Limit the maximum number of items to fetch for each provider
#[arg(short, long)]
limit: Option<usize>,
},
/// Lists all items in the database
List {
/// Filter by tags separated by commas
/// Example: --tags rust,sql
#[clap(short, long, value_delimiter = ',', num_args = 1.. )]
tags: Option<Vec<String>>,
/// Limit the number of items to display
#[arg(short, long)]
limit: Option<usize>,
/// Favorite items only (Default: false)
#[arg(short = 'f', long, default_value = "false")]
favorite_only: bool,
/// Optional timezone (e.g., "America/New_York", "UTC")
#[arg(long)]
timezone: Option<String>,
},
/// Initializes the database
#[command(arg_required_else_help = true)]
Init {
/// This path will be used to create the database file and SAVED for future use.
#[arg(index = 1, required = true)]
path: String,
},
/// Generate a static site
#[command(arg_required_else_help = true)]
Generate {
/// The path to the output directory
#[arg(index = 1, required = true)]
output: String,
/// Path to required site assets (main.css, search.js, tailwind.config.js)
#[arg(long, default_value = "./assets")]
assets: String,
/// Download Tailwind binary to <ASSETS>/tailwindcss if not found
#[arg(long, action = clap::ArgAction::SetTrue)]
download_tailwind: bool,
/// Optional timezone (e.g., "America/New_York", "UTC")
#[arg(long)]
timezone: Option<String>,
},
/// Export data from the current database
#[command(arg_required_else_help = true)]
Export {
/// Export current database to CSV format for import into `raindrop.io`
#[arg(long, action = clap::ArgAction::SetTrue)]
raindrop: bool,
},
/// Handle operations related to the research:// URL scheme
#[command(arg_required_else_help = true)]
Handle {
/// Register the URL handler for research:// URLs
#[arg(long, action = clap::ArgAction::SetTrue)]
register: bool,
/// Unregister the URL handler for research:// URLs
#[arg(long, action = clap::ArgAction::SetTrue)]
unregister: bool,
/// Handle a specific research:// URL
#[arg(long)]
url: Option<String>,
},
}
#[derive(Args)]
pub struct AuthArgs {
/// Consumer key (https://getpocket.com/developer/apps/new)
#[arg(short, long, env = "POCKET_CONSUMER_KEY", required = true)]
pub key: String,
}
#[derive(Args)]
pub struct FetchArgs {
/// Pocket Consumer key
#[arg(long, env = "POCKET_CONSUMER_KEY", required = true)]
pub key: String,
/// Pocket Access token
#[arg(long, env = "POCKET_ACCESS_TOKEN", required = true)]
pub access: String,
/// Limit the maximum number of items to fetch
#[arg(short, long)]
pub limit: Option<usize>,
}
#[derive(Subcommand)]
pub enum PocketCommands {
/// Authenticate using a consumer key
Auth(AuthArgs),
/// Fetch items from pocket
Fetch(FetchArgs),
/// Add an item to pocket
Add(PocketAddArgs),
/// Mark an item as favorite in pocket
Favorite(PocketFavoriteArgs),
}
#[derive(Args)]
pub struct PocketAddArgs {
#[clap(flatten)]
pub add_args: LocalAddArgs,
/// Pocket Consumer key
#[arg(long, env = "POCKET_CONSUMER_KEY")]
pub key: Option<String>,
/// Pocket Access token
#[arg(long, env = "POCKET_ACCESS_TOKEN")]
pub access: Option<String>,
}
#[derive(Args)]
pub struct PocketFavoriteArgs {
#[clap(flatten)]
pub fav_args: LocalFavoriteArgs,
/// Pocket Consumer key
#[arg(long, env = "POCKET_CONSUMER_KEY")]
pub key: Option<String>,
/// Pocket Access token
#[arg(long, env = "POCKET_ACCESS_TOKEN")]
pub access: Option<String>,
}
#[derive(Args)]
pub struct LocalAddArgs {
/// URI (link) of the item (required)
pub uri: String,
/// Title of the item
pub title: Option<String>,
/// Excerpt of the item
pub excerpt: Option<String>,
/// Tags to associate with the item (comma separated)
#[clap(short, long, value_delimiter = ',', num_args = 1.. )]
pub tag: Option<Vec<String>>,
}
#[derive(Args)]
pub struct LocalFavoriteArgs {
/// URI (link) of the item to mark as favorite
pub uri: String,
/// Mark the item as favorite or not (Default: true)
#[arg(short, long, default_value = "true")]
pub mark: bool,
}
#[derive(Subcommand)]
pub enum LocalCommands {
/// Add an item to the local provider in the database
Add(LocalAddArgs),
/// List all items in the local provider
List,
/// Mark an item as favorite in the local provider
Favorite(LocalFavoriteArgs),
}