Skip to content

Commit

Permalink
Merge pull request #2929 from eth-p/add-remove-styles
Browse files Browse the repository at this point in the history
Merge `--style`s from different places using `+`/`-`
  • Loading branch information
eth-p authored Jul 31, 2024
2 parents fd1e0d5 + 39684b8 commit 2616296
Show file tree
Hide file tree
Showing 8 changed files with 376 additions and 53 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- `PrettyPrinter::squeeze_empty_lines` to support line squeezing for bat as a library, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
- Syntax highlighting for JavaScript files that start with `#!/usr/bin/env bun` #2913 (@sharunkumar)
- `bat --strip-ansi={never,always,auto}` to remove ANSI escape sequences from bat's input, see #2999 (@eth-p)
- Add or remove individual style components without replacing all styles #2929 (@eth-p)

## Bugfixes

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,16 @@ and line numbers but no grid and no file header. Set the `BAT_STYLE` environment
variable to make these changes permanent or use `bat`s
[configuration file](https://github.com/sharkdp/bat#configuration-file).

>[!tip]
> If you specify a default style in `bat`'s config file, you can change which components
> are displayed during a single run of `bat` using the `--style` command-line argument.
> By prefixing a component with `+` or `-`, it can be added or removed from the current style.
>
> For example, if your config contains `--style=full,-snip`, you can run bat with
> `--style=-grid,+snip` to remove the grid and add back the `snip` component.
> Or, if you want to override the styles completely, you use `--style=numbers` to
> only show the line numbers.
### Adding new syntaxes / language definitions

Should you find that a particular syntax is not available within `bat`, you can follow these
Expand Down
6 changes: 6 additions & 0 deletions doc/long-help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ Options:
set a default style, add the '--style=".."' option to the configuration file or export the
BAT_STYLE environment variable (e.g.: export BAT_STYLE="..").

When styles are specified in multiple places, the "nearest" set of styles take precedence.
The command-line arguments are the highest priority, followed by the BAT_STYLE environment
variable, and then the configuration file. If any set of styles consists entirely of
components prefixed with "+" or "-", it will modify the previous set of styles instead of
replacing them.

By default, the following components are enabled:
changes, grid, header-filename, numbers, snip

Expand Down
76 changes: 50 additions & 26 deletions src/bin/bat/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ use std::collections::HashSet;
use std::env;
use std::io::IsTerminal;
use std::path::{Path, PathBuf};
use std::str::FromStr;

use crate::{
clap_app,
config::{get_args_from_config_file, get_args_from_env_opts_var, get_args_from_env_vars},
};
use bat::style::StyleComponentList;
use bat::StripAnsiMode;
use clap::ArgMatches;

Expand Down Expand Up @@ -86,7 +88,6 @@ impl App {

// .. and the rest at the end
cli_args.for_each(|a| args.push(a));

args
};

Expand Down Expand Up @@ -364,34 +365,57 @@ impl App {
Ok(file_input)
}

fn forced_style_components(&self) -> Option<StyleComponents> {
// No components if `--decorations=never``.
if self
.matches
.get_one::<String>("decorations")
.map(|s| s.as_str())
== Some("never")
{
return Some(StyleComponents(HashSet::new()));
}

// Only line numbers if `--number`.
if self.matches.get_flag("number") {
return Some(StyleComponents(HashSet::from([
StyleComponent::LineNumbers,
])));
}

// Plain if `--plain` is specified at least once.
if self.matches.get_count("plain") > 0 {
return Some(StyleComponents(HashSet::from([StyleComponent::Plain])));
}

// Default behavior.
None
}

fn style_components(&self) -> Result<StyleComponents> {
let matches = &self.matches;
let mut styled_components = StyleComponents(
if matches.get_one::<String>("decorations").map(|s| s.as_str()) == Some("never") {
HashSet::new()
} else if matches.get_flag("number") {
[StyleComponent::LineNumbers].iter().cloned().collect()
} else if 0 < matches.get_count("plain") {
[StyleComponent::Plain].iter().cloned().collect()
} else {
matches
.get_one::<String>("style")
.map(|styles| {
styles
.split(',')
.map(|style| style.parse::<StyleComponent>())
.filter_map(|style| style.ok())
.collect::<Vec<_>>()
})
.unwrap_or_else(|| vec![StyleComponent::Default])
let mut styled_components = match self.forced_style_components() {
Some(forced_components) => forced_components,

// Parse the `--style` arguments and merge them.
None if matches.contains_id("style") => {
let lists = matches
.get_many::<String>("style")
.expect("styles present")
.map(|v| StyleComponentList::from_str(v))
.collect::<Result<Vec<StyleComponentList>>>()?;

StyleComponentList::to_components(lists, self.interactive_output, true)
}

// Use the default.
None => StyleComponents(HashSet::from_iter(
StyleComponent::Default
.components(self.interactive_output)
.into_iter()
.map(|style| style.components(self.interactive_output))
.fold(HashSet::new(), |mut acc, components| {
acc.extend(components.iter().cloned());
acc
})
},
);
.cloned(),
)),
};

// If `grid` is set, remove `rule` as it is a subset of `grid`, and print a warning.
if styled_components.grid() && styled_components.0.remove(&StyleComponent::Rule) {
Expand Down
37 changes: 12 additions & 25 deletions src/bin/bat/clap_app.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use bat::style::StyleComponentList;
use clap::{
crate_name, crate_version, value_parser, Arg, ArgAction, ArgGroup, ColorChoice, Command,
};
use once_cell::sync::Lazy;
use std::env;
use std::path::{Path, PathBuf};
use std::str::FromStr;

static VERSION: Lazy<String> = Lazy::new(|| {
#[cfg(feature = "bugreport")]
Expand Down Expand Up @@ -419,34 +421,13 @@ pub fn build_app(interactive_output: bool) -> Command {
.arg(
Arg::new("style")
.long("style")
.action(ArgAction::Append)
.value_name("components")
.overrides_with("style")
.overrides_with("plain")
.overrides_with("number")
// Cannot use claps built in validation because we have to turn off clap's delimiters
.value_parser(|val: &str| {
let mut invalid_vals = val.split(',').filter(|style| {
!&[
"auto",
"full",
"default",
"plain",
"header",
"header-filename",
"header-filesize",
"grid",
"rule",
"numbers",
"snip",
#[cfg(feature = "git")]
"changes",
].contains(style)
});

if let Some(invalid) = invalid_vals.next() {
Err(format!("Unknown style, '{invalid}'"))
} else {
Ok(val.to_owned())
match StyleComponentList::from_str(val) {
Err(err) => Err(err),
Ok(_) => Ok(val.to_owned()),
}
})
.help(
Expand All @@ -461,6 +442,12 @@ pub fn build_app(interactive_output: bool) -> Command {
pre-defined style ('full'). To set a default style, add the \
'--style=\"..\"' option to the configuration file or export the \
BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\
When styles are specified in multiple places, the \"nearest\" set \
of styles take precedence. The command-line arguments are the highest \
priority, followed by the BAT_STYLE environment variable, and then \
the configuration file. If any set of styles consists entirely of \
components prefixed with \"+\" or \"-\", it will modify the \
previous set of styles instead of replacing them.\n\n\
By default, the following components are enabled:\n \
changes, grid, header-filename, numbers, snip\n\n\
Possible values:\n\n \
Expand Down
7 changes: 5 additions & 2 deletions src/bin/bat/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,11 @@ pub fn get_args_from_env_vars() -> Vec<OsString> {
("--style", "BAT_STYLE"),
]
.iter()
.filter_map(|(flag, key)| env::var(key).ok().map(|var| [flag.to_string(), var]))
.flatten()
.filter_map(|(flag, key)| {
env::var(key)
.ok()
.map(|var| [flag.to_string(), var].join("="))
})
.map(|a| a.into())
.collect()
}
Expand Down
Loading

0 comments on commit 2616296

Please sign in to comment.