Use keyspaces for database, organize structs differently
This commit is contained in:
parent
93aac94326
commit
c775aff793
|
@ -90,6 +90,7 @@ dependencies = [
|
||||||
"strsim",
|
"strsim",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
|
"unicase",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -697,6 +698,9 @@ name = "textwrap"
|
||||||
version = "0.14.2"
|
version = "0.14.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
|
@ -753,6 +757,15 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
|
|
@ -30,7 +30,7 @@ sled = { version = "0.34.7", features = ["compression"] }
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
paris = { version = "1.5", features = ["macros"] }
|
paris = { version = "1.5", features = ["macros"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
clap = { version = "3.0.0-rc.9", features = ["derive"] }
|
clap = { version = "3.0.0-rc.9", features = ["derive","color","suggestions","unicode"] }
|
||||||
exitcode = "1.1.2"
|
exitcode = "1.1.2"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::database;
|
use crate::database;
|
||||||
use crate::structures::{Bookmark, Container, ContainerTypes};
|
use crate::structures::{Bookmark, Container, ContainerTypes, Keyspace};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use paris::*;
|
use paris::*;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
@ -13,7 +13,7 @@ use uuid_simd::UuidExt;
|
||||||
|
|
||||||
use dialoguer::{console::Term, theme::ColorfulTheme, Select};
|
use dialoguer::{console::Term, theme::ColorfulTheme, Select};
|
||||||
|
|
||||||
pub fn edit(json: bool, url: &Option<Url>, path: Option<PathBuf>) {
|
pub fn edit_bookmark(json: bool, url: &Option<Url>, path: Option<PathBuf>) {
|
||||||
if json {
|
if json {
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
|
@ -28,7 +28,7 @@ pub fn edit(json: bool, url: &Option<Url>, path: Option<PathBuf>) {
|
||||||
Some(link) => {
|
Some(link) => {
|
||||||
println!("User selected item :\n{}", link);
|
println!("User selected item :\n{}", link);
|
||||||
}
|
}
|
||||||
None => match database::get_all(json, path) {
|
None => match database::get_all(json, path, Keyspace::Bookmarks) {
|
||||||
Some(bookmarks) => {
|
Some(bookmarks) => {
|
||||||
let mut items: Vec<&Url> = Vec::new();
|
let mut items: Vec<&Url> = Vec::new();
|
||||||
for i in &bookmarks {
|
for i in &bookmarks {
|
||||||
|
@ -41,7 +41,12 @@ pub fn edit(json: bool, url: &Option<Url>, path: Option<PathBuf>) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
match selection {
|
match selection {
|
||||||
Some(index) => println!("User selected item :\n{}", bookmarks[index]),
|
Some(index) => {
|
||||||
|
println!(
|
||||||
|
"User selected item :\n{}",
|
||||||
|
bookmarks[index]
|
||||||
|
);
|
||||||
|
}
|
||||||
None => println!("User did not select anything"),
|
None => println!("User did not select anything"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +68,7 @@ pub fn edit(json: bool, url: &Option<Url>, path: Option<PathBuf>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(
|
pub fn add_bookmark(
|
||||||
url: &Url,
|
url: &Url,
|
||||||
name: &String,
|
name: &String,
|
||||||
description: &Option<String>,
|
description: &Option<String>,
|
||||||
|
@ -80,7 +85,7 @@ pub fn add(
|
||||||
created_at: Utc::now(),
|
created_at: Utc::now(),
|
||||||
};
|
};
|
||||||
|
|
||||||
database::insert_entry(&bookmark, json, path);
|
database::insert_entry(json, path, Keyspace::Bookmarks, &bookmark);
|
||||||
if json {
|
if json {
|
||||||
println!("{}", serde_json::to_string(&bookmark).unwrap());
|
println!("{}", serde_json::to_string(&bookmark).unwrap());
|
||||||
} else {
|
} else {
|
||||||
|
@ -89,14 +94,17 @@ pub fn add(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list(json: bool, path: Option<PathBuf>) {
|
pub fn list_bookmarks(json: bool, path: Option<PathBuf>) {
|
||||||
match database::get_all(json, path) {
|
match database::get_all(json, path, Keyspace::Bookmarks) {
|
||||||
Some(bookmarks) => {
|
Some(bookmarks) => {
|
||||||
for i in bookmarks {
|
for i in bookmarks {
|
||||||
if json {
|
if json {
|
||||||
println!("{}", serde_json::to_string(&i).unwrap());
|
println!(
|
||||||
|
"{}",
|
||||||
|
serde_json::to_string(&i).unwrap()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("{}", i);
|
println!("{}", &i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +158,7 @@ pub fn export(file_path: PathBuf, json: bool, path: Option<PathBuf>) {
|
||||||
};
|
};
|
||||||
let writer = BufWriter::new(file);
|
let writer = BufWriter::new(file);
|
||||||
|
|
||||||
match database::get_all(json, path) {
|
match database::get_all(json, path, Keyspace::Bookmarks) {
|
||||||
Some(bookmarks) => serde_json::to_writer(writer, &bookmarks).unwrap(),
|
Some(bookmarks) => serde_json::to_writer(writer, &bookmarks).unwrap(),
|
||||||
None => std::process::exit(exitcode::IOERR),
|
None => std::process::exit(exitcode::IOERR),
|
||||||
}
|
}
|
||||||
|
@ -209,7 +217,7 @@ pub fn import(file_path: PathBuf, json: bool, store_path: Option<PathBuf>) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
database::insert_multiple(&bookmarks, json, store_path);
|
database::insert_multiple(&bookmarks, json, store_path, Keyspace::Bookmarks);
|
||||||
|
|
||||||
if json {
|
if json {
|
||||||
println!(
|
println!(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::commands::env_err;
|
use crate::commands::env_err;
|
||||||
use crate::structures::Bookmark;
|
use crate::structures::{Bookmark, Keyspace};
|
||||||
|
|
||||||
use paris::*;
|
use paris::*;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
@ -7,7 +7,7 @@ use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
fn open_database(json: bool, path: Option<PathBuf>) -> Option<sled::Db> {
|
fn open_database(json: bool, path: Option<PathBuf>, keyspace: Keyspace) -> Option<sled::Tree> {
|
||||||
let db: sled::Db;
|
let db: sled::Db;
|
||||||
let database_path = match path {
|
let database_path = match path {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
|
@ -18,7 +18,7 @@ fn open_database(json: bool, path: Option<PathBuf>) -> Option<sled::Db> {
|
||||||
let mut tmp_path = PathBuf::new();
|
let mut tmp_path = PathBuf::new();
|
||||||
tmp_path.push(val);
|
tmp_path.push(val);
|
||||||
tmp_path.push(".local/share/tinymark");
|
tmp_path.push(".local/share/tinymark");
|
||||||
tmp_path.push("bookmarks_db");
|
tmp_path.push("database");
|
||||||
tmp_path
|
tmp_path
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -28,6 +28,7 @@ fn open_database(json: bool, path: Option<PathBuf>) -> Option<sled::Db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match sled::open(database_path) {
|
match sled::open(database_path) {
|
||||||
Ok(database) => db = database,
|
Ok(database) => db = database,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
@ -46,11 +47,38 @@ fn open_database(json: bool, path: Option<PathBuf>) -> Option<sled::Db> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Some(db);
|
let keyspace_str = match keyspace {
|
||||||
|
Keyspace::Bookmarks => "bookmarks",
|
||||||
|
Keyspace::Containers => "containers",
|
||||||
|
};
|
||||||
|
|
||||||
|
let database: Option<sled::Tree> = match db.open_tree(keyspace_str) {
|
||||||
|
Ok(nya) => Some(nya),
|
||||||
|
Err(e) => {
|
||||||
|
if json {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": e.to_string(),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
error!("error in opening Tree: {}", e);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return database;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_multiple(entries: &Vec<Bookmark>, json: bool, path: Option<PathBuf>) {
|
pub fn insert_multiple(
|
||||||
let db = match open_database(json, path) {
|
entries: &Vec<Bookmark>,
|
||||||
|
json: bool,
|
||||||
|
path: Option<PathBuf>,
|
||||||
|
keyspace: Keyspace,
|
||||||
|
) {
|
||||||
|
let db = match open_database(json, path, keyspace) {
|
||||||
Some(database) => database,
|
Some(database) => database,
|
||||||
None => std::process::exit(exitcode::NOINPUT),
|
None => std::process::exit(exitcode::NOINPUT),
|
||||||
};
|
};
|
||||||
|
@ -102,8 +130,9 @@ pub fn insert_multiple(entries: &Vec<Bookmark>, json: bool, path: Option<PathBuf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
|
pub fn insert_entry(json: bool, path: Option<PathBuf>, keyspace: Keyspace, _entry: &Bookmark) {
|
||||||
let db = match open_database(json, path) {
|
let entry = _entry;
|
||||||
|
let db = match open_database(json, path, keyspace) {
|
||||||
Some(database) => database,
|
Some(database) => database,
|
||||||
None => std::process::exit(exitcode::NOINPUT),
|
None => std::process::exit(exitcode::NOINPUT),
|
||||||
};
|
};
|
||||||
|
@ -113,8 +142,7 @@ pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
|
||||||
Ok(result) => bytes = result,
|
Ok(result) => bytes = result,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
if json {
|
if json {
|
||||||
println!(
|
println!("{}",
|
||||||
"{}",
|
|
||||||
json!({
|
json!({
|
||||||
"status": "fail",
|
"status": "fail",
|
||||||
"reason": error.to_string(),
|
"reason": error.to_string(),
|
||||||
|
@ -125,9 +153,11 @@ pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
|
||||||
}
|
}
|
||||||
std::process::exit(exitcode::DATAERR);
|
std::process::exit(exitcode::DATAERR);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
match db.insert(entry.link.to_string(), bytes) {
|
let name = &entry.link.to_string();
|
||||||
|
|
||||||
|
match db.insert(&name, bytes) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if json {
|
if json {
|
||||||
println!(
|
println!(
|
||||||
|
@ -138,7 +168,7 @@ pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
info!("succesfully inserted entry <i>{}", entry.link);
|
info!("succesfully inserted entry <i>{}", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
@ -151,7 +181,7 @@ pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
error!("failed to insert entry <i>{}</i>!\n {}", entry.link, error);
|
error!("failed to insert entry <i>{}</i>!\n {}", name, error);
|
||||||
}
|
}
|
||||||
std::process::exit(exitcode::IOERR);
|
std::process::exit(exitcode::IOERR);
|
||||||
}
|
}
|
||||||
|
@ -160,8 +190,8 @@ pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
|
||||||
db.flush().unwrap();
|
db.flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_entry(link: &Url, json: bool, path: Option<PathBuf>) {
|
pub fn remove_entry(link: &Url, json: bool, path: Option<PathBuf>, keyspace: Keyspace) {
|
||||||
let db = match open_database(json, path) {
|
let db = match open_database(json, path, keyspace) {
|
||||||
Some(database) => database,
|
Some(database) => database,
|
||||||
None => std::process::exit(exitcode::NOINPUT),
|
None => std::process::exit(exitcode::NOINPUT),
|
||||||
};
|
};
|
||||||
|
@ -187,14 +217,30 @@ pub fn remove_entry(link: &Url, json: bool, path: Option<PathBuf>) {
|
||||||
db.flush().unwrap();
|
db.flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all(json: bool, path: Option<PathBuf>) -> Option<Vec<Bookmark>> {
|
pub fn get_all(json: bool, path: Option<PathBuf>, keyspace: Keyspace) -> Option<Vec<Bookmark>> {
|
||||||
let db = match open_database(json, path) {
|
let db = match open_database(json, path, keyspace) {
|
||||||
Some(database) => database,
|
Some(database) => database,
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_key = match db.first() {
|
let first_key = match db.first() {
|
||||||
Ok(pair) => pair.unwrap().0,
|
Ok(pair) => match pair {
|
||||||
|
Some(key) => key.0,
|
||||||
|
None => {
|
||||||
|
if json {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
json!({
|
||||||
|
"status": "error",
|
||||||
|
"reason": "could not get first key",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
error!("error in getting first key");
|
||||||
|
}
|
||||||
|
std::process::exit(exitcode::IOERR);
|
||||||
|
}
|
||||||
|
},
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
if json {
|
if json {
|
||||||
println!(
|
println!(
|
||||||
|
@ -240,7 +286,6 @@ pub fn get_all(json: bool, path: Option<PathBuf>) -> Option<Vec<Bookmark>> {
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(bookmarks_vector);
|
return Some(bookmarks_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
src/main.rs
32
src/main.rs
|
@ -1,13 +1,11 @@
|
||||||
|
mod commands;
|
||||||
|
mod database;
|
||||||
pub mod structures;
|
pub mod structures;
|
||||||
mod tests;
|
mod tests;
|
||||||
mod database;
|
|
||||||
mod commands;
|
|
||||||
|
|
||||||
use crate::structures::{Commands, Cli, Config};
|
use crate::structures::{Cli, Commands, Config, Keyspace};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use paris::*;
|
use paris::*;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cfg: Config = confy::load("tinymark").unwrap();
|
let cfg: Config = confy::load("tinymark").unwrap();
|
||||||
|
@ -21,7 +19,6 @@ fn main() {
|
||||||
std::process::exit(exitcode::DATAERR);
|
std::process::exit(exitcode::DATAERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
let json: bool;
|
let json: bool;
|
||||||
|
|
||||||
|
@ -33,11 +30,22 @@ fn main() {
|
||||||
|
|
||||||
match &args.command {
|
match &args.command {
|
||||||
Commands::New_Folder { name } => commands::new_folder(name, json),
|
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::Add {
|
||||||
Commands::Edit { url } => commands::edit(json, url, cfg.storage_location),
|
url,
|
||||||
Commands::Delete { url } => database::remove_entry(url, json, cfg.storage_location),
|
name,
|
||||||
Commands::List { } => commands::list(json, cfg.storage_location),
|
description,
|
||||||
Commands::Export { file } => commands::export(file.to_path_buf(), json, cfg.storage_location),
|
tags,
|
||||||
Commands::Import { file } => commands::import(file.to_path_buf(), json, cfg.storage_location),
|
} => commands::add_bookmark(url, name, description, tags, json, cfg.storage_location),
|
||||||
|
Commands::Edit { url } => commands::edit_bookmark(json, url, cfg.storage_location),
|
||||||
|
Commands::Delete { url } => {
|
||||||
|
database::remove_entry(url, json, cfg.storage_location, Keyspace::Bookmarks)
|
||||||
|
}
|
||||||
|
Commands::List {} => commands::list_bookmarks(json, cfg.storage_location),
|
||||||
|
Commands::Export { file } => {
|
||||||
|
commands::export(file.to_path_buf(), json, cfg.storage_location)
|
||||||
|
}
|
||||||
|
Commands::Import { file } => {
|
||||||
|
commands::import(file.to_path_buf(), json, cfg.storage_location)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,15 +24,15 @@ impl Default for Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct Bookmark {
|
pub struct Bookmark {
|
||||||
//pub id: Uuid,
|
|
||||||
pub link: Url,
|
|
||||||
pub label: String,
|
|
||||||
pub description: Option<String>,
|
|
||||||
pub tags: Vec<String>,
|
|
||||||
pub container: Option<Uuid>,
|
pub container: Option<Uuid>,
|
||||||
pub created_at: DateTime<Utc>,
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub label: String,
|
||||||
|
//pub id: Uuid,
|
||||||
|
pub link: Url,
|
||||||
|
pub tags: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_nothing() {
|
fn do_nothing() {
|
||||||
|
@ -65,10 +65,26 @@ impl fmt::Display for Bookmark {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
pub id: Uuid,
|
|
||||||
pub label: String,
|
|
||||||
pub container: Option<Uuid>,
|
pub container: Option<Uuid>,
|
||||||
pub container_type: ContainerTypes,
|
pub container_type: ContainerTypes,
|
||||||
|
pub id: Uuid,
|
||||||
|
pub label: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Container {
|
||||||
|
pub fn new(
|
||||||
|
container: Option<Uuid>,
|
||||||
|
container_type: ContainerTypes,
|
||||||
|
id: Uuid,
|
||||||
|
label: String,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
container,
|
||||||
|
container_type,
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
@ -78,15 +94,28 @@ pub enum ContainerTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub enum Thingy {
|
pub enum Keyspace {
|
||||||
Bookmark(Bookmark),
|
Bookmarks,
|
||||||
Container(Container),
|
Containers,
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
impl Keyspace {
|
||||||
|
pub fn as_bookmarks(&self) -> Option<&Option<Bookmark>> {
|
||||||
|
if let Self::Bookmarks(v) = self {
|
||||||
|
Some(v)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Heirarchy {
|
pub fn as_containers(&self) -> Option<&Option<Container>> {
|
||||||
pub root: Container,
|
if let Self::Containers(v) = self {
|
||||||
pub heirarchy: Vec<Vec<Thingy>>,
|
Some(v)
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
|
|
Loading…
Reference in New Issue