feat: add actually working sorting
This commit is contained in:
parent
a409532425
commit
c1f80f9abe
4 changed files with 171 additions and 12 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -101,6 +101,7 @@ version = "0.8.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
|
|
12
Cargo.toml
12
Cargo.toml
|
@ -4,4 +4,14 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
toml = "0.8.19"
|
||||
toml = {version="0.8.19", default-features = false, features = ["parse", "preserve_order"]}
|
||||
|
||||
[profile.release.package."*"]
|
||||
opt-level = "z"
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
codegen-units = 1
|
||||
opt-level = "s"
|
||||
lto = "thin"
|
||||
panic = "abort"
|
||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -13,17 +13,17 @@ pub struct Config {
|
|||
}
|
||||
|
||||
pub const PICTURE_EXTENTIONS: [&str; 17] = [
|
||||
".jpg", ".jpeg", ".png", ".gif", ".webp", ".jfif", ".bmp", ".apng", ".avif", ".tif", ".tga",
|
||||
".psd", ".eps", ".ai", ".indd", ".raw", ".ico",
|
||||
"jpg", "jpeg", "png", "gif", "webp", "jfif", "bmp", "apng", "avif", "tif", "tga",
|
||||
"psd", "eps", "ai", "indd", "raw", "ico",
|
||||
];
|
||||
pub const SOUND_EXTENTIONS: [&str; 10] = [
|
||||
".mp3", ".wav", ".flac", ".ogg", ".aac", ".m4a", ".wma", ".aiff", ".au", ".opus",
|
||||
"mp3", "wav", "flac", "ogg", "aac", "m4a", "wma", "aiff", "au", "opus",
|
||||
];
|
||||
pub const BOOK_EXTENTIONS: [&str; 11] = [
|
||||
".pdf", ".epub", ".mobi", ".cbz", ".cbr", ".chm", ".djvu", ".fb2", ".lit", ".prc", ".xps",
|
||||
"pdf", "epub", "mobi", "cbz", "cbr", "chm", "djvu", "fb2", "lit", "prc", "xps",
|
||||
];
|
||||
pub const VIDEO_EXTENTIONS: [&str; 11] = [
|
||||
".mp4", ".mkv", ".avi", ".flv", ".webm", ".wmv", ".mov", ".m4v", ".3gp", ".3g2", ".swf",
|
||||
"mp4", "mkv", "avi", "flv", "webm", "wmv", "mov", "m4v", "3gp", "3g2", "swf",
|
||||
];
|
||||
|
||||
impl Config {
|
||||
|
|
160
src/main.rs
160
src/main.rs
|
@ -1,23 +1,171 @@
|
|||
use std::{env, path::PathBuf};
|
||||
use std::{
|
||||
env, fs,
|
||||
io::{self, Write},
|
||||
path::PathBuf,
|
||||
process,
|
||||
sync::OnceLock,
|
||||
thread,
|
||||
};
|
||||
|
||||
use filesorters::Config;
|
||||
|
||||
static CONFIG: OnceLock<Config> = OnceLock::new();
|
||||
|
||||
fn main() {
|
||||
let config_path = get_config_path();
|
||||
|
||||
println!("Using config file: {}", config_path.display());
|
||||
|
||||
if !config_path.exists() {
|
||||
println!("Config file does not exist, creating...");
|
||||
filesorters::Config::create(&config_path).unwrap();
|
||||
}
|
||||
|
||||
match filesorters::Config::parse(config_path) {
|
||||
Ok(config) => {
|
||||
println!("{:#?}", config);
|
||||
Ok(parsed_config) => {
|
||||
CONFIG.set(parsed_config).unwrap();
|
||||
println!("Config file loaded successfully");
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {}", err);
|
||||
eprintln!("Error: {}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut counter = 1;
|
||||
for alias in CONFIG.get().unwrap().sources.keys() {
|
||||
println!("{}: {}", counter, alias);
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut actual_selection: Vec<String> = Vec::new();
|
||||
|
||||
loop {
|
||||
print!("Enter: ");
|
||||
io::stdout().flush().unwrap();
|
||||
let mut selected = String::new();
|
||||
io::stdin()
|
||||
.read_line(&mut selected)
|
||||
.expect("Failed to read line");
|
||||
|
||||
let parsed_selection: Vec<usize> = selected
|
||||
.split(" ")
|
||||
.filter(|y| !y.is_empty())
|
||||
.map(|y| y.replace("\n", ""))
|
||||
.flat_map(|x| x.parse::<usize>())
|
||||
.collect();
|
||||
|
||||
if parsed_selection.is_empty() {
|
||||
println!("Invalid selection");
|
||||
continue;
|
||||
}
|
||||
if parsed_selection.len() > CONFIG.get().unwrap().sources.keys().len() {
|
||||
println!("Too many selections made");
|
||||
continue;
|
||||
}
|
||||
if parsed_selection
|
||||
.iter()
|
||||
.any(|x| *x > CONFIG.get().unwrap().sources.keys().len())
|
||||
{
|
||||
println!("Invalid selection");
|
||||
continue;
|
||||
}
|
||||
|
||||
for selection in parsed_selection {
|
||||
actual_selection.push(
|
||||
CONFIG
|
||||
.get()
|
||||
.unwrap()
|
||||
.sources
|
||||
.keys()
|
||||
.nth(selection - 1)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
println!("Selected: {}", actual_selection.join(", "));
|
||||
|
||||
let mut thread_pool: Vec<thread::JoinHandle<()>> = Vec::new();
|
||||
|
||||
for selection in actual_selection {
|
||||
let thread = thread::spawn(move || {
|
||||
let _ = sort_files(selection, false); // TODO: handle errors
|
||||
});
|
||||
|
||||
thread_pool.push(thread);
|
||||
}
|
||||
|
||||
for thread in thread_pool {
|
||||
thread.join().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_files(selection: String, _recursive: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Sorting {}", selection);
|
||||
|
||||
let search_path = CONFIG
|
||||
.get()
|
||||
.and_then(|config| config.sources.get(&selection))
|
||||
.cloned()
|
||||
.unwrap();
|
||||
|
||||
println!("Searching in {}", search_path.display());
|
||||
|
||||
let dir = fs::read_dir(search_path)?;
|
||||
|
||||
|
||||
// TODO: Simplyfy by using an array of tulpes instead of a bucket of ifs
|
||||
for entry in dir.flatten().filter(|e| e.metadata().unwrap().is_file()) {
|
||||
if let Some(extension) = entry.path().extension().and_then(|e| e.to_str()) {
|
||||
let config = CONFIG.get().unwrap();
|
||||
let path = entry.path();
|
||||
|
||||
// Book files
|
||||
if config.books_dir.is_some() && filesorters::BOOK_EXTENTIONS.contains(&extension) {
|
||||
println!("Moved to Books: {}", path.display());
|
||||
if let Some(books_dir) = &config.books_dir {
|
||||
move_file_to_directory(&path, books_dir);
|
||||
}
|
||||
}
|
||||
|
||||
// Picture files
|
||||
if config.pictures_dir.is_some() && filesorters::PICTURE_EXTENTIONS.contains(&extension)
|
||||
{
|
||||
println!("Moved to Pictures: {}", path.display());
|
||||
if let Some(pictures_dir) = &config.pictures_dir {
|
||||
move_file_to_directory(&path, pictures_dir);
|
||||
}
|
||||
}
|
||||
|
||||
// Video files
|
||||
if config.videos_dir.is_some() && filesorters::VIDEO_EXTENTIONS.contains(&extension) {
|
||||
println!("Moved to Videos: {}", path.display());
|
||||
if let Some(videos_dir) = &config.videos_dir {
|
||||
move_file_to_directory(&path, videos_dir);
|
||||
}
|
||||
}
|
||||
|
||||
// Music files
|
||||
if config.music_dir.is_some() && filesorters::SOUND_EXTENTIONS.contains(&extension) {
|
||||
println!("Moved to Music: {}", path.display());
|
||||
if let Some(music_dir) = &config.music_dir {
|
||||
move_file_to_directory(&path, music_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn move_file_to_directory(path: &std::path::Path, dir: &std::path::Path) {
|
||||
let _ = fs::rename(
|
||||
path,
|
||||
dir.join(path.file_name().unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
fn get_config_path() -> PathBuf {
|
||||
|
|
Loading…
Reference in a new issue