use crate::cli;
use crate::shared_logic;
use regex::Regex;
use std::path::{Path, PathBuf};
pub fn add_tag(path: &Path, data: &cli::Args) {
if !path.exists() {
eprintln!(
"Error: Couldn't find expected file: \"{}\"",
path.to_str().unwrap()
);
return;
}
let current_stem: String = path.file_stem().unwrap().to_str().unwrap().to_owned();
let tag: String = if data.tag_varies {
shared_logic::convert_tag_characters(path, &data.tag)
} else {
data.tag.clone()
};
if tag_in_brackets(¤t_stem, &tag, &data.delimiter) {
if data.verbose {
println!("Ignored: {}", path.to_str().unwrap());
}
return;
}
let mut new_name: String;
if contains_brackets(¤t_stem) {
new_name = add_tag_to_brackets(¤t_stem, &tag, &data.delimiter);
} else {
new_name = String::from(¤t_stem);
new_name.push('[');
new_name.push_str(&tag);
new_name.push(']');
}
if path.extension().is_some() {
new_name.push('.');
new_name.push_str(path.extension().unwrap().to_str().unwrap());
}
let final_path: PathBuf = get_valid_path(path.parent().unwrap(), &new_name);
if data.verbose {
println!(
"Moving: \"{}\" -> \"{}\"",
path.to_str().unwrap(),
final_path.to_str().unwrap()
);
}
std::fs::rename(path.to_str().unwrap(), final_path.to_str().unwrap())
.map_err(|err| {
eprintln!(
"Couldn't rename: \"{}\" -> \"{}\"\nerror: {}",
path.to_str().unwrap(),
final_path.to_str().unwrap(),
err
);
})
.ok();
}
pub fn remove_tag(path: &Path, data: &cli::Args) {
if !path.exists() {
eprintln!(
"Error: Couldn't find expected file: \"{}\"",
path.to_str().unwrap()
);
return;
}
let current_stem: String = path.file_stem().unwrap().to_str().unwrap().to_owned();
let tag: String = if data.tag_varies {
shared_logic::convert_tag_characters(path, &data.tag)
} else {
data.tag.clone()
};
if !tag_in_brackets(¤t_stem, &tag, &data.delimiter) {
if data.verbose {
println!("Ignored: \"{}\"", path.to_str().unwrap());
}
return;
}
let mut new_name: String = remove_tag_from_brackets(¤t_stem, &tag, &data.delimiter);
if path.extension().is_some() {
new_name.push('.');
new_name.push_str(path.extension().unwrap().to_str().unwrap());
}
let final_path: PathBuf = get_valid_path(path.parent().unwrap(), &new_name);
if data.verbose {
println!(
"Moving: \"{}\" -> \"{}\"",
path.to_str().unwrap(),
final_path.to_str().unwrap()
);
}
std::fs::rename(path.to_str().unwrap(), final_path.to_str().unwrap())
.map_err(|err| {
eprintln!(
"Couldn't rename: \"{}\" -> \"{}\"\nerror: {}",
path.to_str().unwrap(),
final_path.to_str().unwrap(),
err
);
})
.ok();
}
pub fn remove_all_tags(path: &Path, data: &cli::Args) {
if !path.exists() {
eprintln!(
"Error: Couldn't find expected file: \"{}\"",
path.to_str().unwrap()
);
return;
}
let current_stem: String = path.file_stem().unwrap().to_str().unwrap().to_owned();
if !contains_brackets(¤t_stem) {
if data.verbose {
println!("Ignored: \"{}\"", path.to_str().unwrap());
}
return;
}
let mut new_name: String = String::new();
let indices: (usize, usize) = get_bracket_indices(¤t_stem);
new_name.push_str(¤t_stem.clone()[..indices.0]);
new_name.push_str(¤t_stem.clone()[indices.1..]);
if path.extension().is_some() {
new_name.push('.');
new_name.push_str(path.extension().unwrap().to_str().unwrap());
}
let final_path: PathBuf = get_valid_path(path.parent().unwrap(), &new_name);
if data.verbose {
println!(
"Moving: \"{}\" -> \"{}\"",
path.to_str().unwrap(),
final_path.to_str().unwrap()
);
}
std::fs::rename(path.to_str().unwrap(), final_path.to_str().unwrap())
.map_err(|err| {
eprintln!(
"Couldn't rename: \"{}\" -> \"{}\"\nerror: {}",
path.to_str().unwrap(),
final_path.to_str().unwrap(),
err
);
})
.ok();
}
pub fn get_valid_path(directory: &Path, name: &str) -> PathBuf {
let re = Regex::new("~[0-9]+$").unwrap();
let mut new_name: String = String::from(name);
if re.is_match(name) {
let indices = re.find(name).unwrap();
new_name = new_name[..indices.start()].to_owned();
}
if !directory.join(new_name.clone()).exists() {
return directory.join(new_name);
}
let mut count: u32 = 1;
new_name.push('~');
while directory
.join(new_name.clone() + count.clone().to_string().as_str())
.exists()
{
count += 1;
}
new_name.push_str(count.to_string().as_str());
directory.join(new_name)
}
pub fn add_tag_to_brackets(name: &str, tag: &str, delimiter: &str) -> String {
let mut bracket_list: Vec<String> = split_bracket_contents(name, delimiter);
bracket_list.push(tag.to_owned());
let bracket_string: String = bracket_list.join(delimiter);
let indices: (usize, usize) = get_bracket_indices(name);
let mut new_name: String = name[..=indices.0].to_owned();
new_name.push_str(&bracket_string);
new_name.push_str(&name[indices.1 - 1..name.len()]);
new_name
}
pub fn remove_tag_from_brackets(name: &str, tag: &str, delimiter: &str) -> String {
let mut bracket_list: Vec<String> = split_bracket_contents(name, delimiter);
if bracket_list.contains(&tag.to_owned()) {
bracket_list.remove(bracket_list.iter().position(|r| r == tag).unwrap());
}
let mut new_name: String = String::new();
let indices: (usize, usize) = get_bracket_indices(name);
if bracket_list.is_empty() {
new_name.push_str(&name.to_owned()[..indices.0]);
new_name.push_str(&name.to_owned()[indices.1..]);
return new_name;
}
let bracket_string: String = bracket_list.join(delimiter);
new_name.push_str(&name.to_owned()[..indices.0]);
new_name.push('[');
new_name.push_str(&bracket_string);
new_name.push(']');
new_name.push_str(&name.to_owned()[indices.1..]);
new_name
}
pub fn get_bracket_indices(name: &str) -> (usize, usize) {
let indices = Regex::new("\\[.*?\\]").unwrap().find(name).unwrap();
(indices.start(), indices.end())
}
pub fn tag_in_brackets(name: &str, tag: &str, delimiter: &str) -> bool {
if !contains_brackets(name) {
return false;
}
let bracket_list: Vec<String> = split_bracket_contents(name, delimiter);
if !(bracket_list.contains(&tag.to_owned())) {
return false;
}
true
}
pub fn contains_brackets(name: &str) -> bool {
Regex::new("\\[.*?\\]").unwrap().is_match(name)
}
pub fn split_bracket_contents(name: &str, delimiter: &str) -> Vec<String> {
let pattern = Regex::new("\\[.*?\\]").unwrap();
let mut inside_brackets = pattern.find(name).unwrap().as_str().to_owned();
inside_brackets = inside_brackets[1..inside_brackets.len() - 1].to_owned();
let mut bracket_list = vec![];
for each_item in inside_brackets.split(delimiter) {
bracket_list.push(each_item.to_owned());
}
bracket_list
}