Use uuid-simd
This commit is contained in:
parent
5ac60c85d6
commit
93aac94326
|
@ -614,10 +614,10 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.6.0"
|
||||
name = "simd-abstraction"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||
checksum = "df70fadc9b3167d59d7301bffe0eee7f0a353024d338e7d25d822c28450ae893"
|
||||
|
||||
[[package]]
|
||||
name = "sled"
|
||||
|
@ -725,7 +725,8 @@ dependencies = [
|
|||
"serde_json",
|
||||
"sled",
|
||||
"url",
|
||||
"uuid",
|
||||
"uuid 1.0.0-alpha.1",
|
||||
"uuid-simd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -803,9 +804,26 @@ name = "uuid"
|
|||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.0.0-alpha.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb3ab47baa004111b323696c6eaa2752e7356f7f77cf6b6dc7a2087368ce1ca4"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"rand",
|
||||
"serde",
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uuid-simd"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "591acd57f5258ca9b664e0866820e999ab913e0777c6db32b7a7d0c34c5f0fcd"
|
||||
dependencies = [
|
||||
"simd-abstraction",
|
||||
"uuid 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -19,9 +19,13 @@ lto = true
|
|||
codegen-units = 1
|
||||
panic = "abort"
|
||||
|
||||
[build]
|
||||
rustflags = ["-C", "target-cpu=native"]
|
||||
|
||||
[dependencies]
|
||||
url = { version = "2.2.2", features = ["serde"] }
|
||||
uuid = { version = "0.8.2", features = ["v5", "serde"] }
|
||||
uuid = { version = "1.0.0-alpha.1", features = ["v4", "serde", "fast-rng"] }
|
||||
uuid-simd = "0.5.0"
|
||||
sled = { version = "0.34.7", features = ["compression"] }
|
||||
bincode = "1.3.3"
|
||||
paris = { version = "1.5", features = ["macros"] }
|
||||
|
|
204
src/commands.rs
204
src/commands.rs
|
@ -1,66 +1,76 @@
|
|||
use url::Url;
|
||||
use std::env::VarError;
|
||||
use chrono::Utc;
|
||||
use crate::structures::Bookmark;
|
||||
use paris::*;
|
||||
use crate::database;
|
||||
use crate::structures::{Bookmark, Container, ContainerTypes};
|
||||
use chrono::Utc;
|
||||
use paris::*;
|
||||
use serde_json::json;
|
||||
use std::path::PathBuf;
|
||||
use std::env::VarError;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, BufWriter};
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
use uuid_simd::UuidExt;
|
||||
|
||||
use dialoguer::{
|
||||
Select,
|
||||
theme::ColorfulTheme,
|
||||
console::Term
|
||||
};
|
||||
use dialoguer::{console::Term, theme::ColorfulTheme, Select};
|
||||
|
||||
pub fn edit(json: bool, url: &Option<Url>, path: Option<PathBuf>) {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": "unsupported command",
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": "unsupported command",
|
||||
})
|
||||
);
|
||||
std::process::exit(exitcode::DATAERR);
|
||||
} else {
|
||||
match url {
|
||||
Some(link) => {
|
||||
println!("User selected item :\n{}", link);
|
||||
},
|
||||
None => {
|
||||
match database::get_all(json, path) {
|
||||
Some(bookmarks) => {
|
||||
let mut items: Vec<&Url> = Vec::new();
|
||||
for i in &bookmarks {
|
||||
items.push(&i.link);
|
||||
}
|
||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||
.items(&items)
|
||||
.default(0)
|
||||
.interact_on_opt(&Term::stderr()).unwrap();
|
||||
}
|
||||
None => match database::get_all(json, path) {
|
||||
Some(bookmarks) => {
|
||||
let mut items: Vec<&Url> = Vec::new();
|
||||
for i in &bookmarks {
|
||||
items.push(&i.link);
|
||||
}
|
||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||
.items(&items)
|
||||
.default(0)
|
||||
.interact_on_opt(&Term::stderr())
|
||||
.unwrap();
|
||||
|
||||
match selection {
|
||||
Some(index) => println!("User selected item :\n{}", bookmarks[index]),
|
||||
None => println!("User did not select anything")
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
match selection {
|
||||
Some(index) => println!("User selected item :\n{}", bookmarks[index]),
|
||||
None => println!("User did not select anything"),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if json {
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": "an error ocurred in running your command",
|
||||
}));
|
||||
} else {
|
||||
warn!("an error ocurred in running your command");
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
} else {
|
||||
warn!("an error ocurred in running your command");
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(url: &Url, name: &String, description: &Option<String>, tags: &Vec<String>, json: bool, path: Option<PathBuf>) {
|
||||
pub fn add(
|
||||
url: &Url,
|
||||
name: &String,
|
||||
description: &Option<String>,
|
||||
tags: &Vec<String>,
|
||||
json: bool,
|
||||
path: Option<PathBuf>,
|
||||
) {
|
||||
let bookmark = Bookmark {
|
||||
link: url.to_owned(),
|
||||
label: name.to_string(),
|
||||
|
@ -89,13 +99,16 @@ pub fn list(json: bool, path: Option<PathBuf>) {
|
|||
println!("{}", i);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
None => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": "an error ocurred in running your command",
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": "an error ocurred in running your command",
|
||||
})
|
||||
);
|
||||
} else {
|
||||
warn!("an error ocurred in running your command");
|
||||
}
|
||||
|
@ -105,10 +118,13 @@ pub fn list(json: bool, path: Option<PathBuf>) {
|
|||
|
||||
pub fn env_err(json: bool, e: VarError) {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
warn!("couldn't read $HOME environment variable: {}", e);
|
||||
}
|
||||
|
@ -119,30 +135,39 @@ pub fn export(file_path: PathBuf, json: bool, path: Option<PathBuf>) {
|
|||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
warn!("error opening file! {}", e);
|
||||
}
|
||||
std::process::exit(exitcode::DATAERR);
|
||||
},
|
||||
}
|
||||
};
|
||||
let writer = BufWriter::new(file);
|
||||
|
||||
|
||||
match database::get_all(json, path) {
|
||||
Some(bookmarks) => serde_json::to_writer(writer, &bookmarks).unwrap(),
|
||||
None => std::process::exit(exitcode::IOERR),
|
||||
}
|
||||
|
||||
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "success",
|
||||
"reason": format!("exported bookmarks to {}", file_path.to_str().unwrap()),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "success",
|
||||
"reason": format!("exported bookmarks to {}", file_path.to_str().unwrap()),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
info!("Succesfully exported bookmarks to {}!", file_path.to_str().unwrap());
|
||||
info!(
|
||||
"Succesfully exported bookmarks to {}!",
|
||||
file_path.to_str().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,10 +176,13 @@ pub fn import(file_path: PathBuf, json: bool, store_path: Option<PathBuf>) {
|
|||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
warn!("error opening file! {}", e);
|
||||
}
|
||||
|
@ -167,10 +195,13 @@ pub fn import(file_path: PathBuf, json: bool, store_path: Option<PathBuf>) {
|
|||
Ok(contents) => contents,
|
||||
Err(e) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
warn!("error serializing file! {}", e);
|
||||
}
|
||||
|
@ -181,11 +212,34 @@ pub fn import(file_path: PathBuf, json: bool, store_path: Option<PathBuf>) {
|
|||
database::insert_multiple(&bookmarks, json, store_path);
|
||||
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "success",
|
||||
"reason": format!("imported bookmarks from {}", file_path.to_str().unwrap()),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "success",
|
||||
"reason": format!("imported bookmarks from {}", file_path.to_str().unwrap()),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
info!("succesfully imported bookmarks from {}!", file_path.to_str().unwrap());
|
||||
info!(
|
||||
"succesfully imported bookmarks from {}!",
|
||||
file_path.to_str().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_folder(label: &String, json: bool) {
|
||||
let folder = Container {
|
||||
id: Uuid::new_v4(),
|
||||
label: label.to_string(),
|
||||
container: None,
|
||||
container_type: ContainerTypes::Folder,
|
||||
};
|
||||
println!("{:?}", folder);
|
||||
if json {
|
||||
println!("{}", serde_json::to_string(&folder).unwrap());
|
||||
} else {
|
||||
println!("{:?}", folder);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_heirarchy(bookmarks: Vec<Bookmark>, containers: Vec<Container>) {}
|
||||
|
|
145
src/database.rs
145
src/database.rs
|
@ -1,11 +1,11 @@
|
|||
use crate::structures::Bookmark;
|
||||
use crate::commands::env_err;
|
||||
use crate::structures::Bookmark;
|
||||
|
||||
use paris::*;
|
||||
use url::Url;
|
||||
use std::env;
|
||||
use serde_json::json;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
|
||||
fn open_database(json: bool, path: Option<PathBuf>) -> Option<sled::Db> {
|
||||
let db: sled::Db;
|
||||
|
@ -20,27 +20,30 @@ fn open_database(json: bool, path: Option<PathBuf>) -> Option<sled::Db> {
|
|||
tmp_path.push(".local/share/tinymark");
|
||||
tmp_path.push("bookmarks_db");
|
||||
tmp_path
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
env_err(json, e);
|
||||
std::process::exit(exitcode::DATAERR);
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
match sled::open(database_path) {
|
||||
Ok(database) => db = database,
|
||||
Err(error) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
error!("error in opening database: {}", error);
|
||||
}
|
||||
return None;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
return Some(db);
|
||||
|
@ -60,36 +63,42 @@ pub fn insert_multiple(entries: &Vec<Bookmark>, json: bool, path: Option<PathBuf
|
|||
Ok(result) => bytes = result,
|
||||
Err(error) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
error!("failed serializing entry: {}", error);
|
||||
}
|
||||
std::process::exit(exitcode::DATAERR);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
batch.insert(i.link.as_str(), bytes);
|
||||
}
|
||||
|
||||
|
||||
match db.apply_batch(batch) {
|
||||
Ok(_) => {
|
||||
if !json {
|
||||
info!("succesfully applied batch insert");
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": e.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
warn!("error in applying batch insert: {}", e);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,39 +113,48 @@ pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
|
|||
Ok(result) => bytes = result,
|
||||
Err(error) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
error!("failed serializing entry: {}", error);
|
||||
}
|
||||
std::process::exit(exitcode::DATAERR);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
match db.insert(entry.link.to_string(), bytes) {
|
||||
Ok(_) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "success",
|
||||
"reason": "inserted entry",
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "success",
|
||||
"reason": "inserted entry",
|
||||
})
|
||||
);
|
||||
} else {
|
||||
info!("succesfully inserted entry <i>{}", entry.link);
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(error) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
error!("failed to insert entry <i>{}</i>!\n {}", entry.link, error);
|
||||
}
|
||||
std::process::exit(exitcode::IOERR);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
db.flush().unwrap();
|
||||
|
@ -152,15 +170,18 @@ pub fn remove_entry(link: &Url, json: bool, path: Option<PathBuf>) {
|
|||
Ok(_) => info!("succesfully removed entry <i>{}", link),
|
||||
Err(error) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
error!("failed to remove entry <i>{}</i>!\n {}", link, error);
|
||||
}
|
||||
std::process::exit(exitcode::IOERR);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
db.flush().unwrap();
|
||||
|
@ -173,20 +194,21 @@ pub fn get_all(json: bool, path: Option<PathBuf>) -> Option<Vec<Bookmark>> {
|
|||
};
|
||||
|
||||
let first_key = match db.first() {
|
||||
Ok(pair) => {
|
||||
pair.unwrap().0
|
||||
},
|
||||
Ok(pair) => pair.unwrap().0,
|
||||
Err(error) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
error!("failed to get first key: {}", error);
|
||||
}
|
||||
return None;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let mut bookmarks_vector: Vec<Bookmark> = Vec::new();
|
||||
|
@ -200,19 +222,22 @@ pub fn get_all(json: bool, path: Option<PathBuf>) -> Option<Vec<Bookmark>> {
|
|||
Ok(result) => read_entry = result,
|
||||
Err(error) => {
|
||||
if json {
|
||||
println!("{}", json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
}));
|
||||
println!(
|
||||
"{}",
|
||||
json!({
|
||||
"status": "fail",
|
||||
"reason": error.to_string(),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
error!("failed deserializing entry: {}", error);
|
||||
}
|
||||
return None;
|
||||
},
|
||||
}
|
||||
}
|
||||
bookmarks_vector.push(read_entry);
|
||||
},
|
||||
None => { break },
|
||||
}
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,7 +252,7 @@ pub fn update_entry(entry: &Bookmark) {
|
|||
Ok(bytes) => bytes,
|
||||
Err(error) => panic!("failed to serialize entry: {}", error),
|
||||
};
|
||||
|
||||
|
||||
let old_entry: Bookmark = get_entry(&entry.id.to_simple().to_string()).unwrap();
|
||||
|
||||
let old_bytes = match bincode::serialize(&old_entry) {
|
||||
|
@ -253,7 +278,7 @@ pub fn get_entry(id: &str) -> Option<Bookmark> {
|
|||
Ok(entry) => entry,
|
||||
Err(error) => panic!("failed to get old entry: {}", error),
|
||||
};
|
||||
|
||||
|
||||
if let Some(entry) = db_entry {
|
||||
let read_entry = match bincode::deserialize(&entry) {
|
||||
Ok(entry) => entry,
|
||||
|
|
|
@ -32,6 +32,7 @@ fn main() {
|
|||
}
|
||||
|
||||
match &args.command {
|
||||
Commands::New_Folder { name } => commands::new_folder(name, json),
|
||||
Commands::Add { url, name, description, tags } => commands::add(url, name, description, tags, json, cfg.storage_location),
|
||||
Commands::Edit { url } => commands::edit(json, url, cfg.storage_location),
|
||||
Commands::Delete { url } => database::remove_entry(url, json, cfg.storage_location),
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use chrono::prelude::*;
|
||||
use clap::{AppSettings, Parser, Subcommand};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
use clap::{AppSettings, Parser, Subcommand};
|
||||
use std::fmt;
|
||||
use chrono::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use uuid_simd::UuidExt;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
|
@ -18,7 +19,7 @@ impl Default for Config {
|
|||
Config {
|
||||
tui: false,
|
||||
json: false,
|
||||
storage_location: Some(PathBuf::from(r"$HOME/.local/share/tinymark")),
|
||||
storage_location: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +36,7 @@ pub struct Bookmark {
|
|||
}
|
||||
|
||||
fn do_nothing() {
|
||||
//yea
|
||||
//yea
|
||||
}
|
||||
|
||||
impl fmt::Display for Bookmark {
|
||||
|
@ -54,7 +55,11 @@ impl fmt::Display for Bookmark {
|
|||
}
|
||||
print!("]");
|
||||
|
||||
write!(f, "\nCreated at: {}\n", &self.created_at.with_timezone(&Local).to_rfc2822())
|
||||
write!(
|
||||
f,
|
||||
"\nCreated at: {}\n",
|
||||
&self.created_at.with_timezone(&Local).to_rfc2822()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +77,17 @@ pub enum ContainerTypes {
|
|||
Group,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum Thingy {
|
||||
Bookmark(Bookmark),
|
||||
Container(Container),
|
||||
}
|
||||
|
||||
pub struct Heirarchy {
|
||||
pub root: Container,
|
||||
pub heirarchy: Vec<Vec<Thingy>>,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
pub struct Cli {
|
||||
/// Output as JSON
|
||||
|
@ -84,6 +100,10 @@ pub struct Cli {
|
|||
|
||||
#[derive(Subcommand)]
|
||||
pub enum Commands {
|
||||
/// Add a folder
|
||||
#[clap(setting(AppSettings::ArgRequiredElseHelp))]
|
||||
New_Folder { name: String },
|
||||
|
||||
/// Add a bookmark
|
||||
#[clap(setting(AppSettings::ArgRequiredElseHelp))]
|
||||
Add {
|
||||
|
@ -97,13 +117,11 @@ pub enum Commands {
|
|||
description: Option<String>,
|
||||
|
||||
/// Optional comma-seperated tags
|
||||
tags: Vec<String>
|
||||
tags: Vec<String>,
|
||||
},
|
||||
|
||||
/// Edit a bookmark
|
||||
Edit {
|
||||
url: Option<Url>,
|
||||
},
|
||||
Edit { url: Option<Url> },
|
||||
|
||||
/// Delete a bookmark
|
||||
#[clap(setting(AppSettings::ArgRequiredElseHelp))]
|
||||
|
|
Loading…
Reference in New Issue