# Run Builder Implementation Plan This document outlines the plan for refactoring the `run.rs` module to use the builder pattern. ## Current Implementation Analysis The current implementation has several functions for running commands and scripts: - `run_command` and `run_command_silent` for single commands - `run_script` and `run_script_silent` for multiline scripts - `run` and `run_silent` as convenience functions that detect whether the input is a command or script These functions don't support all the options we want (die, async, log), and they don't follow the builder pattern. ## Builder Pattern Implementation Plan ### 1. Create a `RunBuilder` struct ```rust pub struct RunBuilder<'a> { cmd: &'a str, die: bool, silent: bool, async_exec: bool, log: bool, } ``` ### 2. Implement Default Values and Builder Methods ```rust impl<'a> RunBuilder<'a> { pub fn new(cmd: &'a str) -> Self { Self { cmd, die: true, // Default: true silent: false, // Default: false async_exec: false, // Default: false log: false, // Default: false } } pub fn die(mut self, die: bool) -> Self { self.die = die; self } pub fn silent(mut self, silent: bool) -> Self { self.silent = silent; self } pub fn async_exec(mut self, async_exec: bool) -> Self { self.async_exec = async_exec; self } pub fn log(mut self, log: bool) -> Self { self.log = log; self } pub fn execute(self) -> Result { // Implementation will go here } } ``` ### 3. Implement the `execute` Method The `execute` method will: 1. Determine if the command is a script or a single command 2. Handle the `async_exec` option by spawning a process without waiting 3. Handle the `log` option by logging command execution if enabled 4. Handle the `die` option by returning a CommandResult instead of an Err when die=false 5. Use the existing internal functions for the actual execution ### 4. Create a Public Function to Start the Builder ```rust pub fn run(cmd: &str) -> RunBuilder { RunBuilder::new(cmd) } ``` ### 5. Update Existing Functions for Backward Compatibility Update the existing functions to use the new builder pattern internally for backward compatibility. ## Structure Diagram ```mermaid classDiagram class RunBuilder { +String cmd +bool die +bool silent +bool async_exec +bool log +new(cmd: &str) RunBuilder +die(bool) RunBuilder +silent(bool) RunBuilder +async_exec(bool) RunBuilder +log(bool) RunBuilder +execute() Result } class CommandResult { +String stdout +String stderr +bool success +int code } RunBuilder ..> CommandResult : produces note for RunBuilder "Builder pattern implementation\nfor command execution" ``` ## Implementation Details ### Handling the `async_exec` Option When `async_exec` is true, we'll spawn the process but not wait for it to complete. We'll return a CommandResult with: - Empty stdout and stderr - success = true (since we don't know the outcome) - code = 0 (since we don't know the exit code) ### Handling the `log` Option When `log` is true, we'll log the command execution with a "[LOG]" prefix. For example: ``` [LOG] Executing command: ls -la ``` ### Handling the `die` Option When `die` is false and a command fails, instead of returning an Err, we'll return a CommandResult with: - success = false - The appropriate error message in stderr - code = -1 or the actual exit code if available ## Usage Examples After implementation, users will be able to use the builder pattern like this: ```rust // Simple usage with defaults let result = run("ls -la").execute()?; // With options let result = run("ls -la") .silent(true) .die(false) .execute()?; // Async execution run("long_running_command") .async_exec(true) .execute()?; // With logging let result = run("important_command") .log(true) .execute()?; // Script execution let result = run("echo 'Hello'\necho 'World'") .silent(true) .execute()?; ``` ## Implementation Steps 1. Add the `RunBuilder` struct and its methods 2. Implement the `execute` method 3. Create the public `run` function 4. Update the existing functions to use the builder pattern internally 5. Add tests for the new functionality 6. Update documentation