1use clap::*;
2use crate::archive::Archive;
3use crate::*;
4use soulog::*;
5
6pub static mut VERBOSE: bool = false;
7
8#[derive(Parser)]
9#[command(author, version, about)]
10pub struct Cli {
11 #[arg(short, long, help="Specifies if you want it to log everything it does")]
12 pub verbose: bool,
13 #[command(subcommand)]
14 pub command: Commands,
15}
16
17#[derive(Subcommand)]
18pub enum Commands {
19 #[command(about="A mere test command")]
20 Test,
21 #[command(about="Initialises a new archive")]
22 Init,
23 #[command(about="Wipes the archive")]
24 Wipe,
25 #[command(about="Commit an entry into the archive")]
26 Commit {
27 #[arg(index=1, required=true, help="The path to the entry config toml file to commit.")]
28 file_path: String,
29 },
30 #[command(about="Backs up the archive")]
31 Backup {
32 #[arg(index=1, required=false, help="Specifies the path that you want the backup file to be generated.")]
33 out_path: Option<String>,
34 },
35 #[command(about="Loads a backed up archive")]
36 Load {
37 #[arg(short, long, help="Force loads a backup even if you may lose archive data.")]
38 force: bool,
39 #[arg(index=1, required=true, help="The path of the backup file you want to load.")]
40 file_path: String,
41 },
42 #[command(about="Rolls back to the last backed up archive")]
43 Rollback {
44 #[arg(short, long, help="Force loads a backup even if you may lose archive data.")]
45 force: bool,
46 },
47 #[command(about="Returns the days since 2020 from a specified date")]
48 Since {
49 #[arg(short, long, number_of_values=3, value_names=&["year", "month", "day"])]
50 date: Option<Vec<u16>>,
51 #[arg(short, long)]
52 today: bool,
53 },
54 #[command(about="Pulls a entry or moc from the archive as toml in case you need to change something")]
55 Pull {
56 #[arg(short='m', long, help="Specifies if it is a moc or not (otherwise it is an entry).")]
57 is_moc: bool,
58 #[arg(index=1, required=true, help="The uid of the entry or moc.")]
59 uid: String,
60 #[arg(short='1', long, help="Specifies if you want it all in one file.")]
61 one_file: bool,
62 #[arg(short, long, default_value=".", help="Specfies path of the containing folder of the config file.")]
63 path: String,
64 #[arg(short, long, default_value="config.toml", help="Specifies the name of the output config file.")]
65 file_name: String,
66 },
67 #[command(about="Searches the archive with specified tags.")]
68 List {
69 #[arg(short='f', long="filter", num_args=1.., help="Filters out the list accordding to specified tags")]
70 tags: Option<Vec<String>>,
71 #[arg(short, long, requires="tags", help="Sets if the search is strict or not (if the item must implement all tags)")]
72 strict: bool,
73 #[arg(short='e', long, help="Sets if you want to show entries")]
74 show_entries: bool,
75 #[arg(short='m', long, help="Sets if you want to show mocs")]
76 show_mocs: bool,
77 },
78 #[command(about="Sorts the unsorted, committed, entries.")]
79 Sort,
80 #[command(about="Exports the archive as an `Obsidian.md` vault.")]
81 Export {
82 #[arg(short, long, num_args=1.., help="Filters out entries and mocs that don't have all these tags")]
83 tags: Option<Vec<String>>,
84 #[arg(short, long, requires="tags", help="Determines if the tags filter strictly or not")]
85 strict: bool,
86 #[arg(index=1, required=true, help="The path the `Obsidian.md` vault is going to be placed")]
87 path: String,
88 },
89 #[command(about="Lists the attributes about an entry or moc.")]
90 About {
91 #[arg(short='m', long, help="Determines if it is a moc or not")]
92 is_moc: bool,
93 #[arg(index=1, required=true, help="The uid of the entry or moc")]
94 uid: String,
95 },
96 #[command(about="Removes an entry or moc from the archive.")]
97 Remove {
98 #[arg(short='m', long, help="Determines if it is a moc or not")]
99 is_moc: bool,
100 #[arg(index=1)]
101 uid: String,
102 },
103}
104
105impl Commands {
106 pub fn execute(self) {
107 use Commands::*;
108 let logger = DynamicLogger::new();
109 match self {
110 Test => println!("Hello, world!"),
111 Init => {Archive::init(logger);},
112 Wipe => Archive::load(logger.hollow()).wipe(logger),
113 Commit { file_path } => Archive::load(logger.hollow()).commit(file_path, logger),
114 Load { file_path, force } => Archive::load_backup(file_path, force, logger),
115 Rollback { force } => Archive::rollback(force, logger),
116 Backup { out_path } => {
117 match out_path {
118 Some(path) => Archive::backup(path, logger),
119 None => Archive::backup(home_dir().join("backup.ldb"), logger),
120 }
121 },
122 Since { date, today: _ } => since::since_2023(date, logger),
123 Pull { is_moc, one_file, uid, path, file_name } => pull::pull(std::path::PathBuf::from(path), file_name, is_moc, uid, one_file, logger),
124 List { strict, tags, show_entries, show_mocs } => search::list_command(strict, show_mocs, show_entries, tags, logger),
125 Sort => sort::sort(logger),
126 Export { strict, tags, path } => export::export_md(strict, tags, path, logger.hollow()),
127 About { is_moc, uid } => about::about(is_moc, uid, logger),
128 Remove { is_moc, uid } => uncommit::uncommmit(uid, is_moc, logger),
129 }
130 }
131}
132
133pub fn run() {
134 let args = Cli::parse();
135 unsafe { VERBOSE = args.verbose };
136 args.command.execute();
137}