diff options
Diffstat (limited to 'src/name.rs')
-rw-r--r-- | src/name.rs | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/name.rs b/src/name.rs new file mode 100644 index 0000000..9cfca6b --- /dev/null +++ b/src/name.rs @@ -0,0 +1,198 @@ +use crate::util::{join_subpath, make_path_absolute, make_path_relative_to}; +use std::fmt; +use std::path::{Path, PathBuf}; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Name { + is_wikitext: bool, + src: PathBuf, + dest: PathBuf, + page: PathBuf, + page_name: String, +} + +impl Name { + fn new(is_wikitext: bool, src: PathBuf, dest: PathBuf, page: PathBuf) -> Self { + let page_name = page + .file_name() + .unwrap_or_else(|| panic!("get filename from {}", page.display())) + .to_string_lossy() + .to_string(); + Self { + is_wikitext, + src, + dest, + page, + page_name, + } + } + + pub fn is_wikitext_page(&self) -> bool { + self.is_wikitext + } + + pub fn source_path(&self) -> &Path { + &self.src + } + + pub fn destination_path(&self) -> &Path { + &self.dest + } + + pub fn page_path(&self) -> &Path { + &self.page + } + + pub fn page_name(&self) -> &str { + &self.page_name + } +} + +impl PartialEq<Name> for &Name { + fn eq(&self, other: &Name) -> bool { + self.src == other.src + } +} + +impl fmt::Display for Name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}", self.src.display()) + } +} + +pub struct NameBuilder { + srcdir: PathBuf, + destdir: PathBuf, +} + +impl NameBuilder { + pub fn new(srcdir: &Path, destdir: &Path) -> Self { + Self { + srcdir: srcdir.into(), + destdir: destdir.into(), + } + } + + pub fn srcdir(&self) -> &Path { + &self.srcdir + } + + pub fn destdir(&self) -> &Path { + &self.destdir + } + + fn name(&self, path: &Path, ext: Option<&str>) -> Name { + assert!(path.starts_with(&self.srcdir)); + let src = path.into(); + let relative = make_path_relative_to(&self.srcdir, path); + let dest = join_subpath(&self.destdir, &relative); + let page = make_path_absolute(&relative); + if let Some(ext) = ext { + Name::new(true, src, dest.with_extension(ext), page.with_extension("")) + } else { + Name::new(false, src, dest, page) + } + } + + pub fn page(&self, path: &Path) -> Name { + self.name(path, Some("html")) + } + + pub fn file(&self, path: &Path) -> Name { + self.name(path, None) + } +} + +#[derive(Default, Debug)] +pub struct Names { + names: Vec<Name>, +} + +impl Names { + pub fn insert(&mut self, name: Name) { + self.names.push(name); + } + + pub fn iter(&self) -> impl Iterator<Item = &Name> { + self.names.iter() + } + + pub fn source_paths(&self) -> impl Iterator<Item = &PathBuf> { + self.names.iter().map(|name| &name.src) + } + + pub fn pages(&self) -> impl Iterator<Item = &Name> { + self.names.iter().filter(|name| name.is_wikitext_page()) + } + + pub fn files(&self) -> impl Iterator<Item = &Name> { + self.names.iter().filter(|name| !name.is_wikitext_page()) + } + + pub fn get_source_path(&self, path: &Path) -> Option<&Name> { + self.names.iter().find(|name| name.src == path) + } + + pub fn get_page_path(&self, path: &Path) -> Option<&Name> { + self.names.iter().find(|name| name.page == path) + } +} + +#[cfg(test)] +mod test { + use super::{Name, NameBuilder, Names}; + use std::path::Path; + + fn builder() -> NameBuilder { + NameBuilder::new(Path::new("/src"), Path::new("/dest")) + } + + #[test] + fn builds_page_name() { + let name = builder().page(Path::new("/src/foo/bar.mdwn")); + assert_eq!(name.source_path(), Path::new("/src/foo/bar.mdwn")); + assert_eq!(name.destination_path(), Path::new("/dest/foo/bar.html")); + assert_eq!(name.page_path(), Path::new("/foo/bar")); + assert_eq!(name.page_name(), "bar"); + } + + #[test] + fn builds_file_name() { + let name = builder().file(Path::new("/src/foo/bar.jpg")); + assert_eq!(name.source_path(), Path::new("/src/foo/bar.jpg")); + assert_eq!(name.destination_path(), Path::new("/dest/foo/bar.jpg")); + assert_eq!(name.page_path(), Path::new("/foo/bar.jpg")); + assert_eq!(name.page_name(), "bar.jpg"); + } + + #[test] + fn names_is_empty_by_default() { + let names = Names::default(); + assert!(names.names.is_empty()); + } + + #[test] + fn names_remembers_inserted() { + let mut names = Names::default(); + let name = builder().page(Path::new("/src/foo/bar.mdwn")); + names.insert(name.clone()); + assert_eq!( + names.get_source_path(Path::new("/src/foo/bar.mdwn")), + Some(&name) + ); + assert_eq!(names.get_page_path(Path::new("/foo/bar")), Some(&name)); + } + + #[test] + fn names_remembers_inserted_pages_and_files() { + let mut names = Names::default(); + let page = builder().page(Path::new("/src/foo/bar.mdwn")); + let file = builder().file(Path::new("/src/foo/bar.jpg")); + names.insert(page.clone()); + names.insert(file.clone()); + let pages: Vec<&Name> = names.pages().collect(); + let files: Vec<&Name> = names.files().collect(); + assert_eq!(pages, vec![page],); + assert_eq!(files, vec![file],); + } +} |