Add --no-syntax-highlight and --theme options

This patch adds two new command-line options for the rich text viewer:
--no-syntax-highlight and --theme.  --no-syntax-highlight disables the
syntax highlighting for code snippets.  --theme selects a color theme
for the syntax highlighting.
This commit is contained in:
Robin Krahl 2020-08-10 21:46:23 +02:00
parent a37d7e0d6a
commit c48711f3cf
No known key found for this signature in database
GPG Key ID: 8E9B0870524F69D8
5 changed files with 48 additions and 20 deletions

View File

@ -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)

View File

@ -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();

View File

@ -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<Self>;
fn print_title(&self, left: &str, middle: &str, right: &str) -> io::Result<()>;
@ -48,7 +48,7 @@ impl<P: Printer> TextViewer<P> {
{
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)
}

View File

@ -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<Self> {
Ok(Self {
line_length: viewer::get_line_length(),
}
})
}
fn print_title(&self, left: &str, middle: &str, right: &str) -> io::Result<()> {

View File

@ -13,8 +13,9 @@ type RichString = text_renderer::TaggedString<Vec<text_renderer::RichAnnotation>
#[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<Self> {
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(())
}