Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for ignored-suffix CLI arguments #1892

Merged
merged 17 commits into from
Nov 19, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ use path_abs::PathAbs;

use crate::bat_warning;
use crate::error::*;
use crate::ignored_suffixes::IgnoredSuffixes;
use crate::input::{InputReader, OpenedInput};
use crate::syntax_mapping::{MappingTarget, SyntaxMapping};

use ignored_suffixes::*;
use minimal_assets::*;
use serialized_syntax_set::*;

Expand All @@ -24,7 +24,6 @@ pub use crate::assets::build_assets::*;
pub(crate) mod assets_metadata;
#[cfg(feature = "build-assets")]
mod build_assets;
mod ignored_suffixes;
mod minimal_assets;
mod serialized_syntax_set;

Expand All @@ -37,6 +36,7 @@ pub struct HighlightingAssets {

theme_set: ThemeSet,
fallback_theme: Option<&'static str>,
ignored_suffixes: IgnoredSuffixes,
}

#[derive(Debug)]
Expand Down Expand Up @@ -67,21 +67,23 @@ impl HighlightingAssets {
serialized_syntax_set: SerializedSyntaxSet,
minimal_syntaxes: MinimalSyntaxes,
theme_set: ThemeSet,
ignored_suffixes: IgnoredSuffixes,
) -> Self {
HighlightingAssets {
syntax_set_cell: LazyCell::new(),
serialized_syntax_set,
minimal_assets: MinimalAssets::new(minimal_syntaxes),
theme_set,
fallback_theme: None,
ignored_suffixes,
}
}

pub fn default_theme() -> &'static str {
"Monokai Extended"
}

pub fn from_cache(cache_path: &Path) -> Result<Self> {
pub fn from_cache(cache_path: &Path, ignored_suffixes: IgnoredSuffixes) -> Result<Self> {
Enselic marked this conversation as resolved.
Show resolved Hide resolved
Ok(HighlightingAssets::new(
SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")),
asset_from_cache(
Expand All @@ -90,14 +92,16 @@ impl HighlightingAssets {
COMPRESS_MINIMAL_SYNTAXES,
)?,
asset_from_cache(&cache_path.join("themes.bin"), "theme set", COMPRESS_THEMES)?,
ignored_suffixes,
))
}

pub fn from_binary() -> Self {
pub fn from_binary(ignored_suffixes: IgnoredSuffixes) -> Self {
HighlightingAssets::new(
SerializedSyntaxSet::FromBinary(get_serialized_integrated_syntaxset()),
get_integrated_minimal_syntaxes(),
get_integrated_themeset(),
ignored_suffixes,
)
}

Expand Down Expand Up @@ -269,9 +273,12 @@ impl HighlightingAssets {
syntax = self.find_syntax_by_extension(Path::new(file_name).extension())?;
}
if syntax.is_none() {
syntax = try_with_stripped_suffix(file_name, |stripped_file_name| {
self.get_extension_syntax(stripped_file_name) // Note: recursion
})?;
syntax = self.ignored_suffixes.try_with_stripped_suffix(
file_name,
|stripped_file_name| {
self.get_extension_syntax(stripped_file_name) // Note: recursion
},
)?;
}
Ok(syntax)
}
Expand Down Expand Up @@ -358,7 +365,7 @@ mod tests {
impl<'a> SyntaxDetectionTest<'a> {
fn new() -> Self {
SyntaxDetectionTest {
assets: HighlightingAssets::from_binary(),
assets: HighlightingAssets::from_binary(IgnoredSuffixes::default()),
syntax_mapping: SyntaxMapping::builtin(),
temp_dir: TempDir::new().expect("creation of temporary directory"),
}
Expand Down
42 changes: 0 additions & 42 deletions src/assets/ignored_suffixes.rs

This file was deleted.

6 changes: 6 additions & 0 deletions src/bin/bat/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ impl App {
.map(HighlightedLineRanges)
.unwrap_or_default(),
use_custom_assets: !self.matches.is_present("no-custom-assets"),
ignored_suffixes: self
.matches
.values_of("ignored-suffix")
.unwrap_or_default()
.map(String::from)
.collect(),
})
}

Expand Down
11 changes: 7 additions & 4 deletions src/bin/bat/assets.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::borrow::Cow;
use std::fs;

use bat::config::Config;
use bat::ignored_suffixes::IgnoredSuffixes;
use clap::crate_version;

use crate::directories::PROJECT_DIRS;
Expand All @@ -24,7 +26,7 @@ pub fn clear_assets() {
clear_asset("metadata.yaml", "metadata file");
}

pub fn assets_from_cache_or_binary(use_custom_assets: bool) -> Result<HighlightingAssets> {
pub fn assets_from_cache_or_binary(config: &Config) -> Result<HighlightingAssets> {
let cache_dir = PROJECT_DIRS.cache_dir();
if let Some(metadata) = AssetsMetadata::load_from_folder(cache_dir)? {
if !metadata.is_compatible_with(crate_version!()) {
Expand All @@ -42,12 +44,13 @@ pub fn assets_from_cache_or_binary(use_custom_assets: bool) -> Result<Highlighti
}
}

let custom_assets = if use_custom_assets {
HighlightingAssets::from_cache(cache_dir).ok()
let ignored_suffixes = IgnoredSuffixes::new(config.ignored_suffixes.clone());
let custom_assets = if config.use_custom_assets {
HighlightingAssets::from_cache(cache_dir, ignored_suffixes.clone()).ok()
} else {
None
};
Ok(custom_assets.unwrap_or_else(HighlightingAssets::from_binary))
Ok(custom_assets.unwrap_or_else(|| HighlightingAssets::from_binary(ignored_suffixes.clone())))
}

fn clear_asset(filename: &str, description: &str) {
Expand Down
11 changes: 11 additions & 0 deletions src/bin/bat/clap_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,17 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.hidden_short_help(true)
.help("Show diagnostic information for bug reports.")
)
.arg(
Arg::with_name("ignored-suffix")
.number_of_values(1)
.multiple(true)
.takes_value(true)
.long("ignored-suffix")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should consider making this .hidden_short_help(true), such that we only show it on bat --help, but not for bat -h (which should only show the most commonly used options).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sharkdp for explanation.
It's updated.

.help(
"Ignore extension. For example:\n \
'bat --ignored-suffix \".dev\" my_file.json.dev' will use JSON syntax, and ignore '.dev'"
)
)
.help_message("Print this help message.")
.version_message("Show version information.");

Expand Down
6 changes: 3 additions & 3 deletions src/bin/bat/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ fn get_syntax_mapping_to_paths<'a>(
pub fn get_languages(config: &Config) -> Result<String> {
let mut result: String = String::new();

let assets = assets_from_cache_or_binary(config.use_custom_assets)?;
let assets = assets_from_cache_or_binary(config)?;
let mut languages = assets
.get_syntaxes()?
.iter()
Expand Down Expand Up @@ -177,7 +177,7 @@ fn theme_preview_file<'a>() -> Input<'a> {
}

pub fn list_themes(cfg: &Config) -> Result<()> {
let assets = assets_from_cache_or_binary(cfg.use_custom_assets)?;
let assets = assets_from_cache_or_binary(cfg)?;
let mut config = cfg.clone();
let mut style = HashSet::new();
style.insert(StyleComponent::Plain);
Expand Down Expand Up @@ -218,7 +218,7 @@ pub fn list_themes(cfg: &Config) -> Result<()> {
}

fn run_controller(inputs: Vec<Input>, config: &Config) -> Result<bool> {
let assets = assets_from_cache_or_binary(config.use_custom_assets)?;
let assets = assets_from_cache_or_binary(config)?;
let controller = Controller::new(config, &assets);
controller.run(inputs)
}
Expand Down
3 changes: 3 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ pub struct Config<'a> {
/// Whether or not to allow custom assets. If this is false or if custom assets (a.k.a.
/// cached assets) are not available, assets from the binary will be used instead.
pub use_custom_assets: bool,

/// Ignored suffixes
pub ignored_suffixes: Vec<String>,
}

#[cfg(all(feature = "minimal-application", feature = "paging"))]
Expand Down
104 changes: 104 additions & 0 deletions src/ignored_suffixes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use std::ffi::OsStr;
use std::path::Path;

use crate::error::*;

const IGNORED_SUFFIXES: [&str; 13] = [
// Editor etc backups
"~",
".bak",
".old",
".orig",
// Debian and derivatives apt/dpkg/ucf backups
".dpkg-dist",
".dpkg-old",
".ucf-dist",
".ucf-new",
".ucf-old",
// Red Hat and derivatives rpm backups
".rpmnew",
".rpmorig",
".rpmsave",
// Build system input/template files
".in",
];

#[derive(Debug, Clone, Default)]
pub struct IgnoredSuffixes {
values: Vec<String>,
}

impl IgnoredSuffixes {
pub fn new(values: Vec<String>) -> Self {
IgnoredSuffixes { values }
}

/// If we find an ignored suffix on the file name, e.g. '~', we strip it and
/// then try again without it.
pub fn try_with_stripped_suffix<'a, T, F>(
&self,
file_name: &'a OsStr,
func: F,
) -> Result<Option<T>>
where
F: Fn(&'a OsStr) -> Result<Option<T>>,
{
let mut from_stripped = None;
if let Some(file_str) = Path::new(file_name).to_str() {
for suffix in self
.values
.iter()
.map(|v| v.as_str())
.chain(IGNORED_SUFFIXES.iter().map(|v| *v))
{
if let Some(stripped_filename) = file_str.strip_suffix(suffix) {
from_stripped = func(OsStr::new(stripped_filename))?;
break;
}
}
}
Ok(from_stripped)
}
}

#[test]
fn internal_suffixes() {
let ignored_suffixes = IgnoredSuffixes::new(vec![]);

let file_names = IGNORED_SUFFIXES
.iter()
.map(|suffix| format!("test.json{}", suffix));
for file_name_str in file_names {
let file_name = OsStr::new(&file_name_str);
let expected_stripped_file_name = OsStr::new("test.json");
let stripped_file_name = ignored_suffixes
.try_with_stripped_suffix(file_name, |stripped_file_name| Ok(Some(stripped_file_name)));
assert_eq!(
expected_stripped_file_name,
stripped_file_name.unwrap().unwrap()
);
}
}

#[test]
fn external_suffixes() {
let ignored_suffixes = IgnoredSuffixes::new(vec![
String::from(".development"),
String::from(".production"),
]);

let file_names = ignored_suffixes
.values
.iter()
.map(|suffix| format!("test.json{}", suffix));
for file_name_str in file_names {
let file_name = OsStr::new(&file_name_str);
let expected_stripped_file_name = OsStr::new("test.json");
let stripped_file_name = ignored_suffixes
.try_with_stripped_suffix(file_name, |stripped_file_name| Ok(Some(stripped_file_name)));
assert_eq!(
expected_stripped_file_name,
stripped_file_name.unwrap().unwrap()
);
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub mod controller;
mod decorations;
mod diff;
pub mod error;
pub mod ignored_suffixes;
Enselic marked this conversation as resolved.
Show resolved Hide resolved
pub mod input;
mod less;
pub mod line_range;
Expand Down
3 changes: 2 additions & 1 deletion src/pretty_printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
config::{Config, VisibleLines},
controller::Controller,
error::Result,
ignored_suffixes::IgnoredSuffixes,
input,
line_range::{HighlightedLineRanges, LineRange, LineRanges},
style::{StyleComponent, StyleComponents},
Expand Down Expand Up @@ -49,7 +50,7 @@ impl<'a> PrettyPrinter<'a> {
PrettyPrinter {
inputs: vec![],
config,
assets: HighlightingAssets::from_binary(),
assets: HighlightingAssets::from_binary(IgnoredSuffixes::default()),

highlighted_lines: vec![],
term_width: None,
Expand Down
4 changes: 2 additions & 2 deletions tests/assets.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use bat::assets::HighlightingAssets;
use bat::{assets::HighlightingAssets, ignored_suffixes::IgnoredSuffixes};

/// This test ensures that we are not accidentally removing themes due to submodule updates.
/// It is 'ignore'd by default because it requires themes.bin to be up-to-date.
#[test]
#[ignore]
fn all_themes_are_present() {
let assets = HighlightingAssets::from_binary();
let assets = HighlightingAssets::from_binary(IgnoredSuffixes::default());

let mut themes: Vec<_> = assets.themes().collect();
themes.sort_unstable();
Expand Down
Loading