diff options
Diffstat (limited to 'src/kona-cli.rs')
| -rw-r--r-- | src/kona-cli.rs | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/kona-cli.rs b/src/kona-cli.rs new file mode 100644 index 0000000..04adfc8 --- /dev/null +++ b/src/kona-cli.rs @@ -0,0 +1,121 @@ +// Copyright © 2020 Jakob L. Kreuze <zerodaysfordays@sdf.org> +// +// This file is part of Kona. +// +// Kona is free software; you can redistribute it and/or modify it under +// the terms of the GNU Affero General Public License as published by +// the Free Software Foundation; either version 3 of the License, or (at +// your option) any later version. +// +// Kona 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 Affero General Public +// License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with Kona. If not, see <http://www.gnu.org/licenses/>. + +#[macro_use] +extern crate anyhow; +extern crate dirs; +#[macro_use] +extern crate rusqlite; + +mod database; + +use database::TagDatabase; +use std::env; +use std::path::Path; + +fn main() { + let mut args: Vec<String> = env::args().collect(); + if args.len() < 2 || args.iter().any(|arg| arg == "-h" || arg == "--help") { + println!("usage: {} ACTION [ARGS ...]", args[0]); + println!(); + println!("\t-o, --output [PATH]: Path to the tag database."); + println!(); + println!("\tACTION: add [PATH] [TAGS ...]: index an image, optionally tagged."); + println!("\tACTION: remove [PATH]: remove an image from the database."); + println!("\tACTION: add_tags [PATH] [TAGS ...]: add tags to an indexed image."); + println!("\tACTION: remove_tags [PATH] [TAGS ...]: remove tags from an indexed image."); + println!("\tACTION: query [QUERY_STRING]: list images in the database."); + std::process::exit(1); + } + + let tb = if let Some(i) = args.iter().position(|x| x == "-o" || x == "--output") { + // Ensure that a path follows the "-o" argument. + if i + 1 >= args.len() { + eprintln!("{} requires an argument", args[i]); + std::process::exit(1); + } + + args.remove(i); + TagDatabase::new(args.remove(i + 1)) + } else if let Ok(path) = std::env::var("TB_PATH") { + TagDatabase::new(path) + } else { + TagDatabase::new("./kona.db") + } + .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]).canonicalize().unwrap(); + if path.is_dir() { + eprintln!("'{}' is a directory", args[2]); + } + + tb.add_file(&path, &args[3..].to_vec()).unwrap(); + } + "remove" => { + if args.len() < 3 { + eprintln!("usage: {} remove PATH", args[0]); + std::process::exit(1); + } + + let file = tb.file_by_path(&args[2]).unwrap(); + tb.remove_file(file.id).unwrap(); + } + "add_tags" => { + if args.len() < 3 { + eprintln!("usage: {} add_tags PATH [TAGS ...]", args[0]); + std::process::exit(1); + } + let file = tb.file_by_path(&args[2]).unwrap(); + tb.tag_file(file.id, &args[3..].to_vec()).unwrap(); + } + "remove_tags" => { + if args.len() < 3 { + eprintln!("usage: {} remove_tags PATH [TAGS ...]", args[0]); + std::process::exit(1); + } + let file = tb.file_by_path(&args[2]).unwrap(); + tb.untag_file(file.id, &args[3..].to_vec()).unwrap(); + } + "query" => { + let query = if args.len() < 3 { + database::parse_query("").unwrap() + } else { + database::parse_query(&args[2]).unwrap() + }; + for file in tb.query(&query, None).unwrap() { + println!("{}", file.path); + } + } + "tags" => { + for (count, tag) in tb.top_tags(None).unwrap() { + println!("{}: {}", count, tag); + } + } + _ => { + eprintln!("Unknown action '{}'", action); + std::process::exit(1); + } + } +} |