Skip to content

Commit

Permalink
Use assets API from bat library instead of vendored code (#903)
Browse files Browse the repository at this point in the history
Use assets API from bat library

Fixes #895
Ref sharkdp/bat#2026
Thanks @Enselic
  • Loading branch information
dandavison committed Feb 27, 2022
1 parent e44435c commit 1403fe2
Show file tree
Hide file tree
Showing 12 changed files with 357 additions and 139 deletions.
324 changes: 316 additions & 8 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -15,6 +15,7 @@ name = "delta"
path = "src/main.rs"

[dependencies]
bat = "0.20.0"
chrono = "0.4.19"
chrono-humanize = "0.2.1"
ansi_colours = "1.0.4"
Expand Down
Binary file removed etc/assets/syntaxes.bin
Binary file not shown.
Binary file removed etc/assets/themes.bin
Binary file not shown.
5 changes: 3 additions & 2 deletions src/cli.rs
Expand Up @@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
use std::ffi::OsString;
use std::path::PathBuf;

use bat::assets::HighlightingAssets;
use clap::{AppSettings, ColorChoice, FromArgMatches, IntoApp, Parser};
use lazy_static::lazy_static;
use syntect::highlighting::Theme as SyntaxTheme;
Expand All @@ -10,7 +11,7 @@ use syntect::parsing::SyntaxSet;
use crate::config::delta_unreachable;
use crate::git_config::{GitConfig, GitConfigEntry};
use crate::options;
use crate::utils::bat::assets::HighlightingAssets;
use crate::utils;
use crate::utils::bat::output::PagingMode;

#[derive(Parser)]
Expand Down Expand Up @@ -1130,7 +1131,7 @@ impl Opt {
I: IntoIterator,
I::Item: Into<OsString> + Clone,
{
let assets = HighlightingAssets::new();
let assets = utils::bat::assets::load_highlighting_assets();
Self::from_clap_and_git_config(Self::into_app().get_matches_from(iter), git_config, assets)
}

Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Expand Up @@ -35,7 +35,7 @@ use std::process;
use bytelines::ByteLinesReader;

use crate::delta::delta;
use crate::utils::bat::assets::{list_languages, HighlightingAssets};
use crate::utils::bat::assets::list_languages;
use crate::utils::bat::output::OutputType;

pub fn fatal<T>(errmsg: T) -> !
Expand Down Expand Up @@ -85,7 +85,7 @@ fn main() -> std::io::Result<()> {
// report that two files differ when delta is called with two positional
// arguments and without standard input; 2 is used to report a real problem.
fn run_app() -> std::io::Result<i32> {
let assets = HighlightingAssets::new();
let assets = utils::bat::assets::load_highlighting_assets();
let opt = cli::Opt::from_args_and_git_config(git_config::GitConfig::try_create(), assets);

let subcommand_result = if opt.list_languages {
Expand Down
2 changes: 1 addition & 1 deletion src/options/set.rs
Expand Up @@ -3,6 +3,7 @@ use std::convert::TryInto;
use std::result::Result;
use std::str::FromStr;

use bat::assets::HighlightingAssets;
use console::Term;

use crate::cli;
Expand All @@ -14,7 +15,6 @@ use crate::features;
use crate::git_config::{GitConfig, GitConfigEntry};
use crate::options::option_value::{OptionValue, ProvenancedOptionValue};
use crate::options::theme;
use crate::utils::bat::assets::HighlightingAssets;
use crate::utils::bat::output::PagingMode;

macro_rules! set_options {
Expand Down
39 changes: 10 additions & 29 deletions src/options/theme.rs
Expand Up @@ -6,11 +6,11 @@
/// by the user, it is determined by the classification of the syntax theme into light-background
/// vs dark-background syntax themes. If the user didn't choose a syntax theme, a dark-background
/// default is selected.
use syntect::highlighting::ThemeSet;
use bat;
use bat::assets::HighlightingAssets;

use crate::cli;
use crate::env;
use crate::utils::bat::assets::HighlightingAssets;

#[allow(non_snake_case)]
pub fn set__is_light_mode__syntax_theme__syntax_set(
Expand All @@ -22,16 +22,15 @@ pub fn set__is_light_mode__syntax_theme__syntax_set(
opt.syntax_theme.as_ref(),
syntax_theme_name_from_bat_theme.as_ref(),
opt.light,
&assets.theme_set,
);
opt.computed.is_light_mode = is_light_mode;

opt.computed.syntax_theme = if is_no_syntax_highlighting_syntax_theme_name(&syntax_theme_name) {
None
} else {
Some(assets.theme_set.themes[&syntax_theme_name].clone())
Some(assets.get_theme(&syntax_theme_name).clone())
};
opt.computed.syntax_set = assets.syntax_set;
opt.computed.syntax_set = assets.get_syntax_set().unwrap().clone();
}

pub fn is_light_syntax_theme(theme: &str) -> bool {
Expand Down Expand Up @@ -86,34 +85,16 @@ fn get_is_light_mode_and_syntax_theme_name(
theme_arg: Option<&String>,
bat_theme_env_var: Option<&String>,
light_mode_arg: bool,
theme_set: &ThemeSet,
) -> (bool, String) {
let theme_arg = valid_syntax_theme_name_or_none(theme_arg, theme_set);
let bat_theme_env_var = valid_syntax_theme_name_or_none(bat_theme_env_var, theme_set);
match (theme_arg, bat_theme_env_var, light_mode_arg) {
(None, None, false) => (false, DEFAULT_DARK_SYNTAX_THEME.to_string()),
(Some(theme_name), _, false) => (is_light_syntax_theme(&theme_name), theme_name),
(None, Some(theme_name), false) => (is_light_syntax_theme(&theme_name), theme_name),
(None, None, true) => (true, DEFAULT_LIGHT_SYNTAX_THEME.to_string()),
(Some(theme_name), _, is_light_mode) => (is_light_mode, theme_name),
(None, Some(theme_name), is_light_mode) => (is_light_mode, theme_name),
}
}

// At this stage the theme name is considered valid if it is either a real theme name or the special
// no-syntax-highlighting name.
fn valid_syntax_theme_name_or_none(
theme_name: Option<&String>,
theme_set: &ThemeSet,
) -> Option<String> {
match theme_name {
Some(name)
if is_no_syntax_highlighting_syntax_theme_name(name)
|| theme_set.themes.contains_key(name) =>
{
Some(name.to_string())
(Some(theme_name), _, false) => (is_light_syntax_theme(theme_name), theme_name.to_string()),
(None, Some(theme_name), false) => {
(is_light_syntax_theme(theme_name), theme_name.to_string())
}
_ => None,
(None, None, true) => (true, DEFAULT_LIGHT_SYNTAX_THEME.to_string()),
(Some(theme_name), _, is_light_mode) => (is_light_mode, theme_name.to_string()),
(None, Some(theme_name), is_light_mode) => (is_light_mode, theme_name.to_string()),
}
}

Expand Down
18 changes: 6 additions & 12 deletions src/subcommands/list_syntax_themes.rs
Expand Up @@ -2,8 +2,7 @@ use std::io::{self, Write};

use itertools::Itertools;

use crate::options::theme::is_light_syntax_theme;
use crate::utils::bat::assets::HighlightingAssets;
use crate::{options::theme::is_light_syntax_theme, utils};

#[cfg(not(tarpaulin_include))]
pub fn list_syntax_themes() -> std::io::Result<()> {
Expand All @@ -17,15 +16,14 @@ pub fn list_syntax_themes() -> std::io::Result<()> {
}

pub fn _list_syntax_themes_for_humans(writer: &mut dyn Write) -> std::io::Result<()> {
let assets = HighlightingAssets::new();
let themes = &assets.theme_set.themes;
let assets = utils::bat::assets::load_highlighting_assets();

writeln!(writer, "Light syntax themes:")?;
for (theme, _) in themes.iter().filter(|(t, _)| is_light_syntax_theme(*t)) {
for theme in assets.themes().filter(|t| is_light_syntax_theme(*t)) {
writeln!(writer, " {}", theme)?;
}
writeln!(writer, "\nDark syntax themes:")?;
for (theme, _) in themes.iter().filter(|(t, _)| !is_light_syntax_theme(*t)) {
for theme in assets.themes().filter(|t| !is_light_syntax_theme(*t)) {
writeln!(writer, " {}", theme)?;
}
writeln!(
Expand All @@ -36,12 +34,8 @@ pub fn _list_syntax_themes_for_humans(writer: &mut dyn Write) -> std::io::Result
}

pub fn _list_syntax_themes_for_machines(writer: &mut dyn Write) -> std::io::Result<()> {
let assets = HighlightingAssets::new();
let themes = &assets.theme_set.themes;
for (theme, _) in themes
.iter()
.sorted_by_key(|(t, _)| is_light_syntax_theme(*t))
{
let assets = utils::bat::assets::load_highlighting_assets();
for theme in assets.themes().sorted_by_key(|t| is_light_syntax_theme(*t)) {
writeln!(
writer,
"{}\t{}",
Expand Down
5 changes: 2 additions & 3 deletions src/subcommands/show_colors.rs
Expand Up @@ -7,16 +7,15 @@ use crate::git_config;
use crate::paint;
use crate::paint::BgShouldFill;
use crate::style;
use crate::utils::bat::assets::HighlightingAssets;
use crate::utils::bat::output::{OutputType, PagingMode};

#[cfg(not(tarpaulin_include))]
pub fn show_colors() -> std::io::Result<()> {
use itertools::Itertools;

use crate::delta::DiffType;
use crate::{delta::DiffType, utils};

let assets = HighlightingAssets::new();
let assets = utils::bat::assets::load_highlighting_assets();
let opt = cli::Opt::from_args_and_git_config(git_config::GitConfig::try_create(), assets);
let config = config::Config::from(opt);

Expand Down
17 changes: 7 additions & 10 deletions src/subcommands/show_syntax_themes.rs
Expand Up @@ -2,14 +2,14 @@ use crate::cli;
use crate::config;
use crate::delta;
use crate::options::theme::is_light_syntax_theme;
use crate::utils::bat::assets::HighlightingAssets;
use crate::utils;
use crate::utils::bat::output::{OutputType, PagingMode};
use clap::Parser;
use std::io::{self, ErrorKind, Read, Write};

#[cfg(not(tarpaulin_include))]
pub fn show_syntax_themes() -> std::io::Result<()> {
let assets = HighlightingAssets::new();
let assets = utils::bat::assets::load_highlighting_assets();
let mut output_type = OutputType::from_mode(
PagingMode::QuitIfOneScreen,
None,
Expand All @@ -32,7 +32,7 @@ pub fn show_syntax_themes() -> std::io::Result<()> {

let make_opt = || {
let mut opt = cli::Opt::parse();
opt.computed.syntax_set = assets.syntax_set.clone();
opt.computed.syntax_set = assets.get_syntax_set().unwrap().clone();
opt
};
let opt = make_opt();
Expand Down Expand Up @@ -80,21 +80,18 @@ index f38589a..0f1bb83 100644
opt.computed.is_light_mode = is_light_mode;
let mut config = config::Config::from(opt);
let title_style = ansi_term::Style::new().bold();
let assets = HighlightingAssets::new();
let assets = utils::bat::assets::load_highlighting_assets();

for syntax_theme in assets
.theme_set
.themes
.iter()
.filter(|(t, _)| is_light_syntax_theme(t) == is_light_mode)
.map(|(t, _)| t)
.themes()
.filter(|t| is_light_syntax_theme(t) == is_light_mode)
{
writeln!(
writer,
"\n\nSyntax theme: {}\n",
title_style.paint(syntax_theme)
)?;
config.syntax_theme = Some(assets.theme_set.themes[syntax_theme.as_str()].clone());
config.syntax_theme = Some(assets.get_theme(syntax_theme).clone());
if let Err(error) =
delta::delta(ByteLines::new(BufReader::new(&input[0..])), writer, &config)
{
Expand Down
81 changes: 9 additions & 72 deletions src/utils/bat/assets.rs
@@ -1,87 +1,24 @@
// Based on code from https://github.com/sharkdp/bat a1b9334a44a2c652f52dddaa83dbacba57372468
// See src/utils/bat/LICENSE

use std::fs::File;
use std::io::{self, BufReader, Write};
use std::path::PathBuf;
use std::io::{self, Write};

use ansi_term::Colour::Green;
use ansi_term::Style;
use syntect::dumps::{from_binary, from_reader};
use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;
use bat;

use crate::errors::*;
use crate::utils::bat::dirs::PROJECT_DIRS;
use crate::utils;

pub struct HighlightingAssets {
pub syntax_set: SyntaxSet,
pub theme_set: ThemeSet,
}

impl HighlightingAssets {
pub fn new() -> Self {
Self::from_cache().unwrap_or_else(|_| Self::from_binary())
}

fn get_integrated_syntaxset() -> SyntaxSet {
from_binary(include_bytes!("../../../etc/assets/syntaxes.bin"))
}

fn get_integrated_themeset() -> ThemeSet {
from_binary(include_bytes!("../../../etc/assets/themes.bin"))
}

fn from_cache() -> Result<Self> {
let theme_set_path = theme_set_path();
let syntax_set_file = File::open(&syntax_set_path()).chain_err(|| {
format!(
"Could not load cached syntax set '{}'",
syntax_set_path().to_string_lossy()
)
})?;
let syntax_set: SyntaxSet = from_reader(BufReader::new(syntax_set_file))
.chain_err(|| "Could not parse cached syntax set")?;

let theme_set_file = File::open(&theme_set_path).chain_err(|| {
format!(
"Could not load cached theme set '{}'",
theme_set_path.to_string_lossy()
)
})?;
let theme_set: ThemeSet = from_reader(BufReader::new(theme_set_file))
.chain_err(|| "Could not parse cached theme set")?;

Ok(HighlightingAssets {
syntax_set,
theme_set,
})
}

fn from_binary() -> Self {
let syntax_set = Self::get_integrated_syntaxset();
let theme_set = Self::get_integrated_themeset();

HighlightingAssets {
syntax_set,
theme_set,
}
}
}

fn theme_set_path() -> PathBuf {
PROJECT_DIRS.cache_dir().join("themes.bin")
}

fn syntax_set_path() -> PathBuf {
PROJECT_DIRS.cache_dir().join("syntaxes.bin")
pub fn load_highlighting_assets() -> bat::assets::HighlightingAssets {
bat::assets::HighlightingAssets::from_cache(utils::bat::dirs::PROJECT_DIRS.cache_dir())
.unwrap_or_else(|_| bat::assets::HighlightingAssets::from_binary())
}

pub fn list_languages() -> std::io::Result<()> {
let assets = HighlightingAssets::new();
let assets = utils::bat::assets::load_highlighting_assets();
let mut languages = assets
.syntax_set
.syntaxes()
.get_syntaxes()
.unwrap()
.iter()
.filter(|syntax| !syntax.hidden && !syntax.file_extensions.is_empty())
.collect::<Vec<_>>();
Expand Down

0 comments on commit 1403fe2

Please sign in to comment.