diff --git a/Cargo.lock b/Cargo.lock index 575734d..e41f628 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,6 +234,18 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "filetime" version = "0.2.12" @@ -440,6 +452,14 @@ name = "httparse" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hyper" version = "0.13.7" @@ -905,6 +925,11 @@ dependencies = [ "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "1.0.7" @@ -1142,7 +1167,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "snekdown" -version = "0.26.2" +version = "0.26.3" dependencies = [ "asciimath-rs 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1151,9 +1176,11 @@ dependencies = [ "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "gh-emoji 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1251,6 +1278,14 @@ dependencies = [ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -1613,6 +1648,7 @@ dependencies = [ "checksum dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum encoding_rs 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" +"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum filetime 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" "checksum flate2 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" "checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" @@ -1638,6 +1674,7 @@ dependencies = [ "checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" "checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb" "checksum hyper-tls 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" @@ -1692,6 +1729,7 @@ dependencies = [ "checksum proc-macro-error 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" "checksum proc-macro-error-attr 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" "checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" "checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" "checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" "checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" @@ -1725,6 +1763,7 @@ dependencies = [ "checksum syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" "checksum syntect 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b57a45fdcf4891bc79f635be5c559210a4cfa464891f969724944c713282eedb" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" diff --git a/Cargo.toml b/Cargo.toml index b39657a..6a50a36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snekdown" -version = "0.26.2" +version = "0.26.3" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" @@ -39,4 +39,6 @@ mime_guess = "2.0.3" mime = "0.3.16" base64 = "0.12.3" rayon = "1.3.1" -maplit = "1.0.2" \ No newline at end of file +maplit = "1.0.2" +log = "0.4.11" +env_logger = "0.7.1" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index d145f31..0eee2f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ use colored::Colorize; +use env_logger::Env; +use log::{Level, LevelFilter}; use notify::{watcher, RecursiveMode, Watcher}; use snekdown::format::html::html_writer::HTMLWriter; use snekdown::format::html::to_html::ToHtml; @@ -40,14 +42,31 @@ enum SubCommand { fn main() { let opt: Opt = Opt::from_args(); - if !opt.input.exists() { - println!( - "{}", - format!( - "The input file {} could not be found", - opt.input.to_str().unwrap() + env_logger::Builder::from_env(Env::default().filter_or("SNEKDOWN_LOG", "info")) + .filter_module("reqwest", LevelFilter::Warn) + .filter_module("hyper", LevelFilter::Warn) + .filter_module("mio", LevelFilter::Warn) + .filter_module("want", LevelFilter::Warn) + .format(|buf, record| { + use std::io::Write; + let color = get_level_style(record.level()); + writeln!( + buf, + "{}: {}", + record + .level() + .to_string() + .to_lowercase() + .as_str() + .color(color), + record.args() ) - .red() + }) + .init(); + if !opt.input.exists() { + log::error!( + "The input file {} could not be found", + opt.input.to_str().unwrap() ); return; } @@ -60,6 +79,16 @@ fn main() { }; } +fn get_level_style(level: Level) -> colored::Color { + match level { + Level::Trace => colored::Color::Magenta, + Level::Debug => colored::Color::Blue, + Level::Info => colored::Color::Green, + Level::Warn => colored::Color::Yellow, + Level::Error => colored::Color::Red, + } +} + /// Watches a file with all of its imports and renders on change fn watch(opt: &Opt) { let parser = render(opt); @@ -82,10 +111,8 @@ fn render(opt: &Opt) -> Parser { let start = Instant::now(); let mut parser = Parser::new_from_file(opt.input.clone()).unwrap(); let document = parser.parse(); - println!( - "{}", - format!("Parsing took: {:?}", start.elapsed()).italic() - ); + + log::info!("Parsing took: {:?}", start.elapsed()); let start_render = Instant::now(); let file = OpenOptions::new() .read(true) @@ -101,16 +128,10 @@ fn render(opt: &Opt) -> Parser { document.to_html(&mut writer).unwrap(); writer.flush().unwrap(); } - _ => println!("Unknown format {}", opt.format), + _ => log::error!("Unknown format {}", opt.format), } - println!( - "{}", - format!("Rendering took: {:?}", start_render.elapsed()).italic() - ); - println!( - "{}", - format!("Total: {:?}", start.elapsed()).italic() - ); + log::info!("Rendering took: {:?}", start_render.elapsed()); + log::info!("Total: {:?}", start.elapsed()); parser } diff --git a/src/parser/block.rs b/src/parser/block.rs index 60ee3b0..bcb0c1a 100644 --- a/src/parser/block.rs +++ b/src/parser/block.rs @@ -32,30 +32,40 @@ impl ParseBlock for Parser { } } let token = if let Ok(section) = self.parse_section() { + log::trace!("Block::Section"); Block::Section(section) } else if let Some(_) = self.section_return { return Err(self.ctm.err()); } else if let Ok(list) = self.parse_list() { + log::trace!("Block::List"); Block::List(list) } else if let Ok(table) = self.parse_table() { + log::trace!("Block::Table"); Block::Table(table) } else if let Ok(code_block) = self.parse_code_block() { + log::trace!("Block::CodeBlock"); Block::CodeBlock(code_block) } else if let Ok(math_block) = self.parse_math_block() { + log::trace!("Block::MathBlock"); Block::MathBlock(math_block) } else if let Ok(quote) = self.parse_quote() { + log::trace!("Block::Quote"); Block::Quote(quote) } else if let Ok(import) = self.parse_import() { if let Some(import) = import { + log::trace!("Block::Import"); Block::Import(import) } else { + log::trace!("Block::Null"); Block::Null } } else if let Some(_) = self.section_return { return Err(self.ctm.err()); } else if let Ok(pholder) = self.parse_placeholder() { + log::trace!("Block::Placeholder"); Block::Placeholder(pholder) } else if let Ok(paragraph) = self.parse_paragraph() { + log::trace!("Block::Paragraph"); Block::Paragraph(paragraph) } else { return Err(self.ctm.err()); diff --git a/src/parser/inline.rs b/src/parser/inline.rs index ce64b81..7ef0684 100644 --- a/src/parser/inline.rs +++ b/src/parser/inline.rs @@ -60,44 +60,62 @@ impl ParseInline for Parser { fn parse_inline(&mut self) -> ParseResult { if self.parse_variables { if let Ok(var) = self.parse_template_variable() { + log::trace!("Inline::TemplateVar"); return Ok(Inline::TemplateVar(var)); } } if self.ctm.check_char(&PIPE) || self.ctm.check_char(&LB) { Err(self.ctm.err()) } else if self.ctm.check_eof() { + log::trace!("EOF"); Err(self.ctm.err()) } else if let Ok(image) = self.parse_image() { + log::trace!("Inline::Image"); Ok(Inline::Image(image)) } else if let Ok(url) = self.parse_url(false) { + log::trace!("Inline::Url"); Ok(Inline::Url(url)) } else if let Ok(pholder) = self.parse_placeholder() { + log::trace!("Inline::Placeholder"); Ok(Inline::Placeholder(pholder)) } else if let Ok(bold) = self.parse_bold() { + log::trace!("Inline::Bold"); Ok(Inline::Bold(bold)) } else if let Ok(italic) = self.parse_italic() { + log::trace!("Inline::Italic"); Ok(Inline::Italic(italic)) } else if let Ok(under) = self.parse_underlined() { + log::trace!("Inline::Underlined"); Ok(Inline::Underlined(under)) } else if let Ok(mono) = self.parse_monospace() { + log::trace!("Inline::Monospace"); Ok(Inline::Monospace(mono)) } else if let Ok(striked) = self.parse_striked() { + log::trace!("Inline::Striked"); Ok(Inline::Striked(striked)) } else if let Ok(superscript) = self.parse_superscript() { + log::trace!("Inline::Superscript"); Ok(Inline::Superscript(superscript)) } else if let Ok(checkbox) = self.parse_checkbox() { + log::trace!("Inline::Checkbox"); Ok(Inline::Checkbox(checkbox)) } else if let Ok(emoji) = self.parse_emoji() { + log::trace!("Inline::Emoji"); Ok(Inline::Emoji(emoji)) } else if let Ok(colored) = self.parse_colored() { + log::trace!("Inline::Colored"); Ok(Inline::Colored(colored)) } else if let Ok(bibref) = self.parse_bibref() { + log::trace!("Inline::BibReference"); Ok(Inline::BibReference(bibref)) } else if let Ok(math) = self.parse_math() { + log::trace!("Inline::Math"); Ok(Inline::Math(math)) } else if let Ok(char_code) = self.parse_character_code() { + log::trace!("Inline::Character Code"); Ok(Inline::CharacterCode(char_code)) } else { + log::trace!("Inline::Plain"); Ok(Inline::Plain(self.parse_plain()?)) } } diff --git a/src/parser/line.rs b/src/parser/line.rs index 4640d01..a9dbeca 100644 --- a/src/parser/line.rs +++ b/src/parser/line.rs @@ -24,15 +24,20 @@ impl ParseLine for Parser { /// parses inline definitions fn parse_line(&mut self) -> ParseResult { if self.ctm.check_eof() { + log::trace!("EOF"); Err(self.ctm.err()) } else { if let Ok(ruler) = self.parse_ruler() { + log::trace!("Line::Ruler"); Ok(Line::Ruler(ruler)) } else if let Ok(centered) = self.parse_centered() { + log::trace!("Line::Centered"); Ok(Line::Centered(centered)) } else if let Ok(bib) = self.parse_bib_entry() { + log::trace!("Line::BibEntry"); Ok(Line::BibEntry(bib)) } else if let Ok(text) = self.parse_text_line() { + log::trace!("Line::Text"); Ok(Line::Text(text)) } else { Err(self.ctm.err()) @@ -49,6 +54,7 @@ impl ParseLine for Parser { .iter() .for_each(|e| anchor.push(*e)); anchor.retain(|c| !c.is_whitespace()); + log::trace!("Line::Header"); Ok(Header::new(line, anchor)) } @@ -78,6 +84,7 @@ impl ParseLine for Parser { } let item = ListItem::new(self.parse_line()?, level as u16, ordered); + log::trace!("Line::ListItem"); Ok(item) } @@ -124,6 +131,7 @@ impl ParseLine for Parser { } if row.cells.len() > 0 { + log::trace!("Line::TableRow"); Ok(row) } else { return Err(self.ctm.rewind_with_error(start_index)); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d6eb1e6..46de6d6 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -3,6 +3,7 @@ pub(crate) mod inline; pub(crate) mod line; use self::block::ParseBlock; +use crate::elements::tokens::LB; use crate::elements::{Document, ImportAnchor}; use crate::references::configuration::keys::{ IMP_BIBLIOGRAPHY, IMP_CONFIGS, IMP_IGNORE, IMP_STYLESHEETS, @@ -10,7 +11,6 @@ use crate::references::configuration::keys::{ use crate::references::configuration::{Configuration, Value}; use bibliographix::bib_manager::BibManager; use charred::tapemachine::{CharTapeMachine, TapeError, TapeResult}; -use colored::*; use crossbeam_utils::sync::WaitGroup; use regex::Regex; use std::collections::HashMap; @@ -154,6 +154,25 @@ impl Parser { self.paths.lock().unwrap().clone() } + /// Returns a string of the current position in the file + pub(crate) fn get_position_string(&self) -> String { + let char_index = self.ctm.get_index(); + let text = self.ctm.get_text(); + let mut text_unil = text[..char_index].to_vec(); + let line_number = text_unil.iter().filter(|c| c == &&LB).count(); + text_unil.reverse(); + let mut inline_pos = 0; + + while text_unil[inline_pos] != LB { + inline_pos += 1; + } + if let Some(path) = &self.path { + format!("{}:{}:{}", path.to_str().unwrap(), line_number, inline_pos) + } else { + format!("{}:{}", line_number, inline_pos) + } + } + /// transform an import path to be relative to the current parsers file fn transform_path(&mut self, path: String) -> PathBuf { let mut path = PathBuf::from(path); @@ -172,27 +191,20 @@ impl Parser { /// starts up a new thread to parse the imported document fn import_document(&mut self, path: PathBuf) -> ParseResult>> { if !path.exists() || !path.is_file() { - println!( - "{}", - format!( - "Import of \"{}\" failed: The file doesn't exist.", - path.to_str().unwrap() - ) - .red() + log::error!( + "Import of \"{}\" failed: The file doesn't exist.\n\t--> {}\n", + path.to_str().unwrap(), + self.get_position_string(), ); - eprintln!("file {} does not exist", path.to_str().unwrap()); return Err(self.ctm.assert_error(None)); } { let mut paths = self.paths.lock().unwrap(); if paths.iter().find(|item| **item == path) != None { - eprintln!( - "{}", - format!( - "Import of \"{}\" failed: Cyclic import.", - path.to_str().unwrap() - ) - .yellow() + log::warn!( + "Import of \"{}\" failed: Cyclic import.\n\t--> {}\n", + path.to_str().unwrap(), + self.get_position_string(), ); return Err(self.ctm.assert_error(None)); } @@ -252,7 +264,20 @@ impl Parser { /// Imports a path fn import(&mut self, path: String, args: &HashMap) -> ImportType { + log::debug!( + "Importing file {}\n\t--> {}\n", + path, + self.get_position_string() + ); let path = self.transform_path(path); + if !path.exists() { + log::error!( + "Import of \"{}\" failed: The file doesn't exist.\n\t--> {}\n", + path.to_str().unwrap(), + self.get_position_string(), + ); + return ImportType::None; + } if let Some(fname) = path .file_name() .and_then(|f| Some(f.to_str().unwrap().to_string())) @@ -328,10 +353,12 @@ impl Parser { self.wg = WaitGroup::new(); if !self.is_child { for (path, file_type) in DEFAULT_IMPORTS { - self.import( - path.to_string(), - &maplit::hashmap! {"type".to_string() => Value::String(file_type.to_string())}, - ); + if PathBuf::from(path).exists() { + self.import( + path.to_string(), + &maplit::hashmap! {"type".to_string() => Value::String(file_type.to_string())}, + ); + } } } wg.wait();