1
0
mirror of https://github.com/sharkdp/bat.git synced 2025-02-22 21:08:40 +00:00

Major restructuring of theme/syntax handling

This commit is contained in:
sharkdp 2020-03-21 16:48:27 +01:00 committed by David Peter
parent b1b8addf7e
commit 06b7be7ee9
10 changed files with 84 additions and 72 deletions

View File

@ -29,7 +29,7 @@ fn main() {
theme: "1337".into(), theme: "1337".into(),
..Default::default() ..Default::default()
}; };
let assets = HighlightingAssets::new(); let assets = HighlightingAssets::from_binary();
Controller::new(&config, &assets).run().expect("no errors"); Controller::new(&config, &assets).run().expect("no errors");
} }

View File

@ -1,15 +1,12 @@
use std::borrow::Cow;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::BufReader; use std::io::BufReader;
use std::path::{Path, PathBuf}; use std::path::Path;
use syntect::dumps::{dump_to_file, from_binary, from_reader}; use syntect::dumps::{dump_to_file, from_binary, from_reader};
use syntect::highlighting::{Theme, ThemeSet}; use syntect::highlighting::{Theme, ThemeSet};
use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder}; use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder};
use crate::dirs::PROJECT_DIRS;
use crate::errors::*; use crate::errors::*;
use crate::inputfile::{InputFile, InputFileReader}; use crate::inputfile::{InputFile, InputFileReader};
use crate::syntax_mapping::SyntaxMapping; use crate::syntax_mapping::SyntaxMapping;
@ -23,13 +20,7 @@ pub struct HighlightingAssets {
} }
impl HighlightingAssets { impl HighlightingAssets {
pub fn new() -> Self { pub fn from_files(source_dir: &Path, start_empty: bool) -> Result<Self> {
Self::from_cache().unwrap_or_else(|_| Self::from_binary())
}
pub fn from_files(dir: Option<&Path>, start_empty: bool) -> Result<Self> {
let source_dir = dir.unwrap_or_else(|| PROJECT_DIRS.config_dir());
let mut theme_set = if start_empty { let mut theme_set = if start_empty {
ThemeSet { ThemeSet {
themes: BTreeMap::new(), themes: BTreeMap::new(),
@ -72,12 +63,11 @@ impl HighlightingAssets {
}) })
} }
fn from_cache() -> Result<Self> { pub fn from_cache(theme_set_path: &Path, syntax_set_path: &Path) -> Result<Self> {
let theme_set_path = theme_set_path(); let syntax_set_file = File::open(syntax_set_path).chain_err(|| {
let syntax_set_file = File::open(&syntax_set_path()).chain_err(|| {
format!( format!(
"Could not load cached syntax set '{}'", "Could not load cached syntax set '{}'",
syntax_set_path().to_string_lossy() syntax_set_path.to_string_lossy()
) )
})?; })?;
let syntax_set: SyntaxSet = from_reader(BufReader::new(syntax_set_file)) let syntax_set: SyntaxSet = from_reader(BufReader::new(syntax_set_file))
@ -106,7 +96,7 @@ impl HighlightingAssets {
from_binary(include_bytes!("../assets/themes.bin")) from_binary(include_bytes!("../assets/themes.bin"))
} }
fn from_binary() -> Self { pub fn from_binary() -> Self {
let syntax_set = Self::get_integrated_syntaxset(); let syntax_set = Self::get_integrated_syntaxset();
let theme_set = Self::get_integrated_themeset(); let theme_set = Self::get_integrated_themeset();
@ -116,8 +106,7 @@ impl HighlightingAssets {
} }
} }
pub fn save(&self, dir: Option<&Path>) -> Result<()> { pub fn save(&self, target_dir: &Path) -> Result<()> {
let target_dir = dir.unwrap_or_else(|| PROJECT_DIRS.cache_dir());
let _ = fs::create_dir_all(target_dir); let _ = fs::create_dir_all(target_dir);
let theme_set_path = target_dir.join("themes.bin"); let theme_set_path = target_dir.join("themes.bin");
let syntax_set_path = target_dir.join("syntaxes.bin"); let syntax_set_path = target_dir.join("syntaxes.bin");
@ -204,29 +193,3 @@ impl HighlightingAssets {
syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text()) syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text())
} }
} }
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 config_dir() -> Cow<'static, str> {
PROJECT_DIRS.config_dir().to_string_lossy()
}
pub fn cache_dir() -> Cow<'static, str> {
PROJECT_DIRS.cache_dir().to_string_lossy()
}
pub fn clear_assets() {
print!("Clearing theme set cache ... ");
fs::remove_file(theme_set_path()).ok();
println!("okay");
print!("Clearing syntax set cache ... ");
fs::remove_file(syntax_set_path()).ok();
println!("okay");
}

37
src/bin/bat/assets.rs Normal file
View File

@ -0,0 +1,37 @@
use std::borrow::Cow;
use std::fs;
use std::path::PathBuf;
use crate::directories::PROJECT_DIRS;
use bat::assets::HighlightingAssets;
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 config_dir() -> Cow<'static, str> {
PROJECT_DIRS.config_dir().to_string_lossy()
}
pub fn cache_dir() -> Cow<'static, str> {
PROJECT_DIRS.cache_dir().to_string_lossy()
}
pub fn clear_assets() {
print!("Clearing theme set cache ... ");
fs::remove_file(theme_set_path()).ok();
println!("okay");
print!("Clearing syntax set cache ... ");
fs::remove_file(syntax_set_path()).ok();
println!("okay");
}
pub fn assets_from_cache_or_binary() -> HighlightingAssets {
HighlightingAssets::from_cache(&theme_set_path(), &syntax_set_path()).unwrap_or(HighlightingAssets::from_binary())
}

View File

@ -5,7 +5,7 @@ use std::path::PathBuf;
use shell_words; use shell_words;
use bat::dirs::PROJECT_DIRS; use crate::directories::PROJECT_DIRS;
pub fn config_file() -> PathBuf { pub fn config_file() -> PathBuf {
env::var("BAT_CONFIG_PATH") env::var("BAT_CONFIG_PATH")

View File

@ -1,7 +1,9 @@
use crate::dirs_rs;
use std::env; use std::env;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use dirs;
use lazy_static::lazy_static;
/// Wrapper for 'dirs' that treats MacOS more like Linux, by following the XDG specification. /// Wrapper for 'dirs' that treats MacOS more like Linux, by following the XDG specification.
/// This means that the `XDG_CACHE_HOME` and `XDG_CONFIG_HOME` environment variables are /// This means that the `XDG_CACHE_HOME` and `XDG_CONFIG_HOME` environment variables are
/// checked first. The fallback directories are `~/.cache/bat` and `~/.config/bat`, respectively. /// checked first. The fallback directories are `~/.cache/bat` and `~/.config/bat`, respectively.
@ -18,10 +20,10 @@ impl BatProjectDirs {
let config_dir_op = env::var_os("XDG_CONFIG_HOME") let config_dir_op = env::var_os("XDG_CONFIG_HOME")
.map(PathBuf::from) .map(PathBuf::from)
.filter(|p| p.is_absolute()) .filter(|p| p.is_absolute())
.or_else(|| dirs_rs::home_dir().map(|d| d.join(".config"))); .or_else(|| dirs::home_dir().map(|d| d.join(".config")));
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
let config_dir_op = dirs_rs::config_dir(); let config_dir_op = dirs::config_dir();
let config_dir = config_dir_op.map(|d| d.join("bat"))?; let config_dir = config_dir_op.map(|d| d.join("bat"))?;
@ -42,10 +44,10 @@ impl BatProjectDirs {
let cache_dir_op = env::var_os("XDG_CACHE_HOME") let cache_dir_op = env::var_os("XDG_CACHE_HOME")
.map(PathBuf::from) .map(PathBuf::from)
.filter(|p| p.is_absolute()) .filter(|p| p.is_absolute())
.or_else(|| dirs_rs::home_dir().map(|d| d.join(".cache"))); .or_else(|| dirs::home_dir().map(|d| d.join(".cache")));
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
let cache_dir_op = dirs_rs::cache_dir(); let cache_dir_op = dirs::cache_dir();
cache_dir_op.map(|d| d.join("bat")) cache_dir_op.map(|d| d.join("bat"))
} }

View File

@ -4,9 +4,13 @@
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;
extern crate dirs as dirs_rs;
mod app; mod app;
mod clap_app; mod clap_app;
mod config; mod config;
mod directories;
mod assets;
use std::collections::HashSet; use std::collections::HashSet;
use std::ffi::OsStr; use std::ffi::OsStr;
@ -19,10 +23,12 @@ use ansi_term::Colour::Green;
use ansi_term::Style; use ansi_term::Style;
use crate::{app::App, config::config_file}; use crate::{app::App, config::config_file};
use directories::PROJECT_DIRS;
use assets::{cache_dir, clear_assets, config_dir, assets_from_cache_or_binary};
use bat::controller::Controller; use bat::controller::Controller;
use bat::{ use bat::{
assets::{cache_dir, clear_assets, config_dir, HighlightingAssets}, assets::HighlightingAssets,
errors::*, errors::*,
inputfile::InputFile, inputfile::InputFile,
style::{OutputComponent, OutputComponents}, style::{OutputComponent, OutputComponents},
@ -31,8 +37,8 @@ use bat::{
fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> { fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
if matches.is_present("build") { if matches.is_present("build") {
let source_dir = matches.value_of("source").map(Path::new); let source_dir = matches.value_of("source").map(Path::new).unwrap_or_else(|| PROJECT_DIRS.config_dir());
let target_dir = matches.value_of("target").map(Path::new); let target_dir = matches.value_of("target").map(Path::new).unwrap_or_else(|| PROJECT_DIRS.cache_dir());
let blank = matches.is_present("blank"); let blank = matches.is_present("blank");
@ -46,7 +52,7 @@ fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
} }
pub fn list_languages(config: &Config) -> Result<()> { pub fn list_languages(config: &Config) -> Result<()> {
let assets = HighlightingAssets::new(); let assets = assets_from_cache_or_binary();
let mut languages = assets let mut languages = assets
.syntax_set .syntax_set
.syntaxes() .syntaxes()
@ -109,7 +115,7 @@ pub fn list_languages(config: &Config) -> Result<()> {
} }
pub fn list_themes(cfg: &Config) -> Result<()> { pub fn list_themes(cfg: &Config) -> Result<()> {
let assets = HighlightingAssets::new(); let assets = assets_from_cache_or_binary();
let themes = &assets.theme_set.themes; let themes = &assets.theme_set.themes;
let mut config = cfg.clone(); let mut config = cfg.clone();
let mut style = HashSet::new(); let mut style = HashSet::new();
@ -141,7 +147,7 @@ pub fn list_themes(cfg: &Config) -> Result<()> {
} }
fn run_controller(config: &Config) -> Result<bool> { fn run_controller(config: &Config) -> Result<bool> {
let assets = HighlightingAssets::new(); let assets = assets_from_cache_or_binary();
let controller = Controller::new(&config, &assets); let controller = Controller::new(&config, &assets);
controller.run() controller.run()
} }

View File

@ -4,9 +4,6 @@
#[macro_use] #[macro_use]
extern crate error_chain; extern crate error_chain;
#[macro_use]
extern crate lazy_static;
extern crate ansi_term; extern crate ansi_term;
extern crate atty; extern crate atty;
extern crate console; extern crate console;
@ -22,7 +19,6 @@ pub mod assets;
pub mod controller; pub mod controller;
mod decorations; mod decorations;
mod diff; mod diff;
pub mod dirs;
pub mod inputfile; pub mod inputfile;
mod less; mod less;
pub mod line_range; pub mod line_range;

View File

@ -6,20 +6,22 @@ pub struct LineRange {
pub upper: usize, pub upper: usize,
} }
impl LineRange { impl Default for LineRange {
pub fn from(range_raw: &str) -> Result<LineRange> { fn default() -> LineRange {
LineRange::parse_range(range_raw)
}
pub fn new() -> LineRange {
LineRange { LineRange {
lower: usize::min_value(), lower: usize::min_value(),
upper: usize::max_value(), upper: usize::max_value(),
} }
} }
}
impl LineRange {
pub fn from(range_raw: &str) -> Result<LineRange> {
LineRange::parse_range(range_raw)
}
pub fn parse_range(range_raw: &str) -> Result<LineRange> { pub fn parse_range(range_raw: &str) -> Result<LineRange> {
let mut new_range = LineRange::new(); let mut new_range = LineRange::default();
if range_raw.bytes().nth(0).ok_or("Empty line range")? == b':' { if range_raw.bytes().nth(0).ok_or("Empty line range")? == b':' {
new_range.upper = range_raw[1..].parse()?; new_range.upper = range_raw[1..].parse()?;
@ -103,12 +105,18 @@ pub enum RangeCheckResult {
AfterLastRange, AfterLastRange,
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone)]
pub struct LineRanges { pub struct LineRanges {
ranges: Vec<LineRange>, ranges: Vec<LineRange>,
largest_upper_bound: usize, largest_upper_bound: usize,
} }
impl Default for LineRanges {
fn default() -> Self {
LineRanges::from(vec![LineRange { lower: 0, upper: 0 }])
}
}
impl LineRanges { impl LineRanges {
pub fn from(ranges: Vec<LineRange>) -> LineRanges { pub fn from(ranges: Vec<LineRange>) -> LineRanges {
let largest_upper_bound = ranges let largest_upper_bound = ranges

View File

@ -19,7 +19,7 @@ fn no_duplicate_extensions() {
"sass", "sass",
]; ];
let assets = HighlightingAssets::new(); let assets = HighlightingAssets::from_binary();
let mut extensions = HashSet::new(); let mut extensions = HashSet::new();

View File

@ -18,7 +18,7 @@ struct SyntaxDetectionTest {
impl SyntaxDetectionTest { impl SyntaxDetectionTest {
fn new() -> Self { fn new() -> Self {
SyntaxDetectionTest { SyntaxDetectionTest {
assets: HighlightingAssets::new(), assets: HighlightingAssets::from_binary(),
syntax_mapping: SyntaxMapping::new(), syntax_mapping: SyntaxMapping::new(),
temp_dir: TempDir::new("bat_syntax_detection_tests") temp_dir: TempDir::new("bat_syntax_detection_tests")
.expect("creation of temporary directory"), .expect("creation of temporary directory"),