Skip to content

Commit

Permalink
Harper + Mockingbird 0.0.2.
Browse files Browse the repository at this point in the history
This release includes the following major changes:

  * `derive_more` was removed as a dependency.
  * Collections are now associated with a name.
  * Internal refactor for a new `OwnedEntry`.
  * Updated to minijinja2.
  * Undefined variables now result in errors.
  * Added a `get()` template helper with a default when undefined.
  * Added a real CLI parser.
  * Added a `time!()` macro for wall-clock time measurements.
  * Now exits with status 1 if rendering fails.
  • Loading branch information
SergioBenitez committed Apr 5, 2024
1 parent a40f5fd commit 34954dd
Show file tree
Hide file tree
Showing 28 changed files with 343 additions and 311 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Version 0.0.2 (Apr 4, 2024)

This is the second testing release of Mockingbird. More details to come.

# Version 0.0.1 (Mar 3, 2024)

This is the initial testing release of Mockingbird. More details to come.
8 changes: 2 additions & 6 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "harper"
version = "0.0.1"
version = "0.0.2"
edition = "2021"
authors = ["Sergio Benitez <sb@sergio.bz>"]
license = "MIT OR Apache-2.0"
Expand All @@ -23,7 +23,6 @@ serde = { version = "1", features = ["rc", "derive"] }
toml = { version = "0.8", features = ["preserve_order"] }
memchr = "2"
either = "1.10"
derive_more = { version = "=1.0.0-beta.6", features = ["debug", "deref", "from"] }
grass = { version = "0.13", default-features = false, features = ["random"], optional = true }
pulldown-cmark = { version = "0.10", default-features = false, features = ["simd", "html"] }

Expand Down Expand Up @@ -56,11 +55,8 @@ default-features = false
features = ["html", "default-syntaxes", "regex-onig", "plist-load"]

[dependencies.minijinja]
# git = "https://github.com/SergioBenitez/minijinja.git"
# # branch = "value-unification"
# rev = "517d147"
package = "unified-minijinja"
version = "1.0.12"
version = "=0.0.2"
default-features = false
features = ["speedups", "loader", "builtins", "debug", "deserialization", "macros", "multi_template"]

Expand Down
58 changes: 36 additions & 22 deletions lib/src/fstree.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
use std::{fs, fmt};
use std::ops::Deref;
use std::sync::Arc;
use std::path::Path;
use std::collections::VecDeque;
use std::{fs, fmt};

use rustc_hash::FxHashMap;

use crate::error::Result;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EntryId(pub(crate) usize);

#[derive(Debug)]
pub struct FsTree {
entries: Vec<Entry>,
map: FxHashMap<Arc<Path>, EntryId>,
}

pub struct FsSubTree<'a> {
tree: &'a FsTree,
root: EntryId
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EntryId(usize);

#[derive(Clone)]
pub struct OwnedEntry {
pub tree: Arc<FsTree>,
pub id: EntryId,
}

#[derive(Debug)]
Expand All @@ -44,10 +46,12 @@ impl FsTree {
}
}

#[inline(always)]
pub fn build<P: AsRef<Path>>(root: P) -> Result<Self> {
Self::build_with(root.as_ref(), |_, _| Ok(()))
}

#[inline]
pub fn build_with<P, F>(root: P, mut callback: F) -> Result<Self>
where P: AsRef<Path>,
F: FnMut(&Self, EntryId) -> Result<()>,
Expand Down Expand Up @@ -91,12 +95,6 @@ impl FsTree {
EntryId(0)
}

#[inline]
pub fn subtree(&self, root: EntryId) -> FsSubTree<'_> {
assert!(self[root].id == root);
FsSubTree { tree: self, root }
}

#[inline]
pub fn get<R, P>(&self, root: R, path: P) -> Option<&Entry>
where R: Into<Option<EntryId>>, P: AsRef<Path>
Expand Down Expand Up @@ -227,22 +225,38 @@ impl FsTree {
}
}

impl FsSubTree<'_> {
pub fn get<P: AsRef<Path>>(&self, path: P) -> Option<&Entry> {
self.tree.get(self.root, path.as_ref())
impl OwnedEntry {
pub fn new(tree: Arc<FsTree>, id: EntryId) -> Self {
OwnedEntry { tree, id }
}

#[inline]
pub fn get_file_id<P: AsRef<Path>>(&self, path: P) -> Option<EntryId> {
self.tree.get_file_id(self.root, path.as_ref())
pub fn entry(&self) -> &Entry {
&self.tree[self.id]
}
}

#[inline]
pub fn get_id<P: AsRef<Path>>(&self, path: P) -> Option<EntryId> {
self.tree.get_id(self.root, path.as_ref())
impl Deref for OwnedEntry {
type Target = Entry;

fn deref(&self) -> &Self::Target {
self.entry()
}
}

impl fmt::Debug for OwnedEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.entry().fmt(f)
}
}

impl PartialEq for OwnedEntry {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}

impl Eq for OwnedEntry { }

impl Entry {
/// File name without the extension.
pub fn file_stem(&self) -> &str {
Expand Down
4 changes: 2 additions & 2 deletions lib/src/markdown/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ impl<'a> Alias<'a> {
}

impl crate::markdown::Plugin for Alias<'_> {
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
Box::new(AliasIterator { inner: events, map: self.map })
AliasIterator { inner: events, map: self.map }
}
}

Expand Down
12 changes: 6 additions & 6 deletions lib/src/markdown/auto_heading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for HeadingIterator<'a, I> {
}

impl Plugin for AutoHeading {
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
Box::new(HeadingIterator {
HeadingIterator {
seen: FxHashMap::default(),
inner: events,
stack: VecDeque::with_capacity(4),
})
}
}
}

Expand Down Expand Up @@ -92,12 +92,12 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for AnchorIterator<'a, I> {
}

impl Plugin for HeadingAnchor {
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
Box::new(AnchorIterator {
AnchorIterator {
inner: events,
pending: None,
})
}
}
}
6 changes: 3 additions & 3 deletions lib/src/markdown/code_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ impl CodeTrim<()> {
}

impl<F: CodeFilter> Plugin for CodeTrim<F> {
fn remap<'a, I>(&'a mut self, i: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, i: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
Box::new(Iter {
Iter {
trimmer: &mut self.trimmer,
inner: i,
line_num: None,
stack: VecDeque::new(),
})
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/markdown/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ impl SyntaxHighlight {
}

impl Plugin for SyntaxHighlight {
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
Box::new(Highlighter { generator: None, lines: 0, inner: events })
Highlighter { generator: None, lines: 0, inner: events }
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/markdown/parts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<O: Sink> Plugin for Parts<O> {
// secion. This causes the HTML renderer to emit the string so far. We then
// reuse the same iterator in the renderer again until it signals it cannot
// be reused. We finally return one string containing all of the HTML.
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
let mut sections = SectionIterator {
Expand Down Expand Up @@ -84,7 +84,7 @@ impl<O: Sink> Plugin for Parts<O> {
_ => self.sections.join("").into(),
};

Box::new(Some(Event::Html(complete_html)).into_iter())
Some(Event::Html(complete_html)).into_iter()
}

fn finalize(&mut self) -> Result<()> {
Expand Down
7 changes: 2 additions & 5 deletions lib/src/markdown/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ pub trait Plugin {
Ok(Cow::Borrowed(input))
}

// FIXME: To get rid of this box, we need (ideally) `-> impl Trait` in trait
// methods, or generic associated types. Edit: We now have GATs! But they're
// incredibly annoying to use because of the required bounds everywhere.
#[inline(always)]
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
Box::new(events)
events
}

#[inline(always)]
Expand Down
7 changes: 3 additions & 4 deletions lib/src/markdown/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,16 @@ impl<O: Sink> Renderer<O> {
}

impl<O: Sink> Plugin for Renderer<O> {
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>>
{
let mut html_output = String::new();
html::push_html(&mut html_output, events);
self.rendered = html_output;
Box::new(std::iter::empty())
std::iter::empty()
}

fn finalize(&mut self) -> Result<()> {
let string = std::mem::replace(&mut self.rendered, String::new());
self.output.write(string)
self.output.write(std::mem::take(&mut self.rendered))
}
}
6 changes: 3 additions & 3 deletions lib/src/markdown/snippet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,17 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SnippetIterator<'a, I> {
// IDEA: What if we just take the first k character of the text and render that as markdown?

impl<O: Sink> Plugin for Snippet<O> {
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
Box::new(SnippetIterator {
SnippetIterator {
snippet: &mut self.snippet,
snip_text_len: 0,
inner: events,
capture: vec![],
min_length: self.length,
done: self.length == 0,
})
}
}

fn finalize(&mut self) -> Result<()> {
Expand Down
7 changes: 4 additions & 3 deletions lib/src/markdown/toc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ impl<O: Sink> TableOfContents<O> {
}

impl<O: Sink> Plugin for TableOfContents<O> {
fn remap<'a, I>(&'a mut self, events: I) -> Box<dyn Iterator<Item = Event<'a>> + 'a>
fn remap<'a, I>(&'a mut self, events: I) -> impl Iterator<Item = Event<'a>> + 'a
where I: Iterator<Item = Event<'a>> + 'a
{
self.reset();
Box::new(events.inspect(|ev| match ev {

events.inspect(|ev| match ev {
Event::Start(Tag::Heading { level, id, .. }) => {
self.entry = Some(Entry {
title: String::new(),
Expand All @@ -75,7 +76,7 @@ impl<O: Sink> Plugin for TableOfContents<O> {
}
}
_ => {}
}))
})
}

fn finalize(&mut self) -> Result<()> {
Expand Down
1 change: 0 additions & 1 deletion lib/src/markdown/ts_highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for Highlighter<I> {
.unwrap_or(&*label);

self.code = String::new();
// self.config = time!(find_ts_highlight_config(lang));
self.config = find_ts_highlight_config(lang);
}
Event::Text(text) if self.config.is_some() => {
Expand Down
27 changes: 12 additions & 15 deletions lib/src/taxonomy/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@ use std::sync::Arc;

use rayon::prelude::*;
use rustc_hash::FxHashMap;
use derive_more::Debug;

use crate::fstree::{Entry, EntryId, FsTree};
use crate::fstree::{Entry, EntryId, FsTree, OwnedEntry};
use crate::value::List;
use crate::taxonomy::*;

#[derive(Debug)]
pub struct Collection {
#[debug(ignore)]
pub tree: Arc<FsTree>,
#[debug("{:?}", tree[**root])]
pub root: EntryId,
pub entry: OwnedEntry,
pub name: Arc<str>,
pub index: Option<Arc<Item>>,
pub items: Arc<List<Arc<Item>>>,
pub data: FxHashMap<EntryId, Arc<List<Arc<Item>>>>,
Expand All @@ -32,34 +29,34 @@ pub enum Kind {
}

impl Collection {
pub fn new(tree: Arc<FsTree>, root: EntryId) -> Collection {
pub fn new(name: Arc<str>, tree: Arc<FsTree>, root: EntryId) -> Collection {
Collection {
tree,
root,
name,
entry: OwnedEntry::new(tree, root),
index: None,
items: Default::default(),
data: Default::default(),
}
}

pub fn root_entry(&self) -> &Entry {
&self.tree[self.root]
pub fn entry(&self) -> &Entry {
&self.entry
}

pub fn new_item(&mut self, entry: EntryId) -> Arc<Item> {
let item = Arc::new(Item::new(self.tree.clone(), entry));
pub fn new_item(&mut self, id: EntryId) -> Arc<Item> {
let item = Arc::new(Item::new(self.entry.tree.clone(), id));
self.items.push(item.clone());
item
}

pub fn new_datum(&mut self, parent: EntryId, entry: EntryId) -> Arc<Item> {
let datum = Arc::new(Item::new(self.tree.clone(), entry));
let datum = Arc::new(Item::new(self.entry.tree.clone(), entry));
self.data.entry(parent).or_default().push(datum.clone());
datum
}

pub fn set_index_item(&mut self, entry: EntryId) -> Arc<Item> {
let index = Arc::new(Item::new(self.tree.clone(), entry));
let index = Arc::new(Item::new(self.entry.tree.clone(), entry));
self.index = Some(index.clone());
index
}
Expand Down
Loading

0 comments on commit 34954dd

Please sign in to comment.