Skip to content

Commit

Permalink
fix: refactor CLI enums to use clap::ValueEnum
Browse files Browse the repository at this point in the history
Signed-off-by: Tarek <[email protected]>
  • Loading branch information
tareknaser committed Apr 8, 2024
1 parent 5cf25df commit 84d0464
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 89 deletions.
36 changes: 28 additions & 8 deletions ark-cli/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -36,26 +40,30 @@ 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
```

### Navigate your data

The simplest command to observe your resources is `list`:

```
$ ark-cli list
Expand All @@ -64,6 +72,7 @@ $ ark-cli list
```

You can also target this command to other folders:

```
$ ark-cli list ~/Pictures/
Expand All @@ -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
Expand All @@ -104,6 +117,7 @@ https://github.com
```

Or, sort by score:

```
$ ark-cli list -s --sort=asc
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -161,16 +179,18 @@ 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
2 22-207093268 0592a937-a5d1-4843-8f03-ae0d6a9e77b5 ./.ark/user/properties/22-207093268/22-207093268_0592a937-a5d1-4843-8f03-ae0d6a9e77b5.2
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...
Expand Down
20 changes: 5 additions & 15 deletions ark-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<StorageEntry> = provide_index(&root)
.map_err(|_| {
Expand Down Expand Up @@ -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) {
Expand Down
77 changes: 64 additions & 13 deletions ark-cli/src/models/cli.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::AppError;
use anyhow::Result;
use std::path::PathBuf;

use arklib::id::ResourceId;
Expand Down Expand Up @@ -43,16 +45,31 @@ pub enum Command {
#[clap(parse(from_os_str))]
root_dir: Option<PathBuf>,

#[clap(long)]
entry: Option<EntryOutput>,

#[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)]
Expand All @@ -64,7 +81,7 @@ pub enum Command {
#[clap(long, short, action)]
scores: bool,

#[clap(long)]
#[clap(long, value_enum)]
sort: Option<Sort>,

#[clap(long)]
Expand All @@ -81,6 +98,40 @@ pub enum Command {
Storage(StorageCommand),
}

impl Command {
/// Get the entry output format
/// Default to Id
pub fn entry(&self) -> Result<EntryOutput> {
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 {
Expand All @@ -92,7 +143,7 @@ pub enum StorageCommand {
#[clap(short, long)]
versions: Option<bool>,

#[clap(short, long)]
#[clap(short, long, value_enum)]
type_: Option<StorageType>,
},
}
Expand All @@ -109,10 +160,10 @@ pub enum FileCommand {

content: String,

#[clap(short, long)]
#[clap(short, long, value_enum)]
format: Option<Format>,

#[clap(short, long)]
#[clap(short, long, value_enum)]
type_: Option<StorageType>,
},

Expand All @@ -126,10 +177,10 @@ pub enum FileCommand {

content: String,

#[clap(short, long)]
#[clap(short, long, value_enum)]
format: Option<Format>,

#[clap(short, long)]
#[clap(short, long, value_enum)]
type_: Option<StorageType>,
},

Expand All @@ -141,7 +192,7 @@ pub enum FileCommand {

id: String,

#[clap(short, long)]
#[clap(short, long, value_enum)]
type_: Option<StorageType>,
},
}
Expand Down
14 changes: 0 additions & 14 deletions ark-cli/src/models/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self, Self::Err> {
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'"),
}
}
}
16 changes: 3 additions & 13 deletions ark-cli/src/models/format.rs
Original file line number Diff line number Diff line change
@@ -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<Self, Self::Err> {
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<Vec<(String, String)>, InlineJsonParseError> {
Expand Down
14 changes: 1 addition & 13 deletions ark-cli/src/models/sort.rs
Original file line number Diff line number Diff line change
@@ -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<Self, Self::Err> {
match s.to_lowercase().as_str() {
"asc" => Ok(Sort::Asc),
"desc" => Ok(Sort::Desc),
_ => Err("Sort must be either 'asc' or 'desc'"),
}
}
}
Loading

0 comments on commit 84d0464

Please sign in to comment.