diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c1bc1e..c4f6c74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ SPDX-License-Identifier: MIT - Add syntax highlighting: - Add syntax highlighting using `syntect` for code snippets displayed with the rich text viewer. + - Add the `--no-syntax-highlight` option to disable syntax highlighting. + - Add the `--theme [theme]` option to select the syntax highlighting theme. ## v0.1.3 (2020-07-28) diff --git a/src/main.rs b/src/main.rs index aa25ece..2e53edf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -99,7 +99,21 @@ struct Opt { } #[derive(Debug, StructOpt)] -pub struct ViewerArgs {} +pub struct ViewerArgs { + /// Disable syntax highlighting. + /// + /// Per default, rusty-man tries to highlight Rust code snippets in its output if the rich text + /// viewer is selected. If this option is set, it renders the HTML representation instead. + #[structopt(long)] + no_syntax_highlight: bool, + + /// The color theme for syntax highlighting + /// + /// rusty-man includes these color themes: base16-ocean.dark, base16-eighties.dark, + /// base16-mocha.dark, base16-ocean.light, InspiredGitHub, Solarized (dark), Solarized (light). + #[structopt(long, default_value = "base16-eighties.dark")] + theme: String, +} fn main() -> anyhow::Result<()> { env_logger::init(); diff --git a/src/viewer/text/mod.rs b/src/viewer/text/mod.rs index 5174cf8..187b9b9 100644 --- a/src/viewer/text/mod.rs +++ b/src/viewer/text/mod.rs @@ -11,8 +11,8 @@ use std::marker; use crate::doc; use crate::viewer; -pub trait Printer: fmt::Debug { - fn new(args: crate::ViewerArgs) -> Self; +pub trait Printer: fmt::Debug + marker::Sized { + fn new(args: crate::ViewerArgs) -> anyhow::Result; fn print_title(&self, left: &str, middle: &str, right: &str) -> io::Result<()>; @@ -48,7 +48,7 @@ impl TextViewer

{ { spawn_pager(); - let printer = P::new(args); + let printer = P::new(args)?; let renderer = TextRenderer::new(printer); op(&renderer).or_else(ignore_pipe_error).map_err(Into::into) } diff --git a/src/viewer/text/plain.rs b/src/viewer/text/plain.rs index 37d39f0..79c232d 100644 --- a/src/viewer/text/plain.rs +++ b/src/viewer/text/plain.rs @@ -20,10 +20,10 @@ struct Decorator { } impl super::Printer for PlainTextRenderer { - fn new(_args: crate::ViewerArgs) -> Self { - Self { + fn new(_args: crate::ViewerArgs) -> anyhow::Result { + Ok(Self { line_length: viewer::get_line_length(), - } + }) } fn print_title(&self, left: &str, middle: &str, right: &str) -> io::Result<()> { diff --git a/src/viewer/text/rich.rs b/src/viewer/text/rich.rs index 3e5778e..a5de47f 100644 --- a/src/viewer/text/rich.rs +++ b/src/viewer/text/rich.rs @@ -13,8 +13,9 @@ type RichString = text_renderer::TaggedString #[derive(Debug)] pub struct RichTextRenderer { line_length: usize, + highlight: bool, syntax_set: syntect::parsing::SyntaxSet, - theme_set: syntect::highlighting::ThemeSet, + theme: syntect::highlighting::Theme, } impl RichTextRenderer { @@ -53,12 +54,20 @@ impl RichTextRenderer { } impl super::Printer for RichTextRenderer { - fn new(_args: crate::ViewerArgs) -> Self { - Self { + fn new(args: crate::ViewerArgs) -> anyhow::Result { + use anyhow::Context; + + let mut theme_set = syntect::highlighting::ThemeSet::load_defaults(); + let theme = theme_set + .themes + .remove(&args.theme) + .with_context(|| format!("Could not find theme {}", &args.theme))?; + Ok(Self { line_length: viewer::get_line_length(), + highlight: !args.no_syntax_highlight, syntax_set: syntect::parsing::SyntaxSet::load_defaults_newlines(), - theme_set: syntect::highlighting::ThemeSet::load_defaults(), - } + theme, + }) } fn print_title(&self, left: &str, middle: &str, right: &str) -> io::Result<()> { @@ -87,16 +96,19 @@ impl super::Printer for RichTextRenderer { } fn print_code(&self, indent: usize, code: &doc::Text) -> io::Result<()> { - let syntax = self.syntax_set.find_syntax_by_extension("rs").unwrap(); - let theme = &self.theme_set.themes["base16-eighties.dark"]; - let mut h = syntect::easy::HighlightLines::new(syntax, theme); + if self.highlight { + let syntax = self.syntax_set.find_syntax_by_extension("rs").unwrap(); + let mut h = syntect::easy::HighlightLines::new(syntax, &self.theme); - for line in syntect::util::LinesWithEndings::from(&code.plain) { - let ranges = h.highlight(line, &self.syntax_set); - write!(io::stdout(), "{}", " ".repeat(indent))?; - self.render_syntax(&ranges)?; + for line in syntect::util::LinesWithEndings::from(&code.plain) { + let ranges = h.highlight(line, &self.syntax_set); + write!(io::stdout(), "{}", " ".repeat(indent))?; + self.render_syntax(&ranges)?; + } + writeln!(io::stdout())?; + } else { + self.print_html(indent, code, false)?; } - writeln!(io::stdout())?; Ok(()) }