mirror of
https://github.com/uutils/coreutils
synced 2024-11-16 01:38:04 +00:00
fold: variable width tabs, guard treating tab as whitespace
Treat tab chars as advancing to the next tab stop rather than having a fixed 8-column width. Also treat tab as a whitespace split target only when splitting on word boundaries.
This commit is contained in:
parent
bd8b129d9a
commit
e5c61a28be
5 changed files with 114 additions and 4 deletions
|
@ -14,6 +14,8 @@ use std::fs::File;
|
||||||
use std::io::{stdin, BufRead, BufReader, Read};
|
use std::io::{stdin, BufRead, BufReader, Read};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
const TAB_WIDTH: usize = 8;
|
||||||
|
|
||||||
static SYNTAX: &str = "[OPTION]... [FILE]...";
|
static SYNTAX: &str = "[OPTION]... [FILE]...";
|
||||||
static SUMMARY: &str = "Writes each file (or standard input if no files are given)
|
static SUMMARY: &str = "Writes each file (or standard input if no files are given)
|
||||||
to standard output whilst breaking long lines";
|
to standard output whilst breaking long lines";
|
||||||
|
@ -220,11 +222,14 @@ fn fold_file<T: Read>(mut file: BufReader<T>, spaces: bool, width: usize) {
|
||||||
|
|
||||||
match ch {
|
match ch {
|
||||||
'\t' => {
|
'\t' => {
|
||||||
if col_count + 8 > width && !output.is_empty() {
|
let next_tab_stop = col_count + TAB_WIDTH - col_count % TAB_WIDTH;
|
||||||
|
|
||||||
|
if next_tab_stop > width && !output.is_empty() {
|
||||||
emit_output!();
|
emit_output!();
|
||||||
}
|
}
|
||||||
col_count += 8;
|
|
||||||
last_space = Some(char_count);
|
col_count = next_tab_stop;
|
||||||
|
last_space = if spaces { Some(char_count) } else { None };
|
||||||
}
|
}
|
||||||
'\x08' => {
|
'\x08' => {
|
||||||
// FIXME: does not match GNU's handling of backspace
|
// FIXME: does not match GNU's handling of backspace
|
||||||
|
|
|
@ -132,7 +132,7 @@ fn test_single_tab_should_not_add_extra_newline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tab_counts_as_8_columns() {
|
fn test_initial_tab_counts_as_8_columns() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
.arg("-w8")
|
.arg("-w8")
|
||||||
.pipe_in("\t1")
|
.pipe_in("\t1")
|
||||||
|
@ -140,6 +140,33 @@ fn test_tab_counts_as_8_columns() {
|
||||||
.stdout_is("\t\n1");
|
.stdout_is("\t\n1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tab_should_advance_to_next_tab_stop() {
|
||||||
|
// tab advances the column count to the next tab stop, i.e. the width
|
||||||
|
// of the tab varies based on the leading text
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-w8", "tab_stops.input"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_fixture("tab_stops_w8.expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_all_tabs_should_advance_to_next_tab_stops() {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-w16", "tab_stops.input"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_fixture("tab_stops_w16.expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_before_tab_with_narrow_width() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("-w7")
|
||||||
|
.pipe_in("a\t1")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("a\n\t\n1");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fold_at_word_boundary() {
|
fn test_fold_at_word_boundary() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
@ -167,8 +194,35 @@ fn test_fold_at_word_boundary_preserve_final_newline() {
|
||||||
.stdout_is("one \ntwo\n");
|
.stdout_is("one \ntwo\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_at_tab() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("-w8")
|
||||||
|
.pipe_in("a\tbbb\n")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("a\t\nbbb\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_after_tab() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("-w10")
|
||||||
|
.pipe_in("a\tbbb\n")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("a\tbb\nb\n");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fold_at_tab_as_word_boundary() {
|
fn test_fold_at_tab_as_word_boundary() {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-w8", "-s"])
|
||||||
|
.pipe_in("a\tbbb\n")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("a\t\nbbb\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_after_tab_as_word_boundary() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
.args(&["-w10", "-s"])
|
.args(&["-w10", "-s"])
|
||||||
.pipe_in("a\tbbb\n")
|
.pipe_in("a\tbbb\n")
|
||||||
|
@ -317,6 +371,15 @@ fn test_tab_counts_as_one_byte() {
|
||||||
.stdout_is("1\t\n2\n");
|
.stdout_is("1\t\n2\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bytewise_fold_before_tab_with_narrow_width() {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-w7", "-b"])
|
||||||
|
.pipe_in("a\t1")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is("a\t1");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bytewise_fold_at_word_boundary_only_whitespace() {
|
fn test_bytewise_fold_at_word_boundary_only_whitespace() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
|
11
tests/fixtures/fold/tab_stops.input
vendored
Normal file
11
tests/fixtures/fold/tab_stops.input
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
1
|
||||||
|
12
|
||||||
|
123
|
||||||
|
1234
|
||||||
|
12345
|
||||||
|
123456
|
||||||
|
1234567
|
||||||
|
12345678
|
||||||
|
123456781
|
||||||
|
12345678 2
|
||||||
|
12345678 2 4
|
13
tests/fixtures/fold/tab_stops_w16.expected
vendored
Normal file
13
tests/fixtures/fold/tab_stops_w16.expected
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
1
|
||||||
|
12
|
||||||
|
123
|
||||||
|
1234
|
||||||
|
12345
|
||||||
|
123456
|
||||||
|
1234567
|
||||||
|
12345678
|
||||||
|
123456781
|
||||||
|
12345678
|
||||||
|
2
|
||||||
|
12345678
|
||||||
|
2 4
|
18
tests/fixtures/fold/tab_stops_w8.expected
vendored
Normal file
18
tests/fixtures/fold/tab_stops_w8.expected
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
1
|
||||||
|
12
|
||||||
|
123
|
||||||
|
1234
|
||||||
|
12345
|
||||||
|
123456
|
||||||
|
1234567
|
||||||
|
12345678
|
||||||
|
|
||||||
|
12345678
|
||||||
|
1
|
||||||
|
12345678
|
||||||
|
|
||||||
|
2
|
||||||
|
12345678
|
||||||
|
|
||||||
|
2
|
||||||
|
4
|
Loading…
Reference in a new issue