diff --git a/src/cli.rs b/src/cli.rs index be95100..851dc7b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -13,7 +13,16 @@ pub struct CliArgs { pub enum Commands { Init, Untag(UntagArgs), - Tag(TagArgs), + Tag { + #[clap(flatten)] + args: TagArgs, + + #[arg(short, long, requires = "file_tags", value_delimiter = ' ', num_args = 1..)] + files: Vec, + + #[arg(short('t'), long("tags"), requires = "files", value_delimiter = ' ', num_args = 1..)] + file_tags: Vec, + }, Tags(TagsArgs), Files(FilesArgs), } @@ -31,13 +40,15 @@ pub enum TagsCommands { List, Add { add: Vec }, Remove { remove: Vec }, - Rename { old: String, new: String }, + Rename { renames: Vec }, } #[derive(Debug, Args, PartialEq, Eq)] pub struct TagArgs { - pub file: PathBuf, + // #[clap(conflicts_with = "files")] + pub file: Option, + // #[clap(conflicts_with = "files")] pub tags: Vec, } diff --git a/src/main.rs b/src/main.rs index e71d03a..28a26ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,11 @@ fn main() -> anyhow::Result<()> { match args.commands { cli::Commands::Init => init_db().map_err(|_| anyhow!("Database already exists!")), - cli::Commands::Tag(args) => tags::handle_tag(args), + cli::Commands::Tag { + args, + files, + file_tags, + } => tags::handle_tag(args, files, file_tags), cli::Commands::Untag(args) => tags::handle_untag(args), cli::Commands::Tags(args) => tags::handle_tags(args), cli::Commands::Files(args) => tags::handle_files(args), diff --git a/src/tags.rs b/src/tags.rs index 5cb89fa..c732015 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -95,10 +95,17 @@ pub fn handle_files(args: FilesArgs) -> Result<()> { Ok(()) } -pub fn handle_tag(args: TagArgs) -> Result<()> { +pub fn handle_tag(args: TagArgs, files: Vec, file_tags: Vec) -> Result<()> { let mut conn = try_database()?; - tag_file(&mut conn, args.file, args.tags)?; + if let Some(file) = args.file { + tag_file(&mut conn, &file, &args.tags)?; + } else { + // TODO: Maybe rework this at some point so its more optimized for batch insertion ? + for file in &files { + tag_file(&mut conn, file, &file_tags)?; + } + } Ok(()) } @@ -130,14 +137,32 @@ pub fn handle_tags(args: TagsArgs) -> Result<()> { } Some(cli::TagsCommands::Add { add }) => add_tags(&mut conn, add), Some(cli::TagsCommands::Remove { remove }) => remove_tags(&mut conn, remove), - Some(cli::TagsCommands::Rename { old, new }) => rename_tag(&conn, old, new), + Some(cli::TagsCommands::Rename { renames }) => rename_tag(&conn, renames), } } -fn rename_tag(conn: &Connection, old: String, new: String) -> Result<()> { +fn rename_tag(conn: &Connection, renames: Vec) -> Result<()> { + if renames.is_empty() { + return Err(anyhow!("No input found!")); + } else if renames.len() % 2 != 0 { + return Err(anyhow!( + "Attempting to rename an uneven amount of entries: {}", + renames.len() + )); + } + let mut stmt = conn.prepare("UPDATE tag SET name = ? WHERE name = ?")?; - stmt.execute([&new, &old])?; + let mut i = 0; + while i < renames.len() { + // TODO: Merge this when let chaining is stabilized in 1.88 + if let Some(old) = renames.get(i) { + if let Some(new) = renames.get(i + 1) { + stmt.execute([&new, &old])?; + } + } + i += 2; + } Ok(()) } @@ -217,7 +242,7 @@ fn add_tags(conn: &mut Connection, tags: Vec) -> Result<()> { Ok(()) } -fn tag_file(conn: &mut Connection, file: PathBuf, tags: Vec) -> Result<()> { +fn tag_file(conn: &mut Connection, file: &PathBuf, tags: &Vec) -> Result<()> { let file = file .to_str() .ok_or(anyhow!("Unable to find path {:?}", file))?