mirror of
https://github.com/sharkdp/bat.git
synced 2025-10-02 10:02:28 +01:00
Support merging --style
arguments
The `overrides_with` clap builder option was removed because it interfered with the matcher's ability to retain all occurrences of `--style`. The behavior it covered is expressed within the new `forced_style_components` function.
This commit is contained in:
194
src/style.rs
194
src/style.rs
@@ -138,3 +138,197 @@ impl StyleComponents {
|
||||
self.0.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum ComponentAction {
|
||||
Override,
|
||||
Add,
|
||||
Remove,
|
||||
}
|
||||
|
||||
impl ComponentAction {
|
||||
fn extract_from_str(string: &str) -> (ComponentAction, &str) {
|
||||
match string.chars().next() {
|
||||
Some('-') => (ComponentAction::Remove, string.strip_prefix('-').unwrap()),
|
||||
Some('+') => (ComponentAction::Add, string.strip_prefix('+').unwrap()),
|
||||
_ => (ComponentAction::Override, string),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of [StyleComponent] that can be parsed from a string.
|
||||
pub struct StyleComponentList(Vec<(ComponentAction, StyleComponent)>);
|
||||
|
||||
impl StyleComponentList {
|
||||
fn expand_into(&self, components: &mut HashSet<StyleComponent>, interactive_terminal: bool) {
|
||||
for (action, component) in self.0.iter() {
|
||||
let subcomponents = component.components(interactive_terminal);
|
||||
|
||||
use ComponentAction::*;
|
||||
match action {
|
||||
Override | Add => components.extend(subcomponents),
|
||||
Remove => components.retain(|c| !subcomponents.contains(c)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if any component in the list was not prefixed with `+` or `-`.
|
||||
fn contains_override(&self) -> bool {
|
||||
self.0.iter().any(|(a, _)| *a == ComponentAction::Override)
|
||||
}
|
||||
|
||||
/// Combines multiple [StyleComponentList]s into a single [StyleComponents] set.
|
||||
///
|
||||
/// ## Precedence
|
||||
/// The most recent list will take precedence and override all previous lists
|
||||
/// unless it only contains components prefixed with `-` or `+`. When this
|
||||
/// happens, the list's components will be merged into the previous list.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```text
|
||||
/// [numbers,grid] + [header,changes] -> [header,changes]
|
||||
/// [numbers,grid] + [+header,-grid] -> [numbers,header]
|
||||
/// ```
|
||||
pub fn to_components(
|
||||
lists: impl IntoIterator<Item = StyleComponentList>,
|
||||
interactive_terminal: bool,
|
||||
) -> StyleComponents {
|
||||
StyleComponents(
|
||||
lists
|
||||
.into_iter()
|
||||
.fold(HashSet::new(), |mut components, list| {
|
||||
if list.contains_override() {
|
||||
components.clear();
|
||||
}
|
||||
|
||||
list.expand_into(&mut components, interactive_terminal);
|
||||
components
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for StyleComponentList {
|
||||
fn default() -> Self {
|
||||
StyleComponentList(vec![(ComponentAction::Override, StyleComponent::Default)])
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for StyleComponentList {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
Ok(StyleComponentList(
|
||||
s.split(",")
|
||||
.map(|s| ComponentAction::extract_from_str(s)) // If the component starts with "-", it's meant to be removed
|
||||
.map(|(a, s)| Ok((a, StyleComponent::from_str(s)?)))
|
||||
.collect::<Result<Vec<(ComponentAction, StyleComponent)>>>()?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::HashSet;
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::ComponentAction::*;
|
||||
use super::StyleComponent::*;
|
||||
use super::StyleComponentList;
|
||||
|
||||
#[test]
|
||||
pub fn style_component_list_parse() {
|
||||
assert_eq!(
|
||||
StyleComponentList::from_str("grid,+numbers,snip,-snip,header")
|
||||
.expect("no error")
|
||||
.0,
|
||||
vec![
|
||||
(Override, Grid),
|
||||
(Add, LineNumbers),
|
||||
(Override, Snip),
|
||||
(Remove, Snip),
|
||||
(Override, Header),
|
||||
]
|
||||
);
|
||||
|
||||
assert!(StyleComponentList::from_str("not-a-component").is_err());
|
||||
assert!(StyleComponentList::from_str("grid,not-a-component").is_err());
|
||||
assert!(StyleComponentList::from_str("numbers,-not-a-component").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn style_component_list_to_components() {
|
||||
assert_eq!(
|
||||
StyleComponentList::to_components(
|
||||
vec![StyleComponentList::from_str("grid,numbers").expect("no error")],
|
||||
false
|
||||
)
|
||||
.0,
|
||||
HashSet::from([Grid, LineNumbers])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn style_component_list_to_components_removes_negated() {
|
||||
assert_eq!(
|
||||
StyleComponentList::to_components(
|
||||
vec![StyleComponentList::from_str("grid,numbers,-grid").expect("no error")],
|
||||
false
|
||||
)
|
||||
.0,
|
||||
HashSet::from([LineNumbers])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn style_component_list_to_components_expands_subcomponents() {
|
||||
assert_eq!(
|
||||
StyleComponentList::to_components(
|
||||
vec![StyleComponentList::from_str("full").expect("no error")],
|
||||
false
|
||||
)
|
||||
.0,
|
||||
HashSet::from_iter(Full.components(true).to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn style_component_list_expand_negates_subcomponents() {
|
||||
assert!(!StyleComponentList::to_components(
|
||||
vec![StyleComponentList::from_str("full,-numbers").expect("no error")],
|
||||
true
|
||||
)
|
||||
.numbers());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn style_component_list_to_components_precedence_overrides_previous_lists() {
|
||||
assert_eq!(
|
||||
StyleComponentList::to_components(
|
||||
vec![
|
||||
StyleComponentList::from_str("grid").expect("no error"),
|
||||
StyleComponentList::from_str("numbers").expect("no error"),
|
||||
],
|
||||
false
|
||||
)
|
||||
.0,
|
||||
HashSet::from([LineNumbers])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn style_component_list_to_components_precedence_merges_previous_lists() {
|
||||
assert_eq!(
|
||||
StyleComponentList::to_components(
|
||||
vec![
|
||||
StyleComponentList::from_str("grid,header").expect("no error"),
|
||||
StyleComponentList::from_str("-grid").expect("no error"),
|
||||
StyleComponentList::from_str("+numbers").expect("no error"),
|
||||
],
|
||||
false
|
||||
)
|
||||
.0,
|
||||
HashSet::from([HeaderFilename, LineNumbers])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user