diff --git a/Cargo.lock b/Cargo.lock index b5422ca..eedf019 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,21 +8,13 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - [[package]] name = "aichat" version = "0.4.0" dependencies = [ "anyhow", "atty", + "bincode", "bytes", "chrono", "clap", @@ -97,21 +89,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" version = "1.3.2" @@ -506,16 +483,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "fancy-regex" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6b8560a05112eb52f04b00e5d3790c0dd75d9d980eb8a122fb23b92a623ccf" -dependencies = [ - "bit-set", - "regex", -] - [[package]] name = "fd-lock" version = "3.0.10" @@ -1114,6 +1081,28 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "onig" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +dependencies = [ + "bitflags", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "os_str_bytes" version = "6.4.1" @@ -1255,17 +1244,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "regex" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - [[package]] name = "regex-syntax" version = "0.6.28" @@ -1611,11 +1589,11 @@ checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8" dependencies = [ "bincode", "bitflags", - "fancy-regex", "flate2", "fnv", "lazy_static", "once_cell", + "onig", "regex-syntax", "serde", "serde_derive", diff --git a/Cargo.toml b/Cargo.toml index 216e8cb..731bbfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,11 +31,12 @@ copypasta = "0.8.2" chrono = "0.4.23" atty = "0.2.14" unicode-width = "0.1.10" +bincode = "1.3.3" [dependencies.syntect] version = "5.0.0" default-features = false -features = ["parsing", "regex-fancy", "default-syntaxes"] +features = ["parsing", "regex-onig"] [profile.release] lto = true diff --git a/assets/syntaxes.bin b/assets/syntaxes.bin new file mode 100644 index 0000000..df582f5 Binary files /dev/null and b/assets/syntaxes.bin differ diff --git a/src/render/theme.yaml b/assets/theme.yaml similarity index 100% rename from src/render/theme.yaml rename to assets/theme.yaml diff --git a/src/render/markdown.rs b/src/render/markdown.rs index fc0bc3e..5316653 100644 --- a/src/render/markdown.rs +++ b/src/render/markdown.rs @@ -3,7 +3,10 @@ use syntect::parsing::SyntaxSet; use syntect::util::as_24_bit_terminal_escaped; use syntect::{easy::HighlightLines, parsing::SyntaxReference}; -const THEME: &[u8] = include_bytes!("theme.yaml"); +/// Comms from https://github.com/jonschlinkert/sublime-monokai-extended/tree/0ca4e75291515c4d47e2d455e598e03e0dc53745 +const THEME: &[u8] = include_bytes!("../../assets/theme.yaml"); +/// Comes from https://github.com/sharkdp/bat/raw/5e77ca37e89c873e4490b42ff556370dc5c6ba4f/assets/syntaxes.bin +const SYNTAXES: &[u8] = include_bytes!("../../assets/syntaxes.bin"); pub struct MarkdownRender { syntax_set: SyntaxSet, @@ -16,7 +19,8 @@ pub struct MarkdownRender { impl MarkdownRender { pub fn new() -> Self { - let syntax_set = SyntaxSet::load_defaults_newlines(); + let syntax_set: SyntaxSet = + bincode::deserialize_from(SYNTAXES).expect("invalid syntaxes.bin"); let theme: Theme = serde_yaml::from_slice(THEME).unwrap(); let md_syntax = syntax_set.find_syntax_by_extension("md").unwrap().clone(); let txt_syntax = syntax_set.find_syntax_by_extension("txt").unwrap().clone(); @@ -96,12 +100,9 @@ impl MarkdownRender { } fn find_syntax(&self, lang: &str) -> Option<&SyntaxReference> { - self.syntax_set.find_syntax_by_extension(lang).or_else(|| { - LANGEGUATE_NAME_EXTS - .iter() - .find(|(name, _)| *name == lang.to_lowercase()) - .and_then(|(_, ext)| self.syntax_set.find_syntax_by_extension(ext)) - }) + self.syntax_set + .find_syntax_by_token(lang) + .or_else(|| self.syntax_set.find_syntax_by_extension(lang)) } } @@ -113,30 +114,6 @@ enum LineType { CodeEnd, } -const LANGEGUATE_NAME_EXTS: [(&str, &str); 21] = [ - ("asp", "asa"), - ("actionscript", "as"), - ("c#", "cs"), - ("clojure", "clj"), - ("erlang", "erl"), - ("haskell", "hs"), - ("javascript", "js"), - ("bibtex", "bib"), - ("latex", "tex"), - ("tex", "sty"), - ("ocaml", "ml"), - ("ocamllex", "mll"), - ("ocamlyacc", "mly"), - ("objective-c++", "mm"), - ("objective-c", "m"), - ("pascal", "pas"), - ("perl", "pl"), - ("python", "py"), - ("restructuredtext", "rst"), - ("ruby", "rb"), - ("rust", "rs"), -]; - fn detect_code_block(line: &str) -> Option { if !line.starts_with("```") { return None; @@ -148,3 +125,9 @@ fn detect_code_block(line: &str) -> Option { .collect(); Some(lang) } + +#[test] +fn feature() { + let syntax_set: SyntaxSet = bincode::deserialize_from(SYNTAXES).expect("invalid syntaxes.bin"); + assert!(syntax_set.find_syntax_by_extension("md").is_some()); +} diff --git a/src/render/mod.rs b/src/render/mod.rs index b6e28f7..e0f42e7 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -36,7 +36,7 @@ pub fn render_stream_inner( writer: &mut Stdout, ) -> Result<()> { let mut last_tick = Instant::now(); - let tick_rate = Duration::from_millis(200); + let tick_rate = Duration::from_millis(100); let mut buffer = String::new(); let mut markdown_render = MarkdownRender::new(); let terminal_columns = terminal::size()?.0; @@ -55,12 +55,15 @@ pub fn render_stream_inner( let mut lines: Vec<&str> = text.split('\n').collect(); buffer = lines.pop().unwrap_or_default().to_string(); let output = markdown_render.render(&lines.join("\n")); - queue!( - writer, - style::Print(output), - style::Print("\n"), - style::Print(&buffer), - )?; + for line in output.split('\n') { + queue!( + writer, + style::Print(line), + style::Print("\n"), + cursor::MoveLeft(terminal_columns), + )?; + } + queue!(writer, style::Print(&buffer),)?; } else { buffer = format!("{buffer}{text}"); let output = markdown_render.render_line_stateless(&buffer); @@ -107,7 +110,9 @@ pub fn render_stream_inner( fn recover_cursor(writer: &mut Stdout, terminal_columns: u16, buffer: &str) -> Result<()> { let buffer_rows = (buffer.width() as u16 + terminal_columns - 1) / terminal_columns; let (_, row) = cursor::position()?; - if row + 1 >= buffer_rows { + if buffer_rows == 0 { + queue!(writer, cursor::MoveTo(0, row))?; + } else if row + 1 >= buffer_rows { queue!(writer, cursor::MoveTo(0, row + 1 - buffer_rows))?; } else { queue!(