use std::fmt::{self, Display};
use std::time::Duration;
use kawauso_process::run::Line;
use kawauso_process::{Invocation, ProcessId};
pub use self::outcome::Outcome;
pub use self::run_id::RunId;
mod outcome;
mod run_id;
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum ProcessEvent {
Started {
id: RunId,
invocation: Invocation,
process_id: Option<ProcessId>,
},
Line {
id: RunId,
line: Line,
},
Finished {
id: RunId,
invocation: Invocation,
outcome: Outcome,
duration: Duration,
},
}
impl ProcessEvent {
pub fn id(&self) -> RunId {
match self {
Self::Started { id, .. } => *id,
Self::Line { id, .. } => *id,
Self::Finished { id, .. } => *id,
}
}
}
impl Display for ProcessEvent {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Started { invocation, .. } => write!(formatter, "$ {invocation}"),
Self::Line { line, .. } => Display::fmt(line, formatter),
Self::Finished {
invocation,
outcome,
..
} => write!(formatter, "{invocation} {outcome}"),
}
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::missing_panics_doc)]
use kawauso_process::run::Stream;
use super::*;
#[test]
fn display_with_finished_names_the_command_and_the_outcome() {
let event = ProcessEvent::Finished {
id: RunId::next(),
invocation: Invocation::new("git").arg("status"),
outcome: Outcome::Cancelled,
duration: Duration::from_secs(1),
};
let text = event.to_string();
assert_eq!(text, "git status was cancelled before it ended");
}
#[test]
fn display_with_line_returns_the_line_alone() {
let event = ProcessEvent::Line {
id: RunId::next(),
line: Line::new(Stream::StandardError, "no such file"),
};
let text = event.to_string();
assert_eq!(text, "no such file");
}
#[test]
fn display_with_started_reads_as_a_prompt() {
let event = ProcessEvent::Started {
id: RunId::next(),
invocation: Invocation::new("git").arg("status"),
process_id: None,
};
let text = event.to_string();
assert_eq!(text, "$ git status");
}
#[test]
fn id_with_finished_returns_the_run() {
let id = RunId::next();
let event = ProcessEvent::Finished {
id,
invocation: Invocation::new("git"),
outcome: Outcome::Incomplete,
duration: Duration::ZERO,
};
let found = event.id();
assert_eq!(found, id);
}
#[test]
fn id_with_line_returns_the_run() {
let id = RunId::next();
let event = ProcessEvent::Line {
id,
line: Line::new(Stream::StandardOutput, "hello"),
};
let found = event.id();
assert_eq!(found, id);
}
#[test]
fn id_with_started_returns_the_run() {
let id = RunId::next();
let event = ProcessEvent::Started {
id,
invocation: Invocation::new("git"),
process_id: None,
};
let found = event.id();
assert_eq!(found, id);
}
#[test]
fn trait_send() {
fn assert_send<T: Send>() {}
assert_send::<ProcessEvent>();
}
#[test]
fn trait_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<ProcessEvent>();
}
#[test]
fn trait_unpin() {
fn assert_unpin<T: Unpin>() {}
assert_unpin::<ProcessEvent>();
}
}