diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index 435e5c67..23ac7a05 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -215,11 +215,13 @@ impl App { Some("always") => true, _ => false, }, - highlight_lines: self - .matches - .values_of("highlight-line") - .and_then(|ws| ws.map(|w| w.parse().ok()).collect()) - .unwrap_or_default(), + highlight_lines: LineRanges::from( + self.matches + .values_of("highlight-line") + .map(|ws| ws.map(LineRange::from).collect()) + .transpose()? + .unwrap_or_else(|| vec![LineRange { lower: 0, upper: 0 }]), + ), }) } diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs index 2b4801db..0e46c885 100644 --- a/src/bin/bat/clap_app.rs +++ b/src/bin/bat/clap_app.rs @@ -82,10 +82,15 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> { .takes_value(true) .number_of_values(1) .multiple(true) - .value_name("N") - .help("Highlight the given line.") + .value_name("N:M") + .help("Highlight lines N through M.") .long_help( - "Highlight the N-th line with a different background color", + "Highlight the specified line ranges with a different background color \ + For example:\n \ + '--highlight-line 30:40' highlights lines 30 to 40\n \ + '--highlight-line :40' highlights lines 1 to 40\n \ + '--highlight-line 40:' highlights lines 40 to the end of the file\n \ + '--highlight-line 40' highlights only line 40", ), ) .arg( @@ -328,7 +333,8 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> { For example:\n \ '--line-range 30:40' prints lines 30 to 40\n \ '--line-range :40' prints lines 1 to 40\n \ - '--line-range 40:' prints lines 40 to the end of the file", + '--line-range 40:' prints lines 40 to the end of the file\n \ + '--line-range 40' prints only line 40", ), ) .arg( diff --git a/src/lib.rs b/src/lib.rs index e6743644..2172892f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,5 +128,5 @@ pub struct Config<'a> { pub use_italic_text: bool, /// Lines to highlight - pub highlight_lines: Vec, + pub highlight_lines: LineRanges, } diff --git a/src/line_range.rs b/src/line_range.rs index 5f20c955..ac3ec981 100644 --- a/src/line_range.rs +++ b/src/line_range.rs @@ -30,13 +30,19 @@ impl LineRange { } let line_numbers: Vec<&str> = range_raw.split(':').collect(); - if line_numbers.len() == 2 { - new_range.lower = line_numbers[0].parse()?; - new_range.upper = line_numbers[1].parse()?; - return Ok(new_range); + match line_numbers.len() { + 1 => { + new_range.lower = line_numbers[0].parse()?; + new_range.upper = new_range.lower; + Ok(new_range) + }, + 2 => { + new_range.lower = line_numbers[0].parse()?; + new_range.upper = line_numbers[1].parse()?; + Ok(new_range) + }, + _ => Err("expected at most single ':' character".into()), } - - Err("expected single ':' character".into()) } pub fn is_inside(&self, line: usize) -> bool { @@ -65,6 +71,13 @@ fn test_parse_partial_max() { assert_eq!(usize::max_value(), range.upper); } +#[test] +fn test_parse_single() { + let range = LineRange::from("40").expect("Shouldn't fail on test!"); + assert_eq!(40, range.lower); + assert_eq!(40, range.upper); +} + #[test] fn test_parse_fail() { let range = LineRange::from("40:50:80"); @@ -73,8 +86,6 @@ fn test_parse_fail() { assert!(range.is_err()); let range = LineRange::from(":40:"); assert!(range.is_err()); - let range = LineRange::from("40"); - assert!(range.is_err()); } #[derive(Copy, Clone, Debug, PartialEq)] diff --git a/src/printer.rs b/src/printer.rs index 14d5054a..ff4e59a8 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -24,6 +24,7 @@ use crate::diff::get_git_diff; use crate::diff::LineChanges; use crate::errors::*; use crate::inputfile::{InputFile, InputFileReader}; +use crate::line_range::RangeCheckResult; use crate::preprocessor::{expand_tabs, replace_nonprintable}; use crate::style::OutputWrap; use crate::terminal::{as_terminal_escaped, to_ansi_color}; @@ -369,11 +370,8 @@ impl<'a> Printer for InteractivePrinter<'a> { let mut panel_wrap: Option = None; // Line highlighting - let highlight_this_line = self - .config - .highlight_lines - .iter() - .any(|&l| l == line_number); + let highlight_this_line = + self.config.highlight_lines.check(line_number) == RangeCheckResult::InRange; let background_color = self .background_color_highlight