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:
Ethan P 2024-06-15 16:28:05 -07:00 committed by GitHub
commit 10a1b24191
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 9 deletions

View File

@ -38,6 +38,7 @@
- Display which theme is the default one in colored output, see #2838 (@sblondon) - 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) - Add aarch64-apple-darwin ("Apple Silicon") binary tarballs to releases, see #2967 (@someposer)
- Update the Lisp syntax, see #2970 (@ccqpein) - Update the Lisp syntax, see #2970 (@ccqpein)
- Use bat's ANSI iterator during tab expansion, see #2998 (@eth-p)
## Syntaxes ## Syntaxes

View File

@ -1,17 +1,18 @@
use std::fmt::Write; 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). /// Expand tabs like an ANSI-enabled expand(1).
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String { pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
let mut buffer = String::with_capacity(line.len() * 2); let mut buffer = String::with_capacity(line.len() * 2);
for chunk in AnsiCodeIterator::new(line) { for seq in EscapeSequenceOffsetsIterator::new(line) {
match chunk { match seq {
(text, true) => buffer.push_str(text), EscapeSequenceOffsets::Text { .. } => {
(mut text, false) => { let mut text = &line[seq.index_of_start()..seq.index_past_end()];
while let Some(index) = text.find('\t') { while let Some(index) = text.find('\t') {
// Add previous text. // Add previous text.
if index > 0 { if index > 0 {
@ -31,6 +32,10 @@ pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
*cursor += text.len(); *cursor += text.len();
buffer.push_str(text); buffer.push_str(text);
} }
_ => {
// Copy the ANSI escape sequence.
buffer.push_str(&line[seq.index_of_start()..seq.index_past_end()])
}
} }
} }

View File

@ -285,7 +285,7 @@ fn join(
/// A range of indices for a raw ANSI escape sequence. /// A range of indices for a raw ANSI escape sequence.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum EscapeSequenceOffsets { pub enum EscapeSequenceOffsets {
Text { Text {
start: usize, start: usize,
end: 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. /// An iterator over the offests of ANSI/VT escape sequences within a string.
/// ///
/// ## Example /// ## Example
@ -327,7 +353,7 @@ enum EscapeSequenceOffsets {
/// ```ignore /// ```ignore
/// let iter = EscapeSequenceOffsetsIterator::new("\x1B[33mThis is yellow text.\x1B[m"); /// let iter = EscapeSequenceOffsetsIterator::new("\x1B[33mThis is yellow text.\x1B[m");
/// ``` /// ```
struct EscapeSequenceOffsetsIterator<'a> { pub struct EscapeSequenceOffsetsIterator<'a> {
text: &'a str, text: &'a str,
chars: Peekable<CharIndices<'a>>, chars: Peekable<CharIndices<'a>>,
} }