Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
small qol changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Sky9x committed Nov 25, 2023
1 parent 29a9687 commit 724a80a
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 93 deletions.
17 changes: 9 additions & 8 deletions src/dircheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ pub struct DirCheck {
pub fn dir_check(dir: &Path, root: &NavFolder) -> Result<DirCheck> {
trace!(target: "dir_check", "dir={dir:?}");

let nav_paths = root
.into_iter() // recursive iterator over all pages in the folder
.map(|p| &p.path)
.collect::<HashSet<&Path>>();
let mut nav_paths = HashSet::new();

root.for_each_page(|p| {
nav_paths.insert(&p.path);
});

let mut unused = Vec::new();
let mut extra = Vec::new();

walk_dir_recursive(dir, &mut |path| {
walk_dir_recursive(dir, |path| {
if path.extension() != Some("md".as_ref()) {
// if it's not an .md file, it's extra
extra.push(path);
Expand All @@ -40,12 +41,12 @@ pub fn dir_check(dir: &Path, root: &NavFolder) -> Result<DirCheck> {
Ok(DirCheck { unused, extra })
}

fn walk_dir_recursive(dir: &Path, cb: &mut impl FnMut(Path)) -> Result<()> {
fn walk_dir_recursive(dir: &Path, mut cb: impl FnMut(Path)) -> Result<()> {
let read_dir = unwrap!(fs::read_dir(dir), "couldn't read dir {dir}");

for entry in read_dir {
let entry = entry.unwrap();
let path = Path::new(entry.path());
let path = Path::new_owned(entry.path());
let metadata = entry.metadata().unwrap();
trace!(
target: "walk_dir_recursive",
Expand All @@ -54,7 +55,7 @@ fn walk_dir_recursive(dir: &Path, cb: &mut impl FnMut(Path)) -> Result<()> {
);

if metadata.is_dir() {
walk_dir_recursive(&path, cb)?;
walk_dir_recursive(&path, &mut cb)?;
} else {
cb(path);
}
Expand Down
8 changes: 2 additions & 6 deletions src/modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::nav::NavFolder;
use crate::path::Path;
use anyhow::{anyhow, Result};
use log::{debug, error, info};
use std::convert::Infallible;
use std::fs::File;
use std::io::Write;

Expand All @@ -22,8 +21,7 @@ pub fn mode_check(root: &NavFolder) -> Result<()> {
let mut total = 0;
let mut fails = 0;

// Result<(), !>
let _ = root.into_iter().try_for_each(|page| {
root.for_each_page(|page| {
total += 1;

// TODO rich diff?
Expand All @@ -33,8 +31,6 @@ pub fn mode_check(root: &NavFolder) -> Result<()> {
} else {
debug!(target: "mode_check", "pass {}", page.path);
}

Ok::<(), Infallible>(())
});

if fails == 0 {
Expand All @@ -51,7 +47,7 @@ pub fn mode_fix(root: &NavFolder) -> Result<()> {
let mut fixed = 0;
let mut total = 0;

root.into_iter().try_for_each(|page| {
root.try_for_each_page(|page| {
total += 1;

if page.fixed_content == page.raw_content {
Expand Down
100 changes: 27 additions & 73 deletions src/nav.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::front_matter::FrontMatter;
use crate::path::Path;
use std::iter::{once, Chain, Once};
use anyhow::Result;

/// a regular page, eg. `example.md`
#[derive(Debug)]
Expand All @@ -15,20 +15,16 @@ pub struct NavPage {
pub fixed_content: String,
}

type NavPageIter<'a> = Once<&'a NavPage>;

/// A folder with an index
///
/// name is index.page.name (ignored for root)
/// name is index.page.name
#[derive(Debug)]
pub struct NavFolder {
// this may not be an index.md (if it was tagged in nav: `!index abc.md`)
pub index: NavPage,
pub children: Vec<NavItem>,
}

type NavFolderIter<'a> = Chain<NavPageIter<'a>, NavChildrenIter<'a>>;

/// a category
///
/// no index page
Expand All @@ -39,88 +35,46 @@ pub struct NavCategory {
pub children: Vec<NavItem>,
}

// without indirection rustc cant resolve the type layout
type NavChildrenIter<'a> = Box<dyn Iterator<Item = &'a NavPage> + 'a>;

fn nav_children_iter<'a>(data: &'a [NavItem]) -> NavChildrenIter<'a> {
Box::new(data.iter().flat_map(<&'a NavItem>::into_iter))
}

#[derive(Debug)]
pub enum NavItem {
Page(NavPage),
Folder(NavFolder),
Category(NavCategory),
}

pub enum NavItemIter<'a> {
Page(NavPageIter<'a>),
Folder(NavFolderIter<'a>),
Category(NavChildrenIter<'a>),
}

//

impl<'a> IntoIterator for &'a NavPage {
type Item = &'a NavPage;
type IntoIter = NavPageIter<'a>;

fn into_iter(self) -> Self::IntoIter {
once(self)
}
}

impl<'a> IntoIterator for &'a NavFolder {
type Item = &'a NavPage;
type IntoIter = NavFolderIter<'a>;

fn into_iter(self) -> Self::IntoIter {
self.index
.into_iter()
.chain(nav_children_iter(&self.children))
}
}

impl<'a> IntoIterator for &'a NavCategory {
type Item = &'a NavPage;
type IntoIter = NavChildrenIter<'a>;

fn into_iter(self) -> Self::IntoIter {
nav_children_iter(&self.children)
impl NavItem {
#[allow(clippy::needless_lifetimes)] // ???
pub fn for_each_page<'s>(&'s self, mut f: impl FnMut(&'s NavPage)) {
match self {
NavItem::Page(x) => f(x),
NavItem::Folder(x) => x.for_each_page(f),
NavItem::Category(x) => x.children.iter().for_each(|i| i.for_each_page(&mut f)),
}
}
}

impl<'a> IntoIterator for &'a NavItem {
type Item = &'a NavPage;
type IntoIter = NavItemIter<'a>;

fn into_iter(self) -> Self::IntoIter {
pub fn try_for_each_page(&self, mut f: impl FnMut(&NavPage) -> Result<()>) -> Result<()> {
match self {
NavItem::Page(p) => NavItemIter::Page(p.into_iter()),
NavItem::Folder(f) => NavItemIter::Folder(f.into_iter()),
NavItem::Category(c) => NavItemIter::Category(c.into_iter()),
NavItem::Page(x) => f(x),
NavItem::Folder(x) => x.try_for_each_page(f),
NavItem::Category(x) => x
.children
.iter()
.try_for_each(|i| i.try_for_each_page(&mut f)),
}
}
}

//

impl<'a> Iterator for NavItemIter<'a> {
type Item = &'a NavPage;

fn next(&mut self) -> Option<Self::Item> {
match self {
NavItemIter::Page(i) => i.next(),
NavItemIter::Folder(i) => i.next(),
NavItemIter::Category(i) => i.next(),
}
impl NavFolder {
#[allow(clippy::needless_lifetimes)] // ???
pub fn for_each_page<'s>(&'s self, mut f: impl FnMut(&'s NavPage)) {
f(&self.index);
self.children.iter().for_each(|i| i.for_each_page(&mut f));
}

fn size_hint(&self) -> (usize, Option<usize>) {
match self {
NavItemIter::Page(i) => i.size_hint(),
NavItemIter::Folder(i) => i.size_hint(),
NavItemIter::Category(i) => i.size_hint(),
}
pub fn try_for_each_page(&self, mut f: impl FnMut(&NavPage) -> Result<()>) -> Result<()> {
f(&self.index)?;
self.children
.iter()
.try_for_each(|i| i.try_for_each_page(&mut f))
}
}
12 changes: 7 additions & 5 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ pub struct Path {
}

impl Path {
pub fn new<T: AsRef<StdPath>>(path: T) -> Self {
Path {
inner: path.as_ref().to_path_buf(),
}
pub fn new(path: impl AsRef<StdPath>) -> Self {
Path::new_owned(path.as_ref().to_path_buf())
}

pub fn join<T: AsRef<StdPath>>(&self, path: T) -> Self {
pub fn new_owned(buf: PathBuf) -> Self {
Path { inner: buf }
}

pub fn join(&self, path: impl AsRef<StdPath>) -> Self {
let mut p = self.clone();
p.inner.push(path);
p
Expand Down
2 changes: 1 addition & 1 deletion src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub fn process_include(dir: &Path, name: String) -> Result<NavCategory> {

for entry in read_dir {
let entry = entry.unwrap();
let path = Path::new(entry.path());
let path = Path::new_owned(entry.path());
let metadata = entry.metadata().unwrap();

if metadata.is_dir() {
Expand Down

0 comments on commit 724a80a

Please sign in to comment.