on v0.9.0 help sign in
bat/src/preprocessor.rs
73 lines 2.1 kB history raw
1use console::AnsiCodeIterator;
3/// Expand tabs like an ANSI-enabled expand(1).
4pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
5 let mut buffer = String::with_capacity(line.len() * 2);
7 for chunk in AnsiCodeIterator::new(line) {
8 match chunk {
9 (text, true) => buffer.push_str(text),
10 (mut text, false) => {
11 while let Some(index) = text.find('\t') {
12 // Add previous text.
13 if index > 0 {
14 *cursor += index;
15 buffer.push_str(&text[0..index]);
16 }
18 // Add tab.
19 let spaces = width - (*cursor % width);
20 *cursor += spaces;
21 buffer.push_str(&*" ".repeat(spaces));
23 // Next.
24 text = &text[index + 1..text.len()];
25 }
27 *cursor += text.len();
28 buffer.push_str(text);
29 }
30 }
31 }
33 buffer
36pub fn replace_nonprintable(input: &str, tab_width: usize) -> String {
37 let mut output = String::new();
39 let tab_width = if tab_width == 0 { 4 } else { tab_width };
41 for chr in input.chars() {
42 match chr {
43 // space
44 ' ' => output.push('•'),
45 // tab
46 '\t' => {
47 if tab_width == 1 {
48 output.push('↹');
49 } else {
50 output.push('├');
51 output.push_str(&"─".repeat(tab_width - 2));
52 output.push('┤');
53 }
54 }
55 // line feed
56 '\x0A' => output.push('␊'),
57 // carriage return
58 '\x0D' => output.push('␍'),
59 // null
60 '\x00' => output.push('␀'),
61 // bell
62 '\x07' => output.push('␇'),
63 // backspace
64 '\x08' => output.push('␈'),
65 // escape
66 '\x1B' => output.push('␛'),
67 // anything else
68 _ => output.push(chr),
69 }
70 }
72 output