summaryrefslogtreecommitdiff
path: root/src/name.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/name.rs')
-rw-r--r--src/name.rs198
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],);
+ }
+}