Moved the file listing logic into the lib
parent
1e05be83bb
commit
c323c64e28
|
@ -1,8 +1,6 @@
|
|||
use std::{
|
||||
fs,
|
||||
io::{self, Write},
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
|
@ -35,59 +33,20 @@ fn main() -> anyhow::Result<()> {
|
|||
fn handle_files(args: FilesArgs) -> Result<()> {
|
||||
let conn = try_database()?;
|
||||
|
||||
let mut sql = r#"SELECT path, group_concat(name) as tags FROM file_tag
|
||||
JOIN file ON file.id = file_tag.file_id
|
||||
JOIN tag ON tag.id = file_tag.tag_id"#
|
||||
.to_string();
|
||||
|
||||
let mut show_tags = true;
|
||||
|
||||
let mut paths: Vec<PathBuf> = vec![];
|
||||
if args.all {
|
||||
paths = fs::read_dir(".")?
|
||||
.filter_map(|f| f.ok())
|
||||
.filter(|f| f.metadata().is_ok() && f.metadata().unwrap().is_file())
|
||||
.map(|f| f.path())
|
||||
.collect();
|
||||
} else if let Some(query) = args.query {
|
||||
let path = PathBuf::from_str(&query).unwrap_or_default();
|
||||
match path.exists() {
|
||||
true => {
|
||||
sql.push_str(&format!(" WHERE path IN ('{}')", query));
|
||||
paths = vec![path];
|
||||
}
|
||||
false => {
|
||||
sql.push_str(&format!(" WHERE tag.name LIKE '%{}%'", query));
|
||||
show_tags = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let mut all_paths: Vec<String> = paths
|
||||
.iter_mut()
|
||||
.map(|f| f.to_string_lossy().replace("./", "").to_string())
|
||||
.collect();
|
||||
|
||||
sql.push_str(" GROUP BY path");
|
||||
|
||||
let mut stmt = conn.prepare(&sql)?;
|
||||
let tagged_files: Vec<(String, String)> = stmt
|
||||
.query_map([], |row| Ok((row.get(0)?, row.get(1)?)))?
|
||||
.flatten()
|
||||
.collect();
|
||||
let mut files = taggo::list_files(&conn, args.all, args.query)?;
|
||||
|
||||
let mut w = io::stdout();
|
||||
if !tagged_files.is_empty() {
|
||||
if !files.files.is_empty() {
|
||||
if args.all {
|
||||
writeln!(&mut w, "{TERM_BOLD}Tagged Files: {TERM_RESET}")?;
|
||||
}
|
||||
for (file, tags) in tagged_files {
|
||||
for (file, tags) in files.files {
|
||||
// Remove already tagged files
|
||||
if let Some(idx) = all_paths.iter().position(|v| *v == file) {
|
||||
all_paths.swap_remove(idx);
|
||||
if let Some(idx) = files.paths.iter().position(|v| *v == file) {
|
||||
files.paths.swap_remove(idx);
|
||||
}
|
||||
|
||||
if show_tags {
|
||||
if files.show_tags {
|
||||
writeln!(&mut w, "{}: {}", file, tags)?;
|
||||
} else {
|
||||
writeln!(&mut w, "{}", file)?;
|
||||
|
@ -97,9 +56,9 @@ fn handle_files(args: FilesArgs) -> Result<()> {
|
|||
writeln!(&mut w, "No files registered!")?;
|
||||
}
|
||||
|
||||
if args.all && !all_paths.is_empty() {
|
||||
if args.all && !files.paths.is_empty() {
|
||||
writeln!(&mut w, "\n{TERM_BOLD}Untagged Files: {TERM_RESET}")?;
|
||||
for path in all_paths {
|
||||
for path in files.paths {
|
||||
let path_str = path;
|
||||
writeln!(&mut w, "{}", path_str)?;
|
||||
}
|
||||
|
|
57
src/lib.rs
57
src/lib.rs
|
@ -1,4 +1,6 @@
|
|||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
use std::{io, path::PathBuf};
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
|
@ -6,6 +8,12 @@ use rusqlite::{Connection, OpenFlags, params_from_iter, types::Value};
|
|||
|
||||
const DB_PATH: &str = ".tags";
|
||||
|
||||
pub struct Files {
|
||||
pub files: Vec<(String, String)>,
|
||||
pub paths: Vec<String>,
|
||||
pub show_tags: bool,
|
||||
}
|
||||
|
||||
pub fn init_db() -> anyhow::Result<()> {
|
||||
let conn = Connection::open(DB_PATH)?;
|
||||
|
||||
|
@ -250,3 +258,52 @@ pub fn untag_file(conn: &mut Connection, file: PathBuf, tags: Option<Vec<String>
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn list_files(conn: &Connection, all_files: bool, query: Option<String>) -> Result<Files> {
|
||||
let mut sql = r#"SELECT path, group_concat(name) as tags FROM file_tag
|
||||
JOIN file ON file.id = file_tag.file_id
|
||||
JOIN tag ON tag.id = file_tag.tag_id"#
|
||||
.to_string();
|
||||
|
||||
let mut show_tags = true;
|
||||
|
||||
let mut paths: Vec<PathBuf> = vec![];
|
||||
if all_files {
|
||||
paths = fs::read_dir(".")?
|
||||
.filter_map(|f| f.ok())
|
||||
.filter(|f| f.metadata().is_ok() && f.metadata().unwrap().is_file())
|
||||
.map(|f| f.path())
|
||||
.collect();
|
||||
} else if let Some(query) = query {
|
||||
let path = PathBuf::from_str(&query).unwrap_or_default();
|
||||
match path.exists() {
|
||||
true => {
|
||||
sql.push_str(&format!(" WHERE path IN ('{}')", query));
|
||||
paths = vec![path];
|
||||
}
|
||||
false => {
|
||||
sql.push_str(&format!(" WHERE tag.name LIKE '%{}%'", query));
|
||||
show_tags = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let paths: Vec<String> = paths
|
||||
.iter_mut()
|
||||
.map(|f| f.to_string_lossy().replace("./", "").to_string())
|
||||
.collect();
|
||||
|
||||
sql.push_str(" GROUP BY path");
|
||||
|
||||
let mut stmt = conn.prepare(&sql)?;
|
||||
let files: Vec<(String, String)> = stmt
|
||||
.query_map([], |row| Ok((row.get(0)?, row.get(1)?)))?
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
Ok(Files {
|
||||
files,
|
||||
paths,
|
||||
show_tags,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue