mirror of
				https://github.com/sharkdp/bat.git
				synced 2025-11-04 09:01:56 +00:00 
			
		
		
		
	Merge pull request #2998 from eth-p/improve-preprocessor
Update bat's tab expansion preprocessor to use bat's ANSI escape sequence iterator.
This commit is contained in:
		@@ -38,6 +38,7 @@
 | 
			
		||||
- Display which theme is the default one in colored output, see #2838 (@sblondon)
 | 
			
		||||
- Add aarch64-apple-darwin ("Apple Silicon") binary tarballs to releases, see #2967 (@someposer)
 | 
			
		||||
- Update the Lisp syntax, see #2970 (@ccqpein)
 | 
			
		||||
- Use bat's ANSI iterator during tab expansion, see #2998 (@eth-p)
 | 
			
		||||
 | 
			
		||||
## Syntaxes
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,18 @@
 | 
			
		||||
use std::fmt::Write;
 | 
			
		||||
 | 
			
		||||
use console::AnsiCodeIterator;
 | 
			
		||||
 | 
			
		||||
use crate::nonprintable_notation::NonprintableNotation;
 | 
			
		||||
use crate::{
 | 
			
		||||
    nonprintable_notation::NonprintableNotation,
 | 
			
		||||
    vscreen::{EscapeSequenceOffsets, EscapeSequenceOffsetsIterator},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Expand tabs like an ANSI-enabled expand(1).
 | 
			
		||||
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
 | 
			
		||||
    let mut buffer = String::with_capacity(line.len() * 2);
 | 
			
		||||
 | 
			
		||||
    for chunk in AnsiCodeIterator::new(line) {
 | 
			
		||||
        match chunk {
 | 
			
		||||
            (text, true) => buffer.push_str(text),
 | 
			
		||||
            (mut text, false) => {
 | 
			
		||||
    for seq in EscapeSequenceOffsetsIterator::new(line) {
 | 
			
		||||
        match seq {
 | 
			
		||||
            EscapeSequenceOffsets::Text { .. } => {
 | 
			
		||||
                let mut text = &line[seq.index_of_start()..seq.index_past_end()];
 | 
			
		||||
                while let Some(index) = text.find('\t') {
 | 
			
		||||
                    // Add previous text.
 | 
			
		||||
                    if index > 0 {
 | 
			
		||||
@@ -31,6 +32,10 @@ pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
 | 
			
		||||
                *cursor += text.len();
 | 
			
		||||
                buffer.push_str(text);
 | 
			
		||||
            }
 | 
			
		||||
            _ => {
 | 
			
		||||
                // Copy the ANSI escape sequence.
 | 
			
		||||
                buffer.push_str(&line[seq.index_of_start()..seq.index_past_end()])
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -285,7 +285,7 @@ fn join(
 | 
			
		||||
 | 
			
		||||
/// A range of indices for a raw ANSI escape sequence.
 | 
			
		||||
#[derive(Debug, PartialEq)]
 | 
			
		||||
enum EscapeSequenceOffsets {
 | 
			
		||||
pub enum EscapeSequenceOffsets {
 | 
			
		||||
    Text {
 | 
			
		||||
        start: usize,
 | 
			
		||||
        end: usize,
 | 
			
		||||
@@ -320,6 +320,32 @@ enum EscapeSequenceOffsets {
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EscapeSequenceOffsets {
 | 
			
		||||
    /// Returns the byte-index of the first character in the escape sequence.
 | 
			
		||||
    pub fn index_of_start(&self) -> usize {
 | 
			
		||||
        use EscapeSequenceOffsets::*;
 | 
			
		||||
        match self {
 | 
			
		||||
            Text { start, .. } => *start,
 | 
			
		||||
            Unknown { start, .. } => *start,
 | 
			
		||||
            NF { start_sequence, .. } => *start_sequence,
 | 
			
		||||
            OSC { start_sequence, .. } => *start_sequence,
 | 
			
		||||
            CSI { start_sequence, .. } => *start_sequence,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns the byte-index past the last character in the escape sequence.
 | 
			
		||||
    pub fn index_past_end(&self) -> usize {
 | 
			
		||||
        use EscapeSequenceOffsets::*;
 | 
			
		||||
        match self {
 | 
			
		||||
            Text { end, .. } => *end,
 | 
			
		||||
            Unknown { end, .. } => *end,
 | 
			
		||||
            NF { end, .. } => *end,
 | 
			
		||||
            OSC { end, .. } => *end,
 | 
			
		||||
            CSI { end, .. } => *end,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// An iterator over the offests of ANSI/VT escape sequences within a string.
 | 
			
		||||
///
 | 
			
		||||
/// ## Example
 | 
			
		||||
@@ -327,7 +353,7 @@ enum EscapeSequenceOffsets {
 | 
			
		||||
/// ```ignore
 | 
			
		||||
/// let iter = EscapeSequenceOffsetsIterator::new("\x1B[33mThis is yellow text.\x1B[m");
 | 
			
		||||
/// ```
 | 
			
		||||
struct EscapeSequenceOffsetsIterator<'a> {
 | 
			
		||||
pub struct EscapeSequenceOffsetsIterator<'a> {
 | 
			
		||||
    text: &'a str,
 | 
			
		||||
    chars: Peekable<CharIndices<'a>>,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user