taggo/src/main.rs

120 lines
2.3 KiB
Rust
Raw Normal View History

use std::{io, path, process::exit};
use io::Write;
use clap::Parser;
use cli::CliArgs;
use rusqlite::{Connection, params_from_iter};
const DB_PATH: &str = ".tags";
mod cli;
2025-05-01 00:18:55 +03:00
fn main() {
let args = CliArgs::parse();
match args.commands {
cli::Commands::Init => {
if !has_database() {
let conn = Connection::open(DB_PATH).unwrap();
init_db(&conn);
} else {
panic!("Database is already initialized in this folder");
}
exit(0);
}
cli::Commands::Tags(args) => {
let conn = Connection::open(DB_PATH).unwrap();
if args.list {
let mut w = io::stdout();
let tags = list_tags(&conn);
for tag in tags {
writeln!(&mut w, "{}", tag).unwrap();
}
w.flush().unwrap();
return;
}
match args.commands {
Some(cli::TagsCommands::Add { add }) => add_tags(&conn, add),
Some(cli::TagsCommands::Remove { remove }) => remove_tags(&conn, remove),
_ => (),
};
}
}
}
fn list_tags(conn: &Connection) -> Vec<String> {
let mut stmt = conn.prepare("SELECT name FROM tag").unwrap();
let result = stmt.query_map([], |row| row.get(0)).unwrap();
let mut tags = Vec::new();
for name in result {
tags.push(name.unwrap());
}
tags
}
fn remove_tags(conn: &Connection, tags: Vec<String>) {
let mut query = r#"DELETE FROM tag WHERE name IN ("#.to_string();
for (i, _tag) in tags.iter().enumerate() {
query.push('?');
if i < tags.len() - 1 {
query.push(',');
}
}
query.push(')');
conn.execute(&query, params_from_iter(tags)).unwrap();
}
fn add_tags(conn: &Connection, tags: Vec<String>) {
let mut query = r#"INSERT INTO tag(name) VALUES"#.to_string();
for (i, _tag) in tags.iter().enumerate() {
query.push_str("(?)");
if i < tags.len() - 1 {
query.push(',');
}
}
conn.execute(&query, params_from_iter(tags)).unwrap();
}
fn init_db(conn: &Connection) {
conn.execute(
r#"CREATE TABLE IF NOT EXISTS tag(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(255) NOT NULL UNIQUE
);"#,
(),
)
.unwrap();
conn.execute(
r#"CREATE TABLE IF NOT EXISTS file(
id INT NOT NULL PRIMARY KEY,
path VARCHAR(255) NOT NULL UNIQUE
);"#,
(),
)
.unwrap();
conn.execute(
r#"CREATE TABLE IF NOT EXISTS file_tag(
tag_id INT REFERENCES tag(id),
file_id INT REFERENCES file(id)
);"#,
(),
)
.unwrap();
}
pub fn has_database() -> bool {
path::Path::new(DB_PATH).exists()
2025-05-01 00:18:55 +03:00
}