#[derive(Debug, Clone, Default)]
pub struct SessionContext {
last_command: Option<String>,
last_exit_code: Option<i32>,
execution_count: u64,
}
impl SessionContext {
pub fn new() -> Self {
Self::default()
}
pub fn last_command(&self) -> Option<&str> {
self.last_command.as_deref()
}
pub fn last_exit_code(&self) -> Option<i32> {
self.last_exit_code
}
pub fn execution_count(&self) -> u64 {
self.execution_count
}
pub fn record_execution(&mut self, command: impl Into<String>, exit_code: Option<i32>) {
self.last_command = Some(command.into());
self.last_exit_code = exit_code;
self.execution_count += 1;
}
pub fn last_succeeded(&self) -> bool {
self.last_exit_code == Some(0)
}
pub fn last_failed(&self) -> bool {
matches!(self.last_exit_code, Some(code) if code != 0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_context_new() {
let ctx = SessionContext::new();
assert!(ctx.last_command().is_none());
assert!(ctx.last_exit_code().is_none());
assert_eq!(ctx.execution_count(), 0);
}
#[test]
fn test_record_execution() {
let mut ctx = SessionContext::new();
ctx.record_execution("ls -la", Some(0));
assert_eq!(ctx.last_command(), Some("ls -la"));
assert_eq!(ctx.last_exit_code(), Some(0));
assert_eq!(ctx.execution_count(), 1);
assert!(ctx.last_succeeded());
assert!(!ctx.last_failed());
}
#[test]
fn test_execution_count_increments() {
let mut ctx = SessionContext::new();
ctx.record_execution("first", Some(0));
ctx.record_execution("second", Some(1));
assert_eq!(ctx.execution_count(), 2);
assert_eq!(ctx.last_command(), Some("second"));
assert!(ctx.last_failed());
assert!(!ctx.last_succeeded());
}
#[test]
fn a_command_that_never_reported_an_exit_code_neither_succeeded_nor_failed() {
let mut ctx = SessionContext::new();
ctx.record_execution("killed", None);
assert!(!ctx.last_succeeded());
assert!(!ctx.last_failed());
}
}