summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConrad Ludgate <conradludgate@gmail.com>2023-05-02 03:31:25 +0100
committerGitHub <noreply@github.com>2023-05-01 22:31:25 -0400
commit20845a5cf55626a54b176f3ec9b9cf80bd5fc91d (patch)
tree358b9af5763a19587f10ca2a41184381c6306623
parent50e2770f3782d43ca114455c577c8881a9bdc084 (diff)
fix broken pipe on history list (#927)
* fix #626 * slightly refactor
-rw-r--r--Cargo.lock4
-rw-r--r--atuin/Cargo.toml2
-rw-r--r--atuin/src/command/client/history.rs74
3 files changed, 44 insertions, 36 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bc262bd0..06feb06a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
]
diff --git a/atuin/Cargo.toml b/atuin/Cargo.toml
index 6b43aa34..1bd77289 100644
--- a/atuin/Cargo.toml
+++ b/atuin/Cargo.toml
@@ -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"
diff --git a/atuin/src/command/client/history.rs b/atuin/src/command/client/history.rs
index 76c796ef..4670e8c3 100644
--- a/atuin/src/command/client/history.rs
+++ b/atuin/src/command/client/history.rs
@@ -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");
}
}