readable errors
This commit is contained in:
10
src/main.rs
10
src/main.rs
@@ -37,7 +37,7 @@ fn main() {
|
|||||||
let specs = &args[2..];
|
let specs = &args[2..];
|
||||||
let src = || std::fs::read_to_string(&args[0]).unwrap();
|
let src = || std::fs::read_to_string(&args[0]).unwrap();
|
||||||
match args[1].to_lowercase().trim() {
|
match args[1].to_lowercase().trim() {
|
||||||
"html" => println!(
|
"html" => print!(
|
||||||
"{}",
|
"{}",
|
||||||
to::html::page(&parse(&src()).unwrap(), specs, &mut to::html::State::new())
|
to::html::page(&parse(&src()).unwrap(), specs, &mut to::html::State::new())
|
||||||
),
|
),
|
||||||
@@ -122,7 +122,13 @@ const BODY_REGEX = new RegExp("<bo"+"dy>.*<\\/bo"+"dy>", "misv");
|
|||||||
}
|
}
|
||||||
buf1[i] = src();
|
buf1[i] = src();
|
||||||
let src = unsafe { &*((&buf1[i]) as *const String) };
|
let src = unsafe { &*((&buf1[i]) as *const String) };
|
||||||
buf2[i] = Some(parse(src).unwrap());
|
buf2[i] = Some(match parse(src) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("{}", e.display(src));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
});
|
||||||
let doc = unsafe { &*(buf2[i].as_ref().unwrap() as *const Document<'_>) };
|
let doc = unsafe { &*(buf2[i].as_ref().unwrap() as *const Document<'_>) };
|
||||||
i += 1;
|
i += 1;
|
||||||
let mut http =
|
let mut http =
|
||||||
|
|||||||
72
src/parse.rs
72
src/parse.rs
@@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::doc::{Component, Document, Section, Text};
|
use crate::doc::{Component, Document, Section, Text};
|
||||||
|
|
||||||
pub fn parse<'a>(mut src: &'a str) -> Result<Document<'a>, ParseError<'a>> {
|
pub fn parse<'a>(mut src: &'a str) -> Result<Document<'a>, ParseError<'a>> {
|
||||||
@@ -6,6 +8,8 @@ pub fn parse<'a>(mut src: &'a str) -> Result<Document<'a>, ParseError<'a>> {
|
|||||||
Ok(doc)
|
Ok(doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ParseErrorPlus<'a>(ParseErr<'a>, usize, &'a str);
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseError<'a>(ParseErr<'a>, usize);
|
pub struct ParseError<'a>(ParseErr<'a>, usize);
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -20,7 +24,7 @@ pub enum ParseErr<'a> {
|
|||||||
MissingClosing(char),
|
MissingClosing(char),
|
||||||
InvalidBacktickBracketCountSpecifier,
|
InvalidBacktickBracketCountSpecifier,
|
||||||
InvalidBacktickModifier,
|
InvalidBacktickModifier,
|
||||||
SubsectionNotAllowedHere,
|
SubdocumentNotAllowedHere,
|
||||||
FileTitleWithLink,
|
FileTitleWithLink,
|
||||||
r#__Zzzz(&'a str),
|
r#__Zzzz(&'a str),
|
||||||
}
|
}
|
||||||
@@ -371,7 +375,7 @@ fn parse_sections<'a>(
|
|||||||
// => section hashes
|
// => section hashes
|
||||||
Some(' ' | '\n') | None => {
|
Some(' ' | '\n') | None => {
|
||||||
if !document {
|
if !document {
|
||||||
return Err(ParseError(ParseErr::SubsectionNotAllowedHere, pos));
|
return Err(ParseError(ParseErr::SubdocumentNotAllowedHere, pos));
|
||||||
}
|
}
|
||||||
src.reset_to(pos);
|
src.reset_to(pos);
|
||||||
match parse_document(src.get(), depth + 1)
|
match parse_document(src.get(), depth + 1)
|
||||||
@@ -517,3 +521,67 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ParseError<'a> {
|
||||||
|
pub fn display(self, src: &'a str) -> ParseErrorPlus<'a> {
|
||||||
|
ParseErrorPlus(self.0, self.1, src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Display for ParseErrorPlus<'a> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let ln = self
|
||||||
|
.2
|
||||||
|
.char_indices()
|
||||||
|
.take_while(|(i, _)| *i <= self.1)
|
||||||
|
.filter(|(_, c)| *c == '\n')
|
||||||
|
.count();
|
||||||
|
write!(f, "Line {}: {}", ln + 1, self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Display for ParseErr<'a> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ParseErr::InvalidSectionHash => write!(
|
||||||
|
f,
|
||||||
|
"this section hash isn't valid, if you want a title, add a space after your hashtags"
|
||||||
|
),
|
||||||
|
ParseErr::InvalidHeadingDepth => write!(f, "this heading depth isn't allowed here"),
|
||||||
|
ParseErr::BracketsAtStartOfSectionWithNoLinebreakAfter => write!(
|
||||||
|
f,
|
||||||
|
"brackets at the start of a section must be on their own line"
|
||||||
|
),
|
||||||
|
ParseErr::BracketedSectionNotTerminated => {
|
||||||
|
write!(f, "this bracketed section isn't terminated anywhere")
|
||||||
|
}
|
||||||
|
ParseErr::BracketedSectionTerminatedByTooManyBrackets => write!(
|
||||||
|
f,
|
||||||
|
"this bracketed section is terminated by more brackets than expected"
|
||||||
|
),
|
||||||
|
ParseErr::IncompleteBacktick => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"incomplete backtick, there needs to be something here (or escape the backtick: ``)"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ParseErr::MissingClosing(c) => {
|
||||||
|
write!(f, "couldn't find an appropriate closing {c} bracket")
|
||||||
|
}
|
||||||
|
ParseErr::InvalidBacktickBracketCountSpecifier => write!(
|
||||||
|
f,
|
||||||
|
"invalid backtick bracket count between ` and the next ascii symbol"
|
||||||
|
),
|
||||||
|
ParseErr::InvalidBacktickModifier => write!(
|
||||||
|
f,
|
||||||
|
"invalid backtick modifier between ` and the next bracket"
|
||||||
|
),
|
||||||
|
ParseErr::SubdocumentNotAllowedHere => {
|
||||||
|
write!(f, "found a subdocument where it isn't allowed")
|
||||||
|
}
|
||||||
|
ParseErr::FileTitleWithLink => write!(
|
||||||
|
f,
|
||||||
|
"file title (title at the start of the file) cannot have a link"
|
||||||
|
),
|
||||||
|
ParseErr::__Zzzz(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,15 +7,13 @@ use crate::{
|
|||||||
|
|
||||||
pub struct State<'a> {
|
pub struct State<'a> {
|
||||||
pub head_to_body: &'a str,
|
pub head_to_body: &'a str,
|
||||||
cache_docs: BTreeMap<&'a Document<'a>, String>,
|
cache: BTreeMap<&'a Section<'a>, String>,
|
||||||
cache_secs: BTreeMap<&'a Section<'a>, String>,
|
|
||||||
}
|
}
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
State {
|
State {
|
||||||
head_to_body: "</head>\n<body>",
|
head_to_body: "</head>\n<body>",
|
||||||
cache_docs: Default::default(),
|
cache: Default::default(),
|
||||||
cache_secs: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,11 +252,6 @@ fn doc_to_impl<'a>(
|
|||||||
out: &mut String,
|
out: &mut String,
|
||||||
doc_args: &mut DocArgs<'a, '_>,
|
doc_args: &mut DocArgs<'a, '_>,
|
||||||
) {
|
) {
|
||||||
if let Some(prev) = doc_args.state.cache_docs.get(doc) {
|
|
||||||
out.push_str(prev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let out_start = out.len();
|
|
||||||
let depth = doc_args.depth;
|
let depth = doc_args.depth;
|
||||||
let end_at = doc_args.max_len.map(|len| out.len() + len);
|
let end_at = doc_args.max_len.map(|len| out.len() + len);
|
||||||
for d in depth..=doc.depth {
|
for d in depth..=doc.depth {
|
||||||
@@ -285,7 +278,7 @@ fn doc_to_impl<'a>(
|
|||||||
out.push_str(&format!("</span>{a}</div>\n"));
|
out.push_str(&format!("</span>{a}</div>\n"));
|
||||||
}
|
}
|
||||||
for section in &doc.sections {
|
for section in &doc.sections {
|
||||||
if let Some(prev) = doc_args.state.cache_secs.get(section) {
|
if let Some(prev) = doc_args.state.cache.get(section) {
|
||||||
out.push_str(prev);
|
out.push_str(prev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -385,16 +378,12 @@ fn doc_to_impl<'a>(
|
|||||||
out.push_str("</div>\n");
|
out.push_str("</div>\n");
|
||||||
doc_args
|
doc_args
|
||||||
.state
|
.state
|
||||||
.cache_secs
|
.cache
|
||||||
.insert(section, out[section_start..].to_owned());
|
.insert(section, out[section_start..].to_owned());
|
||||||
}
|
}
|
||||||
for _ in depth..=doc.depth {
|
for _ in depth..=doc.depth {
|
||||||
out.push_str("</div>\n");
|
out.push_str("</div>\n");
|
||||||
}
|
}
|
||||||
doc_args
|
|
||||||
.state
|
|
||||||
.cache_docs
|
|
||||||
.insert(doc, out[out_start..].to_owned());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_to<'a: 'b, 'b>(
|
fn text_to<'a: 'b, 'b>(
|
||||||
|
|||||||
Reference in New Issue
Block a user