mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 13:37:48 +00:00
Merge pull request #2982 from Dr-Emann/paste_cleanup
paste: Fixes and cleanup
This commit is contained in:
commit
142c24e579
2 changed files with 44 additions and 20 deletions
|
@ -9,8 +9,7 @@
|
||||||
|
|
||||||
use clap::{crate_version, App, AppSettings, Arg};
|
use clap::{crate_version, App, AppSettings, Arg};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{stdin, BufRead, BufReader, Read};
|
use std::io::{stdin, stdout, BufRead, BufReader, Read, Write};
|
||||||
use std::iter::repeat;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use uucore::error::{FromIo, UResult};
|
use uucore::error::{FromIo, UResult};
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) -> UResult<()> {
|
fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) -> UResult<()> {
|
||||||
let mut files = vec![];
|
let mut files = Vec::with_capacity(filenames.len());
|
||||||
for name in filenames {
|
for name in filenames {
|
||||||
let file = if name == "-" {
|
let file = if name == "-" {
|
||||||
None
|
None
|
||||||
|
@ -89,55 +88,62 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) -> UResult<()>
|
||||||
files.push(file);
|
files.push(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
let delimiters: Vec<String> = unescape(delimiters)
|
let delimiters: Vec<char> = unescape(delimiters).chars().collect();
|
||||||
.chars()
|
|
||||||
.map(|x| x.to_string())
|
|
||||||
.collect();
|
|
||||||
let mut delim_count = 0;
|
let mut delim_count = 0;
|
||||||
|
let stdout = stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
|
let mut output = String::new();
|
||||||
if serial {
|
if serial {
|
||||||
for file in &mut files {
|
for file in &mut files {
|
||||||
let mut output = String::new();
|
output.clear();
|
||||||
loop {
|
loop {
|
||||||
let mut line = String::new();
|
match read_line(file.as_mut(), &mut output) {
|
||||||
match read_line(file.as_mut(), &mut line) {
|
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
output.push_str(line.trim_end());
|
if output.ends_with('\n') {
|
||||||
output.push_str(&delimiters[delim_count % delimiters.len()]);
|
output.pop();
|
||||||
|
}
|
||||||
|
output.push(delimiters[delim_count % delimiters.len()]);
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e.map_err_context(String::new)),
|
Err(e) => return Err(e.map_err_context(String::new)),
|
||||||
}
|
}
|
||||||
delim_count += 1;
|
delim_count += 1;
|
||||||
}
|
}
|
||||||
println!("{}", &output[..output.len() - 1]);
|
output.pop();
|
||||||
|
writeln!(stdout, "{}", output)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut eof: Vec<bool> = repeat(false).take(files.len()).collect();
|
let mut eof = vec![false; files.len()];
|
||||||
loop {
|
loop {
|
||||||
let mut output = String::new();
|
output.clear();
|
||||||
let mut eof_count = 0;
|
let mut eof_count = 0;
|
||||||
for (i, file) in files.iter_mut().enumerate() {
|
for (i, file) in files.iter_mut().enumerate() {
|
||||||
if eof[i] {
|
if eof[i] {
|
||||||
eof_count += 1;
|
eof_count += 1;
|
||||||
} else {
|
} else {
|
||||||
let mut line = String::new();
|
match read_line(file.as_mut(), &mut output) {
|
||||||
match read_line(file.as_mut(), &mut line) {
|
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
eof[i] = true;
|
eof[i] = true;
|
||||||
eof_count += 1;
|
eof_count += 1;
|
||||||
}
|
}
|
||||||
Ok(_) => output.push_str(line.trim_end()),
|
Ok(_) => {
|
||||||
|
if output.ends_with('\n') {
|
||||||
|
output.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(e) => return Err(e.map_err_context(String::new)),
|
Err(e) => return Err(e.map_err_context(String::new)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output.push_str(&delimiters[delim_count % delimiters.len()]);
|
output.push(delimiters[delim_count % delimiters.len()]);
|
||||||
delim_count += 1;
|
delim_count += 1;
|
||||||
}
|
}
|
||||||
if files.len() == eof_count {
|
if files.len() == eof_count {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
println!("{}", &output[..output.len() - 1]);
|
// Remove final delimiter
|
||||||
|
output.pop();
|
||||||
|
writeln!(stdout, "{}", output)?;
|
||||||
delim_count = 0;
|
delim_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,24 @@ static EXAMPLE_DATA: &[TestData] = &[
|
||||||
ins: &["1\na\n", "2\nb\n"],
|
ins: &["1\na\n", "2\nb\n"],
|
||||||
out: "1 2\na b\n",
|
out: "1 2\na b\n",
|
||||||
},
|
},
|
||||||
|
TestData {
|
||||||
|
name: "multibyte-delim",
|
||||||
|
args: &["-d", "💣"],
|
||||||
|
ins: &["1\na\n", "2\nb\n"],
|
||||||
|
out: "1💣2\na💣b\n",
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
name: "multibyte-delim-serial",
|
||||||
|
args: &["-d", "💣", "-s"],
|
||||||
|
ins: &["1\na\n", "2\nb\n"],
|
||||||
|
out: "1💣a\n2💣b\n",
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
name: "trailing whitespace",
|
||||||
|
args: &["-d", "|"],
|
||||||
|
ins: &["1 \na \n", "2\t\nb\t\n"],
|
||||||
|
out: "1 |2\t\na |b\t\n",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue