fix broken pipe on history list (#927)

* fix #626

* slightly refactor
This commit is contained in:
Conrad Ludgate 2023-05-02 03:31:25 +01:00 committed by GitHub
parent 50e2770f37
commit 20845a5cf5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 36 deletions

4
Cargo.lock generated
View file

@ -1793,9 +1793,9 @@ dependencies = [
[[package]]
name = "runtime-format"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b035308411b1af4683acc4fc928366443f08b893bb73e235c85de4c2be572495"
checksum = "09958d5b38bca768ede7928c767c89a08ba568144a7b61992aecae79b03c8c94"
dependencies = [
"tinyvec",
]

View file

@ -68,7 +68,7 @@ fs-err = { workspace = true }
whoami = { workspace = true }
rpassword = "7.0"
semver = { workspace = true }
runtime-format = "0.1.2"
runtime-format = "0.1.3"
tiny-bip39 = "1"
futures-util = "0.3"
fuzzy-matcher = "0.3.7"

View file

@ -1,14 +1,14 @@
use std::{
env,
fmt::{self, Display},
io::{StdoutLock, Write},
io::{self, Write},
time::Duration,
};
use atuin_common::utils;
use clap::Subcommand;
use eyre::Result;
use runtime_format::{FormatKey, FormatKeyError, ParsedFmt};
use runtime_format::{FormatKey, FormatKeyError, ParseSegment, ParsedFmt};
use atuin_client::{
database::{current_context, Database},
@ -97,13 +97,45 @@ pub fn print_list(h: &[History], list_mode: ListMode, format: Option<&str>) {
let w = std::io::stdout();
let mut w = w.lock();
match list_mode {
ListMode::Human => print_human_list(&mut w, h, format),
ListMode::CmdOnly => print_cmd_only(&mut w, h),
ListMode::Regular => print_regular(&mut w, h, format),
let fmt_str = match list_mode {
ListMode::Human => format
.unwrap_or("{time} · {duration}\t{command}")
.replace("\\t", "\t"),
ListMode::Regular => format
.unwrap_or("{time}\t{command}\t{duration}")
.replace("\\t", "\t"),
// not used
ListMode::CmdOnly => String::new(),
};
let parsed_fmt = match list_mode {
ListMode::Human | ListMode::Regular => parse_fmt(&fmt_str),
ListMode::CmdOnly => std::iter::once(ParseSegment::Key("command")).collect(),
};
for h in h.iter().rev() {
match writeln!(w, "{}", parsed_fmt.with_args(&FmtHistory(h))) {
Ok(()) => {}
// ignore broken pipe (issue #626)
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => {
return;
}
Err(err) => {
eprintln!("ERROR: History output failed with the following error: {err}");
std::process::exit(1);
}
}
}
w.flush().expect("failed to flush history");
match w.flush() {
Ok(()) => {}
// ignore broken pipe (issue #626)
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => {}
Err(err) => {
eprintln!("ERROR: History output failed with the following error: {err}");
std::process::exit(1);
}
}
}
/// type wrapper around `History` so we can implement traits
@ -140,38 +172,14 @@ impl FormatKey for FmtHistory<'_> {
}
}
fn print_list_with(w: &mut StdoutLock, h: &[History], format: &str) {
let fmt = match ParsedFmt::new(format) {
fn parse_fmt(format: &str) -> ParsedFmt {
match ParsedFmt::new(format) {
Ok(fmt) => fmt,
Err(err) => {
eprintln!("ERROR: History formatting failed with the following error: {err}");
println!("If your formatting string contains curly braces (eg: {{var}}) you need to escape them this way: {{{{var}}.");
std::process::exit(1)
}
};
for h in h.iter().rev() {
writeln!(w, "{}", fmt.with_args(&FmtHistory(h))).expect("failed to write history");
}
}
pub fn print_human_list(w: &mut StdoutLock, h: &[History], format: Option<&str>) {
let format = format
.unwrap_or("{time} · {duration}\t{command}")
.replace("\\t", "\t");
print_list_with(w, h, &format);
}
pub fn print_regular(w: &mut StdoutLock, h: &[History], format: Option<&str>) {
let format = format
.unwrap_or("{time}\t{command}\t{duration}")
.replace("\\t", "\t");
print_list_with(w, h, &format);
}
pub fn print_cmd_only(w: &mut StdoutLock, h: &[History]) {
for h in h.iter().rev() {
writeln!(w, "{}", h.command.trim()).expect("failed to write history");
}
}