1
Fork 0
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:
Sylvestre Ledru 2022-02-12 19:00:39 +01:00 committed by GitHub
commit 142c24e579
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 20 deletions

View file

@ -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;
} }
} }

View file

@ -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]