From b21b1238401f75e6bf7503ba8d42decdeeb10708 Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Thu, 21 May 2020 19:56:05 -0400 Subject: Implement an initial command-line interface. TODO: - Tabulate `query` output: show internal id, blake2, etc. - `remove` command. - `add_tags` command. - `remove_tags` command. --- src/main.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 10 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index 4b3fcc1..db43ea9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,10 +17,12 @@ #[macro_use] extern crate anyhow; +extern crate dirs; use anyhow::Result; use blake2::{Blake2b, Digest}; use rusqlite::{params, Connection}; +use std::env; use std::io; use std::path::Path; @@ -167,7 +169,10 @@ impl TagBase { /// Return the intersection of the sets of images matching each of `tags`. fn images_by_tags(&self, tags: &[&str]) -> Result> { - let ids = tags.iter().map(|tag| self.tag_id(tag)); + let ids: Vec = tags + .iter() + .filter_map(|tag| self.tag_id(tag).ok()) + .collect(); let mut tags = Vec::from(tags); tags.dedup(); @@ -181,16 +186,16 @@ impl TagBase { ON images.id = mapping.image", ) } else { - (1..tags.len() + 1) - .zip(tags) + (1..ids.len() + 1) + .zip(ids) .map(|pair| { - let (n, tag) = pair; + let (n, id) = pair; format!( "INNER JOIN mapping as m{n} ON images.id = m{n}.image AND {id} = m{n}.tag", n = n, - id = tag + id = id ) }) .collect::>() @@ -314,9 +319,53 @@ mod tests { } fn main() { - let tb = TagBase::new("/tmp/test.db").unwrap(); - let path = Path::new("/home/jakob/Sync/06fc9ae71549eb4d.jpeg"); - let hash = hash_file(path).unwrap(); - tb.import_image(path, &hash).unwrap(); - println!("{:?}", tb); + let args: Vec = env::args().collect(); + if args.len() < 2 { + eprintln!("usage: {} ACTION [ARGS ...]", args[0]); + std::process::exit(1); + } + + let tb = if let Ok(val) = env::var("TB_PATH") { + TagBase::new(&val) + } else { + if let Some(dir) = dirs::config_dir() { + TagBase::new(dir.join("pometka.db").to_str().unwrap()) + } else { + TagBase::new(Path::new("/tmp").join("pometka.db").to_str().unwrap()) + } + } + .unwrap(); + + let action = &args[1]; + match action.to_lowercase().as_str() { + "add" => { + if args.len() < 3 { + eprintln!("usage: {} add PATH [TAGS ...]", args[0]); + std::process::exit(1); + } + let path = Path::new(&args[2]); + let hash = hash_file(path).unwrap(); + let id = tb.import_image(path, &hash).unwrap(); + for arg in args[3..].iter() { + tb.add_tag(arg).unwrap(); + tb.tag_image(id, arg).unwrap(); + } + } + "query" => { + let tags = args[2..].iter().map(|s| s.as_str()).collect::>(); + for tag in tags.iter() { + if let Err(_) = tb.tag_id(tag) { + eprintln!("unknown tag: {}", tag); + std::process::exit(1); + } + } + for image in tb.images_by_tags(&tags[..]).unwrap() { + println!("{}/{}", image.orig_dir, image.filename); + } + } + _ => { + eprintln!("Unknown action '{}'", action); + std::process::exit(1); + } + } } -- cgit v1.3