Skip to content
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
70 changes: 24 additions & 46 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Binary file added assets/syntaxes.bin
Binary file not shown.
File renamed without changes.
47 changes: 15 additions & 32 deletions src/render/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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();
Expand Down Expand Up @@ -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))
}
}

Expand All @@ -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<String> {
if !line.starts_with("```") {
return None;
Expand All @@ -148,3 +125,9 @@ fn detect_code_block(line: &str) -> Option<String> {
.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());
}
21 changes: 13 additions & 8 deletions src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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!(
Expand Down