2
0
mirror of https://github.com/sharkdp/bat synced 2024-11-18 15:26:16 +00:00

Added tab expansion preprocessing step.

This commit is contained in:
eth-p 2018-09-10 18:11:59 -07:00
parent 8b4abb03db
commit b23ff24ebc
No known key found for this signature in database
GPG Key ID: 1F8DF8091CD46FBC
4 changed files with 64 additions and 1 deletions

View File

@ -41,6 +41,9 @@ pub struct Config<'a> {
/// The character width of the terminal /// The character width of the terminal
pub term_width: usize, pub term_width: usize,
/// The width of tab characters.
pub tab_width: usize,
/// Whether or not to simply loop through all input (`cat` mode) /// Whether or not to simply loop through all input (`cat` mode)
pub loop_through: bool, pub loop_through: bool,
@ -276,6 +279,15 @@ impl App {
'unbuffered'). The output is always unbuffered - this option \ 'unbuffered'). The output is always unbuffered - this option \
is simply ignored.", is simply ignored.",
), ),
).arg(
Arg::with_name("tabs")
.long("tabs")
.short("t")
.takes_value(true)
.value_name("width")
.help("Sets the tab width.")
.long_help("Sets the tab width. Use a width of 0 to pass tabs through \
directly"),
).arg( ).arg(
Arg::with_name("terminal-width") Arg::with_name("terminal-width")
.long("terminal-width") .long("terminal-width")
@ -393,6 +405,12 @@ impl App {
|| self.matches.value_of("color") == Some("always") || self.matches.value_of("color") == Some("always")
|| self.matches.value_of("decorations") == Some("always")), || self.matches.value_of("decorations") == Some("always")),
files, files,
tab_width: self
.matches
.value_of("tabs")
.and_then(|w| w.parse().ok())
.or_else(|| env::var("BAT_TABS").ok().and_then(|w| w.parse().ok()))
.unwrap_or(8),
theme: self theme: self
.matches .matches
.value_of("theme") .value_of("theme")

View File

@ -24,6 +24,7 @@ mod decorations;
mod diff; mod diff;
mod line_range; mod line_range;
mod output; mod output;
mod preprocessor;
mod printer; mod printer;
mod style; mod style;
mod terminal; mod terminal;

35
src/preprocessor.rs Normal file
View File

@ -0,0 +1,35 @@
use console::AnsiCodeIterator;
/// Expand tabs like an ANSI-enabled expand(1).
pub fn expand(line: &str, width: usize) -> String {
let mut buffer = String::with_capacity(line.len() * 2);
let mut cursor = 0;
for chunk in AnsiCodeIterator::new(line) {
match chunk {
(text, true) => buffer.push_str(text),
(mut text, false) => {
while let Some(index) = text.find('\t') {
// Add previous text.
if index > 0 {
cursor += index;
buffer.push_str(&text[0..index]);
}
// Add tab.
let spaces = width - (cursor % width);
cursor += spaces;
buffer.push_str(&*" ".repeat(spaces));
// Next.
text = &text[index + 1..text.len()];
}
cursor += text.len();
buffer.push_str(text);
}
}
}
buffer
}

View File

@ -16,6 +16,7 @@ use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineN
use diff::get_git_diff; use diff::get_git_diff;
use diff::LineChanges; use diff::LineChanges;
use errors::*; use errors::*;
use preprocessor::expand;
use style::OutputWrap; use style::OutputWrap;
use terminal::{as_terminal_escaped, to_ansi_color}; use terminal::{as_terminal_escaped, to_ansi_color};
@ -200,9 +201,17 @@ impl<'a> Printer for InteractivePrinter<'a> {
line_number: usize, line_number: usize,
line_buffer: &[u8], line_buffer: &[u8],
) -> Result<()> { ) -> Result<()> {
let line = String::from_utf8_lossy(&line_buffer); let mut line = String::from_utf8_lossy(&line_buffer).to_string();
// Preprocess.
if self.config.tab_width > 0 {
line = expand(&line, self.config.tab_width);
}
// Highlight.
let regions = self.highlighter.highlight(line.as_ref()); let regions = self.highlighter.highlight(line.as_ref());
// Print.
if out_of_range { if out_of_range {
return Ok(()); return Ok(());
} }