use std::fs;
use std::io;
use argh::FromArgs;
use syntect::{easy, highlighting, parsing, util};
#[derive(FromArgs)]
struct Args {
#[argh(positional)]
input: String,
#[argh(positional)]
backend: String,
}
fn render<'a, 's, I>(backend: &str, strings: I)
where
's: 'a,
I: Iterator<Item = &'a text_style::StyledStr<'s>>,
{
match backend {
"ansi_term" => {
text_style::ansi_term::render_iter(io::stdout(), strings)
.expect("ansi_term rendering failed");
}
"crossterm" => {
text_style::crossterm::render_iter(io::stdout(), strings)
.expect("crossterm rendering failed");
}
"cursive" => {
use cursive::view::Scrollable as _;
let mut s = cursive::default();
let mut view = cursive::views::TextView::new("");
for s in strings {
view.append(s);
}
s.add_layer(view.scrollable());
s.add_global_callback('q', |s| s.quit());
s.run();
}
"termion" => {
text_style::termion::render_iter(io::stdout(), strings)
.expect("termion rendering failed");
}
"debug" => {
for s in strings {
println!("{:?}", s);
}
}
_ => {
panic!("Unsupported backend {}", backend);
}
}
}
fn main() {
let ps = parsing::SyntaxSet::load_defaults_newlines();
let ts = highlighting::ThemeSet::load_defaults();
let args: Args = argh::from_env();
let syntax = ps
.find_syntax_for_file(&args.input)
.expect("Could not read input file")
.unwrap_or_else(|| ps.find_syntax_plain_text());
let mut h = easy::HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
let s = fs::read_to_string(&args.input).expect("Could not read input file");
let mut lines = Vec::new();
for line in util::LinesWithEndings::from(&s) {
let ranges = h.highlight(line, &ps);
let styled_strs: Vec<text_style::StyledStr<'_>> =
ranges.into_iter().map(Into::into).collect();
lines.push(styled_strs);
}
render(&args.backend, lines.iter().flatten());
}