From da013d65dce38583c85ed7b61e9aeaa26d1dbed2 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 12 Oct 2017 17:50:20 +0200 Subject: [PATCH] Initial import for imag-annotate --- Cargo.toml | 1 + bin/core/imag-annotate/Cargo.toml | 30 +++++ bin/core/imag-annotate/src/main.rs | 189 +++++++++++++++++++++++++++++ bin/core/imag-annotate/src/ui.rs | 88 ++++++++++++++ 4 files changed, 308 insertions(+) create mode 100644 bin/core/imag-annotate/Cargo.toml create mode 100644 bin/core/imag-annotate/src/main.rs create mode 100644 bin/core/imag-annotate/src/ui.rs diff --git a/Cargo.toml b/Cargo.toml index 459f9f9d..3ec4b5b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "bin/core/imag", + "bin/core/imag-annotate", "bin/core/imag-gps", "bin/core/imag-grep", "bin/core/imag-link", diff --git a/bin/core/imag-annotate/Cargo.toml b/bin/core/imag-annotate/Cargo.toml new file mode 100644 index 00000000..68dc29cc --- /dev/null +++ b/bin/core/imag-annotate/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "imag-annotate" +version = "0.5.0" +authors = ["Matthias Beyer "] + +description = "Part of the imag core distribution: imag-annotate command" + +keywords = ["imag", "PIM", "personal", "information", "management"] +readme = "../../../README.md" +license = "LGPL-2.1" + +documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html" +repository = "https://github.com/matthiasbeyer/imag" +homepage = "http://imag-pim.org" + +[dependencies] +clap = ">=2.17" +log = "0.3" +version = "2.0.1" +url = "1.2" +toml = "0.4" +toml-query = "0.3.0" + +libimagstore = { version = "0.5.0", path = "../../../lib/core/libimagstore" } +libimagrt = { version = "0.5.0", path = "../../../lib/core/libimagrt" } +libimagerror = { version = "0.5.0", path = "../../../lib/core/libimagerror" } +libimagentryannotation = { version = "0.5.0", path = "../../../lib/entry/libimagentryannotation" } +libimagentryedit = { version = "0.5.0", path = "../../../lib/entry/libimagentryedit" } +libimagutil = { version = "0.5.0", path = "../../../lib/etc/libimagutil" } + diff --git a/bin/core/imag-annotate/src/main.rs b/bin/core/imag-annotate/src/main.rs new file mode 100644 index 00000000..13d0bfcb --- /dev/null +++ b/bin/core/imag-annotate/src/main.rs @@ -0,0 +1,189 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +#[macro_use] +extern crate log; +#[macro_use] +extern crate version; + +extern crate libimagentryannotation; +extern crate libimagentryedit; +extern crate libimagerror; +extern crate libimagrt; +extern crate libimagstore; +extern crate libimagutil; + +use std::path::PathBuf; + +use libimagentryannotation::annotateable::*; +use libimagentryannotation::annotation_fetcher::*; +use libimagentryannotation::error::AnnotationError as AE; +use libimagentryedit::edit::*; +use libimagerror::trace::MapErrTrace; +use libimagrt::runtime::Runtime; +use libimagrt::setup::generate_runtime_setup; +use libimagstore::store::FileLockEntry; +use libimagstore::storeid::IntoStoreId; +use libimagutil::warn_exit::warn_exit; + +mod ui; + +fn main() { + let rt = generate_runtime_setup("imag-annotation", + &version!()[..], + "Add annotations to entries", + ui::build_ui); + + rt.cli() + .subcommand_name() + .map(|name| { + match name { + "add" => add(&rt), + "remove" => remove(&rt), + "list" => list(&rt), + _ => warn_exit("No commandline call", 1) + } + }); +} + +fn add(rt: &Runtime) { + let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main() + let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap + let entry_name = scmd + .value_of("entry") + .map(PathBuf::from) + .map(|pb| pb.into_storeid().map_err_trace_exit(1).unwrap()) + .unwrap(); // safed by clap + + let _ = rt.store() + .get(entry_name) + .map_err_trace_exit(1) + .unwrap() + .ok_or(AE::from("Entry does not exist".to_owned())) + .map_err_trace_exit(1) + .unwrap() + .annotate(rt.store(), annotation_name) + .map_err_trace_exit(1) + .unwrap() + .edit_content(&rt) + .map_err_trace_exit(1) + .unwrap(); + + info!("Ok"); +} + +fn remove(rt: &Runtime) { + let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main() + let entry_name = scmd.value_of("entry").unwrap(); // safed by clap + let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap + let delete = scmd.is_present("delete-annotation"); + + let mut entry = rt.store() + .get(PathBuf::from(entry_name).into_storeid().map_err_trace_exit(1).unwrap()) + .map_err_trace_exit(1) + .unwrap() + .ok_or(AE::from("Entry does not exist".to_owned())) + .map_err_trace_exit(1) + .unwrap(); + + let annotation = entry + .denotate(rt.store(), annotation_name) + .map_err_trace_exit(1) + .unwrap(); + + if delete { + if let Some(an) = annotation { + let loc = an.get_location().clone(); + drop(an); + + let _ = rt + .store() + .delete(loc) + .map_err_trace_exit(1) + .unwrap(); + } + } + + info!("Ok"); +} + +fn list(rt: &Runtime) { + let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap + let with_text = scmd.is_present("list-with-text"); + match scmd.value_of("entry").map(PathBuf::from) { + Some(pb) => { + let _ = rt + .store() + .get(pb.into_storeid().map_err_trace_exit(1).unwrap()) + .map_err_trace_exit(1) + .unwrap() + .ok_or(AE::from("Entry does not exist".to_owned())) + .map_err_trace_exit(1) + .unwrap() + .annotations(rt.store()) + .map_err_trace_exit(1) + .unwrap() + .enumerate() + .map(|(i, a)| list_annotation(i, a.map_err_trace_exit(1).unwrap(), with_text)) + .collect::>(); + } + + None => { + // show them all + let _ = rt + .store() + .all_annotations() + .map_err_trace_exit(1) + .unwrap() + .enumerate() + .map(|(i, a)| list_annotation(i, a.map_err_trace_exit(1).unwrap(), with_text)) + .collect::>(); + } + } + + info!("Ok"); +} + +fn list_annotation<'a>(i: usize, a: FileLockEntry<'a>, with_text: bool) { + if with_text { + println!("--- {i: >5} | {id}\n{text}\n\n", + i = i, + id = a.get_location(), + text = a.get_content()); + } else { + println!("{: >5} | {}", i, a.get_location()); + } +} + diff --git a/bin/core/imag-annotate/src/ui.rs b/bin/core/imag-annotate/src/ui.rs new file mode 100644 index 00000000..fd7d62f8 --- /dev/null +++ b/bin/core/imag-annotate/src/ui.rs @@ -0,0 +1,88 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +use clap::{Arg, App, SubCommand}; + +pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + app + .subcommand(SubCommand::with_name("add") + .about("Add annotation to an entry") + .version("0.1") + .arg(Arg::with_name("entry") + .index(1) + .takes_value(true) + .required(true) + .multiple(false) + .help("The entry to add the latitude/longitude to") + .value_name("ENTRY")) + .arg(Arg::with_name("annotation_name") + .index(2) + .takes_value(true) + .required(true) + .multiple(false) + .help("Name of the new annotation") + .value_name("NAME")) + ) + + .subcommand(SubCommand::with_name("remove") + .about("Remove annotation from an entry") + .version("0.1") + .arg(Arg::with_name("entry") + .index(1) + .takes_value(true) + .required(true) + .multiple(false) + .help("The entry to remove the latitude/longitude from") + .value_name("ENTRY")) + .arg(Arg::with_name("annotation_name") + .index(2) + .takes_value(true) + .required(true) + .multiple(false) + .help("Name of the annotation to remove") + .value_name("NAME")) + .arg(Arg::with_name("delete-annotation") + .short("D") + .long("delete") + .takes_value(false) + .required(false) + .multiple(false) + .help("Do not only 'unlink' the annotation, but also delete it from the store")) + ) + + .subcommand(SubCommand::with_name("list") + .about("List annotations") + .version("0.1") + .arg(Arg::with_name("entry") + .index(1) + .takes_value(true) + .required(false) + .multiple(false) + .help("The entry to list annotations for (all annotations if not passed)") + .value_name("ENTRY")) + .arg(Arg::with_name("list-with-text") + .long("text") + .short("t") + .takes_value(false) + .required(false) + .multiple(false) + .help("List annotations with text")) + ) +} +