From 84d0464f72761efdfb35e7da42e5688f58b01dd9 Mon Sep 17 00:00:00 2001 From: Tarek Date: Mon, 8 Apr 2024 17:06:02 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20refactor=C2=A0CLI=C2=A0enums=20to=20use?= =?UTF-8?q?=C2=A0`clap::ValueEnum`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tarek --- ark-cli/USAGE.md | 36 ++++++++++++---- ark-cli/src/main.rs | 20 +++------ ark-cli/src/models/cli.rs | 77 +++++++++++++++++++++++++++++------ ark-cli/src/models/entry.rs | 14 ------- ark-cli/src/models/format.rs | 16 ++------ ark-cli/src/models/sort.rs | 14 +------ ark-cli/src/models/storage.rs | 14 +------ 7 files changed, 102 insertions(+), 89 deletions(-) diff --git a/ark-cli/USAGE.md b/ark-cli/USAGE.md index fe48aac2..0a0a543a 100644 --- a/ark-cli/USAGE.md +++ b/ark-cli/USAGE.md @@ -3,18 +3,21 @@ ## Get started Create an empty dir: + ``` mkdir /tmp/test cd /tmp/test ``` Let's fill it with something. One of the simplest ways to create resources it is to save a link to web page using `ark-cli link` command: + ``` $ ark-cli link create . http://google.com goo $ ark-cli link create . http://duckduckgo.com duck ``` We can use `ark-cli list` to see just created resources: + ``` 22-207093268 18-1909444406 @@ -23,6 +26,7 @@ We can use `ark-cli list` to see just created resources: These are just ids, derived from the URLs themselves. Now, the dir structure should resemble this: + ``` /tmp/test └───.ark @@ -36,19 +40,22 @@ Now, the dir structure should resemble this: └───tags ``` -### Label your data +### Label your data You can attach various metadata to your data, e.g. tags: + ``` $ ark-cli file append . tags 22-207093268 search,engine ``` The same way we can append scores: + ``` $ ark-cli file append . scores 22-207093268 15 ``` Generic metadata is possible using JSON-based properties: + ``` $ ark-cli file append . properties 22-207093268 favorites:false,ai:true --format=json ``` @@ -56,6 +63,7 @@ $ ark-cli file append . properties 22-207093268 favorites:false,ai:true --format ### Navigate your data The simplest command to observe your resources is `list`: + ``` $ ark-cli list @@ -64,6 +72,7 @@ $ ark-cli list ``` You can also target this command to other folders: + ``` $ ark-cli list ~/Pictures/ @@ -74,14 +83,18 @@ $ ark-cli list ~/Pictures/ ``` But it's a bit boring and doesn't really tell anything, right? Various flags should be used to gain more knowledge about your collections of resources: -* `--entry=id|path|both|link` to show the path,the id or both of a resource -* `--modified` to show or not the last modified timestamp of a resource -* `--tags=true` to show or not the tags for every resource -* `--scores=true` to show or not the scores for every resource -* `--sort=asc|desc` to sort resources by asc or dsc order of scores -* `--filter=query` to filter resources by their tags + +- `--entry=id|path|ip|link` to show the path,the id or both of a resource +- `--modified` to show or not the last modified timestamp of a resource +- `--tags=true` to show or not the tags for every resource +- `--scores=true` to show or not the scores for every resource +- `--sort=asc|desc` to sort resources by asc or dsc order of scores +- `--filter=query` to filter resources by their tags + +> **Note**: if `--entry` is set to `link`, other values are ignored For instance, you can list files with their paths and attached tags: + ``` $ ark-cli list -pt @@ -104,6 +117,7 @@ https://github.com ``` Or, sort by score: + ``` $ ark-cli list -s --sort=asc @@ -114,6 +128,7 @@ $ ark-cli list -s --sort=asc ``` Finally, you can filter resources using their tags: + ``` $ /tmp/ark-cli list -t --filter=search @@ -128,12 +143,14 @@ There are commands which could be useful with time, when you grasp the basic con ### Retrieve the metadata You can read these properties: + ``` $ ark-cli file read . properties 22-207093268 {"ai":"true","desc":null,"favorites":"false","title":"duck"} ``` As well as scores or tags: + ``` $ ark-cli file read . scores 22-207093268 15 @@ -144,6 +161,7 @@ search,engine ### Inspect storages It's also possible to list resources having some metadata in a particular storage: + ``` $ ark-cli storage list . properties 22-207093268 @@ -161,6 +179,7 @@ Note that, in this example, resource with id `18-1909444406` is listed only in ` ### Inspect versions For delving into history of storage mutations, we made `--versions` flag: + ``` $ ark-cli storage list . properties --versions=true version name machine path @@ -168,9 +187,10 @@ version name machine path 1 18-1909444406 0592a937-a5d1-4843-8f03-ae0d6a9e77b5 ./.ark/user/properties/18-1909444406/18-1909444406_0592a937-a5d1-4843-8f03-ae0d6a9e77b5.1 ``` -Each storage mutation made by `ark-cli file append` or `ark-cli file insert` commands increases the number in `version` column. Versions help to prevent dirty-writes caused by using same storages by separate apps, or devices. +Each storage mutation made by `ark-cli file append` or `ark-cli file insert` commands increases the number in `version` column. Versions help to prevent dirty-writes caused by using same storages by separate apps, or devices. The `properties` storage is _folder-based_, but same command can be used with _file-based_ storages like `tags`: + ``` $ ark-cli storage list . tags --versions=true Loading app id at /home/kirill/.ark... diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 51b441ea..00e1cc8b 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -69,10 +69,9 @@ async fn main() -> anyhow::Result<()> { match &args.command { Command::List { - entry, - entry_id, - entry_path, - entry_link, + entry_id: _, + entry_path: _, + entry_link: _, root_dir, modified, @@ -82,16 +81,7 @@ async fn main() -> anyhow::Result<()> { filter, } => { let root = provide_root(root_dir)?; - - let entry_output = match (entry, entry_id, entry_path, entry_link) { - (Some(e), false, false, false) => Ok(*e), - (None, true, false, false) => Ok(EntryOutput::Id), - (None, false, true, false) => Ok(EntryOutput::Path), - (None, true, true, false) => Ok(EntryOutput::Both), - (None, false, false, false) => Ok(EntryOutput::Id), - (None, false, false, true) => Ok(EntryOutput::Link), - _ => Err(AppError::InvalidEntryOption), - }?; + let entry_output = &args.command.entry()?; let mut storage_entries: Vec = provide_index(&root) .map_err(|_| { @@ -157,7 +147,7 @@ async fn main() -> anyhow::Result<()> { (Some(path.to_owned().into_path_buf()), None, None) } EntryOutput::Id => (None, Some(resource.id), None), - EntryOutput::Link => match File::open(&path) { + EntryOutput::Link => match File::open(path) { Ok(mut file) => { let mut contents = String::new(); match file.read_to_string(&mut contents) { diff --git a/ark-cli/src/models/cli.rs b/ark-cli/src/models/cli.rs index 24f3d485..f45434cb 100644 --- a/ark-cli/src/models/cli.rs +++ b/ark-cli/src/models/cli.rs @@ -1,3 +1,5 @@ +use crate::AppError; +use anyhow::Result; use std::path::PathBuf; use arklib::id::ResourceId; @@ -43,16 +45,31 @@ pub enum Command { #[clap(parse(from_os_str))] root_dir: Option, - #[clap(long)] - entry: Option, - - #[clap(long, short = 'i', action)] + #[clap( + long, + short = 'i', + long = "id", + action, + help = "Show entries' IDs" + )] entry_id: bool, - #[clap(long, short = 'p', action)] + #[clap( + long, + short = 'p', + long = "path", + action, + help = "Show entries' paths" + )] entry_path: bool, - #[clap(long, short = 'l', action)] + #[clap( + long, + short = 'l', + long = "link", + action, + help = "Show entries' links" + )] entry_link: bool, #[clap(long, short, action)] @@ -64,7 +81,7 @@ pub enum Command { #[clap(long, short, action)] scores: bool, - #[clap(long)] + #[clap(long, value_enum)] sort: Option, #[clap(long)] @@ -81,6 +98,40 @@ pub enum Command { Storage(StorageCommand), } +impl Command { + /// Get the entry output format + /// Default to Id + pub fn entry(&self) -> Result { + match self { + Command::List { + entry_id, + entry_path, + entry_link, + .. + } => { + // Link can only be used alone + if *entry_link { + if *entry_id || *entry_path { + return Err(AppError::InvalidEntryOption)?; + } else { + return Ok(EntryOutput::Link); + } + } + + if *entry_id && *entry_path { + Ok(EntryOutput::Both) + } else if *entry_path { + Ok(EntryOutput::Path) + } else { + // Default to id + Ok(EntryOutput::Id) + } + } + _ => Ok(EntryOutput::Id), + } + } +} + #[derive(Subcommand, Debug)] pub enum StorageCommand { List { @@ -92,7 +143,7 @@ pub enum StorageCommand { #[clap(short, long)] versions: Option, - #[clap(short, long)] + #[clap(short, long, value_enum)] type_: Option, }, } @@ -109,10 +160,10 @@ pub enum FileCommand { content: String, - #[clap(short, long)] + #[clap(short, long, value_enum)] format: Option, - #[clap(short, long)] + #[clap(short, long, value_enum)] type_: Option, }, @@ -126,10 +177,10 @@ pub enum FileCommand { content: String, - #[clap(short, long)] + #[clap(short, long, value_enum)] format: Option, - #[clap(short, long)] + #[clap(short, long, value_enum)] type_: Option, }, @@ -141,7 +192,7 @@ pub enum FileCommand { id: String, - #[clap(short, long)] + #[clap(short, long, value_enum)] type_: Option, }, } diff --git a/ark-cli/src/models/entry.rs b/ark-cli/src/models/entry.rs index 475909bf..7b75fd9b 100644 --- a/ark-cli/src/models/entry.rs +++ b/ark-cli/src/models/entry.rs @@ -7,17 +7,3 @@ pub enum EntryOutput { Path, Both, } - -impl std::str::FromStr for EntryOutput { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "id" => Ok(EntryOutput::Id), - "path" => Ok(EntryOutput::Path), - "both" => Ok(EntryOutput::Both), - "link" => Ok(EntryOutput::Link), - _ => Err("Entry output must be either 'id', 'path' or 'both'"), - } - } -} diff --git a/ark-cli/src/models/format.rs b/ark-cli/src/models/format.rs index c8d6fb55..31c69f5e 100644 --- a/ark-cli/src/models/format.rs +++ b/ark-cli/src/models/format.rs @@ -1,23 +1,13 @@ use crate::error::InlineJsonParseError; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, clap::ValueEnum)] pub enum Format { + #[clap(name = "json")] KeyValue, + #[clap(name = "raw")] Raw, } -impl std::str::FromStr for Format { - type Err = String; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "json" => Ok(Format::KeyValue), - "raw" => Ok(Format::Raw), - _ => Err("Invalid format".to_owned()), - } - } -} - pub fn key_value_to_str( s: &str, ) -> Result, InlineJsonParseError> { diff --git a/ark-cli/src/models/sort.rs b/ark-cli/src/models/sort.rs index 000da162..ddd6315c 100644 --- a/ark-cli/src/models/sort.rs +++ b/ark-cli/src/models/sort.rs @@ -1,19 +1,7 @@ use clap::Parser; -#[derive(Parser, Debug)] +#[derive(Parser, Debug, clap::ValueEnum, Clone)] pub enum Sort { Asc, Desc, } - -impl std::str::FromStr for Sort { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "asc" => Ok(Sort::Asc), - "desc" => Ok(Sort::Desc), - _ => Err("Sort must be either 'asc' or 'desc'"), - } - } -} diff --git a/ark-cli/src/models/storage.rs b/ark-cli/src/models/storage.rs index 6e49d32b..d2afb445 100644 --- a/ark-cli/src/models/storage.rs +++ b/ark-cli/src/models/storage.rs @@ -11,24 +11,12 @@ use crate::{ models::format::Format, }; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, clap::ValueEnum)] pub enum StorageType { File, Folder, } -impl std::str::FromStr for StorageType { - type Err = String; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "file" => Ok(StorageType::File), - "folder" => Ok(StorageType::Folder), - _ => Err(format!("Invalid storage type: {}", s)), - } - } -} - pub struct Storage { path: PathBuf, storage_type: StorageType,