style(tui): format shell dispatcher stack

This commit is contained in:
Paulo Aboim Pinto
2026-05-27 16:56:30 +02:00
committed by Hunter Bown
parent 6e5d8ddf01
commit 45e7b12583
6 changed files with 49 additions and 22 deletions
+3
View File
@@ -14,12 +14,14 @@ use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};
use tempfile::TempDir;
#[cfg(test)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum EvalShellPlatform {
Windows,
Unix,
}
#[cfg(test)]
#[derive(Debug, Clone, PartialEq, Eq)]
struct EvalShellInvocation {
program: &'static str,
@@ -27,6 +29,7 @@ struct EvalShellInvocation {
raw_payload_on_windows: bool,
}
#[cfg(test)]
fn eval_shell_invocation_for_platform(
command: &str,
platform: EvalShellPlatform,
+1 -1
View File
@@ -63,9 +63,9 @@ mod schema_migration;
mod seam_manager;
#[allow(dead_code)]
mod session_failure_classifier;
mod shell_dispatcher;
mod session_manager;
mod settings;
mod shell_dispatcher;
mod skill_state;
mod skills;
mod snapshot;
-1
View File
@@ -868,4 +868,3 @@ mod tests {
}
}
}
}
+32 -17
View File
@@ -28,6 +28,7 @@ static LOG_MUTEX: Mutex<()> = Mutex::new(());
// ---------------------------------------------------------------------------
/// The concrete shell that the dispatcher will use.
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ShellKind {
/// PowerShell 7+ (`pwsh.exe`).
@@ -104,6 +105,7 @@ pub struct ShellDispatcher {
kind: ShellKind,
}
#[allow(dead_code)]
impl ShellDispatcher {
/// Detect the user's shell from the environment.
///
@@ -159,13 +161,10 @@ impl ShellDispatcher {
// `detect()` which calls `log_startup()` which also acquires the mutex.
let kind = global_dispatcher().kind();
let _lock = LOG_MUTEX.lock();
let line = format!(
"[{}] exec via {kind:?}: {command}\n", now_iso()
);
let line = format!("[{}] exec via {kind:?}: {command}\n", now_iso());
Self::append_log(path, &line)
}
/// The detected shell kind.
pub fn kind(&self) -> &ShellKind {
&self.kind
@@ -233,9 +232,7 @@ impl ShellDispatcher {
let _lock = LOG_MUTEX.lock();
if let Ok(path) = std::env::var("SHELL_DISPATCHER_LOG") {
let kind = self.kind();
let line = format!(
"[{}] exec via {kind:?}: {shell_command}\n", now_iso()
);
let line = format!("[{}] exec via {kind:?}: {shell_command}\n", now_iso());
let _ = Self::append_log(&path, &line);
}
}
@@ -318,7 +315,9 @@ impl ShellDispatcher {
r"C:\Program Files\PowerShell\7",
r"C:\Windows\System32\WindowsPowerShell\v1.0",
];
known_dirs.iter().any(|dir| std::path::Path::new(dir).join(name).is_file())
known_dirs
.iter()
.any(|dir| std::path::Path::new(dir).join(name).is_file())
}
fn binary_on_path(name: &str) -> bool {
@@ -336,7 +335,9 @@ impl ShellDispatcher {
// -- Helpers ---------------------------------------------------------------
fn now_iso() -> String {
chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.3f").to_string()
chrono::Utc::now()
.format("%Y-%m-%dT%H:%M:%S%.3f")
.to_string()
}
/// Global dispatcher instance, detected once at startup.
@@ -384,7 +385,9 @@ mod tests {
#[test]
fn powershell_build_command_includes_no_profile_and_command_flags() {
let dispatcher = ShellDispatcher { kind: ShellKind::Pwsh };
let dispatcher = ShellDispatcher {
kind: ShellKind::Pwsh,
};
let cmd = dispatcher.build_command("echo hello");
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
assert!(args.contains(&"-NoProfile"));
@@ -394,7 +397,9 @@ mod tests {
#[test]
fn cmd_build_command_uses_c_flag() {
let dispatcher = ShellDispatcher { kind: ShellKind::Cmd };
let dispatcher = ShellDispatcher {
kind: ShellKind::Cmd,
};
let cmd = dispatcher.build_command("echo hello");
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
assert!(args.contains(&"/C"));
@@ -403,7 +408,9 @@ mod tests {
#[test]
fn sh_build_command_uses_dash_c() {
let dispatcher = ShellDispatcher { kind: ShellKind::Sh };
let dispatcher = ShellDispatcher {
kind: ShellKind::Sh,
};
let cmd = dispatcher.build_command("echo hello");
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
assert!(args.contains(&"-c"));
@@ -412,7 +419,9 @@ mod tests {
#[test]
fn build_direct_preserves_args() {
let dispatcher = ShellDispatcher { kind: ShellKind::Cmd };
let dispatcher = ShellDispatcher {
kind: ShellKind::Cmd,
};
let args = vec!["-m".to_string(), "commit message".to_string()];
let cmd = dispatcher.build_direct("git", &args);
let cmd_args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
@@ -439,7 +448,9 @@ mod tests {
#[test]
fn build_command_quotes_spaces_for_cmd() {
let dispatcher = ShellDispatcher { kind: ShellKind::Cmd };
let dispatcher = ShellDispatcher {
kind: ShellKind::Cmd,
};
let cmd = dispatcher.build_command("git commit -m \"msg with spaces\"");
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
assert_eq!(args.len(), 2);
@@ -450,7 +461,9 @@ mod tests {
#[test]
fn build_command_quotes_spaces_for_pwsh() {
let dispatcher = ShellDispatcher { kind: ShellKind::Pwsh };
let dispatcher = ShellDispatcher {
kind: ShellKind::Pwsh,
};
let cmd = dispatcher.build_command("git commit -m \"msg with spaces\"");
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
assert_eq!(args.len(), 3);
@@ -461,7 +474,9 @@ mod tests {
#[test]
fn build_direct_handles_empty_args() {
let dispatcher = ShellDispatcher { kind: ShellKind::Sh };
let dispatcher = ShellDispatcher {
kind: ShellKind::Sh,
};
let cmd = dispatcher.build_direct("echo", &[]);
let args: Vec<&str> = cmd.get_args().map(|a| a.to_str().unwrap()).collect();
assert!(args.is_empty());
@@ -499,4 +514,4 @@ mod tests {
assert_eq!(kind.binary(), "/bin/zsh");
assert_eq!(kind.command_flag(), "-c");
}
}
}
+11 -3
View File
@@ -850,7 +850,11 @@ impl ShellManager {
// success/failure/timeout (issue #1690).
let _ = crossterm::terminal::disable_raw_mode();
struct SyncRawModeGuard;
impl Drop for SyncRawModeGuard { fn drop(&mut self) { let _ = crossterm::terminal::enable_raw_mode(); } }
impl Drop for SyncRawModeGuard {
fn drop(&mut self) {
let _ = crossterm::terminal::enable_raw_mode();
}
}
let _guard = SyncRawModeGuard;
let mut child = cmd
@@ -990,7 +994,11 @@ impl ShellManager {
// Disable raw mode before spawn; restore on drop (issue #1690).
let _ = crossterm::terminal::disable_raw_mode();
struct InteractiveRawModeGuard;
impl Drop for InteractiveRawModeGuard { fn drop(&mut self) { let _ = crossterm::terminal::enable_raw_mode(); } }
impl Drop for InteractiveRawModeGuard {
fn drop(&mut self) {
let _ = crossterm::terminal::enable_raw_mode();
}
}
let _guard = InteractiveRawModeGuard;
child_env::apply_to_command(&mut cmd, child_env::string_map_env(&exec_env.env));
@@ -2810,4 +2818,4 @@ impl ToolSpec for NoteTool {
}
#[cfg(test)]
mod tests;
mod tests;
+2
View File
@@ -4,6 +4,8 @@ use std::fs;
#[path = "../src/eval.rs"]
mod eval;
#[path = "../src/shell_dispatcher.rs"]
mod shell_dispatcher;
use eval::{EvalHarness, EvalHarnessConfig, ScenarioStepKind};
use tempfile::tempdir;