on master help sign in
Merge pull request #453 from sharkdp/line-highlight
668c8a6David Peter
src/app.rs+9
@@ -77,7 +77,11 @@ pub struct Config<'a> {
77 /// Command to start the pager
77 /// Command to start the pager
78 pub pager: Option<&'a str>,
78 pub pager: Option<&'a str>,
79
79
80+ /// Whether or not to use ANSI italics
80 pub use_italic_text: bool,
81 pub use_italic_text: bool,
82+
83+ /// Lines to highlight
84+ pub highlight_lines: Vec<usize>,
81}
85}
82
86
83fn is_truecolor_terminal() -> bool {
87fn is_truecolor_terminal() -> bool {
@@ -264,6 +268,11 @@ impl App {
264 Some("always") => true,
268 Some("always") => true,
265 _ => false,
269 _ => false,
266 },
270 },
271+ highlight_lines: self
272+ .matches
273+ .values_of("highlight-line")
274+ .and_then(|ws| ws.map(|w| w.parse().ok()).collect())
275+ .unwrap_or_default(),
267 })
276 })
268 }
277 }
269
278
src/clap_app.rs+14
@@ -175,6 +175,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
175 .arg(
175 .arg(
176 Arg::with_name("line-range")
176 Arg::with_name("line-range")
177 .long("line-range")
177 .long("line-range")
178+ .short("r")
178 .multiple(true)
179 .multiple(true)
179 .takes_value(true)
180 .takes_value(true)
180 .number_of_values(1)
181 .number_of_values(1)
@@ -188,6 +189,19 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
188 '--line-range 40:' prints lines 40 to the end of the file",
189 '--line-range 40:' prints lines 40 to the end of the file",
189 ),
190 ),
190 )
191 )
192+ .arg(
193+ Arg::with_name("highlight-line")
194+ .long("highlight-line")
195+ .short("H")
196+ .takes_value(true)
197+ .number_of_values(1)
198+ .multiple(true)
199+ .value_name("N")
200+ .help("Highlight the given line.")
201+ .long_help(
202+ "Highlight the N-th line with a different background color",
203+ ),
204+ )
191 .arg(
205 .arg(
192 Arg::with_name("color")
206 Arg::with_name("color")
193 .long("color")
207 .long("color")
src/printer.rs+53−4
@@ -7,6 +7,7 @@ use ansi_term::Style;
7use console::AnsiCodeIterator;
7use console::AnsiCodeIterator;
8
8
9use syntect::easy::HighlightLines;
9use syntect::easy::HighlightLines;
10+use syntect::highlighting::Color;
10use syntect::highlighting::Theme;
11use syntect::highlighting::Theme;
11use syntect::parsing::SyntaxSet;
12use syntect::parsing::SyntaxSet;
12
13
@@ -79,6 +80,7 @@ pub struct InteractivePrinter<'a> {
79 pub line_changes: Option<LineChanges>,
80 pub line_changes: Option<LineChanges>,
80 highlighter: Option<HighlightLines<'a>>,
81 highlighter: Option<HighlightLines<'a>>,
81 syntax_set: &'a SyntaxSet,
82 syntax_set: &'a SyntaxSet,
83+ background_color_highlight: Option<Color>,
82}
84}
83
85
84impl<'a> InteractivePrinter<'a> {
86impl<'a> InteractivePrinter<'a> {
@@ -90,6 +92,8 @@ impl<'a> InteractivePrinter<'a> {
90 ) -> Self {
92 ) -> Self {
91 let theme = assets.get_theme(&config.theme);
93 let theme = assets.get_theme(&config.theme);
92
94
95+ let background_color_highlight = theme.settings.line_highlight;
96+
93 let colors = if config.colored_output {
97 let colors = if config.colored_output {
94 Colors::colored(theme, config.true_color)
98 Colors::colored(theme, config.true_color)
95 } else {
99 } else {
@@ -156,6 +160,7 @@ impl<'a> InteractivePrinter<'a> {
156 line_changes,
160 line_changes,
157 highlighter,
161 highlighter,
158 syntax_set: &assets.syntax_set,
162 syntax_set: &assets.syntax_set,
163+ background_color_highlight,
159 }
164 }
160 }
165 }
161
166
@@ -287,6 +292,17 @@ impl<'a> Printer for InteractivePrinter<'a> {
287 let mut cursor_total: usize = 0;
292 let mut cursor_total: usize = 0;
288 let mut panel_wrap: Option<String> = None;
293 let mut panel_wrap: Option<String> = None;
289
294
295+ // Line highlighting
296+ let highlight_this_line = self
297+ .config
298+ .highlight_lines
299+ .iter()
300+ .any(|&l| l == line_number);
301+
302+ let background_color = self
303+ .background_color_highlight
304+ .filter(|_| highlight_this_line);
305+
290 // Line decorations.
306 // Line decorations.
291 if self.panel_width > 0 {
307 if self.panel_width > 0 {
292 let decorations = self
308 let decorations = self
@@ -313,9 +329,29 @@ impl<'a> Printer for InteractivePrinter<'a> {
313 write!(
329 write!(
314 handle,
330 handle,
315 "{}",
331 "{}",
316− as_terminal_escaped(style, text_trimmed, true_color, colored_output, italics,)
332+ as_terminal_escaped(
333+ style,
334+ text_trimmed,
335+ true_color,
336+ colored_output,
337+ italics,
338+ background_color
339+ )
317 )?;
340 )?;
341+
342+ if text.len() != text_trimmed.len() {
343+ if let Some(background_color) = background_color {
344+ let mut ansi_style = Style::default();
345+ ansi_style.background = Some(to_ansi_color(background_color, true_color));
346+ let width = if cursor_total <= cursor_max {
347+ cursor_max - cursor_total + 1
348+ } else {
349+ 0
350+ };
351+ write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?;
352+ }
318− write!(handle, "{}", &text[text_trimmed.len()..])?;
353+ write!(handle, "{}", &text[text_trimmed.len()..])?;
354+ }
319 }
355 }
320
356
321 if line.bytes().next_back() != Some(b'\n') {
357 if line.bytes().next_back() != Some(b'\n') {
@@ -370,7 +406,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
370 ),
406 ),
371 self.config.true_color,
407 self.config.true_color,
372 self.config.colored_output,
408 self.config.colored_output,
373− self.config.use_italic_text
409+ self.config.use_italic_text,
410+ background_color
374 )
411 )
375 )?;
412 )?;
376 break;
413 break;
@@ -410,7 +447,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
410 ),
447 ),
411 self.config.true_color,
448 self.config.true_color,
412 self.config.colored_output,
449 self.config.colored_output,
413− self.config.use_italic_text
450+ self.config.use_italic_text,
451+ background_color
414 ),
452 ),
415 panel_wrap.clone().unwrap()
453 panel_wrap.clone().unwrap()
416 )?;
454 )?;
@@ -423,6 +461,17 @@ impl<'a> Printer for InteractivePrinter<'a> {
423 }
461 }
424 }
462 }
425
463
464+ if let Some(background_color) = background_color {
465+ let mut ansi_style = Style::default();
466+ ansi_style.background =
467+ Some(to_ansi_color(background_color, self.config.true_color));
468+
469+ write!(
470+ handle,
471+ "{}",
472+ ansi_style.paint(" ".repeat(cursor_max - cursor))
473+ )?;
474+ }
426 write!(handle, "\n")?;
475 write!(handle, "\n")?;
427 }
476 }
428
477
src/terminal.rs+3−1
@@ -19,8 +19,9 @@ pub fn as_terminal_escaped(
19 true_color: bool,
19 true_color: bool,
20 colored: bool,
20 colored: bool,
21 italics: bool,
21 italics: bool,
22+ background_color: Option<highlighting::Color>,
22) -> String {
23) -> String {
23− let style = if !colored {
24+ let mut style = if !colored {
24 Style::default()
25 Style::default()
25 } else {
26 } else {
26 let color = to_ansi_color(style.foreground, true_color);
27 let color = to_ansi_color(style.foreground, true_color);
@@ -36,5 +37,6 @@ pub fn as_terminal_escaped(
36 }
37 }
37 };
38 };
38
39
40+ style.background = background_color.map(|c| to_ansi_color(c, true_color));
39 style.paint(text).to_string()
41 style.paint(text).to_string()
40}
42}