pr: print 56 lines of content with 5 blank trailer and header lines

This commit is contained in:
tilakpatidar 2018-12-08 21:57:53 +05:30 committed by Max Semenik
parent 035f811dd0
commit 2d58ea5f8b
3 changed files with 162 additions and 0 deletions

View file

@ -64,6 +64,7 @@ feat_common_core = [
"nl",
"od",
"paste",
"pr",
"printenv",
"printf",
"ptx",
@ -285,6 +286,7 @@ od = { optional=true, version="0.0.4", package="uu_od", path="src/uu/od" }
paste = { optional=true, version="0.0.4", package="uu_paste", path="src/uu/paste" }
pathchk = { optional=true, version="0.0.4", package="uu_pathchk", path="src/uu/pathchk" }
pinky = { optional=true, version="0.0.4", package="uu_pinky", path="src/uu/pinky" }
pr = { optional=true, path="src/pr" }
printenv = { optional=true, version="0.0.4", package="uu_printenv", path="src/uu/printenv" }
printf = { optional=true, version="0.0.4", package="uu_printf", path="src/uu/printf" }
ptx = { optional=true, version="0.0.4", package="uu_ptx", path="src/uu/ptx" }

21
src/pr/Cargo.toml Normal file
View file

@ -0,0 +1,21 @@
[package]
name = "pr"
version = "0.0.1"
authors = ["Tilak Patidar <tilakpatidar@gmail.com>"]
build = "../../mkmain.rs"
[lib]
name = "uu_pr"
path = "pr.rs"
[dependencies]
getopts = "0.2.18"
time = "0.1.40"
[dependencies.uucore]
path = "../uucore"
features = ["libc"]
[[bin]]
name = "pr"
path = "../../uumain.rs"

139
src/pr/pr.rs Normal file
View file

@ -0,0 +1,139 @@
#![crate_name = "uu_pr"]
// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.
//
extern crate getopts;
//#[macro_use]
//extern crate uucore;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::vec::Vec;
//use uucore::fs::is_stdin_interactive;
static NAME: &str = "pr";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static LINES_PER_PAGE: usize = 66;
static HEADER_LINES_PER_PAGE: usize = 5;
static TRAILER_LINES_PER_PAGE: usize = 5;
static CONTENT_LINES_PER_PAGE: usize = LINES_PER_PAGE - HEADER_LINES_PER_PAGE - TRAILER_LINES_PER_PAGE;
pub fn uumain(args: Vec<String>) -> i32 {
let mut opts = getopts::Options::new();
opts.optopt(
"h",
"",
"Use the string header to replace the file name \
in the header line.",
"STRING",
);
opts.optflag("h", "help", "display this help and exit");
opts.optflag("V", "version", "output version information and exit");
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(e) => panic!("Invalid options\n{}", e),
};
if matches.opt_present("version") {
println!("{} {}", NAME, VERSION);
return 0;
}
if matches.opt_present("help") || matches.free.is_empty() {
println!("{} {} -- print files", NAME, VERSION);
println!();
println!("Usage: {} [+page] [-column] [-adFfmprt] [[-e] [char] [gap]]
[-L locale] [-h header] [[-i] [char] [gap]]
[-l lines] [-o offset] [[-s] [char]] [[-n] [char]
[width]] [-w width] [-] [file ...].", NAME);
println!();
println!(
"{}",
opts.usage(
"The pr utility is a printing and pagination filter
for text files. When multiple input files are spec-
ified, each is read, formatted, and written to stan-
dard output. By default, the input is separated
into 66-line pages, each with
o A 5-line header with the page number, date,
time, and the pathname of the file.
o A 5-line trailer consisting of blank lines.
If standard output is associated with a terminal,
diagnostic messages are suppressed until the pr
utility has completed processing.
When multiple column output is specified, text col-
umns are of equal width. By default text columns
are separated by at least one <blank>. Input lines
that do not fit into a text column are truncated.
Lines are not truncated under single column output."
)
);
if matches.free.is_empty() {
return 1;
}
return 0;
}
let path = &matches.free[0];
open(&path);
0
}
fn open(path: &str) -> std::io::Result<()> {
let file = File::open(path)?;
let lines = BufReader::new(file).lines();
let mut i = 0;
let mut page: i32 = 0;
let mut buffered_content: Vec<String> = Vec::new();
for line in lines {
if i == CONTENT_LINES_PER_PAGE {
page = page + 1;
i = 0;
print!("{}", print_page(&buffered_content));
buffered_content.clear();
}
i = i + 1;
buffered_content.push(line?);
}
if i != 0 {
print!("{}", print_page(&buffered_content));
buffered_content.clear();
}
Ok(())
}
fn print_page(lines: &Vec<String>) -> String {
let mut page_content: Vec<String> = Vec::new();
let header_content = header_content();
let trailer_content = trailer_content();
assert_eq!(lines.len() <= CONTENT_LINES_PER_PAGE, true, "Only {} lines of content allowed in a pr output page", CONTENT_LINES_PER_PAGE.to_string());
assert_eq!(header_content.len(), HEADER_LINES_PER_PAGE, "Only {} lines of content allowed in a pr header", HEADER_LINES_PER_PAGE.to_string());
assert_eq!(trailer_content.len(), TRAILER_LINES_PER_PAGE, "Only {} lines of content allowed in a pr trailer", TRAILER_LINES_PER_PAGE.to_string());
page_content.extend(header_content);
for x in lines {
page_content.push(x.to_string());
}
page_content.extend(trailer_content);
page_content.join("\n")
}
fn header_content() -> Vec<String> {
vec!["".to_string(), "".to_string(), "".to_string(), "".to_string(), "".to_string()]
}
fn trailer_content() -> Vec<String> {
vec!["".to_string(), "".to_string(), "".to_string(), "".to_string(), "".to_string()]
}