Skip to content

Commit

Permalink
Load custom bat theme assets
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Oct 24, 2024
1 parent 497a5a9 commit 4deda48
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,6 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/install@cargo-outdated
- run: cargo tree --package bat --depth 0 | grep "^bat v$(cat src/bat.version)$"
- run: cargo update
- run: cargo outdated --workspace --exit-code 1
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ bat = { version = "0.24", default-features = false, features = ["paging", "regex
cargo-subcommand-metadata = "0.1"
clap = { version = "4", features = ["deprecated", "derive"] }
console = "0.15"
etcetera = "0.8"
fs-err = "3"
home = "0.5"
prettyplease = { version = "0.2.25", features = ["verbatim"] }
proc-macro2 = "1.0.80"
quote = { version = "1.0.35", default-features = false }
semver = "1"
serde = { version = "1.0.183", features = ["derive"] }
shlex = "1.3"
syn = { version = "2.0.85", default-features = false, features = ["clone-impls", "fold", "full", "parsing", "printing", "visit-mut"] }
Expand Down
26 changes: 26 additions & 0 deletions src/assets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::error::Result;
use etcetera::BaseStrategy as _;
use std::env;
use std::path::PathBuf;
use std::str;

pub const BAT_VERSION: &str = {
let mut bytes = include_str!("bat.version").as_bytes();
while let [rest @ .., b'\n' | b'\r'] = bytes {
bytes = rest;
}
if let Ok(version) = str::from_utf8(bytes) {
version
} else {
panic!()
}
};

pub fn cache_dir() -> Result<PathBuf> {
if let Some(cache_dir) = env::var_os("BAT_CACHE_PATH") {
return Ok(PathBuf::from(cache_dir));
}

let basedirs = etcetera::choose_base_strategy()?;
Ok(basedirs.cache_dir().join("bat"))
}
1 change: 1 addition & 0 deletions src/bat.version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.24.0
18 changes: 18 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub enum Error {
TomlSer(toml::ser::Error),
TomlDe(toml::de::Error),
Quote(shlex::QuoteError),
HomeDir(etcetera::HomeDirError),
Bat(bat::error::Error),
}

pub type Result<T> = std::result::Result<T, Error>;
Expand Down Expand Up @@ -36,13 +38,27 @@ impl From<shlex::QuoteError> for Error {
}
}

impl From<etcetera::HomeDirError> for Error {
fn from(error: etcetera::HomeDirError) -> Self {
Error::HomeDir(error)
}
}

impl From<bat::error::Error> for Error {
fn from(error: bat::error::Error) -> Self {
Error::Bat(error)
}
}

impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Io(e) => e.fmt(formatter),
Error::TomlSer(e) => e.fmt(formatter),
Error::TomlDe(e) => e.fmt(formatter),
Error::Quote(e) => e.fmt(formatter),
Error::HomeDir(e) => e.fmt(formatter),
Error::Bat(e) => e.fmt(formatter),
}
}
}
Expand All @@ -54,6 +70,8 @@ impl StdError for Error {
Error::TomlSer(e) => e.source(),
Error::TomlDe(e) => e.source(),
Error::Quote(e) => e.source(),
Error::HomeDir(e) => e.source(),
Error::Bat(e) => e.source(),
}
}
}
61 changes: 55 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
clippy::uninlined_format_args,
)]

mod assets;
mod cmd;
mod config;
mod edit;
Expand All @@ -33,6 +34,7 @@ use crate::opts::{Coloring, Expand, Subcommand};
use crate::unparse::unparse_maximal;
use crate::version::Version;
use bat::assets::HighlightingAssets;
use bat::assets_metadata::AssetsMetadata;
use bat::config::VisibleLines;
use bat::line_range::{HighlightedLineRanges, LineRanges};
use bat::style::StyleComponents;
Expand Down Expand Up @@ -138,9 +140,7 @@ fn do_cargo_expand() -> Result<i32> {
let config = config::deserialize();

if args.themes {
for theme in HighlightingAssets::from_binary().themes() {
let _ = writeln!(io::stdout(), "{}", theme);
}
print_themes()?;
return Ok(0);
}

Expand Down Expand Up @@ -305,15 +305,27 @@ fn do_cargo_expand() -> Result<i32> {
PagingMode::Never
},
visible_lines: VisibleLines::Ranges(LineRanges::all()),
theme: theme.unwrap_or_else(String::new),
theme: theme.as_ref().map_or_else(String::new, String::clone),
syntax_mapping: SyntaxMapping::empty(),
pager: None,
use_italic_text: false,
highlighted_lines: HighlightedLineRanges(LineRanges::none()),
use_custom_assets: false,
..Default::default()
};
let assets = HighlightingAssets::from_binary();
let mut assets = HighlightingAssets::from_binary();
if let Some(requested_theme) = theme {
if !assets
.themes()
.any(|supported_theme| supported_theme == requested_theme)
{
let cache_dir = assets::cache_dir()?;
if let Some(metadata) = AssetsMetadata::load_from_folder(&cache_dir)? {
if metadata.is_compatible_with(assets::BAT_VERSION) {
assets = HighlightingAssets::from_cache(&cache_dir)?;
}
}
}
}
let controller = bat::controller::Controller::new(&config, &assets);
let inputs = vec![bat::input::Input::from_reader(Box::new(content.as_bytes()))];
// Ignore any errors.
Expand Down Expand Up @@ -657,3 +669,40 @@ fn get_color(args: &Expand, config: &Config) -> Coloring {

Coloring::Auto // default
}

fn print_themes() -> Result<()> {
let mut cache_dir = assets::cache_dir()?;
let metadata = AssetsMetadata::load_from_folder(&cache_dir)?;
let compatible = metadata
.as_ref()
.map_or(false, |m| m.is_compatible_with(assets::BAT_VERSION));
let assets = if compatible {
HighlightingAssets::from_cache(&cache_dir)?
} else {
HighlightingAssets::from_binary()
};

for theme in assets.themes() {
let _ = writeln!(io::stdout(), "{}", theme);
}

if metadata.is_some() && !compatible {
if let Some(home_dir) = home::home_dir() {
if let Ok(relative) = cache_dir.strip_prefix(home_dir) {
cache_dir = Path::new("~").join(relative);
}
}
let bat_version = semver::Version::parse(assets::BAT_VERSION).unwrap();
let _ = writeln!(
io::stderr(),
"\nThere may be other themes in {cache_dir} but they are not \
compatible with the version of bat built into cargo-expand. Run \
`bat cache --build` with bat v{major}.{minor} to update the cache.",
cache_dir = cache_dir.display(),
major = bat_version.major,
minor = bat_version.minor,
);
}

Ok(())
}

0 comments on commit 4deda48

Please sign in to comment.