diff --git a/content/tree/root.tree b/content/tree/root.tree
index 3e8c386..f08b281 100644
--- a/content/tree/root.tree
+++ b/content/tree/root.tree
@@ -1,3 +1,5 @@
+% always_expanded = true
+ id = "treehouse"
- # treehouse
- welcome to the treehouse!
@@ -98,3 +100,16 @@
- expanded
+ + some tests for multiple ps in one block
+
+ - here's a test for multiple paragraphs in one block
+
+ this should be working fine
+
+ - and this shouldn't be breaking yeah
+
+ - nor should
+
+ this be
+
+ - breaking
diff --git a/crates/treehouse-format/src/lib.rs b/crates/treehouse-format/src/lib.rs
index 62dde31..9cb4927 100644
--- a/crates/treehouse-format/src/lib.rs
+++ b/crates/treehouse-format/src/lib.rs
@@ -10,6 +10,9 @@ pub enum ParseErrorKind {
#[error("root branches must not be indented")]
RootIndentLevel,
+
+ #[error("at least {expected} spaces of indentation were expected, but got {got}")]
+ InconsistentIndentation { got: usize, expected: usize },
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
diff --git a/crates/treehouse-format/src/pull.rs b/crates/treehouse-format/src/pull.rs
index 6400208..e5e273d 100644
--- a/crates/treehouse-format/src/pull.rs
+++ b/crates/treehouse-format/src/pull.rs
@@ -1,4 +1,4 @@
-use std::ops::Range;
+use std::{convert::identity, ops::Range};
use crate::{ParseError, ParseErrorKind};
@@ -22,10 +22,10 @@ impl BranchKind {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BranchEvent {
pub indent_level: usize,
- pub attributes: Range,
pub kind: BranchKind,
pub kind_span: Range,
pub content: Range,
+ pub attributes: Range,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -52,8 +52,8 @@ impl<'a> Parser<'a> {
count
}
- fn eat_until(&mut self, c: char) {
- while self.current() != Some(c) {
+ fn eat_until(&mut self, cond: impl Fn(char) -> bool) {
+ while self.current().map(&cond).is_some_and(|x| !x) {
self.advance();
}
self.advance();
@@ -66,6 +66,30 @@ impl<'a> Parser<'a> {
indent_level
}
+ fn eat_indented_lines_until(
+ &mut self,
+ indent_level: usize,
+ cond: impl Fn(char) -> bool,
+ ) -> Result<(), ParseError> {
+ loop {
+ self.eat_until(|c| c == '\n');
+ let before_indentation = self.position;
+ let line_indent_level = self.eat_as_long_as(' ');
+ let after_indentation = self.position;
+ if self.current().map(&cond).is_some_and(identity) || self.current().is_none() {
+ self.position = before_indentation;
+ break;
+ } else if !matches!(self.current(), Some('\n')) && line_indent_level < indent_level {
+ return Err(ParseErrorKind::InconsistentIndentation {
+ got: line_indent_level,
+ expected: indent_level,
+ }
+ .at(before_indentation..after_indentation));
+ }
+ }
+ Ok(())
+ }
+
pub fn next_branch(&mut self) -> Result