diff --git a/Cargo.lock b/Cargo.lock index 5f80dc0..97fa2cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -566,7 +566,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "snekdown" -version = "0.12.4" +version = "0.13.0" dependencies = [ "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 0a8a782..ae3fc87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snekdown" -version = "0.12.4" +version = "0.13.0" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" @@ -16,8 +16,6 @@ crate-type = ["lib"] name = "snekdown" path = "src/main.rs" -[tests] - [dependencies] crossbeam-utils = "0.7.2" structopt = "0.3.14" diff --git a/src/parsing/charstate.rs b/src/parsing/charstate.rs index 80af84a..9c59453 100644 --- a/src/parsing/charstate.rs +++ b/src/parsing/charstate.rs @@ -59,6 +59,16 @@ impl CharStateMachine for Parser { fn next_char(&mut self) -> Option { self.index += 1; self.previous_char = self.current_char; + if (self.text.len() - 1) <= self.index { + for _ in 0..8 { + let mut buf = String::new(); + if let Ok(_) = self.reader.read_line(&mut buf) { + self.text.append(&mut buf.chars().collect()) + } else { + break; + } + } + } self.current_char = *self.text.get(self.index)?; Some(self.current_char) diff --git a/src/parsing/parser.rs b/src/parsing/parser.rs index 2fd063e..a429503 100644 --- a/src/parsing/parser.rs +++ b/src/parsing/parser.rs @@ -7,8 +7,9 @@ use crate::parsing::utils::{ParseError, ParseResult}; use colored::*; use crossbeam_utils::sync::WaitGroup; use std::collections::HashMap; -use std::fs::read_to_string; +use std::fs::File; use std::io; +use std::io::{BufRead, BufReader, Cursor}; use std::path::Path; use std::sync::{Arc, Mutex}; use std::thread; @@ -27,34 +28,63 @@ pub struct Parser { pub(crate) inline_break_at: Vec, document: Document, pub(crate) previous_char: char, + pub(crate) reader: Box, } impl Parser { + /// Creates a new parser from a path pub fn new_from_file(path: String) -> Result { - let content = read_to_string(path.clone())?; - Ok(Self::new(content, Some(path))) + let f = File::open(&path)?; + Ok(Self::create( + Some(path), + Arc::new(Mutex::new(Vec::new())), + false, + Box::new(BufReader::new(f)), + )) } + /// Creates a new parser with text being the markdown text pub fn new(text: String, path: Option) -> Self { - Parser::create(text, path, Arc::new(Mutex::new(Vec::new())), false) + let text_bytes = text.as_bytes(); + Parser::create( + path, + Arc::new(Mutex::new(Vec::new())), + false, + Box::new(Cursor::new(text_bytes.to_vec())), + ) } - pub fn new_as_child(text: String, path: String, paths: Arc>>) -> Self { - Self::create(text, Some(path), paths, true) + /// Creates a child parser from string text + pub fn child(text: String, path: String, paths: Arc>>) -> Self { + let text_bytes = text.as_bytes(); + Self::create( + Some(path), + paths, + true, + Box::new(Cursor::new(text_bytes.to_vec())), + ) + } + + /// Creates a child parser from a file + pub fn child_from_file( + path: String, + paths: Arc>>, + ) -> Result { + let f = File::open(&path)?; + Ok(Self::create( + Some(path), + paths, + true, + Box::new(BufReader::new(f)), + )) } fn create( - text: String, path: Option, paths: Arc>>, is_child: bool, + mut reader: Box, ) -> Self { - let text: Vec = text.chars().collect(); - let current_char = if text.len() > 0 { - text.get(0).unwrap().clone() - } else { - ' ' - }; if let Some(path) = path.clone() { let path_info = Path::new(&path); paths @@ -62,6 +92,19 @@ impl Parser { .unwrap() .push(path_info.to_str().unwrap().to_string()) } + let mut text = Vec::new(); + let mut current_char = ' '; + for _ in 0..8 { + let mut buf = String::new(); + if let Ok(_) = reader.read_line(&mut buf) { + text.append(&mut buf.chars().collect::>()); + } else { + break; + } + } + if let Some(ch) = text.get(0) { + current_char = *ch + } Self { index: 0, text, @@ -76,6 +119,7 @@ impl Parser { previous_char: ' ', inline_break_at: Vec::new(), document: Document::new(!is_child), + reader, } } @@ -141,9 +185,7 @@ impl Parser { let paths = Arc::clone(&self.paths); let _ = thread::spawn(move || { - let text = read_to_string(path.clone()).unwrap(); - - let mut parser = Parser::new_as_child(text.to_string(), path, paths); + let mut parser = Parser::child_from_file(path, paths).unwrap(); let document = parser.parse(); anchor_clone.lock().unwrap().set_document(document);