1use anyhow::Result;
2use clap::Parser;
3use std::path::PathBuf;
4
5use bookmarks_core::config::{edit_config, print_config};
6use bookmarks_core::open::open_links;
7use bookmarks_core::storage::Storage;
8use bookmarks_core::toml_storage::TomlStorage;
9
10#[derive(Parser, Debug)]
11#[command(name = "bookmarks")]
12#[command(about = "Bookmarks in your filesystem")]
13#[command(version)]
14pub struct Args {
15 #[arg(short = 'f', long = "bookmarks-file", conflicts_with = "global")]
17 pub bookmarks_file: Option<PathBuf>,
18
19 #[arg(short, long, conflicts_with = "bookmarks_file")]
21 pub global: bool,
22
23 #[arg(short, long)]
25 pub config: bool,
26
27 #[cfg(feature = "app")]
29 #[arg(short = 'a', long)]
30 pub app: bool,
31
32 #[cfg(feature = "webapp")]
34 #[arg(short = 'w', long)]
35 pub webapp: bool,
36
37 pub links: Vec<String>,
39}
40
41fn resolve_storage(bookmarks_file: Option<PathBuf>, global: bool) -> Result<TomlStorage> {
47 if let Some(path) = bookmarks_file {
48 anyhow::ensure!(
49 path.exists(),
50 "bookmarks file not found: {}",
51 path.display()
52 );
53 return Ok(TomlStorage::new(path));
54 }
55
56 if !global
57 && let Some(cwd_path) = TomlStorage::cwd_path()
58 && cwd_path.exists()
59 {
60 return Ok(TomlStorage::new(cwd_path));
61 }
62
63 let storage = TomlStorage::with_default_path()?;
64 storage.init()?;
65 Ok(storage)
66}
67
68pub fn run_cli<I, T>(args: I) -> Result<()>
69where
70 I: IntoIterator<Item = T>,
71 T: Into<std::ffi::OsString> + Clone,
72{
73 let args = Args::parse_from(args);
74
75 let storage = resolve_storage(args.bookmarks_file, args.global)?;
76
77 #[cfg(feature = "app")]
78 if args.app {
79 return bookmarks_app::run(Box::new(storage)).map_err(|e| anyhow::anyhow!("{e}"));
80 }
81
82 #[cfg(feature = "webapp")]
83 if args.webapp {
84 return bookmarks_webapp::run(Box::new(storage));
85 }
86
87 if args.config {
88 if let Some(path) = storage.path() {
89 edit_config(path)?;
90 }
91 return Ok(());
92 }
93
94 let config = storage.load()?;
95
96 if args.links.is_empty() {
97 print_config(&config);
98 } else {
99 open_links(&args.links, &config)?;
100 }
101
102 if let Some(path) = storage.path() {
103 println!(
104 "(using {}, use --bookmarks-file to override)",
105 path.display()
106 );
107 }
108
109 Ok(())
110}