2018-09-10 18:11:59 -07:00
|
|
|
use console::AnsiCodeIterator;
|
|
|
|
|
|
|
|
/// Expand tabs like an ANSI-enabled expand(1).
|
2018-11-01 13:02:29 +01:00
|
|
|
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
|
2018-09-10 18:11:59 -07:00
|
|
|
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) => {
|
|
|
|
while let Some(index) = text.find('\t') {
|
|
|
|
// Add previous text.
|
|
|
|
if index > 0 {
|
2018-09-11 13:45:49 -07:00
|
|
|
*cursor += index;
|
2018-09-10 18:11:59 -07:00
|
|
|
buffer.push_str(&text[0..index]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add tab.
|
2018-09-11 13:45:49 -07:00
|
|
|
let spaces = width - (*cursor % width);
|
|
|
|
*cursor += spaces;
|
2018-09-10 18:11:59 -07:00
|
|
|
buffer.push_str(&*" ".repeat(spaces));
|
|
|
|
|
|
|
|
// Next.
|
|
|
|
text = &text[index + 1..text.len()];
|
|
|
|
}
|
|
|
|
|
2018-09-11 13:45:49 -07:00
|
|
|
*cursor += text.len();
|
2018-09-10 18:11:59 -07:00
|
|
|
buffer.push_str(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer
|
|
|
|
}
|
2018-11-01 13:02:29 +01:00
|
|
|
|
2018-11-01 20:29:48 +01:00
|
|
|
pub fn replace_nonprintable(input: &str, tab_width: usize) -> String {
|
|
|
|
let mut output = String::new();
|
2018-11-01 13:02:29 +01:00
|
|
|
|
2018-11-01 19:40:26 +01:00
|
|
|
let tab_width = if tab_width == 0 { 4 } else { tab_width };
|
2018-11-01 13:02:29 +01:00
|
|
|
|
2018-11-01 20:29:48 +01:00
|
|
|
for chr in input.chars() {
|
|
|
|
match chr {
|
2018-11-01 13:02:29 +01:00
|
|
|
// space
|
2018-11-01 20:29:48 +01:00
|
|
|
' ' => output.push('•'),
|
2018-11-01 13:02:29 +01:00
|
|
|
// tab
|
2018-11-01 20:29:48 +01:00
|
|
|
'\t' => {
|
2018-11-01 19:40:26 +01:00
|
|
|
if tab_width == 1 {
|
2018-11-01 20:29:48 +01:00
|
|
|
output.push('↹');
|
2018-11-01 19:40:26 +01:00
|
|
|
} else {
|
2018-11-01 20:29:48 +01:00
|
|
|
output.push('├');
|
|
|
|
output.push_str(&"─".repeat(tab_width - 2));
|
|
|
|
output.push('┤');
|
2018-11-01 19:40:26 +01:00
|
|
|
}
|
2018-11-01 13:02:29 +01:00
|
|
|
}
|
2018-11-01 19:54:04 +01:00
|
|
|
// line feed
|
2018-11-01 20:29:48 +01:00
|
|
|
'\x0A' => output.push('␊'),
|
2018-11-01 13:02:29 +01:00
|
|
|
// carriage return
|
2018-11-01 20:29:48 +01:00
|
|
|
'\x0D' => output.push('␍'),
|
2018-11-01 13:02:29 +01:00
|
|
|
// null
|
2018-11-01 20:29:48 +01:00
|
|
|
'\x00' => output.push('␀'),
|
2018-11-01 13:02:29 +01:00
|
|
|
// bell
|
2018-11-01 20:29:48 +01:00
|
|
|
'\x07' => output.push('␇'),
|
2018-11-01 13:02:29 +01:00
|
|
|
// backspace
|
2018-11-01 20:29:48 +01:00
|
|
|
'\x08' => output.push('␈'),
|
2018-11-01 13:02:29 +01:00
|
|
|
// escape
|
2018-11-01 20:29:48 +01:00
|
|
|
'\x1B' => output.push('␛'),
|
2018-11-01 13:02:29 +01:00
|
|
|
// anything else
|
2018-11-01 20:29:48 +01:00
|
|
|
_ => output.push(chr),
|
2018-11-01 13:02:29 +01:00
|
|
|
}
|
|
|
|
}
|
2018-11-01 20:29:48 +01:00
|
|
|
|
|
|
|
output
|
2018-11-01 13:02:29 +01:00
|
|
|
}
|