mirror of
https://github.com/atuinsh/atuin.git
synced 2025-02-09 07:02:54 +01:00
fix: Only escape control characters when writing to terminal (#1593)
When piping the output of `atuin history list` to a file, it makes more sense for the literal commands to be written rather than the escaped ones that would be printed to the terminal.
This commit is contained in:
parent
ed1ac5a2a9
commit
2bd7114cea
@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
io::{self, Write},
|
io::{self, IsTerminal, Write},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -150,50 +150,46 @@ pub fn print_list(
|
|||||||
let flush_each_line = print0;
|
let flush_each_line = print0;
|
||||||
|
|
||||||
for h in iterator {
|
for h in iterator {
|
||||||
match write!(
|
let fh = FmtHistory(h, CmdFormat::for_output(&w));
|
||||||
w,
|
let args = parsed_fmt.with_args(&fh);
|
||||||
"{}{}",
|
check_for_write_errors(write!(w, "{args}{entry_terminator}"));
|
||||||
parsed_fmt.with_args(&FmtHistory(h)),
|
|
||||||
entry_terminator
|
|
||||||
) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if flush_each_line {
|
if flush_each_line {
|
||||||
match w.flush() {
|
check_for_write_errors(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !flush_each_line {
|
if !flush_each_line {
|
||||||
match w.flush() {
|
check_for_write_errors(w.flush());
|
||||||
Ok(()) => {}
|
}
|
||||||
// ignore broken pipe (issue #626)
|
}
|
||||||
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => {}
|
|
||||||
Err(err) => {
|
fn check_for_write_errors(write: Result<(), io::Error>) {
|
||||||
eprintln!("ERROR: History output failed with the following error: {err}");
|
if let Err(err) = write {
|
||||||
std::process::exit(1);
|
// Ignore broken pipe (issue #626)
|
||||||
}
|
if err.kind() != io::ErrorKind::BrokenPipe {
|
||||||
|
eprintln!("ERROR: History output failed with the following error: {err}");
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// type wrapper around `History` so we can implement traits
|
/// Wrapper around `History` so we can format output dynamically at runtime
|
||||||
struct FmtHistory<'a>(&'a History);
|
struct FmtHistory<'a>(&'a History, CmdFormat);
|
||||||
|
|
||||||
|
enum CmdFormat {
|
||||||
|
Literal,
|
||||||
|
Escaped,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CmdFormat {
|
||||||
|
fn for_output<O: IsTerminal>(out: &O) -> Self {
|
||||||
|
if out.is_terminal() {
|
||||||
|
Self::Escaped
|
||||||
|
} else {
|
||||||
|
Self::Literal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static TIME_FMT: &[time::format_description::FormatItem<'static>] =
|
static TIME_FMT: &[time::format_description::FormatItem<'static>] =
|
||||||
format_description!("[year]-[month]-[day] [hour repr:24]:[minute]:[second]");
|
format_description!("[year]-[month]-[day] [hour repr:24]:[minute]:[second]");
|
||||||
@ -203,7 +199,10 @@ impl FormatKey for FmtHistory<'_> {
|
|||||||
#[allow(clippy::cast_sign_loss)]
|
#[allow(clippy::cast_sign_loss)]
|
||||||
fn fmt(&self, key: &str, f: &mut fmt::Formatter<'_>) -> Result<(), FormatKeyError> {
|
fn fmt(&self, key: &str, f: &mut fmt::Formatter<'_>) -> Result<(), FormatKeyError> {
|
||||||
match key {
|
match key {
|
||||||
"command" => f.write_str(&self.0.command.trim().escape_control())?,
|
"command" => match self.1 {
|
||||||
|
CmdFormat::Literal => f.write_str(self.0.command.trim()),
|
||||||
|
CmdFormat::Escaped => f.write_str(&self.0.command.trim().escape_control()),
|
||||||
|
}?,
|
||||||
"directory" => f.write_str(self.0.cwd.trim())?,
|
"directory" => f.write_str(self.0.cwd.trim())?,
|
||||||
"exit" => f.write_str(&self.0.exit.to_string())?,
|
"exit" => f.write_str(&self.0.exit.to_string())?,
|
||||||
"duration" => {
|
"duration" => {
|
||||||
|
Loading…
Reference in New Issue
Block a user