mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-02 14:07:46 +00:00
commit
af21772bd4
7 changed files with 140 additions and 26 deletions
1
Makefile
1
Makefile
|
@ -170,6 +170,7 @@ TEST_PROGS := \
|
||||||
false \
|
false \
|
||||||
fold \
|
fold \
|
||||||
hashsum \
|
hashsum \
|
||||||
|
head \
|
||||||
mkdir \
|
mkdir \
|
||||||
mv \
|
mv \
|
||||||
nl \
|
nl \
|
||||||
|
|
|
@ -25,13 +25,29 @@ mod util;
|
||||||
static NAME: &'static str = "head";
|
static NAME: &'static str = "head";
|
||||||
static VERSION: &'static str = "1.0.0";
|
static VERSION: &'static str = "1.0.0";
|
||||||
|
|
||||||
|
enum FilterMode {
|
||||||
|
Bytes(usize),
|
||||||
|
Lines(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Settings {
|
||||||
|
mode: FilterMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Settings {
|
||||||
|
fn default() -> Settings {
|
||||||
|
Settings {
|
||||||
|
mode: FilterMode::Lines(10),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn uumain(args: Vec<String>) -> i32 {
|
pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
let mut line_count = 10usize;
|
let mut settings: Settings = Default::default();
|
||||||
let mut byte_count = 0usize;
|
|
||||||
|
|
||||||
// handle obsolete -number syntax
|
// handle obsolete -number syntax
|
||||||
let options = match obsolete(&args[1..]) {
|
let options = match obsolete(&args[1..]) {
|
||||||
(args, Some(n)) => { line_count = n; args },
|
(args, Some(n)) => { settings.mode = FilterMode::Lines(n); args },
|
||||||
(args, None) => args
|
(args, None) => args
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,8 +57,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
|
|
||||||
opts.optopt("c", "bytes", "Print the first K bytes. With the leading '-', print all but the last K bytes", "[-]K");
|
opts.optopt("c", "bytes", "Print the first K bytes. With the leading '-', print all but the last K bytes", "[-]K");
|
||||||
opts.optopt("n", "lines", "Print the first K lines. With the leading '-', print all but the last K lines", "[-]K");
|
opts.optopt("n", "lines", "Print the first K lines. With the leading '-', print all but the last K lines", "[-]K");
|
||||||
opts.optflag("h", "help", "help");
|
opts.optflag("h", "help", "display this help and exit");
|
||||||
opts.optflag("V", "version", "version");
|
opts.optflag("V", "version", "output version information and exit");
|
||||||
|
|
||||||
let given_options = match opts.parse(&args) {
|
let given_options = match opts.parse(&args) {
|
||||||
Ok (m) => { m }
|
Ok (m) => { m }
|
||||||
|
@ -68,7 +84,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
match n.parse::<usize>() {
|
match n.parse::<usize>() {
|
||||||
Ok(m) => { line_count = m }
|
Ok(m) => { settings.mode = FilterMode::Lines(m) }
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
show_error!("invalid line count '{}': {}", n, e);
|
show_error!("invalid line count '{}': {}", n, e);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -77,7 +93,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
}
|
}
|
||||||
None => match given_options.opt_str("c") {
|
None => match given_options.opt_str("c") {
|
||||||
Some(count) => match count.parse::<usize>() {
|
Some(count) => match count.parse::<usize>() {
|
||||||
Ok(m) => byte_count = m,
|
Ok(m) => settings.mode = FilterMode::Bytes(m),
|
||||||
Err(e)=> {
|
Err(e)=> {
|
||||||
show_error!("invalid byte count '{}': {}", count, e);
|
show_error!("invalid byte count '{}': {}", count, e);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -89,16 +105,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
|
|
||||||
let files = given_options.free;
|
let files = given_options.free;
|
||||||
|
|
||||||
let count =
|
|
||||||
if use_bytes {
|
|
||||||
byte_count
|
|
||||||
} else {
|
|
||||||
line_count
|
|
||||||
};
|
|
||||||
|
|
||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
let mut buffer = BufReader::new(stdin());
|
let mut buffer = BufReader::new(stdin());
|
||||||
head(&mut buffer, count, use_bytes);
|
head(&mut buffer, &settings);
|
||||||
} else {
|
} else {
|
||||||
let mut multiple = false;
|
let mut multiple = false;
|
||||||
let mut firstime = true;
|
let mut firstime = true;
|
||||||
|
@ -117,7 +126,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
let path = Path::new(file);
|
let path = Path::new(file);
|
||||||
let reader = File::open(&path).unwrap();
|
let reader = File::open(&path).unwrap();
|
||||||
let mut buffer = BufReader::new(reader);
|
let mut buffer = BufReader::new(reader);
|
||||||
if !head(&mut buffer, count, use_bytes) {
|
if !head(&mut buffer, &settings) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,17 +170,20 @@ fn obsolete(options: &[String]) -> (Vec<String>, Option<usize>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle errors on read
|
// TODO: handle errors on read
|
||||||
fn head<T: Read>(reader: &mut BufReader<T>, count: usize, use_bytes: bool) -> bool {
|
fn head<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> bool {
|
||||||
if use_bytes {
|
match settings.mode {
|
||||||
for byte in reader.bytes().take(count) {
|
FilterMode::Bytes(count) => {
|
||||||
if !pipe_print!("{}", byte.unwrap() as char) {
|
for byte in reader.bytes().take(count) {
|
||||||
return false;
|
if !pipe_print!("{}", byte.unwrap() as char) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
} else {
|
FilterMode::Lines(count) => {
|
||||||
for line in reader.lines().take(count) {
|
for line in reader.lines().take(count) {
|
||||||
if !pipe_print!("{}", line.unwrap()) {
|
if !pipe_println!("{}", line.unwrap()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
test/fixtures/head/lorem_ipsum.txt
vendored
Normal file
24
test/fixtures/head/lorem_ipsum.txt
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
Lorem ipsum dolor sit amet,
|
||||||
|
consectetur adipiscing elit.
|
||||||
|
Nunc interdum suscipit sem vel ornare.
|
||||||
|
Proin euismod,
|
||||||
|
justo sed mollis dictum,
|
||||||
|
eros urna ultricies augue,
|
||||||
|
eu pharetra mi ex id ante.
|
||||||
|
Duis convallis porttitor aliquam.
|
||||||
|
Nunc vitae tincidunt ex.
|
||||||
|
Suspendisse iaculis ligula ac diam consectetur lacinia.
|
||||||
|
Donec vel velit dui.
|
||||||
|
Etiam fringilla,
|
||||||
|
dolor quis tempor vehicula,
|
||||||
|
lacus turpis bibendum velit,
|
||||||
|
et pellentesque elit odio a magna.
|
||||||
|
Cras vulputate tortor non libero vehicula euismod.
|
||||||
|
Aliquam tincidunt nisl eget enim cursus,
|
||||||
|
viverra sagittis magna commodo.
|
||||||
|
Cras rhoncus egestas leo nec blandit.
|
||||||
|
Suspendisse potenti.
|
||||||
|
Etiam ullamcorper leo vel lacus vestibulum,
|
||||||
|
cursus semper eros efficitur.
|
||||||
|
In hac habitasse platea dictumst.
|
||||||
|
Phasellus scelerisque vehicula fringilla.
|
1
test/fixtures/head/lorem_ipsum_1_line.expected
vendored
Normal file
1
test/fixtures/head/lorem_ipsum_1_line.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Lorem ipsum dolor sit amet,
|
1
test/fixtures/head/lorem_ipsum_5_chars.expected
vendored
Normal file
1
test/fixtures/head/lorem_ipsum_5_chars.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Lorem
|
10
test/fixtures/head/lorem_ipsum_default.expected
vendored
Normal file
10
test/fixtures/head/lorem_ipsum_default.expected
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Lorem ipsum dolor sit amet,
|
||||||
|
consectetur adipiscing elit.
|
||||||
|
Nunc interdum suscipit sem vel ornare.
|
||||||
|
Proin euismod,
|
||||||
|
justo sed mollis dictum,
|
||||||
|
eros urna ultricies augue,
|
||||||
|
eu pharetra mi ex id ante.
|
||||||
|
Duis convallis porttitor aliquam.
|
||||||
|
Nunc vitae tincidunt ex.
|
||||||
|
Suspendisse iaculis ligula ac diam consectetur lacinia.
|
65
test/head.rs
Normal file
65
test/head.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use std::process::Command;
|
||||||
|
use util::*;
|
||||||
|
|
||||||
|
static PROGNAME: &'static str = "./head";
|
||||||
|
static INPUT: &'static str = "lorem_ipsum.txt";
|
||||||
|
|
||||||
|
#[path = "common/util.rs"]
|
||||||
|
#[macro_use]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stdin_default() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run_piped_stdin(&mut cmd, get_file_contents(INPUT));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_default.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stdin_1_line_obsolete() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run_piped_stdin(&mut cmd.args(&["-1"]), get_file_contents(INPUT));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stdin_1_line() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run_piped_stdin(&mut cmd.args(&["-n", "1"]), get_file_contents(INPUT));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stdin_5_chars() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run_piped_stdin(&mut cmd.args(&["-c", "5"]), get_file_contents(INPUT));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_5_chars.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_default() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run(&mut cmd.arg(INPUT));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_default.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_1_line_obsolete() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run(&mut cmd.args(&["-1", INPUT]));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_1_line() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run(&mut cmd.args(&["-n", "1", INPUT]));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_1_line.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_5_chars() {
|
||||||
|
let mut cmd = Command::new(PROGNAME);
|
||||||
|
let result = run(&mut cmd.args(&["-c", "5", INPUT]));
|
||||||
|
assert_eq!(result.stdout, get_file_contents("lorem_ipsum_5_chars.expected"));
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue