mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
pr: add -m and -o option
pr: Add -o option
This commit is contained in:
parent
dd07aed4d1
commit
5956894d00
7 changed files with 1151 additions and 94 deletions
443
src/pr/pr.rs
443
src/pr/pr.rs
|
@ -15,12 +15,12 @@ extern crate chrono;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
use std::io::{BufRead, BufReader, stdin, stdout, stderr, Error, Read, Write, Stdout, Lines};
|
use std::io::{BufRead, BufReader, stdin, stdout, stderr, Error, Read, Write, Stdout, Lines, Stdin};
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use chrono::offset::Local;
|
use chrono::offset::Local;
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use getopts::{Matches, Options};
|
use getopts::{Matches, Options};
|
||||||
use std::fs::{metadata, File};
|
use std::fs::{metadata, File, Metadata};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::fs::FileTypeExt;
|
use std::os::unix::fs::FileTypeExt;
|
||||||
use quick_error::ResultExt;
|
use quick_error::ResultExt;
|
||||||
|
@ -29,6 +29,7 @@ use getopts::{HasArg, Occur};
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
use itertools::{Itertools, GroupBy};
|
use itertools::{Itertools, GroupBy};
|
||||||
use std::iter::{Enumerate, Map, TakeWhile, SkipWhile};
|
use std::iter::{Enumerate, Map, TakeWhile, SkipWhile};
|
||||||
|
use itertools::structs::KMergeBy;
|
||||||
|
|
||||||
static NAME: &str = "pr";
|
static NAME: &str = "pr";
|
||||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
@ -51,6 +52,8 @@ static COLUMN_WIDTH_OPTION: &str = "w";
|
||||||
static ACROSS_OPTION: &str = "a";
|
static ACROSS_OPTION: &str = "a";
|
||||||
static COLUMN_OPTION: &str = "column";
|
static COLUMN_OPTION: &str = "column";
|
||||||
static COLUMN_SEPARATOR_OPTION: &str = "s";
|
static COLUMN_SEPARATOR_OPTION: &str = "s";
|
||||||
|
static MERGE_FILES_PRINT: &str = "m";
|
||||||
|
static OFFSET_SPACES_OPTION: &str = "o";
|
||||||
static FILE_STDIN: &str = "-";
|
static FILE_STDIN: &str = "-";
|
||||||
static READ_BUFFER_SIZE: usize = 1024 * 64;
|
static READ_BUFFER_SIZE: usize = 1024 * 64;
|
||||||
static DEFAULT_COLUMN_WIDTH: usize = 72;
|
static DEFAULT_COLUMN_WIDTH: usize = 72;
|
||||||
|
@ -71,6 +74,22 @@ struct OutputOptions {
|
||||||
content_lines_per_page: usize,
|
content_lines_per_page: usize,
|
||||||
page_separator_char: String,
|
page_separator_char: String,
|
||||||
column_mode_options: Option<ColumnModeOptions>,
|
column_mode_options: Option<ColumnModeOptions>,
|
||||||
|
merge_files_print: Option<usize>,
|
||||||
|
offset_spaces: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FileLine {
|
||||||
|
file_id: usize,
|
||||||
|
line_number: usize,
|
||||||
|
page_number: usize,
|
||||||
|
key: usize,
|
||||||
|
line_content: Result<String, Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<FileLine> for FileLine {
|
||||||
|
fn as_ref(&self) -> &FileLine {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ColumnModeOptions {
|
struct ColumnModeOptions {
|
||||||
|
@ -283,6 +302,27 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
Occur::Optional,
|
Occur::Optional,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
opts.opt(
|
||||||
|
MERGE_FILES_PRINT,
|
||||||
|
"merge",
|
||||||
|
"Merge files. Standard output shall be formatted so the pr utility writes one line from each file specified by a
|
||||||
|
file operand, side by side into text columns of equal fixed widths, in terms of the number of column positions.
|
||||||
|
Implementations shall support merging of at least nine file operands.",
|
||||||
|
"",
|
||||||
|
HasArg::No,
|
||||||
|
Occur::Optional,
|
||||||
|
);
|
||||||
|
|
||||||
|
opts.opt(
|
||||||
|
OFFSET_SPACES_OPTION,
|
||||||
|
"indent",
|
||||||
|
"Each line of output shall be preceded by offset <space>s. If the -o option is not specified, the default offset
|
||||||
|
shall be zero. The space taken is in addition to the output line width (see the -w option below).",
|
||||||
|
"offset",
|
||||||
|
HasArg::Yes,
|
||||||
|
Occur::Optional,
|
||||||
|
);
|
||||||
|
|
||||||
opts.optflag("", "help", "display this help and exit");
|
opts.optflag("", "help", "display this help and exit");
|
||||||
opts.optflag("V", "version", "output version information and exit");
|
opts.optflag("V", "version", "output version information and exit");
|
||||||
|
|
||||||
|
@ -297,21 +337,20 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut files: Vec<String> = matches.free.clone();
|
let mut files: Vec<String> = matches.free.clone();
|
||||||
if files.is_empty() {
|
// -n value is optional if -n <path> is given the opts gets confused
|
||||||
// -n value is optional if -n <path> is given the opts gets confused
|
// if -n is used just before file path it might be captured as value of -n
|
||||||
if matches.opt_present(NUMBERING_MODE_OPTION) {
|
if matches.opt_str(NUMBERING_MODE_OPTION).is_some() {
|
||||||
let maybe_file = matches.opt_str(NUMBERING_MODE_OPTION).unwrap();
|
let maybe_a_file_path: String = matches.opt_str(NUMBERING_MODE_OPTION).unwrap();
|
||||||
let is_afile = is_a_file(&maybe_file);
|
let is_file: bool = is_a_file(&maybe_a_file_path);
|
||||||
if !is_afile {
|
if !is_file && files.is_empty() {
|
||||||
print_error(&matches, PrError::NotExists(maybe_file));
|
print_error(&matches, PrError::NotExists(maybe_a_file_path));
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else if is_file {
|
||||||
files.push(maybe_file);
|
files.insert(0, maybe_a_file_path);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//For stdin
|
|
||||||
files.push(FILE_STDIN.to_owned());
|
|
||||||
}
|
}
|
||||||
|
} else if files.is_empty() {
|
||||||
|
//For stdin
|
||||||
|
files.insert(0, FILE_STDIN.to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,14 +358,25 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
return print_usage(&mut opts, &matches);
|
return print_usage(&mut opts, &matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
for f in files {
|
let file_groups: Vec<Vec<String>> = if matches.opt_present(MERGE_FILES_PRINT) {
|
||||||
let result_options = build_options(&matches, &f);
|
vec![files]
|
||||||
|
} else {
|
||||||
|
files.into_iter().map(|i| vec![i]).collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
for file_group in file_groups {
|
||||||
|
let result_options: Result<OutputOptions, PrError> = build_options(&matches, &file_group);
|
||||||
if result_options.is_err() {
|
if result_options.is_err() {
|
||||||
print_error(&matches, result_options.err().unwrap());
|
print_error(&matches, result_options.err().unwrap());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
let options = &result_options.unwrap();
|
let options: &OutputOptions = &result_options.unwrap();
|
||||||
let status: i32 = match pr(&f, options) {
|
let cmd_result: Result<i32, PrError> = if file_group.len() == 1 {
|
||||||
|
pr(&file_group.get(0).unwrap(), options)
|
||||||
|
} else {
|
||||||
|
mpr(&file_group, options)
|
||||||
|
};
|
||||||
|
let status: i32 = match cmd_result {
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
print_error(&matches, error);
|
print_error(&matches, error);
|
||||||
1
|
1
|
||||||
|
@ -385,22 +435,44 @@ fn print_usage(opts: &mut Options, matches: &Matches) -> i32 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrError> {
|
fn build_options(matches: &Matches, paths: &Vec<String>) -> Result<OutputOptions, PrError> {
|
||||||
let header: String = matches.opt_str(STRING_HEADER_OPTION).unwrap_or(if path == FILE_STDIN {
|
let is_merge_mode: bool = matches.opt_present(MERGE_FILES_PRINT);
|
||||||
|
|
||||||
|
if is_merge_mode && matches.opt_present(COLUMN_OPTION) {
|
||||||
|
let err_msg: String = "cannot specify number of columns when printing in parallel".to_string();
|
||||||
|
return Err(PrError::EncounteredErrors(err_msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_merge_mode && matches.opt_present(ACROSS_OPTION) {
|
||||||
|
let err_msg: String = "cannot specify both printing across and printing in parallel".to_string();
|
||||||
|
return Err(PrError::EncounteredErrors(err_msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let merge_files_print: Option<usize> = if matches.opt_present(MERGE_FILES_PRINT) {
|
||||||
|
Some(paths.len())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let header: String = matches.opt_str(STRING_HEADER_OPTION).unwrap_or(if is_merge_mode {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
path.to_string()
|
if paths[0].to_string() == FILE_STDIN {
|
||||||
|
"".to_string()
|
||||||
|
} else {
|
||||||
|
paths[0].to_string()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let default_first_number = NumberingMode::default().first_number;
|
let default_first_number: usize = NumberingMode::default().first_number;
|
||||||
let first_number = matches.opt_str(FIRST_LINE_NUMBER_OPTION).map(|n| {
|
let first_number: usize = matches.opt_str(FIRST_LINE_NUMBER_OPTION).map(|n| {
|
||||||
n.parse::<usize>().unwrap_or(default_first_number)
|
n.parse::<usize>().unwrap_or(default_first_number)
|
||||||
}).unwrap_or(default_first_number);
|
}).unwrap_or(default_first_number);
|
||||||
|
|
||||||
let numbering_options: Option<NumberingMode> = matches.opt_str(NUMBERING_MODE_OPTION).map(|i| {
|
let numbering_options: Option<NumberingMode> = matches.opt_str(NUMBERING_MODE_OPTION).map(|i| {
|
||||||
let parse_result = i.parse::<usize>();
|
let parse_result: Result<usize, ParseIntError> = i.parse::<usize>();
|
||||||
|
|
||||||
let separator = if parse_result.is_err() {
|
let separator: String = if parse_result.is_err() {
|
||||||
if is_a_file(&i) {
|
if is_a_file(&i) {
|
||||||
NumberingMode::default().separator
|
NumberingMode::default().separator
|
||||||
} else {
|
} else {
|
||||||
|
@ -410,7 +482,7 @@ fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrEr
|
||||||
NumberingMode::default().separator
|
NumberingMode::default().separator
|
||||||
};
|
};
|
||||||
|
|
||||||
let width = if parse_result.is_err() {
|
let width: usize = if parse_result.is_err() {
|
||||||
if is_a_file(&i) {
|
if is_a_file(&i) {
|
||||||
NumberingMode::default().width
|
NumberingMode::default().width
|
||||||
} else {
|
} else {
|
||||||
|
@ -432,7 +504,7 @@ fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrEr
|
||||||
return None;
|
return None;
|
||||||
});
|
});
|
||||||
|
|
||||||
let double_space = matches.opt_present(DOUBLE_SPACE_OPTION);
|
let double_space: bool = matches.opt_present(DOUBLE_SPACE_OPTION);
|
||||||
|
|
||||||
let content_line_separator: String = if double_space {
|
let content_line_separator: String = if double_space {
|
||||||
"\n\n".to_string()
|
"\n\n".to_string()
|
||||||
|
@ -442,21 +514,21 @@ fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrEr
|
||||||
|
|
||||||
let line_separator: String = "\n".to_string();
|
let line_separator: String = "\n".to_string();
|
||||||
|
|
||||||
let last_modified_time = if path.eq(FILE_STDIN) {
|
let last_modified_time: String = if is_merge_mode || paths[0].eq(FILE_STDIN) {
|
||||||
current_time()
|
current_time()
|
||||||
} else {
|
} else {
|
||||||
file_last_modified_time(path)
|
file_last_modified_time(paths.get(0).unwrap())
|
||||||
};
|
};
|
||||||
|
|
||||||
let invalid_pages_map = |i: Result<usize, ParseIntError>| {
|
let invalid_pages_map = |i: Result<usize, ParseIntError>| {
|
||||||
let unparsed_value = matches.opt_str(PAGE_RANGE_OPTION).unwrap();
|
let unparsed_value: String = matches.opt_str(PAGE_RANGE_OPTION).unwrap();
|
||||||
match i {
|
match i {
|
||||||
Ok(val) => Ok(val),
|
Ok(val) => Ok(val),
|
||||||
Err(_e) => Err(PrError::EncounteredErrors(format!("invalid --pages argument '{}'", unparsed_value)))
|
Err(_e) => Err(PrError::EncounteredErrors(format!("invalid --pages argument '{}'", unparsed_value)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let start_page = match matches.opt_str(PAGE_RANGE_OPTION).map(|i| {
|
let start_page: Option<usize> = match matches.opt_str(PAGE_RANGE_OPTION).map(|i| {
|
||||||
let x: Vec<&str> = i.split(":").collect();
|
let x: Vec<&str> = i.split(":").collect();
|
||||||
x[0].parse::<usize>()
|
x[0].parse::<usize>()
|
||||||
}).map(invalid_pages_map)
|
}).map(invalid_pages_map)
|
||||||
|
@ -465,9 +537,9 @@ fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrEr
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
|
|
||||||
let end_page = match matches.opt_str(PAGE_RANGE_OPTION)
|
let end_page: Option<usize> = match matches.opt_str(PAGE_RANGE_OPTION)
|
||||||
.filter(|i| i.contains(":"))
|
.filter(|i: &String| i.contains(":"))
|
||||||
.map(|i| {
|
.map(|i: String| {
|
||||||
let x: Vec<&str> = i.split(":").collect();
|
let x: Vec<&str> = i.split(":").collect();
|
||||||
x[1].parse::<usize>()
|
x[1].parse::<usize>()
|
||||||
})
|
})
|
||||||
|
@ -481,38 +553,38 @@ fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrEr
|
||||||
return Err(PrError::EncounteredErrors(format!("invalid --pages argument '{}:{}'", start_page.unwrap(), end_page.unwrap())));
|
return Err(PrError::EncounteredErrors(format!("invalid --pages argument '{}:{}'", start_page.unwrap(), end_page.unwrap())));
|
||||||
}
|
}
|
||||||
|
|
||||||
let page_length = match matches.opt_str(PAGE_LENGTH_OPTION).map(|i| {
|
let page_length: usize = match matches.opt_str(PAGE_LENGTH_OPTION).map(|i| {
|
||||||
i.parse::<usize>()
|
i.parse::<usize>()
|
||||||
}) {
|
}) {
|
||||||
Some(res) => res?,
|
Some(res) => res?,
|
||||||
_ => LINES_PER_PAGE
|
_ => LINES_PER_PAGE
|
||||||
};
|
};
|
||||||
let page_length_le_ht = page_length < (HEADER_LINES_PER_PAGE + TRAILER_LINES_PER_PAGE);
|
let page_length_le_ht: bool = page_length < (HEADER_LINES_PER_PAGE + TRAILER_LINES_PER_PAGE);
|
||||||
|
|
||||||
let display_header_and_trailer = !(page_length_le_ht) && !matches.opt_present(NO_HEADER_TRAILER_OPTION);
|
let display_header_and_trailer: bool = !(page_length_le_ht) && !matches.opt_present(NO_HEADER_TRAILER_OPTION);
|
||||||
|
|
||||||
let content_lines_per_page = if page_length_le_ht {
|
let content_lines_per_page: usize = if page_length_le_ht {
|
||||||
page_length
|
page_length
|
||||||
} else {
|
} else {
|
||||||
page_length - (HEADER_LINES_PER_PAGE + TRAILER_LINES_PER_PAGE)
|
page_length - (HEADER_LINES_PER_PAGE + TRAILER_LINES_PER_PAGE)
|
||||||
};
|
};
|
||||||
|
|
||||||
let page_separator_char = matches.opt_str(FORM_FEED_OPTION).map(|_i| {
|
let page_separator_char: String = matches.opt_str(FORM_FEED_OPTION).map(|_i| {
|
||||||
'\u{000A}'.to_string()
|
'\u{000A}'.to_string()
|
||||||
}).unwrap_or("\n".to_string());
|
}).unwrap_or("\n".to_string());
|
||||||
|
|
||||||
let column_width = match matches.opt_str(COLUMN_WIDTH_OPTION).map(|i| i.parse::<usize>()) {
|
let column_width: Option<usize> = match matches.opt_str(COLUMN_WIDTH_OPTION).map(|i| i.parse::<usize>()) {
|
||||||
Some(res) => Some(res?),
|
Some(res) => Some(res?),
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
|
|
||||||
let across_mode = matches.opt_present(ACROSS_OPTION);
|
let across_mode: bool = matches.opt_present(ACROSS_OPTION);
|
||||||
|
|
||||||
let column_separator = matches.opt_str(COLUMN_SEPARATOR_OPTION)
|
let column_separator: String = matches.opt_str(COLUMN_SEPARATOR_OPTION)
|
||||||
.unwrap_or(DEFAULT_COLUMN_SEPARATOR.to_string());
|
.unwrap_or(DEFAULT_COLUMN_SEPARATOR.to_string());
|
||||||
|
|
||||||
|
|
||||||
let column_mode_options = match matches.opt_str(COLUMN_OPTION).map(|i| {
|
let column_mode_options: Option<ColumnModeOptions> = match matches.opt_str(COLUMN_OPTION).map(|i| {
|
||||||
i.parse::<usize>()
|
i.parse::<usize>()
|
||||||
}) {
|
}) {
|
||||||
Some(res) => {
|
Some(res) => {
|
||||||
|
@ -529,6 +601,14 @@ fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrEr
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let offset_spaces: usize = matches.opt_str(OFFSET_SPACES_OPTION)
|
||||||
|
.map(|i| {
|
||||||
|
match i.parse::<usize>() {
|
||||||
|
Ok(val)=> Ok(val),
|
||||||
|
Err(e)=> Err(PrError::EncounteredErrors("".to_string()))
|
||||||
|
}
|
||||||
|
}).unwrap_or(Ok(0))?;
|
||||||
|
|
||||||
Ok(OutputOptions {
|
Ok(OutputOptions {
|
||||||
number: numbering_options,
|
number: numbering_options,
|
||||||
header,
|
header,
|
||||||
|
@ -543,16 +623,18 @@ fn build_options(matches: &Matches, path: &String) -> Result<OutputOptions, PrEr
|
||||||
content_lines_per_page,
|
content_lines_per_page,
|
||||||
page_separator_char,
|
page_separator_char,
|
||||||
column_mode_options,
|
column_mode_options,
|
||||||
|
merge_files_print,
|
||||||
|
offset_spaces,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(path: &str) -> Result<Box<Read>, PrError> {
|
fn open(path: &str) -> Result<Box<Read>, PrError> {
|
||||||
if path == FILE_STDIN {
|
if path == FILE_STDIN {
|
||||||
let stdin = stdin();
|
let stdin: Stdin = stdin();
|
||||||
return Ok(Box::new(stdin) as Box<Read>);
|
return Ok(Box::new(stdin) as Box<Read>);
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata(path).map(|i| {
|
metadata(path).map(|i: Metadata| {
|
||||||
let path_string = path.to_string();
|
let path_string = path.to_string();
|
||||||
match i.file_type() {
|
match i.file_type() {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -582,50 +664,217 @@ fn open(path: &str) -> Result<Box<Read>, PrError> {
|
||||||
}).unwrap_or(Err(PrError::NotExists(path.to_string())))
|
}).unwrap_or(Err(PrError::NotExists(path.to_string())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pr(path: &str, options: &OutputOptions) -> Result<i32, PrError> {
|
fn pr(path: &String, options: &OutputOptions) -> Result<i32, PrError> {
|
||||||
let start_page: &usize = options.start_page.as_ref().unwrap_or(&1);
|
let start_page: &usize = options.start_page.as_ref().unwrap_or(&1);
|
||||||
|
let start_line_number: usize = get_start_line_number(options);
|
||||||
let last_page: Option<&usize> = options.end_page.as_ref();
|
let last_page: Option<&usize> = options.end_page.as_ref();
|
||||||
let lines_needed_per_page: usize = lines_to_read_for_page(options);
|
let lines_needed_per_page: usize = lines_to_read_for_page(options);
|
||||||
let start_line_number: usize = get_start_line_number(options);
|
let file_line_groups: GroupBy<usize, Map<TakeWhile<SkipWhile<Map<Enumerate<Lines<BufReader<Box<Read>>>>, _>, _>, _>, _>, _> =
|
||||||
|
BufReader::with_capacity(READ_BUFFER_SIZE, open(path).unwrap())
|
||||||
let pages: GroupBy<usize, Map<TakeWhile<SkipWhile<Enumerate<Lines<BufReader<Box<Read>>>>, _>, _>, _>, _> =
|
|
||||||
BufReader::with_capacity(READ_BUFFER_SIZE, open(path)?)
|
|
||||||
.lines()
|
.lines()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.skip_while(|line_index: &(usize, Result<String, Error>)| {
|
.map(move |i: (usize, Result<String, Error>)| {
|
||||||
// Skip the initial lines if not in page range
|
FileLine {
|
||||||
let start_line_index_of_start_page = (*start_page - 1) * lines_needed_per_page;
|
file_id: 0,
|
||||||
line_index.0 < (start_line_index_of_start_page)
|
line_number: i.0,
|
||||||
|
line_content: i.1,
|
||||||
|
page_number: 0,
|
||||||
|
key: 0,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.take_while(|i: &(usize, Result<String, Error>)| {
|
.skip_while(move |file_line: &FileLine| {
|
||||||
|
// Skip the initial lines if not in page range
|
||||||
|
let start_line_index_of_start_page = (start_page - 1) * lines_needed_per_page;
|
||||||
|
file_line.line_number < (start_line_index_of_start_page)
|
||||||
|
})
|
||||||
|
.take_while(move |file_line: &FileLine| {
|
||||||
// Only read the file until provided last page reached
|
// Only read the file until provided last page reached
|
||||||
last_page
|
last_page
|
||||||
.map(|lp| i.0 < ((*lp) * lines_needed_per_page))
|
.map(|lp| file_line.line_number < ((*lp) * lines_needed_per_page))
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
})
|
})
|
||||||
.map(|i: (usize, Result<String, Error>)| (i.0 + start_line_number, i.1)) // get display line number with line content
|
.map(move |file_line: FileLine| {
|
||||||
.group_by(|i: &(usize, Result<String, Error>)| {
|
let page_number = ((file_line.line_number + 1) as f64 / lines_needed_per_page as f64).ceil() as usize;
|
||||||
((i.0 - start_line_number + 1) as f64 / lines_needed_per_page as f64).ceil() as usize
|
FileLine {
|
||||||
}); // group them by page number
|
line_number: file_line.line_number + start_line_number,
|
||||||
|
page_number,
|
||||||
|
key: page_number,
|
||||||
|
..file_line
|
||||||
|
}
|
||||||
|
}) // get display line number with line content
|
||||||
|
.group_by(|file_line: &FileLine| {
|
||||||
|
file_line.page_number
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
for (page_number, content_with_line_number) in pages.into_iter() {
|
for (page_number, file_line_group) in file_line_groups.into_iter() {
|
||||||
let mut lines: Vec<(usize, String)> = Vec::new();
|
let mut lines: Vec<FileLine> = Vec::new();
|
||||||
for line_number_and_line in content_with_line_number {
|
for file_line in file_line_group {
|
||||||
let line_number: usize = line_number_and_line.0;
|
if file_line.line_content.is_err() {
|
||||||
let line: Result<String, Error> = line_number_and_line.1;
|
return Err(PrError::from(file_line.line_content.unwrap_err()));
|
||||||
let x = line?;
|
}
|
||||||
lines.push((line_number, x));
|
lines.push(file_line);
|
||||||
|
}
|
||||||
|
let print_status: Result<usize, Error> = print_page(&lines, options, &page_number);
|
||||||
|
if print_status.is_err() {
|
||||||
|
return Err(PrError::from(print_status.unwrap_err()));
|
||||||
}
|
}
|
||||||
|
|
||||||
print_page(&lines, options, &page_number);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_page(lines: &Vec<(usize, String)>, options: &OutputOptions, page: &usize) -> Result<usize, Error> {
|
fn mpr(paths: &Vec<String>, options: &OutputOptions) -> Result<i32, PrError> {
|
||||||
|
let nfiles = paths.len();
|
||||||
|
|
||||||
|
let lines_needed_per_page: usize = lines_to_read_for_page(options);
|
||||||
|
let lines_needed_per_page_f64: f64 = lines_needed_per_page as f64;
|
||||||
|
let start_page: &usize = options.start_page.as_ref().unwrap_or(&1);
|
||||||
|
let last_page: Option<&usize> = options.end_page.as_ref();
|
||||||
|
|
||||||
|
let file_line_groups: GroupBy<usize, KMergeBy<Map<TakeWhile<SkipWhile<Map<Enumerate<Lines<BufReader<Box<Read>>>>, _>, _>, _>, _>, _>, _> = paths
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|indexed_path: (usize, &String)| {
|
||||||
|
let start_line_number: usize = get_start_line_number(options);
|
||||||
|
BufReader::with_capacity(READ_BUFFER_SIZE, open(indexed_path.1).unwrap())
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(move |i: (usize, Result<String, Error>)| {
|
||||||
|
FileLine {
|
||||||
|
file_id: indexed_path.0,
|
||||||
|
line_number: i.0,
|
||||||
|
line_content: i.1,
|
||||||
|
page_number: 0,
|
||||||
|
key: 0,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.skip_while(move |file_line: &FileLine| {
|
||||||
|
// Skip the initial lines if not in page range
|
||||||
|
let start_line_index_of_start_page = (start_page - 1) * lines_needed_per_page;
|
||||||
|
file_line.line_number < (start_line_index_of_start_page)
|
||||||
|
})
|
||||||
|
.take_while(move |file_line: &FileLine| {
|
||||||
|
// Only read the file until provided last page reached
|
||||||
|
|
||||||
|
last_page
|
||||||
|
.map(|lp| file_line.line_number < ((*lp) * lines_needed_per_page))
|
||||||
|
.unwrap_or(true)
|
||||||
|
})
|
||||||
|
.map(move |file_line: FileLine| {
|
||||||
|
let page_number = ((file_line.line_number + 2 - start_line_number) as f64 / (lines_needed_per_page_f64)).ceil() as usize;
|
||||||
|
FileLine {
|
||||||
|
line_number: file_line.line_number + start_line_number,
|
||||||
|
page_number,
|
||||||
|
key: page_number * nfiles + file_line.file_id,
|
||||||
|
..file_line
|
||||||
|
}
|
||||||
|
}) // get display line number with line content
|
||||||
|
})
|
||||||
|
.kmerge_by(|a: &FileLine, b: &FileLine| {
|
||||||
|
if a.key == b.key {
|
||||||
|
a.line_number < b.line_number
|
||||||
|
} else {
|
||||||
|
a.key < b.key
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.group_by(|file_line: &FileLine| {
|
||||||
|
file_line.key
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut lines: Vec<FileLine> = Vec::new();
|
||||||
|
let start_page: &usize = options.start_page.as_ref().unwrap_or(&1);
|
||||||
|
let mut page_counter: usize = *start_page;
|
||||||
|
for (_key, file_line_group) in file_line_groups.into_iter() {
|
||||||
|
for file_line in file_line_group {
|
||||||
|
if file_line.line_content.is_err() {
|
||||||
|
return Err(PrError::from(file_line.line_content.unwrap_err()));
|
||||||
|
}
|
||||||
|
let new_page_number = file_line.page_number;
|
||||||
|
if page_counter != new_page_number {
|
||||||
|
fill_missing_files(&mut lines, lines_needed_per_page, &nfiles, page_counter);
|
||||||
|
let print_status: Result<usize, Error> = print_page(&lines, options, &page_counter);
|
||||||
|
if print_status.is_err() {
|
||||||
|
return Err(PrError::from(print_status.unwrap_err()));
|
||||||
|
}
|
||||||
|
lines = Vec::new();
|
||||||
|
}
|
||||||
|
lines.push(file_line);
|
||||||
|
page_counter = new_page_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_missing_files(&mut lines, lines_needed_per_page, &nfiles, page_counter);
|
||||||
|
let print_status: Result<usize, Error> = print_page(&lines, options, &page_counter);
|
||||||
|
if print_status.is_err() {
|
||||||
|
return Err(PrError::from(print_status.unwrap_err()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_missing_files(lines: &mut Vec<FileLine>, lines_per_file: usize, nfiles: &usize, page_number: usize) {
|
||||||
|
let init_line_number = (page_number - 1) * lines_per_file + 1;
|
||||||
|
let final_line_number = page_number * lines_per_file;
|
||||||
|
let mut file_id_counter: usize = 0;
|
||||||
|
let mut line_number_counter: usize = init_line_number;
|
||||||
|
let mut lines_processed: usize = 0;
|
||||||
|
let mut file_id_missing: bool = false;
|
||||||
|
for mut i in 0..lines_per_file * nfiles {
|
||||||
|
let file_id = lines.get(i).map(|i: &FileLine| i.file_id).unwrap_or(file_id_counter);
|
||||||
|
let line_number = lines.get(i).map(|i: &FileLine| i.line_number).unwrap_or(1);
|
||||||
|
if lines_processed == lines_per_file {
|
||||||
|
line_number_counter = init_line_number;
|
||||||
|
file_id_counter += 1;
|
||||||
|
lines_processed = 0;
|
||||||
|
file_id_missing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if file_id_counter >= *nfiles {
|
||||||
|
file_id_counter = 0;
|
||||||
|
file_id_missing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if file_id != file_id_counter {
|
||||||
|
file_id_missing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if file_id_missing {
|
||||||
|
// Insert missing file_ids
|
||||||
|
lines.insert(i, FileLine {
|
||||||
|
file_id: file_id_counter,
|
||||||
|
line_number: line_number_counter,
|
||||||
|
line_content: Ok("".to_string()),
|
||||||
|
page_number,
|
||||||
|
key: 0,
|
||||||
|
});
|
||||||
|
line_number_counter += 1;
|
||||||
|
} else {
|
||||||
|
// Insert missing lines for a file_id
|
||||||
|
if line_number < line_number_counter {
|
||||||
|
line_number_counter += 1;
|
||||||
|
lines.insert(i, FileLine {
|
||||||
|
file_id,
|
||||||
|
line_number: line_number_counter,
|
||||||
|
line_content: Ok("".to_string()),
|
||||||
|
page_number,
|
||||||
|
key: 0,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
line_number_counter = line_number;
|
||||||
|
if line_number_counter == final_line_number {
|
||||||
|
line_number_counter = init_line_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines_processed += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_page(lines: &Vec<FileLine>, options: &OutputOptions, page: &usize) -> Result<usize, Error> {
|
||||||
let page_separator = options.page_separator_char.as_bytes();
|
let page_separator = options.page_separator_char.as_bytes();
|
||||||
let header: Vec<String> = header_content(options, page);
|
let header: Vec<String> = header_content(options, page);
|
||||||
let trailer_content: Vec<String> = trailer_content(options);
|
let trailer_content: Vec<String> = trailer_content(options);
|
||||||
|
@ -653,7 +902,7 @@ fn print_page(lines: &Vec<(usize, String)>, options: &OutputOptions, page: &usiz
|
||||||
Ok(lines_written)
|
Ok(lines_written)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_columns(lines: &Vec<(usize, String)>, options: &OutputOptions, out: &mut Stdout) -> Result<usize, Error> {
|
fn write_columns(lines: &Vec<FileLine>, options: &OutputOptions, out: &mut Stdout) -> Result<usize, Error> {
|
||||||
let line_separator = options.content_line_separator.as_bytes();
|
let line_separator = options.content_line_separator.as_bytes();
|
||||||
let content_lines_per_page = if options.double_space {
|
let content_lines_per_page = if options.double_space {
|
||||||
options.content_lines_per_page / 2
|
options.content_lines_per_page / 2
|
||||||
|
@ -671,26 +920,35 @@ fn write_columns(lines: &Vec<(usize, String)>, options: &OutputOptions, out: &mu
|
||||||
.unwrap_or(NumberingMode::default().separator);
|
.unwrap_or(NumberingMode::default().separator);
|
||||||
|
|
||||||
let blank_line = "".to_string();
|
let blank_line = "".to_string();
|
||||||
let columns = get_columns(options);
|
let columns = options.merge_files_print.unwrap_or(get_columns(options));
|
||||||
|
let def_sep = DEFAULT_COLUMN_SEPARATOR.to_string();
|
||||||
let col_sep: &String = options
|
let col_sep: &String = options
|
||||||
.column_mode_options.as_ref()
|
.column_mode_options.as_ref()
|
||||||
.map(|i| &i.column_separator)
|
.map(|i| &i.column_separator)
|
||||||
.unwrap_or(&blank_line);
|
.unwrap_or(options
|
||||||
|
.merge_files_print
|
||||||
|
.map(|_k| &def_sep)
|
||||||
|
.unwrap_or(&blank_line)
|
||||||
|
);
|
||||||
|
|
||||||
let col_width: Option<usize> = options
|
let col_width: Option<usize> = options
|
||||||
.column_mode_options.as_ref()
|
.column_mode_options.as_ref()
|
||||||
.map(|i| i.width)
|
.map(|i| i.width)
|
||||||
.unwrap_or(None);
|
.unwrap_or(options
|
||||||
|
.merge_files_print
|
||||||
|
.map(|_k| Some(DEFAULT_COLUMN_WIDTH))
|
||||||
|
.unwrap_or(None)
|
||||||
|
);
|
||||||
|
|
||||||
let across_mode = options
|
let across_mode = options
|
||||||
.column_mode_options.as_ref()
|
.column_mode_options.as_ref()
|
||||||
.map(|i| i.across_mode)
|
.map(|i| i.across_mode)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let offset_spaces: &usize = &options.offset_spaces;
|
||||||
|
|
||||||
let mut lines_printed = 0;
|
let mut lines_printed = 0;
|
||||||
let is_number_mode = options.number.is_some();
|
let is_number_mode = options.number.is_some();
|
||||||
|
|
||||||
let fetch_indexes: Vec<Vec<usize>> = if across_mode {
|
let fetch_indexes: Vec<Vec<usize>> = if across_mode {
|
||||||
(0..content_lines_per_page)
|
(0..content_lines_per_page)
|
||||||
.map(|a|
|
.map(|a|
|
||||||
|
@ -707,19 +965,20 @@ fn write_columns(lines: &Vec<(usize, String)>, options: &OutputOptions, out: &mu
|
||||||
).collect()
|
).collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let spaces = " ".repeat(*offset_spaces);
|
||||||
|
|
||||||
for fetch_index in fetch_indexes {
|
for fetch_index in fetch_indexes {
|
||||||
let indexes = fetch_index.len();
|
let indexes = fetch_index.len();
|
||||||
for i in 0..indexes {
|
for i in 0..indexes {
|
||||||
let index = fetch_index[i];
|
let index: usize = fetch_index[i];
|
||||||
if lines.get(index).is_none() {
|
if lines.get(index).is_none() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let read_line: &String = &lines.get(index).unwrap().1;
|
let file_line: &FileLine = lines.get(index).unwrap();
|
||||||
let next_line_number: usize = lines.get(index).unwrap().0;
|
let trimmed_line: String = format!("{}{}", spaces, get_line_for_printing(
|
||||||
let trimmed_line = get_line_for_printing(
|
file_line, &width, &number_separator, columns, col_width,
|
||||||
next_line_number, &width,
|
is_number_mode, &options.merge_files_print, &i,
|
||||||
&number_separator, columns, col_width,
|
));
|
||||||
read_line, is_number_mode);
|
|
||||||
out.write(trimmed_line.as_bytes())?;
|
out.write(trimmed_line.as_bytes())?;
|
||||||
if (i + 1) != indexes {
|
if (i + 1) != indexes {
|
||||||
out.write(col_sep.as_bytes())?;
|
out.write(col_sep.as_bytes())?;
|
||||||
|
@ -731,16 +990,20 @@ fn write_columns(lines: &Vec<(usize, String)>, options: &OutputOptions, out: &mu
|
||||||
Ok(lines_printed)
|
Ok(lines_printed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_line_for_printing(line_number: usize, width: &usize,
|
fn get_line_for_printing(file_line: &FileLine, width: &usize,
|
||||||
separator: &String, columns: usize,
|
separator: &String, columns: usize,
|
||||||
col_width: Option<usize>,
|
col_width: Option<usize>,
|
||||||
read_line: &String, is_number_mode: bool) -> String {
|
is_number_mode: bool, merge_files_print: &Option<usize>,
|
||||||
let fmtd_line_number: String = if is_number_mode {
|
index: &usize,
|
||||||
get_fmtd_line_number(&width, line_number, &separator)
|
) -> String {
|
||||||
|
let should_show_line_number_merge_file = merge_files_print.is_none() || index == &usize::min_value();
|
||||||
|
let should_show_line_number = is_number_mode && should_show_line_number_merge_file;
|
||||||
|
let fmtd_line_number: String = if should_show_line_number {
|
||||||
|
get_fmtd_line_number(&width, file_line.line_number, &separator)
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
let mut complete_line = format!("{}{}", fmtd_line_number, read_line);
|
let mut complete_line = format!("{}{}", fmtd_line_number, file_line.line_content.as_ref().unwrap());
|
||||||
|
|
||||||
let tab_count: usize = complete_line
|
let tab_count: usize = complete_line
|
||||||
.chars()
|
.chars()
|
||||||
|
|
198
tests/fixtures/pr/column_spaces_across.log.expected
vendored
Normal file
198
tests/fixtures/pr/column_spaces_across.log.expected
vendored
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} column.log Page 3
|
||||||
|
|
||||||
|
|
||||||
|
337 337 338 338 339 339
|
||||||
|
340 340 341 341 342 342
|
||||||
|
343 343 344 344 345 345
|
||||||
|
346 346 347 347 348 348
|
||||||
|
349 349 350 350 351 351
|
||||||
|
352 352 353 353 354 354
|
||||||
|
355 355 356 356 357 357
|
||||||
|
358 358 359 359 360 360
|
||||||
|
361 361 362 362 363 363
|
||||||
|
364 364 365 365 366 366
|
||||||
|
367 367 368 368 369 369
|
||||||
|
370 370 371 371 372 372
|
||||||
|
373 373 374 374 375 375
|
||||||
|
376 376 377 377 378 378
|
||||||
|
379 379 380 380 381 381
|
||||||
|
382 382 383 383 384 384
|
||||||
|
385 385 386 386 387 387
|
||||||
|
388 388 389 389 390 390
|
||||||
|
391 391 392 392 393 393
|
||||||
|
394 394 395 395 396 396
|
||||||
|
397 397 398 398 399 399
|
||||||
|
400 400 401 401 402 402
|
||||||
|
403 403 404 404 405 405
|
||||||
|
406 406 407 407 408 408
|
||||||
|
409 409 410 410 411 411
|
||||||
|
412 412 413 413 414 414
|
||||||
|
415 415 416 416 417 417
|
||||||
|
418 418 419 419 420 420
|
||||||
|
421 421 422 422 423 423
|
||||||
|
424 424 425 425 426 426
|
||||||
|
427 427 428 428 429 429
|
||||||
|
430 430 431 431 432 432
|
||||||
|
433 433 434 434 435 435
|
||||||
|
436 436 437 437 438 438
|
||||||
|
439 439 440 440 441 441
|
||||||
|
442 442 443 443 444 444
|
||||||
|
445 445 446 446 447 447
|
||||||
|
448 448 449 449 450 450
|
||||||
|
451 451 452 452 453 453
|
||||||
|
454 454 455 455 456 456
|
||||||
|
457 457 458 458 459 459
|
||||||
|
460 460 461 461 462 462
|
||||||
|
463 463 464 464 465 465
|
||||||
|
466 466 467 467 468 468
|
||||||
|
469 469 470 470 471 471
|
||||||
|
472 472 473 473 474 474
|
||||||
|
475 475 476 476 477 477
|
||||||
|
478 478 479 479 480 480
|
||||||
|
481 481 482 482 483 483
|
||||||
|
484 484 485 485 486 486
|
||||||
|
487 487 488 488 489 489
|
||||||
|
490 490 491 491 492 492
|
||||||
|
493 493 494 494 495 495
|
||||||
|
496 496 497 497 498 498
|
||||||
|
499 499 500 500 501 501
|
||||||
|
502 502 503 503 504 504
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} column.log Page 4
|
||||||
|
|
||||||
|
|
||||||
|
505 505 506 506 507 507
|
||||||
|
508 508 509 509 510 510
|
||||||
|
511 511 512 512 513 513
|
||||||
|
514 514 515 515 516 516
|
||||||
|
517 517 518 518 519 519
|
||||||
|
520 520 521 521 522 522
|
||||||
|
523 523 524 524 525 525
|
||||||
|
526 526 527 527 528 528
|
||||||
|
529 529 530 530 531 531
|
||||||
|
532 532 533 533 534 534
|
||||||
|
535 535 536 536 537 537
|
||||||
|
538 538 539 539 540 540
|
||||||
|
541 541 542 542 543 543
|
||||||
|
544 544 545 545 546 546
|
||||||
|
547 547 548 548 549 549
|
||||||
|
550 550 551 551 552 552
|
||||||
|
553 553 554 554 555 555
|
||||||
|
556 556 557 557 558 558
|
||||||
|
559 559 560 560 561 561
|
||||||
|
562 562 563 563 564 564
|
||||||
|
565 565 566 566 567 567
|
||||||
|
568 568 569 569 570 570
|
||||||
|
571 571 572 572 573 573
|
||||||
|
574 574 575 575 576 576
|
||||||
|
577 577 578 578 579 579
|
||||||
|
580 580 581 581 582 582
|
||||||
|
583 583 584 584 585 585
|
||||||
|
586 586 587 587 588 588
|
||||||
|
589 589 590 590 591 591
|
||||||
|
592 592 593 593 594 594
|
||||||
|
595 595 596 596 597 597
|
||||||
|
598 598 599 599 600 600
|
||||||
|
601 601 602 602 603 603
|
||||||
|
604 604 605 605 606 606
|
||||||
|
607 607 608 608 609 609
|
||||||
|
610 610 611 611 612 612
|
||||||
|
613 613 614 614 615 615
|
||||||
|
616 616 617 617 618 618
|
||||||
|
619 619 620 620 621 621
|
||||||
|
622 622 623 623 624 624
|
||||||
|
625 625 626 626 627 627
|
||||||
|
628 628 629 629 630 630
|
||||||
|
631 631 632 632 633 633
|
||||||
|
634 634 635 635 636 636
|
||||||
|
637 637 638 638 639 639
|
||||||
|
640 640 641 641 642 642
|
||||||
|
643 643 644 644 645 645
|
||||||
|
646 646 647 647 648 648
|
||||||
|
649 649 650 650 651 651
|
||||||
|
652 652 653 653 654 654
|
||||||
|
655 655 656 656 657 657
|
||||||
|
658 658 659 659 660 660
|
||||||
|
661 661 662 662 663 663
|
||||||
|
664 664 665 665 666 666
|
||||||
|
667 667 668 668 669 669
|
||||||
|
670 670 671 671 672 672
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} column.log Page 5
|
||||||
|
|
||||||
|
|
||||||
|
673 673 674 674 675 675
|
||||||
|
676 676 677 677 678 678
|
||||||
|
679 679 680 680 681 681
|
||||||
|
682 682 683 683 684 684
|
||||||
|
685 685 686 686 687 687
|
||||||
|
688 688 689 689 690 690
|
||||||
|
691 691 692 692 693 693
|
||||||
|
694 694 695 695 696 696
|
||||||
|
697 697 698 698 699 699
|
||||||
|
700 700 701 701 702 702
|
||||||
|
703 703 704 704 705 705
|
||||||
|
706 706 707 707 708 708
|
||||||
|
709 709 710 710 711 711
|
||||||
|
712 712 713 713 714 714
|
||||||
|
715 715 716 716 717 717
|
||||||
|
718 718 719 719 720 720
|
||||||
|
721 721 722 722 723 723
|
||||||
|
724 724 725 725 726 726
|
||||||
|
727 727 728 728 729 729
|
||||||
|
730 730 731 731 732 732
|
||||||
|
733 733 734 734 735 735
|
||||||
|
736 736 737 737 738 738
|
||||||
|
739 739 740 740 741 741
|
||||||
|
742 742 743 743 744 744
|
||||||
|
745 745 746 746 747 747
|
||||||
|
748 748 749 749 750 750
|
||||||
|
751 751 752 752 753 753
|
||||||
|
754 754 755 755 756 756
|
||||||
|
757 757 758 758 759 759
|
||||||
|
760 760 761 761 762 762
|
||||||
|
763 763 764 764 765 765
|
||||||
|
766 766 767 767 768 768
|
||||||
|
769 769 770 770 771 771
|
||||||
|
772 772 773 773 774 774
|
||||||
|
775 775 776 776 777 777
|
||||||
|
778 778 779 779 780 780
|
||||||
|
781 781 782 782 783 783
|
||||||
|
784 784 785 785 786 786
|
||||||
|
787 787 788 788 789 789
|
||||||
|
790 790 791 791 792 792
|
||||||
|
793 793 794 794 795 795
|
||||||
|
796 796 797 797 798 798
|
||||||
|
799 799 800 800 801 801
|
||||||
|
802 802 803 803 804 804
|
||||||
|
805 805 806 806 807 807
|
||||||
|
808 808 809 809 810 810
|
||||||
|
811 811 812 812 813 813
|
||||||
|
814 814 815 815 816 816
|
||||||
|
817 817 818 818 819 819
|
||||||
|
820 820 821 821 822 822
|
||||||
|
823 823 824 824 825 825
|
||||||
|
826 826 827 827 828 828
|
||||||
|
829 829 830 830 831 831
|
||||||
|
832 832 833 833 834 834
|
||||||
|
835 835 836 836 837 837
|
||||||
|
838 838 839 839 840 840
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
11
tests/fixtures/pr/hosts.log
vendored
Normal file
11
tests/fixtures/pr/hosts.log
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
##
|
||||||
|
# Host Database
|
||||||
|
#
|
||||||
|
# localhost is used to configure the loopback interface
|
||||||
|
# when the system is booting. Do not change this entry.
|
||||||
|
##
|
||||||
|
127.0.0.1 localhost
|
||||||
|
127.0.0.1 Techopss-MacBook-Pro.local
|
||||||
|
127.0.0.1 tilakpr
|
||||||
|
255.255.255.255 broadcasthost
|
||||||
|
::1 localhost
|
132
tests/fixtures/pr/mpr.log.expected
vendored
Normal file
132
tests/fixtures/pr/mpr.log.expected
vendored
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} Page 1
|
||||||
|
|
||||||
|
|
||||||
|
1 1 ##
|
||||||
|
2 2 # Host Database
|
||||||
|
3 3 #
|
||||||
|
4 4 # localhost is used to configure th
|
||||||
|
5 5 # when the system is booting. Do n
|
||||||
|
6 6 ##
|
||||||
|
7 7 127.0.0.1 localhost
|
||||||
|
8 8 127.0.0.1 Techopss-MacBook-Pro.loca
|
||||||
|
9 9 127.0.0.1 tilakpr
|
||||||
|
10 10 255.255.255.255 broadcasthost
|
||||||
|
11 11 ::1 localhost
|
||||||
|
12 12
|
||||||
|
13 13
|
||||||
|
14 14
|
||||||
|
15 15
|
||||||
|
16 16
|
||||||
|
17 17
|
||||||
|
18 18
|
||||||
|
19 19
|
||||||
|
20 20
|
||||||
|
21 21
|
||||||
|
22 22
|
||||||
|
23 23
|
||||||
|
24 24
|
||||||
|
25 25
|
||||||
|
26 26
|
||||||
|
27 27
|
||||||
|
28 28
|
||||||
|
29 29
|
||||||
|
30 30
|
||||||
|
31 31
|
||||||
|
32 32
|
||||||
|
33 33
|
||||||
|
34 34
|
||||||
|
35 35
|
||||||
|
36 36
|
||||||
|
37 37
|
||||||
|
38 38
|
||||||
|
39 39
|
||||||
|
40 40
|
||||||
|
41 41
|
||||||
|
42 42
|
||||||
|
43 43
|
||||||
|
44 44
|
||||||
|
45 45
|
||||||
|
46 46
|
||||||
|
47 47
|
||||||
|
48 48
|
||||||
|
49 49
|
||||||
|
50 50
|
||||||
|
51 51
|
||||||
|
52 52
|
||||||
|
53 53
|
||||||
|
54 54
|
||||||
|
55 55
|
||||||
|
56 56
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} Page 2
|
||||||
|
|
||||||
|
|
||||||
|
57 57
|
||||||
|
58 58
|
||||||
|
59 59
|
||||||
|
60 60
|
||||||
|
61 61
|
||||||
|
62 62
|
||||||
|
63 63
|
||||||
|
64 64
|
||||||
|
65 65
|
||||||
|
66 66
|
||||||
|
67 67
|
||||||
|
68 68
|
||||||
|
69 69
|
||||||
|
70 70
|
||||||
|
71 71
|
||||||
|
72 72
|
||||||
|
73 73
|
||||||
|
74 74
|
||||||
|
75 75
|
||||||
|
76 76
|
||||||
|
77 77
|
||||||
|
78 78
|
||||||
|
79 79
|
||||||
|
80 80
|
||||||
|
81 81
|
||||||
|
82 82
|
||||||
|
83 83
|
||||||
|
84 84
|
||||||
|
85 85
|
||||||
|
86 86
|
||||||
|
87 87
|
||||||
|
88 88
|
||||||
|
89 89
|
||||||
|
90 90
|
||||||
|
91 91
|
||||||
|
92 92
|
||||||
|
93 93
|
||||||
|
94 94
|
||||||
|
95 95
|
||||||
|
96 96
|
||||||
|
97 97
|
||||||
|
98 98
|
||||||
|
99 99
|
||||||
|
100 100
|
||||||
|
101 101
|
||||||
|
102 102
|
||||||
|
103 103
|
||||||
|
104 104
|
||||||
|
105 105
|
||||||
|
106 106
|
||||||
|
107 107
|
||||||
|
108 108
|
||||||
|
109 109
|
||||||
|
110 110
|
||||||
|
111 111
|
||||||
|
112 112
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
198
tests/fixtures/pr/mpr1.log.expected
vendored
Normal file
198
tests/fixtures/pr/mpr1.log.expected
vendored
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} Page 2
|
||||||
|
|
||||||
|
|
||||||
|
57 57
|
||||||
|
58 58
|
||||||
|
59 59
|
||||||
|
60 60
|
||||||
|
61 61
|
||||||
|
62 62
|
||||||
|
63 63
|
||||||
|
64 64
|
||||||
|
65 65
|
||||||
|
66 66
|
||||||
|
67 67
|
||||||
|
68 68
|
||||||
|
69 69
|
||||||
|
70 70
|
||||||
|
71 71
|
||||||
|
72 72
|
||||||
|
73 73
|
||||||
|
74 74
|
||||||
|
75 75
|
||||||
|
76 76
|
||||||
|
77 77
|
||||||
|
78 78
|
||||||
|
79 79
|
||||||
|
80 80
|
||||||
|
81 81
|
||||||
|
82 82
|
||||||
|
83 83
|
||||||
|
84 84
|
||||||
|
85 85
|
||||||
|
86 86
|
||||||
|
87 87
|
||||||
|
88 88
|
||||||
|
89 89
|
||||||
|
90 90
|
||||||
|
91 91
|
||||||
|
92 92
|
||||||
|
93 93
|
||||||
|
94 94
|
||||||
|
95 95
|
||||||
|
96 96
|
||||||
|
97 97
|
||||||
|
98 98
|
||||||
|
99 99
|
||||||
|
100 100
|
||||||
|
101 101
|
||||||
|
102 102
|
||||||
|
103 103
|
||||||
|
104 104
|
||||||
|
105 105
|
||||||
|
106 106
|
||||||
|
107 107
|
||||||
|
108 108
|
||||||
|
109 109
|
||||||
|
110 110
|
||||||
|
111 111
|
||||||
|
112 112
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} Page 3
|
||||||
|
|
||||||
|
|
||||||
|
113 113
|
||||||
|
114 114
|
||||||
|
115 115
|
||||||
|
116 116
|
||||||
|
117 117
|
||||||
|
118 118
|
||||||
|
119 119
|
||||||
|
120 120
|
||||||
|
121 121
|
||||||
|
122 122
|
||||||
|
123 123
|
||||||
|
124 124
|
||||||
|
125 125
|
||||||
|
126 126
|
||||||
|
127 127
|
||||||
|
128 128
|
||||||
|
129 129
|
||||||
|
130 130
|
||||||
|
131 131
|
||||||
|
132 132
|
||||||
|
133 133
|
||||||
|
134 134
|
||||||
|
135 135
|
||||||
|
136 136
|
||||||
|
137 137
|
||||||
|
138 138
|
||||||
|
139 139
|
||||||
|
140 140
|
||||||
|
141 141
|
||||||
|
142 142
|
||||||
|
143 143
|
||||||
|
144 144
|
||||||
|
145 145
|
||||||
|
146 146
|
||||||
|
147 147
|
||||||
|
148 148
|
||||||
|
149 149
|
||||||
|
150 150
|
||||||
|
151 151
|
||||||
|
152 152
|
||||||
|
153 153
|
||||||
|
154 154
|
||||||
|
155 155
|
||||||
|
156 156
|
||||||
|
157 157
|
||||||
|
158 158
|
||||||
|
159 159
|
||||||
|
160 160
|
||||||
|
161 161
|
||||||
|
162 162
|
||||||
|
163 163
|
||||||
|
164 164
|
||||||
|
165 165
|
||||||
|
166 166
|
||||||
|
167 167
|
||||||
|
168 168
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} Page 4
|
||||||
|
|
||||||
|
|
||||||
|
169 169
|
||||||
|
170 170
|
||||||
|
171 171
|
||||||
|
172 172
|
||||||
|
173 173
|
||||||
|
174 174
|
||||||
|
175 175
|
||||||
|
176 176
|
||||||
|
177 177
|
||||||
|
178 178
|
||||||
|
179 179
|
||||||
|
180 180
|
||||||
|
181 181
|
||||||
|
182 182
|
||||||
|
183 183
|
||||||
|
184 184
|
||||||
|
185 185
|
||||||
|
186 186
|
||||||
|
187 187
|
||||||
|
188 188
|
||||||
|
189 189
|
||||||
|
190 190
|
||||||
|
191 191
|
||||||
|
192 192
|
||||||
|
193 193
|
||||||
|
194 194
|
||||||
|
195 195
|
||||||
|
196 196
|
||||||
|
197 197
|
||||||
|
198 198
|
||||||
|
199 199
|
||||||
|
200 200
|
||||||
|
201 201
|
||||||
|
202 202
|
||||||
|
203 203
|
||||||
|
204 204
|
||||||
|
205 205
|
||||||
|
206 206
|
||||||
|
207 207
|
||||||
|
208 208
|
||||||
|
209 209
|
||||||
|
210 210
|
||||||
|
211 211
|
||||||
|
212 212
|
||||||
|
213 213
|
||||||
|
214 214
|
||||||
|
215 215
|
||||||
|
216 216
|
||||||
|
217 217
|
||||||
|
218 218
|
||||||
|
219 219
|
||||||
|
220 220
|
||||||
|
221 221
|
||||||
|
222 222
|
||||||
|
223 223
|
||||||
|
224 224
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
200
tests/fixtures/pr/mpr2.log.expected
vendored
Normal file
200
tests/fixtures/pr/mpr2.log.expected
vendored
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} Page 1
|
||||||
|
|
||||||
|
|
||||||
|
1 1 ## 1
|
||||||
|
2 2 # Host Database 2
|
||||||
|
3 3 # 3
|
||||||
|
4 4 # localhost is used to 4
|
||||||
|
5 5 # when the system is bo 5
|
||||||
|
6 6 ## 6
|
||||||
|
7 7 127.0.0.1 localhost 7
|
||||||
|
8 8 127.0.0.1 Techopss-MacB 8
|
||||||
|
9 9 127.0.0.1 tilakpr 9
|
||||||
|
10 10 255.255.255.255 broadca 10
|
||||||
|
11 11 ::1 localho 11
|
||||||
|
12 12 12
|
||||||
|
13 13 13
|
||||||
|
14 14 14
|
||||||
|
15 15 15
|
||||||
|
16 16 16
|
||||||
|
17 17 17
|
||||||
|
18 18 18
|
||||||
|
19 19 19
|
||||||
|
20 20 20
|
||||||
|
21 21 21
|
||||||
|
22 22 22
|
||||||
|
23 23 23
|
||||||
|
24 24 24
|
||||||
|
25 25 25
|
||||||
|
26 26 26
|
||||||
|
27 27 27
|
||||||
|
28 28 28
|
||||||
|
29 29 29
|
||||||
|
30 30 30
|
||||||
|
31 31 31
|
||||||
|
32 32 32
|
||||||
|
33 33 33
|
||||||
|
34 34 34
|
||||||
|
35 35 35
|
||||||
|
36 36 36
|
||||||
|
37 37 37
|
||||||
|
38 38 38
|
||||||
|
39 39 39
|
||||||
|
40 40 40
|
||||||
|
41 41 41
|
||||||
|
42 42 42
|
||||||
|
43 43 43
|
||||||
|
44 44 44
|
||||||
|
45 45 45
|
||||||
|
46 46 46
|
||||||
|
47 47 47
|
||||||
|
48 48 48
|
||||||
|
49 49 49
|
||||||
|
50 50 50
|
||||||
|
51 51 51
|
||||||
|
52 52 52
|
||||||
|
53 53 53
|
||||||
|
54 54 54
|
||||||
|
55 55 55
|
||||||
|
56 56 56
|
||||||
|
57 57 57
|
||||||
|
58 58 58
|
||||||
|
59 59 59
|
||||||
|
60 60 60
|
||||||
|
61 61 61
|
||||||
|
62 62 62
|
||||||
|
63 63 63
|
||||||
|
64 64 64
|
||||||
|
65 65 65
|
||||||
|
66 66 66
|
||||||
|
67 67 67
|
||||||
|
68 68 68
|
||||||
|
69 69 69
|
||||||
|
70 70 70
|
||||||
|
71 71 71
|
||||||
|
72 72 72
|
||||||
|
73 73 73
|
||||||
|
74 74 74
|
||||||
|
75 75 75
|
||||||
|
76 76 76
|
||||||
|
77 77 77
|
||||||
|
78 78 78
|
||||||
|
79 79 79
|
||||||
|
80 80 80
|
||||||
|
81 81 81
|
||||||
|
82 82 82
|
||||||
|
83 83 83
|
||||||
|
84 84 84
|
||||||
|
85 85 85
|
||||||
|
86 86 86
|
||||||
|
87 87 87
|
||||||
|
88 88 88
|
||||||
|
89 89 89
|
||||||
|
90 90 90
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{last_modified_time} Page 2
|
||||||
|
|
||||||
|
|
||||||
|
91 91 91
|
||||||
|
92 92 92
|
||||||
|
93 93 93
|
||||||
|
94 94 94
|
||||||
|
95 95 95
|
||||||
|
96 96 96
|
||||||
|
97 97 97
|
||||||
|
98 98 98
|
||||||
|
99 99 99
|
||||||
|
100 100 100
|
||||||
|
101 101 101
|
||||||
|
102 102 102
|
||||||
|
103 103 103
|
||||||
|
104 104 104
|
||||||
|
105 105 105
|
||||||
|
106 106 106
|
||||||
|
107 107 107
|
||||||
|
108 108 108
|
||||||
|
109 109 109
|
||||||
|
110 110 110
|
||||||
|
111 111 111
|
||||||
|
112 112 112
|
||||||
|
113 113 113
|
||||||
|
114 114 114
|
||||||
|
115 115 115
|
||||||
|
116 116 116
|
||||||
|
117 117 117
|
||||||
|
118 118 118
|
||||||
|
119 119 119
|
||||||
|
120 120 120
|
||||||
|
121 121 121
|
||||||
|
122 122 122
|
||||||
|
123 123 123
|
||||||
|
124 124 124
|
||||||
|
125 125 125
|
||||||
|
126 126 126
|
||||||
|
127 127 127
|
||||||
|
128 128 128
|
||||||
|
129 129 129
|
||||||
|
130 130 130
|
||||||
|
131 131 131
|
||||||
|
132 132 132
|
||||||
|
133 133 133
|
||||||
|
134 134 134
|
||||||
|
135 135 135
|
||||||
|
136 136 136
|
||||||
|
137 137 137
|
||||||
|
138 138 138
|
||||||
|
139 139 139
|
||||||
|
140 140 140
|
||||||
|
141 141 141
|
||||||
|
142 142 142
|
||||||
|
143 143 143
|
||||||
|
144 144 144
|
||||||
|
145 145 145
|
||||||
|
146 146 146
|
||||||
|
147 147 147
|
||||||
|
148 148 148
|
||||||
|
149 149 149
|
||||||
|
150 150 150
|
||||||
|
151 151 151
|
||||||
|
152 152 152
|
||||||
|
153 153 153
|
||||||
|
154 154 154
|
||||||
|
155 155 155
|
||||||
|
156 156 156
|
||||||
|
157 157 157
|
||||||
|
158 158 158
|
||||||
|
159 159 159
|
||||||
|
160 160 160
|
||||||
|
161 161 161
|
||||||
|
162 162 162
|
||||||
|
163 163 163
|
||||||
|
164 164 164
|
||||||
|
165 165 165
|
||||||
|
166 166 166
|
||||||
|
167 167 167
|
||||||
|
168 168 168
|
||||||
|
169 169 169
|
||||||
|
170 170 170
|
||||||
|
171 171 171
|
||||||
|
172 172 172
|
||||||
|
173 173 173
|
||||||
|
174 174 174
|
||||||
|
175 175 175
|
||||||
|
176 176 176
|
||||||
|
177 177 177
|
||||||
|
178 178 178
|
||||||
|
179 179 179
|
||||||
|
180 180 180
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -282,7 +282,6 @@ fn test_with_suppress_error_option() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_with_stdin() {
|
fn test_with_stdin() {
|
||||||
let test_file_path = "stdin.log";
|
|
||||||
let expected_file_path = "stdin.log.expected";
|
let expected_file_path = "stdin.log.expected";
|
||||||
let mut scenario = new_ucmd!();
|
let mut scenario = new_ucmd!();
|
||||||
scenario
|
scenario
|
||||||
|
@ -306,7 +305,6 @@ fn test_with_column() {
|
||||||
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
||||||
(&"{last_modified_time}".to_string(), &value),
|
(&"{last_modified_time}".to_string(), &value),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -321,7 +319,6 @@ fn test_with_column_across_option() {
|
||||||
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
||||||
(&"{last_modified_time}".to_string(), &value),
|
(&"{last_modified_time}".to_string(), &value),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -336,6 +333,64 @@ fn test_with_column_across_option_and_column_separator() {
|
||||||
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
||||||
(&"{last_modified_time}".to_string(), &value),
|
(&"{last_modified_time}".to_string(), &value),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_mpr() {
|
||||||
|
let test_file_path = "column.log";
|
||||||
|
let test_file_path1 = "hosts.log";
|
||||||
|
let expected_test_file_path = "mpr.log.expected";
|
||||||
|
let expected_test_file_path1 = "mpr1.log.expected";
|
||||||
|
let expected_test_file_path2 = "mpr2.log.expected";
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--pages=1:2", "-m", "-n", test_file_path, test_file_path1])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
||||||
|
(&"{last_modified_time}".to_string(), &now_time()),
|
||||||
|
]);
|
||||||
|
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--pages=2:4", "-m", "-n", test_file_path, test_file_path1])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_templated_fixture(expected_test_file_path1, vec![
|
||||||
|
(&"{last_modified_time}".to_string(), &now_time()),
|
||||||
|
]);
|
||||||
|
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--pages=1:2", "-l", "100", "-n", "-m", test_file_path, test_file_path1, test_file_path])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_templated_fixture(expected_test_file_path2, vec![
|
||||||
|
(&"{last_modified_time}".to_string(), &now_time()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_mpr_and_column_options() {
|
||||||
|
let test_file_path = "column.log";
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--column=2", "-m", "-n", test_file_path])
|
||||||
|
.fails()
|
||||||
|
.stderr_is("pr: cannot specify number of columns when printing in parallel")
|
||||||
|
.stdout_is("");
|
||||||
|
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-a", "-m", "-n", test_file_path])
|
||||||
|
.fails()
|
||||||
|
.stderr_is("pr: cannot specify both printing across and printing in parallel")
|
||||||
|
.stdout_is("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_offset_space_option() {
|
||||||
|
let test_file_path = "column.log";
|
||||||
|
let expected_test_file_path = "column_spaces_across.log.expected";
|
||||||
|
let mut scenario = new_ucmd!();
|
||||||
|
let value = file_last_modified_time(&scenario, test_file_path);
|
||||||
|
scenario
|
||||||
|
.args(&["-o", "5", "--pages=3:5", "--column=3", "-a", "-n", test_file_path])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_templated_fixture(expected_test_file_path, vec![
|
||||||
|
(&"{last_modified_time}".to_string(), &value),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue