139 lines
3.9 KiB
Rust
139 lines
3.9 KiB
Rust
|
extern crate regex;
|
||
|
|
||
|
use regex::Regex;
|
||
|
|
||
|
use std::fs::{self, ReadDir};
|
||
|
use std::path::PathBuf;
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct Page {
|
||
|
position: Option<u64>,
|
||
|
prefix: String,
|
||
|
number: String,
|
||
|
suffix: String,
|
||
|
}
|
||
|
|
||
|
impl Page {
|
||
|
fn new(prefix: String, number: String, suffix: String) -> Page {
|
||
|
println!("N p:{} n: {} s: {}", prefix, number, suffix);
|
||
|
Page {
|
||
|
position: None,
|
||
|
prefix: prefix,
|
||
|
number: number,
|
||
|
suffix: suffix,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn set_position(&mut self, pos: u64) {
|
||
|
self.position = Some(pos);
|
||
|
}
|
||
|
|
||
|
fn original_filename(&self) -> String {
|
||
|
println!("OF p:{} n: {} s: {}", self.prefix, self.number, self.suffix);
|
||
|
format!("{}{}{}", self.prefix, self.number, self.suffix)
|
||
|
}
|
||
|
|
||
|
fn new_filename(&self, number: &str) -> String {
|
||
|
println!("NF n: {} p:{} n: {} s: {}", number, self.prefix, self.number, self.suffix);
|
||
|
format!("{}-{}{}{}", number, self.prefix, self.number, self.suffix)
|
||
|
//~ TODO I think I will need this on in the end
|
||
|
//~ format!("{}{}{}", self.prefix, number, self.suffix)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct ComicBook {
|
||
|
pages: Vec<Page>,
|
||
|
is_binded: bool,
|
||
|
}
|
||
|
|
||
|
impl ComicBook {
|
||
|
pub fn new(files: ReadDir) -> ComicBook {
|
||
|
let regex = Regex::new(r"\./(?P<prefix>\D*)(?P<number>\d*)(?P<suffix>.*)").unwrap();
|
||
|
ComicBook {
|
||
|
pages: files
|
||
|
.map(|entry| entry.unwrap().path())
|
||
|
.filter(|entry| entry.is_file())
|
||
|
.map(|entry| {
|
||
|
let caps = regex.captures(entry.to_str().unwrap()).unwrap();
|
||
|
Page::new(
|
||
|
String::from(caps.name("prefix").map_or("", |c| c.as_str())),
|
||
|
String::from(&caps["number"]), // FIXME => ignore the file?
|
||
|
String::from(caps.name("suffix").map_or("", |c| c.as_str())),
|
||
|
)
|
||
|
})
|
||
|
.collect(),
|
||
|
//~ book: path.iter().map(|name| Page::new(name)).collect(),
|
||
|
is_binded: false,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn bind(&mut self) {
|
||
|
self.sort();
|
||
|
|
||
|
for page in self.pages.iter() {
|
||
|
if let Some(pos) = page.position {
|
||
|
let original_file = page.original_filename();
|
||
|
let new_file = page.new_filename(&pos.to_string());
|
||
|
|
||
|
println!("{} X {}", original_file, new_file);
|
||
|
|
||
|
fs::rename(
|
||
|
original_file,
|
||
|
new_file,
|
||
|
)
|
||
|
.expect("RENAME FAILED");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn sort(&mut self) {
|
||
|
//~ self.book.sort();
|
||
|
self.pages.sort_by(|a, b| {
|
||
|
a.number
|
||
|
.parse::<u64>()
|
||
|
.unwrap()
|
||
|
.cmp(&b.number.parse::<u64>().unwrap())
|
||
|
});
|
||
|
self.is_binded = true;
|
||
|
|
||
|
// FIXME: Do not use enumerate but the parsed value: there may be gaps in the collection
|
||
|
for (i, page) in self.pages.iter_mut().enumerate() {
|
||
|
page.set_position(i as u64);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
use std::path::Path;
|
||
|
//~ use std::sys_common::io::test::{TempDir, tmpdir};
|
||
|
|
||
|
#[test]
|
||
|
fn comic_book_creation() {
|
||
|
//~ let tmpdir = tmpdir();
|
||
|
//~ println!("{}", tmpdir);
|
||
|
//~ let comic = ComicBook::new(&[
|
||
|
//~ Path::new("01.png").to_path_buf(),
|
||
|
//~ Path::new("02.png").to_path_buf(),
|
||
|
//~ ]);
|
||
|
|
||
|
//~ println!("{:?}", comic.book);
|
||
|
|
||
|
assert!(false);
|
||
|
//~ assert_eq!(comic.book, [Page {filename: "01.png", position: None}, Page {filename: "02.png", position: None}]);
|
||
|
}
|
||
|
|
||
|
//~ #[test]
|
||
|
//~ fn detection_alpha() {
|
||
|
//~ let l = Unsorted(vec!["1", "2", "10"]);
|
||
|
//~ assert_eq!(l.detect_sort_type(), false);
|
||
|
//~ }
|
||
|
|
||
|
//~ #[test]
|
||
|
//~ fn detection_numerical() {
|
||
|
//~ let l = Unsorted(vec!["01", "02", "10"]);
|
||
|
//~ assert_eq!(l.detect_sort_type(), true);
|
||
|
//~ }
|
||
|
}
|