Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Block enum type which will eventually represent all possible block types #13

Merged
merged 1 commit into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/blocks/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use nom::IResult;

use super::SimpleBlock;
use crate::{primitives::consume_empty_lines, Span};

/// Block elements form the main structure of an AsciiDoc document, starting
/// with the document itself.
///
/// A block element (aka block) is a discrete, line-oriented chunk of content in
/// an AsciiDoc document. Once parsed, that chunk of content becomes a block
/// element in the parsed document model. Certain blocks may contain other
/// blocks, so we say that blocks can be nested. The converter visits each block
/// in turn, in document order, converting it to a corresponding chunk of
/// output.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Block<'a> {
/// A block that’s treated as contiguous lines of paragraph text (and
/// subject to normal substitutions) (e.g., a paragraph block).
Simple(SimpleBlock<'a>),
}

impl<'a> Block<'a> {
#[allow(dead_code)]
/// Parse a block of any type and return a `Block` that describes it.
///
/// Consumes any blank lines before and after the block.
pub(crate) fn parse(i: Span<'a>) -> IResult<Span, Self> {
let i = consume_empty_lines(i);

// TEMPORARY: So far, we only know SimpleBlock.
// Later we'll start to try to discern other block types.
let (rem, simple_block) = SimpleBlock::parse(i)?;
Ok((rem, Self::Simple(simple_block)))
}
}
6 changes: 5 additions & 1 deletion src/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@
//! in turn, in document order, converting it to a corresponding chunk of
//! output.

pub(crate) mod simple;
mod block;
pub use block::Block;

mod simple;
pub use simple::SimpleBlock;
95 changes: 95 additions & 0 deletions src/tests/blocks/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
mod simple {
use nom::{
error::{Error, ErrorKind},
Err,
};

use crate::{
blocks::{Block, SimpleBlock},
Span,
};

#[test]
fn empty_source() {
let expected_err = Err::Error(Error::new(Span::new("", true), ErrorKind::TakeTill1));

let actual_err = Block::parse(Span::new("", true)).unwrap_err();

assert_eq!(expected_err, actual_err);
}

#[test]
fn only_spaces() {
let err = Block::parse(Span::new(" ", true)).unwrap_err();

let Err::Error(e) = err else {
panic!("Expected Err::Error: {err:#?}");
};

assert_eq!(e.code, ErrorKind::TakeTill1);

let span = e.input;
assert_eq!(span.data(), &"");
assert_eq!(span.line(), 1);
assert_eq!(span.col(), 5);
}

#[test]
fn single_line() {
let expected = Block::Simple(SimpleBlock {
inlines: vec![Span::new("abc", true)],
});

let (rem, block) = Block::parse(Span::new("abc", true)).unwrap();

assert_eq!(rem.line(), 1);
assert_eq!(rem.col(), 4);
assert_eq!(*rem.data(), "");

assert_eq!(block, expected);
}

#[test]
fn multiple_lines() {
let (rem, block) = Block::parse(Span::new("abc\ndef", true)).unwrap();

assert_eq!(rem.line(), 2);
assert_eq!(rem.col(), 4);
assert_eq!(*rem.data(), "");

let Block::Simple(block) = block;
// else { // ADD THIS ONCE WE HAVE OTHER BLOCK TYPES
//panic!("Expected a SimpleBlock: {block:#?}");
//};

assert_eq!(block.inlines.len(), 2);

assert_eq!(block.inlines[0].line(), 1);
assert_eq!(block.inlines[0].col(), 1);
assert_eq!(*block.inlines[0].data(), "abc");

assert_eq!(block.inlines[1].line(), 2);
assert_eq!(block.inlines[1].col(), 1);
assert_eq!(*block.inlines[1].data(), "def");
}

#[test]
fn consumes_blank_lines_after() {
let expected = SimpleBlock {
inlines: vec![Span::new("abc", true)],
};

let (rem, block) = Block::parse(Span::new("abc\n\ndef", true)).unwrap();

assert_eq!(rem.line(), 3);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "def");

let Block::Simple(block) = block;
// else { // ADD THIS ONCE WE HAVE OTHER BLOCK TYPES
//panic!("Expected a SimpleBlock: {block:#?}");
//};

assert_eq!(block, expected);
}
}
3 changes: 2 additions & 1 deletion src/tests/blocks/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub(crate) mod simple;
mod block;
mod simple;
2 changes: 1 addition & 1 deletion src/tests/blocks/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use nom::{
Err,
};

use crate::{blocks::simple::SimpleBlock, Span};
use crate::{blocks::SimpleBlock, Span};

#[test]
fn empty_source() {
Expand Down
Loading