mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
paste: support multi-stdin (#1791)
- added `-` as the default input, since `paste` reads stdin if no file is provided - `paste` also supports providing `-` multiple times - added a test for it
This commit is contained in:
parent
734ef0a8a1
commit
374a4fde86
2 changed files with 49 additions and 11 deletions
|
@ -12,7 +12,7 @@ extern crate uucore;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{stdin, BufRead, BufReader, Read};
|
use std::io::{stdin, BufRead, BufReader, Stdin};
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
@ -26,6 +26,29 @@ mod options {
|
||||||
pub const FILE: &str = "file";
|
pub const FILE: &str = "file";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need this trait to wrap both BufReader and Stdin. We need
|
||||||
|
// `read_line` function only, but Stdin does not provide BufRead
|
||||||
|
// unless lock function is called, which prevents us from using stdin
|
||||||
|
// multiple times
|
||||||
|
trait ReadLine {
|
||||||
|
fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StdinReadLine(Stdin);
|
||||||
|
struct BufReadReadLine<R: BufRead>(R);
|
||||||
|
|
||||||
|
impl ReadLine for StdinReadLine {
|
||||||
|
fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
|
||||||
|
return self.0.read_line(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: BufRead> ReadLine for BufReadReadLine<R> {
|
||||||
|
fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
|
||||||
|
return self.0.read_line(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
let matches = App::new(executable!())
|
let matches = App::new(executable!())
|
||||||
.version(VERSION)
|
.version(VERSION)
|
||||||
|
@ -49,7 +72,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
Arg::with_name(options::FILE)
|
Arg::with_name(options::FILE)
|
||||||
.value_name("FILE")
|
.value_name("FILE")
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.required(true),
|
.default_value("-"),
|
||||||
)
|
)
|
||||||
.get_matches_from(args);
|
.get_matches_from(args);
|
||||||
|
|
||||||
|
@ -66,15 +89,15 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {
|
fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {
|
||||||
let mut files: Vec<BufReader<Box<dyn Read>>> = filenames
|
let mut files: Vec<Box<dyn ReadLine>> = filenames
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
BufReader::new(if name == "-" {
|
if name == "-" {
|
||||||
Box::new(stdin()) as Box<dyn Read>
|
Box::new(StdinReadLine(stdin())) as Box<dyn ReadLine>
|
||||||
} else {
|
} else {
|
||||||
let r = crash_if_err!(1, File::open(Path::new(&name)));
|
let r = crash_if_err!(1, File::open(Path::new(&name)));
|
||||||
Box::new(r) as Box<dyn Read>
|
Box::new(BufReadReadLine(BufReader::new(r))) as Box<dyn ReadLine>
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,23 @@ use crate::common::util::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_combine_pairs_of_lines() {
|
fn test_combine_pairs_of_lines() {
|
||||||
|
for s in vec!["-s", "--serial"] {
|
||||||
|
for d in vec!["-d", "--delimiters"] {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
.args(&["-s", "-d", "\t\n", "html_colors.txt"])
|
.args(&[s, d, "\t\n", "html_colors.txt"])
|
||||||
.run()
|
.run()
|
||||||
.stdout_is_fixture("html_colors.expected");
|
.stdout_is_fixture("html_colors.expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multi_stdin() {
|
||||||
|
for d in vec!["-d", "--delimiters"] {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&[d, "\t\n", "-", "-"])
|
||||||
|
.pipe_in_fixture("html_colors.txt")
|
||||||
|
.succeeds()
|
||||||
|
.stdout_is_fixture("html_colors.expected");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue