diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2019-12-08 13:16:16 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2019-12-08 13:48:47 +0100 |
commit | 4f2ea236af73d9fc03819933c78d46fbd39e9820 (patch) | |
tree | dc5729db95fa9258c21ccb3042fb09af26c73c6c | |
parent | 37b7b2e67ea89c492abc1b6c6f3b62c5c643e75d (diff) |
Reimplement imag-bookmark commandline frontend
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r-- | bin/domain/imag-bookmark/Cargo.toml | 8 | ||||
-rw-r--r-- | bin/domain/imag-bookmark/src/lib.rs | 132 | ||||
-rw-r--r-- | bin/domain/imag-bookmark/src/ui.rs | 86 |
3 files changed, 91 insertions, 135 deletions
diff --git a/bin/domain/imag-bookmark/Cargo.toml b/bin/domain/imag-bookmark/Cargo.toml index 7e039df1..c5851236 100644 --- a/bin/domain/imag-bookmark/Cargo.toml +++ b/bin/domain/imag-bookmark/Cargo.toml @@ -25,11 +25,14 @@ toml = "0.5.1" toml-query = "0.9.2" failure = "0.1.5" resiter = "0.4.0" +url = "2" libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } +libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } libimagbookmark = { version = "0.10.0", path = "../../../lib/domain/libimagbookmark" } libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" } +libimagentryurl = { version = "0.10.0", path = "../../../lib/entry/libimagentryurl" } libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" } [dependencies.clap] @@ -37,6 +40,11 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[dependencies.uuid] +version = "0.7" +default-features = false +features = ["serde", "v4"] + [lib] name = "libimagbookmarkfrontend" path = "src/lib.rs" diff --git a/bin/domain/imag-bookmark/src/lib.rs b/bin/domain/imag-bookmark/src/lib.rs index 537c6f4d..98f50fca 100644 --- a/bin/domain/imag-bookmark/src/lib.rs +++ b/bin/domain/imag-bookmark/src/lib.rs @@ -37,6 +37,8 @@ extern crate clap; #[macro_use] extern crate log; extern crate toml; +extern crate url; +extern crate uuid; extern crate toml_query; #[macro_use] extern crate failure; extern crate resiter; @@ -44,25 +46,27 @@ extern crate resiter; extern crate libimagbookmark; extern crate libimagrt; extern crate libimagerror; +extern crate libimagstore; extern crate libimagutil; -extern crate libimagentrylink; +extern crate libimagentryurl; use std::io::Write; -use std::ops::DerefMut; -use toml_query::read::TomlValueReadTypeExt; use failure::Error; use failure::err_msg; use failure::Fallible as Result; use resiter::AndThen; +use resiter::IterInnerOkOrElse; use clap::App; +use url::Url; use libimagrt::runtime::Runtime; use libimagrt::application::ImagApplication; -use libimagbookmark::collection::BookmarkCollection; -use libimagbookmark::collection::BookmarkCollectionStore; -use libimagbookmark::link::Link as BookmarkLink; -use libimagentrylink::linkable::Linkable; +use libimagstore::iter::get::StoreIdGetIteratorExtension; +use libimagbookmark::store::BookmarkStore; +use libimagbookmark::bookmark::Bookmark; +use libimagentryurl::link::Link; + mod ui; @@ -75,7 +79,6 @@ impl ImagApplication for ImagBookmark { fn run(rt: Runtime) -> Result<()> { match rt.cli().subcommand_name().ok_or_else(|| err_msg("No subcommand called"))? { "add" => add(&rt), - "collection" => collection(&rt), "list" => list(&rt), "remove" => remove(&rt), other => { @@ -108,105 +111,52 @@ impl ImagApplication for ImagBookmark { fn add(rt: &Runtime) -> Result<()> { let scmd = rt.cli().subcommand_matches("add").unwrap(); - let coll = get_collection_name(rt, "add", "collection")?; - - let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)? - .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?; - - rt.report_touched(collection.get_location())?; - scmd.values_of("urls") .unwrap() .into_iter() - .map(|url| { - let new_ids = BookmarkCollection::add_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))?; - rt.report_all_touched(new_ids.into_iter()).map_err(Error::from) + .map(|s| Url::parse(s).map_err(Error::from)) + .and_then_ok(|url| { + let (uuid, fle) = rt.store().add_bookmark(url.clone())?; + debug!("Created entry for url '{}' with uuid '{}'", url, uuid); + info!("{} = {}", url, uuid); + rt.report_touched(fle.get_location()).map_err(Error::from) }) .collect() } -fn collection(rt: &Runtime) -> Result<()> { - let scmd = rt.cli().subcommand_matches("collection").unwrap(); - - if scmd.is_present("add") { // adding a new collection - let name = scmd.value_of("add").unwrap(); - let id = BookmarkCollectionStore::new(rt.store(), &name)?; - rt.report_touched(id.get_location())?; - info!("Created: {}", name); - } - - if scmd.is_present("remove") { // remove a collection - let name = scmd.value_of("remove").unwrap(); - - { // remove all links - BookmarkCollectionStore::get(rt.store(), &name)? - .ok_or_else(|| format_err!("Collection does not exist: {}", name))? - .unlink(rt.store())?; - } - - BookmarkCollectionStore::delete(rt.store(), &name)?; - info!("Deleted: {}", name); - } - - Ok(()) -} - fn list(rt: &Runtime) -> Result<()> { - let coll = get_collection_name(rt, "list", "collection")?; - - let collection = BookmarkCollectionStore::get(rt.store(), &coll)? - .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?; - - rt.report_touched(collection.get_location())?; - - let mut i = 0; // poor mans enumerate() + rt.store() + .all_bookmarks()? + .into_get_iter() + .map_inner_ok_or_else(|| err_msg("Did not find one entry")) + .and_then_ok(|entry| { + if entry.is_bookmark()? { + let url = entry.get_url()? + .ok_or_else(|| format_err!("Failed to retrieve URL for {}", entry.get_location()))?; + if !rt.output_is_pipe() { + writeln!(rt.stdout(), "{}", url)?; + } - collection - .get_links(rt.store())? - .and_then_ok(|link| { - let r = writeln!(rt.stdout(), "{: >3}: {}", i, link).map_err(Error::from); - i += 1; - r + rt.report_touched(entry.get_location()).map_err(Error::from) + } else { + Ok(()) + } }) .collect() } fn remove(rt: &Runtime) -> Result<()> { - let scmd = rt.cli().subcommand_matches("remove").unwrap(); - let coll = get_collection_name(rt, "list", "collection")?; - - let mut collection = BookmarkCollectionStore::get(rt.store(), &coll)? - .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll))?; - - rt.report_touched(collection.get_location())?; - - scmd.values_of("urls") - .unwrap() + rt.ids::<crate::ui::PathProvider>()? + .ok_or_else(|| err_msg("No ids supplied"))? .into_iter() - .map(|url| { - let removed_links = BookmarkCollection::remove_link(collection.deref_mut(), rt.store(), BookmarkLink::from(url))?; - rt.report_all_touched(removed_links.into_iter()).map_err(Error::from) + .map(Ok) + .into_get_iter(rt.store()) + .map_inner_ok_or_else(|| err_msg("Did not find one entry")) + .and_then_ok(|fle| { + rt.report_touched(fle.get_location()) + .map_err(Error::from) + .and_then(|_| rt.store().remove_bookmark(fle)) }) .collect() } - -fn get_collection_name(rt: &Runtime, - subcommand_name: &str, - collection_argument_name: &str) - -> Result<String> -{ - if let Some(cn) = rt.cli() - .subcommand_matches(subcommand_name) - .and_then(|scmd| scmd.value_of(collection_argument_name).map(String::from)) - { - return Ok(cn) - } else { - rt.config().ok_or_else(|| err_msg("No configuration availablew")) - .and_then(|cfg| { - cfg.read_string("bookmark.default_collection")? - .ok_or_else(|| err_msg("Missing config: 'bookmark.default_collection'.")) - }) - } -} - diff --git a/bin/domain/imag-bookmark/src/ui.rs b/bin/domain/imag-bookmark/src/ui.rs index 93a48cdb..e248a420 100644 --- a/bin/domain/imag-bookmark/src/ui.rs +++ b/bin/domain/imag-bookmark/src/ui.rs @@ -17,23 +17,21 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, App, SubCommand}; +use std::path::PathBuf; + +use failure::Fallible as Result; +use clap::{Arg, ArgMatches, App, SubCommand}; use libimagutil::cli_validators::*; +use libimagstore::storeid::StoreId; +use libimagstore::storeid::IntoStoreId; +use libimagrt::runtime::IdPathProvider; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app .subcommand(SubCommand::with_name("add") .about("Add bookmarks") .version("0.1") - .arg(Arg::with_name("collection") - .long("collection") - .short("c") - .takes_value(true) - .required(false) - .multiple(false) - .value_name("COLLECTION") - .help("Add to this collection, if not specified default from config will be used")) .arg(Arg::with_name("urls") .index(1) .takes_value(true) @@ -47,22 +45,13 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .subcommand(SubCommand::with_name("remove") .about("Remove bookmarks") .version("0.1") - .arg(Arg::with_name("collection") - .long("collection") - .short("c") - .takes_value(true) - .required(false) - .multiple(false) - .value_name("COLLECTION") - .help("Remove from this collection, if not specified default from config will be used")) - .arg(Arg::with_name("urls") + .arg(Arg::with_name("ids") .index(1) .takes_value(true) .required(true) .multiple(true) - .value_name("URL") - .validator(is_url) - .help("Remove this url(s)")) + .value_name("ID") + .help("Remove these urls, specified as ID")) ) // .subcommand(SubCommand::with_name("open") @@ -79,32 +68,41 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { // ) .subcommand(SubCommand::with_name("list") - .about("List bookmarks") + .about("List bookmarks, if used in pipe, ignores everything that is not a bookmark") .version("0.1") - .arg(Arg::with_name("collection") - .long("collection") - .short("c") + + .arg(Arg::with_name("ids") + .index(1) .takes_value(true) .required(false) - .multiple(false) - .value_name("COLLECTION") - .help("Select from this collection, if not specified default from config will be used")) + .multiple(true) + .value_name("ID") + .help("IDs of bookmarks to list")) ) +} - .subcommand(SubCommand::with_name("collection") - .about("Collection commands") - .version("0.1") - .arg(Arg::with_name("add") - .long("add") - .short("a") - .takes_value(true) - .value_name("NAME") - .help("Add a collection with this name")) - .arg(Arg::with_name("remove") - .long("remove") - .short("r") - .takes_value(true) - .value_name("NAME") - .help("Remove a collection with this name (and all links)")) - ) +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Result<Option<Vec<StoreId>>> { + fn no_ids_error() -> Result<Option<Vec<StoreId>>> { + Err(format_err!("Command does not get IDs as input")) + } + + fn get_id_paths(field: &str, subm: &ArgMatches) -> Result<Option<Vec<StoreId>>> { + subm.values_of(field) + .map(|v| v + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::<Result<Vec<_>>>() + ) + .transpose() + } + + match matches.subcommand() { + ("add", _) => no_ids_error(), + ("remove", Some(subm)) => get_id_paths("ids", subm), + ("list", Some(subm)) => get_id_paths("ids", subm), + (other, _) => Err(format_err!("Not a known command: {}", other)), + } + } } |