-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Switch to bat's themes, syntaxes
- Loading branch information
Showing
11 changed files
with
232 additions
and
19 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use super::*; | ||
|
||
use std::collections::BTreeMap; | ||
use std::convert::TryFrom; | ||
|
||
use serde::Deserialize; | ||
use serde::Serialize; | ||
|
||
use once_cell::unsync::OnceCell; | ||
|
||
use syntect::highlighting::{Theme, ThemeSet}; | ||
|
||
/// Same structure as a [`syntect::highlighting::ThemeSet`] but with themes | ||
/// stored in raw serialized form, and deserialized on demand. | ||
#[derive(Debug, Default, Serialize, Deserialize)] | ||
pub struct LazyThemeSet { | ||
/// This is a [`BTreeMap`] because that's what [`syntect::highlighting::ThemeSet`] uses | ||
themes: BTreeMap<String, LazyTheme>, | ||
} | ||
|
||
/// Stores raw serialized data for a theme with methods to lazily deserialize | ||
/// (load) the theme. | ||
#[derive(Debug, Serialize, Deserialize)] | ||
struct LazyTheme { | ||
serialized: Vec<u8>, | ||
|
||
#[serde(skip, default = "OnceCell::new")] | ||
deserialized: OnceCell<syntect::highlighting::Theme>, | ||
} | ||
|
||
impl LazyThemeSet { | ||
/// Lazily load the given theme | ||
pub fn get(&self, name: &str) -> Option<&Theme> { | ||
self.themes.get(name).and_then(|lazy_theme| { | ||
lazy_theme | ||
.deserialized | ||
.get_or_try_init(|| lazy_theme.deserialize()) | ||
.ok() | ||
}) | ||
} | ||
|
||
/// Returns the name of all themes. | ||
pub fn themes(&self) -> impl Iterator<Item = &str> { | ||
self.themes.keys().map(|name| name.as_ref()) | ||
} | ||
} | ||
|
||
impl LazyTheme { | ||
fn deserialize(&self) -> Result<Theme> { | ||
asset_from_contents( | ||
&self.serialized[..], | ||
"lazy-loaded theme", | ||
COMPRESS_LAZY_THEMES, | ||
) | ||
} | ||
} | ||
|
||
impl TryFrom<LazyThemeSet> for ThemeSet { | ||
type Error = Error; | ||
|
||
/// Since the user might want to add custom themes to bat, we need a way to | ||
/// convert from a `LazyThemeSet` to a regular [`ThemeSet`] so that more | ||
/// themes can be added. This function does that pretty straight-forward | ||
/// conversion. | ||
fn try_from(lazy_theme_set: LazyThemeSet) -> Result<Self> { | ||
let mut theme_set = ThemeSet::default(); | ||
|
||
for (name, lazy_theme) in lazy_theme_set.themes { | ||
theme_set.themes.insert(name, lazy_theme.deserialize()?); | ||
} | ||
|
||
Ok(theme_set) | ||
} | ||
} | ||
|
||
#[cfg(feature = "build-assets")] | ||
impl TryFrom<ThemeSet> for LazyThemeSet { | ||
type Error = Error; | ||
|
||
/// To collect themes, a [`ThemeSet`] is needed. Once all desired themes | ||
/// have been added, we need a way to convert that into [`LazyThemeSet`] so | ||
/// that themes can be lazy-loaded later. This function does that | ||
/// conversion. | ||
fn try_from(theme_set: ThemeSet) -> Result<Self> { | ||
let mut lazy_theme_set = LazyThemeSet::default(); | ||
|
||
for (name, theme) in theme_set.themes { | ||
// All we have to do is to serialize the theme | ||
let lazy_theme = LazyTheme { | ||
serialized: crate::assets::build_assets::asset_to_contents( | ||
&theme, | ||
&format!("theme {}", name), | ||
COMPRESS_LAZY_THEMES, | ||
)?, | ||
deserialized: OnceCell::new(), | ||
}; | ||
|
||
// Ok done, now we can add it | ||
lazy_theme_set.themes.insert(name, lazy_theme); | ||
} | ||
|
||
Ok(lazy_theme_set) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
mod lazy_theme_set; | ||
|
||
use anyhow::Error; | ||
use anyhow::Result; | ||
|
||
pub use lazy_theme_set::LazyThemeSet; | ||
|
||
pub fn load_themes() -> LazyThemeSet { | ||
get_integrated_themeset() | ||
} | ||
|
||
pub fn load_syntaxes() -> syntect::parsing::SyntaxSet { | ||
from_binary(get_serialized_integrated_syntaxset(), COMPRESS_SYNTAXES) | ||
} | ||
|
||
pub fn to_anstyle_color(color: syntect::highlighting::Color) -> Option<anstyle::Color> { | ||
if color.a == 0 { | ||
// Themes can specify one of the user-configurable terminal colors by | ||
// encoding them as #RRGGBBAA with AA set to 00 (transparent) and RR set | ||
// to the 8-bit color palette number. The built-in themes ansi, base16, | ||
// and base16-256 use this. | ||
Some(match color.r { | ||
// For the first 8 colors, use the Color enum to produce ANSI escape | ||
// sequences using codes 30-37 (foreground) and 40-47 (background). | ||
// For example, red foreground is \x1b[31m. This works on terminals | ||
// without 256-color support. | ||
0x00 => anstyle::AnsiColor::Black.into(), | ||
0x01 => anstyle::AnsiColor::Red.into(), | ||
0x02 => anstyle::AnsiColor::Green.into(), | ||
0x03 => anstyle::AnsiColor::Yellow.into(), | ||
0x04 => anstyle::AnsiColor::Blue.into(), | ||
0x05 => anstyle::AnsiColor::Magenta.into(), | ||
0x06 => anstyle::AnsiColor::Cyan.into(), | ||
0x07 => anstyle::AnsiColor::White.into(), | ||
// For all other colors, use Fixed to produce escape sequences using | ||
// codes 38;5 (foreground) and 48;5 (background). For example, | ||
// bright red foreground is \x1b[38;5;9m. This only works on | ||
// terminals with 256-color support. | ||
// | ||
// TODO: When ansi_term adds support for bright variants using codes | ||
// 90-97 (foreground) and 100-107 (background), we should use those | ||
// for values 0x08 to 0x0f and only use Fixed for 0x10 to 0xff. | ||
n => anstyle::XTermColor(n).into(), | ||
}) | ||
} else if color.a == 1 { | ||
// Themes can specify the terminal's default foreground/background color | ||
// (i.e. no escape sequence) using the encoding #RRGGBBAA with AA set to | ||
// 01. The built-in theme ansi uses this. | ||
None | ||
} else { | ||
Some(anstyle::RgbColor(color.r, color.g, color.b).into()) | ||
} | ||
} | ||
|
||
/// Lazy-loaded syntaxes are already compressed, and we don't want to compress | ||
/// already compressed data. | ||
const COMPRESS_SYNTAXES: bool = false; | ||
|
||
/// We don't want to compress our [LazyThemeSet] since the lazy-loaded themes | ||
/// within it are already compressed, and compressing another time just makes | ||
/// performance suffer | ||
const COMPRESS_THEMES: bool = false; | ||
|
||
/// Compress for size of ~40 kB instead of ~200 kB without much difference in | ||
/// performance due to lazy-loading | ||
const COMPRESS_LAZY_THEMES: bool = true; | ||
|
||
/// Compress for size of ~10 kB instead of ~120 kB | ||
const COMPRESS_ACKNOWLEDGEMENTS: bool = true; | ||
|
||
fn get_serialized_integrated_syntaxset() -> &'static [u8] { | ||
include_bytes!("../../assets/syntaxes.bin") | ||
} | ||
|
||
fn get_integrated_themeset() -> LazyThemeSet { | ||
from_binary(include_bytes!("../../assets/themes.bin"), COMPRESS_THEMES) | ||
} | ||
|
||
pub fn get_acknowledgements() -> String { | ||
from_binary( | ||
include_bytes!("../../assets/acknowledgements.bin"), | ||
COMPRESS_ACKNOWLEDGEMENTS, | ||
) | ||
} | ||
|
||
fn from_binary<T: serde::de::DeserializeOwned>(v: &[u8], compressed: bool) -> T { | ||
asset_from_contents(v, "n/a", compressed) | ||
.expect("data integrated in binary is never faulty, but make sure `compressed` is in sync!") | ||
} | ||
|
||
fn asset_from_contents<T: serde::de::DeserializeOwned>( | ||
contents: &[u8], | ||
description: &str, | ||
compressed: bool, | ||
) -> Result<T, anyhow::Error> { | ||
if compressed { | ||
bincode::deserialize_from(flate2::read::ZlibDecoder::new(contents)) | ||
} else { | ||
bincode::deserialize_from(contents) | ||
} | ||
.map_err(|_| anyhow::format_err!("Could not parse {}", description)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters