### Example: Full Startup Execution Flow Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md Outlines the step-by-step execution flow following the example startup command, detailing flag parsing, validation, and goroutine spawning. ```text 1. Parses flags: directory=/src, exclude=vendor, etc. 2. Validates: work-delay=500 > 0 ✓ 3. Sets logging flags 4. Defaults: none (directory specified) 5. Validates: platform capabilities ✓ 6. Defaults: none (build command specified) 7. Compiles pattern: `(.+\.go|.+\.c)$` 8. Creates WatcherConfig 9. Creates NotifyWatcher (polling=false) 10. Walks /src, adds vendor-excluded directories 11. Creates channels 12. Spawns builder, runner, watcher 13. watcher.Watch() blocks 14. Waits for file changes... ``` -------------------------------- ### Builder Example Usage Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Demonstrates how to use the builder function by simulating rapid file changes and receiving build requests. This example shows the debouncing mechanism in action. ```go jobs := make(chan string) buildStarted := make(chan string) buildDone := make(chan bool) // Spawn the builder in a goroutine go builder(jobs, buildStarted, buildDone) // Simulate rapid file changes go func() { jobs <- "main.go" time.Sleep(100 * time.Millisecond) jobs <- "main.go" time.Sleep(100 * time.Millisecond) jobs <- "main.go" // After 900ms of no changes, builder will trigger }() // Receive build request buildPath := <-buildStarted // Receives "main.go" after debounce // Perform build... success := true buildDone <- success ``` -------------------------------- ### Example: Full CompileDaemon Startup Command Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md Demonstrates a comprehensive command-line invocation of CompileDaemon with various configuration flags. ```bash $ CompileDaemon \ -directory=/src \ -exclude-dir=vendor \ -build="go build -o /bin/app" \ -command="./app" \ -work-delay=500 \ -color ``` -------------------------------- ### Cross-Platform Process Group Management Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/process-management.md Demonstrates starting a command in a new process group and performing graceful termination if supported, with a fallback to hard termination on timeout. This example highlights differences between POSIX and Windows. ```go // Start command in new process group cmd := exec.Command("./myapp") setProcessGroupId(cmd) err := cmd.Start() // On POSIX: myapp has PGID = myapp's PID // On Windows: No process group setup // Later: Graceful termination (if supported) if gracefulTerminationPossible() { terminateGracefully(cmd.Process) // On POSIX: Sends SIGTERM to group // Process has time to clean up // Wait with timeout select { case <-done: // Process exited cleanly case <-time.After(3 * time.Second): // Timeout: fall back to hard kill terminateHard(cmd.Process) // On POSIX: Sends SIGKILL to group // On Windows: Calls TerminateProcess } } else { // Windows: Jump straight to hard kill terminateHard(cmd.Process) } ``` -------------------------------- ### Example File Matching Configuration Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md This example shows how to configure CompileDaemon to include or exclude files based on patterns and globs. It demonstrates the use of -pattern, -include, and -exclude flags. ```bash # Configuration: CompileDaemon \ -pattern="(.+\.go)$" \ -include="Makefile" \ -exclude=".#*" # Matching: main.go → YES (matches pattern) Makefile → YES (matches include) .#main.go → NO (matches exclude) test_utils.go → YES (matches pattern) README.md → NO (no match) ``` -------------------------------- ### Runner with Multiple Commands Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Demonstrates initializing the runner with a command template that can be formatted using fmt.Sprintf, allowing for dynamic command construction with placeholders. ```go go runner("./myapp -mode %[1]s", buildStarted, buildSuccess) ``` -------------------------------- ### AddFiles to Watcher Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Shows how to recursively add files and subdirectories to the watcher. Handles potential errors during the file addition process. ```go watcher, _ := NewWatcher(cfg) if err := watcher.AddFiles(); err != nil { log.Fatal("Could not add files:", err) } ``` -------------------------------- ### CompileDaemon Startup Sequence Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md Illustrates the sequential steps involved in starting the CompileDaemon application, from flag parsing to blocking on the watcher. ```text main() ├─ Parse flags ├─ Validate configuration ├─ Create watcher ├─ Walk directories ├─ Create channels └─ Spawn goroutines: ├─ builder(jobs, buildStarted, buildSuccess) ├─ runner/flusher(...) └─ watcher.Watch(jobs) ← main thread blocks here ``` -------------------------------- ### Process Start Error: Pipe Creation Failure Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md Shows an example of an error that occurs when CompileDaemon fails to create a pipe for the standard output of the post-build command. This results in a fatal error. ```go // Pipe creation error: // Error: can't get stdout pipe for command: ``` -------------------------------- ### Start Subprocess and Get Output Pipes Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Use this function to start a command and obtain pipes for its standard output and standard error. Ensure you close the returned pipes after use. This function sets up process groups on POSIX systems for coordinated termination. ```Go func startCommand(command string) (cmd *exec.Cmd, stdout io.ReadCloser, stderr io.ReadCloser, err error) ``` ```Go cmd, stdout, stderr, err := startCommand("./myapp -port 8080") if err != nil { log.Fatal("Could not start command:", err) } // Send pipes to logger pipeChan <- stdout pipeChan <- stderr // Wait for process to exit cmd.Wait() ``` -------------------------------- ### Command Template Formatting Examples Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Illustrates how to use printf-style formatting in command templates, including cases with and without placeholders, and how to escape format specifiers to prevent warnings. ```go // No placeholder - file path ignored template := "./myapp" // Result: "./myapp" ``` ```go // With placeholder - file path included template := "./myapp --changed %[1]s" // Result: "./myapp --changed main.go" (if main.go triggered build) ``` ```go // Escaped format specifier - no warning template := "./myapp" // Internally becomes: fmt.Sprintf("%0.s"+template, eventPath) // Prevents "missing format specifier" warning ``` -------------------------------- ### Close Watcher Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Demonstrates how to properly close a watcher to release resources. Ensure Close is called, typically using defer. ```go watcher, _ := NewWatcher(cfg) defer watcher.Close() ``` -------------------------------- ### Example Usage of *regexp.Regexp for File Watching Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/types.md Shows how to pre-compile a regular expression for matching Go and C source files, used for configuring a file watcher. ```Go pattern := regexp.MustCompile(`(.+\.go|.+\.c)$`) cfg := &WatcherConfig{ pattern: pattern, } ``` -------------------------------- ### Initialize and Configure Watcher Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Example of creating a watcher configuration, including setting up a regex pattern for Go and C files, specifying directories to watch, and excluding common development directories like .git and vendor. This snippet demonstrates how to instantiate and defer closing a watcher. ```go import ( "regexp" "github.com/githubnemo/CompileDaemon" ) // Create a regex pattern for Go files pattern := regexp.MustCompile(`(.+\.go|.+\.c)$`) // Configure the watcher cfg := &WatcherConfig{ flagVerbose: false, flagPolling: false, flagRecursive: true, flagDirectories: []string{"."}, flagExcludedDirs: []string{".git", "vendor"}, pattern: pattern, } // Create a watcher instance watcher, err := NewWatcher(cfg) if err != nil { // Handle error } defer watcher.Close() ``` -------------------------------- ### Example Usage of buildCommandList Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/types.md Illustrates how to use the buildCommandList type with command-line flags to specify multiple build commands. The commands are collected and executed sequentially. ```Bash # Command line: CompileDaemon -build="go fmt ./..." -build="go build" # Populates buildCommandList.commands with: // ["go fmt ./...", "go build"] ``` -------------------------------- ### startCommand Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Starts a subprocess and returns pipes for monitoring its output. It sets up a process group on POSIX systems for coordinated termination of child processes. ```APIDOC ## startCommand ### Description Starts a subprocess and returns pipes for monitoring its output. Sets up process group on POSIX systems to allow coordinated termination of child processes. ### Method `startCommand(command string)` ### Parameters #### Path Parameters - **command** (string) - Required - Command string to execute (e.g., "./myapp -flag value") ### Returns #### Success Response - **cmd** (*exec.Cmd) - The started command object; use cmd.Process for process operations - **stdout** (io.ReadCloser) - Pipe for reading stdout; must be closed by caller - **stderr** (io.ReadCloser) - Pipe for reading stderr; must be closed by caller - **err** (error) - Non-nil if any step of command startup fails ### Behavior 1. **Parsing**: Splits command string on whitespace 2. **Process Group**: Calls setProcessGroupId() to set PGID (POSIX) or no-op (Windows) 3. **Working Directory**: Uses -run-dir flag if specified 4. **Pipes**: Obtains stdout and stderr pipes before starting 5. **Startup**: Calls cmd.Start() (not cmd.Run(), which would block) ### Error Handling Throws/Rejects: - `fmt.Errorf("can't get stdout pipe for command: %s", err)` if stdout pipe creation fails - `fmt.Errorf("can't get stderr pipe for command: %s", err)` if stderr pipe creation fails - `fmt.Errorf("can't start command: %s", err)` if cmd.Start() fails ### Example Usage ```go cmd, stdout, stderr, err := startCommand("./myapp -port 8080") if err != nil { log.Fatal("Could not start command:", err) } // Send pipes to logger pipeChan <- stdout pipeChan <- stderr // Wait for process to exit cmd.Wait() ``` **Pipe Handling:** ```go // Pipes are non-blocking; reads from them may return EOF // even if process is still running reader := bufio.NewReader(stdout) line, err := reader.ReadString('\n') if err != nil { // EOF or actual error } ``` ``` -------------------------------- ### Example Usage of globList String Method Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/glob-list.md Demonstrates how to set patterns on a globList and then retrieve their string representation. The output shows the patterns enclosed in square brackets. ```go var excludeDirs globList excludeDirs.Set(".git") excludeDirs.Set("vendor") fmt.Println(excludeDirs.String()) // Output: [.git vendor] ``` -------------------------------- ### Basic Runner Initialization Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Initializes the runner with a simple command template and channels for build events. This is a basic setup without using the file path placeholder. ```go go runner("./myapp", buildStarted, buildSuccess) ``` -------------------------------- ### PollingWatcher Watch Method Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Starts the polling loop in a goroutine and processes file events. It filters paths against inclusion/exclusion patterns and sends matches to the jobs channel, suppressing ErrWatchedFileDeleted errors. Use this for Docker on macOS due to compatibility. ```go // Using polling watcher for Docker on macOS cfg := &WatcherConfig{ flagPolling: true, flagPollingInterval: 500, // Check every 500ms // ... other config } watcher, _ := NewWatcher(cfg) jobs := make(chan string) go watcher.Watch(jobs) ``` -------------------------------- ### Runner with Command Stop Flag Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Illustrates the behavior when the -command-stop flag is enabled. The old process is killed before the build starts, and a new process is started after the build succeeds. ```go // CommandTemplate: "./server" // buildStarted: "main.go" // buildSuccess: true // Actions: // 1. Kill old process // 2. Wait for build to complete // 3. Start new process with "./server" ``` -------------------------------- ### Basic CompileDaemon Usage Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/overview.md Watch the current directory and rebuild on file changes. No additional setup is required. ```bash CompileDaemon ``` -------------------------------- ### Example Usage of globList Set Method Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/glob-list.md Illustrates adding various patterns to a globList, including one with OS-specific path separators that will be normalized. The comment indicates the final state of the list. ```go var patterns globList patterns.Set(".git") // Adds ".git" patterns.Set("vendor") // Adds "vendor" patterns.Set(".\\git") // Normalizes to ".git" or ".\\git" depending on OS // patterns now contains [".git", "vendor", normalized-path] ``` -------------------------------- ### Build Command Failed Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md Illustrates the output when a build command fails due to a syntax error in the Go code. This error is logged when the build command returns a non-nil error. ```bash # File saved with syntax error: CompileDaemon # Output when build fails: # Running build commands! # Error while building: # main.go:5:1: syntax error: unexpected EOF # Command failed: go build ``` -------------------------------- ### Command Parsing Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Shows how CompileDaemon parses build commands. Complex commands with pipes or redirects are not supported; use a shell script for such cases. ```bash -build="go build -o bin/app -v" # Becomes: exec.Command("go", "build", "-o", "bin/app", "-v") ``` ```bash -build="./build.sh" ``` -------------------------------- ### Example Usage of globList Matches Method Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/glob-list.md Demonstrates matching various strings against a glob list containing exact patterns and wildcard patterns. It shows successful matches and non-matches. ```go var patterns globList patterns.Set(".git") patterns.Set(".hg") patterns.Set("vendor") // Matches patterns.Matches(".git") // true (exact match) patterns.Matches(".hg") // true (exact match) patterns.Matches("vendor") // true (exact match) // Does not match patterns.Matches("src") // false (no match) patterns.Matches(".gitignore") // false (no match) // With wildcards patterns.Set("*.tmp") patterns.Matches("file.tmp") // true patterns.Matches("dir.tmp") // true patterns.Matches("file.go") // false // With character sets patterns.Set("[._]#*") patterns.Matches(".#file") // true (emacs temp) patterns.Matches("_#file") // true patterns.Matches("file.go") // false ``` -------------------------------- ### Process Start Error: Command Not Found Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md Demonstrates the error message when the post-build command specified in CompileDaemon cannot be found or executed. This is a fatal error that stops the daemon. ```go err := startCommand("./nonexistent-binary") // Error: can't start command: exec: "nonexistent-binary": executable file not found ``` -------------------------------- ### Run CompileDaemon with Default Settings Source: https://github.com/githubnemo/compiledaemon/blob/master/README.md Use this command to start CompileDaemon with default settings. It will recompile your code whenever a source file is saved. ```bash $ CompileDaemon ``` -------------------------------- ### Logger Function Example Usage Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Demonstrates how to initialize and use the logger function with a subprocess. It shows sending stdout and stderr pipes to the logger channel and the expected output format. ```go pipeChan := make(chan io.ReadCloser) go logger(pipeChan) // When spawning a subprocess cmd, stdout, stderr, err := startCommand("./myapp") if err != nil { log.Fatal(err) } pipeChan <- stdout pipeChan <- stderr // Logger reads and outputs: // [timestamp] stdout: Line from program // [timestamp] stderr: Error from program ``` -------------------------------- ### Watch Method Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Enters the fsnotify event loop to monitor file system events. New directories matching inclusion criteria are automatically added. SyscallError with EINTR is ignored, other errors cause termination. Use this to process file system events and send matched paths to the jobs channel. ```go jobs := make(chan string) go func() { notifyWatcher.Watch(jobs) }() // Watcher automatically picks up changes in .go files ``` -------------------------------- ### Full Color Usage Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Demonstrates how to conditionally apply color to log messages based on a command-line flag. The output will be colored if the -color flag is set, otherwise it will be plain text. ```go package main import ( "log" "flag" ) var flagColor = flag.Bool("color", false, "Colorize output") func okColor(format string, args ...interface{}) string { if *flagColor { return color.GreenString(format, args...) } return fmt.Sprintf(format, args...) } func failColor(format string, args ...interface{}) string { if *flagColor { return color.RedString(format, args...) } return fmt.Sprintf(format, args...) } func main() { flag.Parse() log.Println(okColor("Build ok.")) // Green or plain log.Println(failColor("Build failed")) // Red or plain } ``` -------------------------------- ### AddFiles() error Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Recursively walks the configured directories and adds all matching files and subdirectories to the watcher. This is useful for initial setup or when directories are modified. ```APIDOC ## AddFiles() error ### Description Recursively walks the configured directories and adds all matching files and subdirectories to the watcher. ### Method `AddFiles` ### Parameters No parameters ### Returns error - Non-nil if files could not be added (walk error, permission denied, etc.) ### Example ```go watcher, _ := NewWatcher(cfg) if err := watcher.AddFiles(); err != nil { log.Fatal("Could not add files:", err) } ``` ``` -------------------------------- ### Handle Initial Files Addition Errors Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md This example shows a fatal error scenario where watcher.Addfiles() fails during initialization, often due to a non-existent directory. Ensure the specified directory exists and is accessible. ```bash # Triggers error: CompileDaemon -directory=/nonexistent # Output: # watcher.Addfiles(): filepath.Walk(): no such file or directory ``` -------------------------------- ### Go Example Usage of failColor with Error Output Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Demonstrates using failColor to format an error message along with build output, ensuring all parts are displayed in red. ```go // With error output: log.Println(failColor("Error while building:\n"), failColor(string(output))) // Output: Error message with build output (all in red) ``` -------------------------------- ### Troubleshoot File Watcher Add Errors Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md This example highlights potential issues when adding paths to the file watcher, such as exceeding the open file limit or inotify limits. Adjust system limits or exclude directories as needed. ```text Too many open files: - Typical on macOS/BSD where each watched file consumes a file descriptor - Solution: increase ulimit with `ulimit -n 2048` - Or exclude large directories: -exclude-dir=.git Inotify limit exceeded: - Linux: "no space left on device" in inotify - Solution: increase inotify limits (see troubleshooting) - Or use polling: -polling flag ``` -------------------------------- ### Run CompileDaemon and Execute Program Source: https://github.com/githubnemo/compiledaemon/blob/master/README.md Use this command to have CompileDaemon recompile and then run your program. It will kill the old process and start a new one each time the code builds. ```bash $ CompileDaemon -command="./MyProgram -my-options" ``` -------------------------------- ### Example of Safe Channel Ordering in CompileDaemon Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/channels-and-concurrency.md Illustrates the linear and non-cyclic flow of messages between goroutines using channels, which is key to preventing deadlocks. This pattern ensures that each sender has a guaranteed receiver and avoids resource contention. ```go watcher sends to builder → builder sends to runner → runner reads success from builder (No cycle, linear flow, no deadlock possible) ``` -------------------------------- ### Invalid Regex Pattern Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md This example demonstrates an invalid regex pattern that will cause a fatal panic when used with the -pattern flag. The error originates from regexp.MustCompile(). ```bash CompileDaemon -pattern="(.+\.go" # Unclosed group # Output: # panic: regexp: Compile(.+\.go): error parsing regexp: unclosed group ``` -------------------------------- ### Basic CompileDaemon Usage Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Demonstrates the default behavior of watching the current directory and running 'go build'. Shows how to specify a single directory or multiple directories to watch. ```bash # Default: watches current directory, runs "go build" CompileDaemon ``` ```bash # Watch a specific directory CompileDaemon -directory=/path/to/project ``` ```bash # Watch multiple directories CompileDaemon -directory=/path/to/project1 -directory=/path/to/project2 ``` -------------------------------- ### Goroutine Startup Flow Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/channels-and-concurrency.md Illustrates the initial spawning of goroutines in the main process and their dependencies. ```go main() ├─ spawn: go builder(...) [awaits jobs] ├─ spawn: go runner(...) [awaits buildStarted] │ └─ spawn: go logger(...) [awaits pipeChan] │ └─ spawn: signal handler [awaits signals] └─ main: watcher.Watch(jobs) [main thread blocks] ``` -------------------------------- ### Spawn Builder Goroutine Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md Starts the builder process in a separate goroutine. The builder will continuously wait for jobs to process. ```go go builder(jobs, buildStarted, buildSuccess) ``` -------------------------------- ### Main Function and Entry Point Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/MANIFEST.txt Reference for the `main()` function, detailing the startup sequence, flag registration, and validation process. ```APIDOC ## Main Function and Entry Point ### Description This section provides documentation for the `main()` function, which serves as the entry point of the CompileDaemon application. It outlines the complete startup sequence, including how command-line flags are registered and validated. ### Files - api-reference/main-function.md ### Related - `api-reference/channels-and-concurrency.md` (Concurrency aspects during startup) ``` -------------------------------- ### Go Example Usage of failColor without -color Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Shows how failColor formats a build failure message as plain text when the -color flag is disabled. ```go // Without -color flag: log.Println(failColor("Build failed: syntax error")) // Output: "Build failed: syntax error" ``` -------------------------------- ### Multiple Build Steps Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Execute multiple build commands sequentially by providing multiple -build flags. ```bash # Multiple build steps CompileDaemon -build="go fmt ./..." -build="go vet ./..." -build="go build" ``` -------------------------------- ### Sequential Build Commands Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Demonstrates the execution order of multiple build commands. If an earlier command fails, the subsequent ones are skipped. ```bash -build="go fmt ./..." \ -build="go build" ``` -------------------------------- ### Execute All Build Commands Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Use the `build` function to execute all configured build commands sequentially. It returns false if any command fails, otherwise true. ```go func build() bool ``` ```go // With color enabled build() // Logs: "Running build commands!" // Logs: "Build ok." // With a failed command // Logs: "Running build commands!" // Logs: "Command failed: go build" (in red) // Returns: false ``` -------------------------------- ### Watch Files and Process Changes Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Starts the main watch loop in a goroutine and processes file change notifications received on a channel. This is a blocking operation. ```go jobs := make(chan string) go func() { watcher.Watch(jobs) }() for changedFile := range jobs { log.Println("File changed:", changedFile) } ``` -------------------------------- ### Runner with File Path Placeholder Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/runner.md Initializes the runner using a command template that includes a placeholder for the changed file path. The runner will format the command using this placeholder. ```go go runner("./myapp --changed %[1]s", buildStarted, buildSuccess) ``` -------------------------------- ### Go Example of ANSI Color Codes Used by failColor Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Details the specific ANSI escape sequences used by failColor for red text and resetting the color. ```go // Red code: \x1b[31m // Reset code: \x1b[0m // Result: \x1b[31m\x1b[0m ``` -------------------------------- ### Multiple Build Steps Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Execute a sequence of build commands in order. If any command in the sequence fails, subsequent commands will not be executed. ```bash CompileDaemon \ -directory=. \ -build="go fmt ./..." \ -build="go vet ./..." \ -build="go test ./..." \ -build="go build -o bin/app" \ -command="./bin/app" ``` -------------------------------- ### runBuildCommand(c string) Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Executes a single build command string. Splits the command into program and arguments, respects the build directory flag, and returns combined output if execution fails. ```APIDOC ## runBuildCommand(c string) ### Description Executes a single build command string. Splits the command into program and arguments, respects the build directory flag, and returns combined output if execution fails. ### Method Not applicable (Go function) ### Parameters #### Path Parameters - **c** (string) - Required - Command string to execute (e.g., "go build -o bin/app") ### Returns - error: nil on success, non-nil on command execution failure. ### Behavior - **Parsing**: Splits command string on whitespace using strings.Split(). - **Working Directory**: - Uses -build-dir if specified. - Otherwise uses first directory from flagDirectories. - Defaults to current directory if neither specified. - **Output**: Captures combined stdout and stderr via CombinedOutput(). - **Error Logging**: Logs full command output if execution fails. - **Empty Commands**: Returns nil immediately if args list is empty. ### Error Handling Throws/Rejects: - error from exec.Command().CombinedOutput() if execution fails. - Logs raw output before returning. ### Example Usage ```go // Simple command err := runBuildCommand("go build") if err != nil { log.Println("Build failed") } // Command with arguments err := runBuildCommand("go build -o bin/myapp") // Custom build script err := runBuildCommand("./scripts/build.sh") // With build directory flag // -build-dir=/project/build err := runBuildCommand("go build") // Executes in /project/build directory ``` **Output Logging:** ```go // If command fails // Logs: "Error while building:\n" followed by command output ``` ``` -------------------------------- ### build() Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Executes all configured build commands in sequence. Returns false if any command fails. ```APIDOC ## build() ### Description Executes all configured build commands in sequence. Returns false if any command fails. ### Method Not applicable (Go function) ### Parameters No parameters. ### Returns - bool: true if all build commands succeed, false if any command fails. ### Behavior - Logs "Running build commands!" in green if color is enabled. - Iterates through flagBuildCommandList.commands. - Executes each command via runBuildCommand(). - On first failure, logs error and returns false. - On success, logs "Build ok." and returns true. - Does not continue executing commands after first failure. ### Example Usage ```go // With color enabled build() // Logs: "Running build commands!" // Logs: "Build ok." // With a failed command // Logs: "Running build commands!" // Logs: "Command failed: go build" (in red) // Returns: false ``` ``` -------------------------------- ### Invalid Work Delay Error Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md Demonstrates how setting the -work-delay flag to zero or a negative value triggers a fatal error. Ensure -work-delay is a positive integer. ```bash CompileDaemon -work-delay=0 CompileDaemon -work-delay=-100 ``` ```bash # Does not trigger: CompileDaemon -work-delay=500 ``` -------------------------------- ### Watcher Goroutine Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/channels-and-concurrency.md Starts the watcher, which continuously monitors for file changes and sends detected file paths to the jobs channel. This function blocks indefinitely on the main thread. ```go watcher.Watch(jobs) // Blocks forever ``` -------------------------------- ### Default Build Behavior Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Illustrates the default build behavior when no -build flags are specified, which is a single `go build` command. To customize, at least one -build flag must be provided. ```bash # Default behavior: go build ``` -------------------------------- ### Go Example Usage of failColor with Command String Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Illustrates using failColor to format both a static command failure message and a dynamic command string, ensuring both are colored red. ```go // With command string: log.Println(failColor("Command failed: "), failColor(command)) // Output: "Command failed: " + command (both in red) ``` -------------------------------- ### CompileDaemon with Multiple Build Steps Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/overview.md Define and execute multiple build commands sequentially. This is useful for tasks like formatting, linting, and compiling. ```bash CompileDaemon \ -build="go fmt ./..." \ -build="go vet ./..." \ -build="go build -o bin/app" ``` -------------------------------- ### CompileDaemon Post-Build Command Execution Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Demonstrates how to run an executable after a build, pass the changed file path to the command, stop a command before building, and run commands in a different directory. ```bash # Run executable after build CompileDaemon -command="./myapp -port=8080" ``` ```bash # Pass changed file to command CompileDaemon -command="./myapp --changed %[1]s" ``` ```bash # Stop command before build, start after CompileDaemon -command="./server" -command-stop=true ``` ```bash # Run command in different directory CompileDaemon -directory=/src -run-dir=/output -command="./app" ``` -------------------------------- ### Graceful Kill Not Supported Error Example Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/errors.md Shows how the -graceful-kill flag triggers a fatal error on Windows due to the lack of SIGTERM support. This error does not occur on POSIX systems. ```bash # Windows - triggers error: CompileDaemon -graceful-kill ``` ```bash # POSIX systems - no error: CompileDaemon -graceful-kill ``` -------------------------------- ### Import Color Library Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Import the fatih/color library for terminal color capabilities. ```go import "github.com/fatih/color" ``` -------------------------------- ### CompileDaemon Build Configuration Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Shows how to specify a custom build command, execute multiple build steps sequentially, and configure build output directories. ```bash # Custom build command CompileDaemon -build="go build -o bin/myapp" ``` ```bash # Multiple build steps CompileDaemon -build="go fmt ./..." -build="go vet ./..." -build="go build" ``` ```bash # Build in different directory CompileDaemon -directory=/src -build-dir=/build -build="go build -o /build/app" ``` -------------------------------- ### main() Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md The main function is the entry point for the CompileDaemon executable. It handles initialization, validation, and subsystem management. It does not return under normal operation, exiting via os.Exit() on errors. ```APIDOC ## main() ### Description The main function serves as the single entry point for the CompileDaemon executable. It coordinates initialization, validation, and spawning of all subsystems. ### Parameters No parameters. All configuration comes from command-line flags. ### Returns Does not return under normal operation. Calls os.Exit() on fatal errors. ``` -------------------------------- ### Runner Process Lifecycle Management Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/channels-and-concurrency.md Manages the lifecycle of a runner process, waiting for build events, coordinating termination, and starting new commands. May block if the logger is not reading pipes. ```go for { eventPath := <-buildStarted // Wait for build start if !*flagCommandStop { if !<-buildSuccess { // Wait for build result continue } } if currentProcess != nil { killProcess(currentProcess) // Kill old process } if *flagCommandStop { // ... stop before build if !<-buildSuccess { continue } } cmd, stdout, stderr, err := startCommand(command) pipeChan <- stdout // Send pipes to logger pipeChan <- stderr currentProcess = cmd.Process } ``` -------------------------------- ### NewWatcher Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Initializes a new watcher instance with the provided configuration. It sets up file system monitoring based on the specified parameters. ```APIDOC ## NewWatcher ### Description Initializes a new watcher instance with the provided configuration. It sets up file system monitoring based on the specified parameters. ### Parameters #### Request Body - **cfg** (*WatcherConfig) - Required - Configuration structure for initializing watchers. ### Request Example ```go import ( "regexp" "github.com/githubnemo/CompileDaemon" ) // Create a regex pattern for Go files pattern := regexp.MustCompile(`(.+\.go|.+\.c)$`) // Configure the watcher cfg := &WatcherConfig{ flagVerbose: false, flagPolling: false, flagRecursive: true, flagDirectories: []string{"."}, flagExcludedDirs: []string{".git", "vendor"}, pattern: pattern, } // Create a watcher instance watcher, err := NewWatcher(cfg) if err != nil { // Handle error } defer watcher.Close() ``` ### Response #### Success Response (200) - **watcher** (*Watcher) - A watcher instance that can be used to monitor file system events. - **err** (error) - An error if the watcher could not be initialized. #### Response Example ```json { "watcher": "Watcher Object", "err": null } ``` ``` -------------------------------- ### Go Example Usage of failColor with -color enabled Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Demonstrates using failColor to log a build failure message when the -color flag is enabled. The output includes ANSI red color codes. ```go import "log" // With -color flag enabled: log.Println(failColor("Build failed: syntax error")) // Output (with color codes): "\x1b[31mBuild failed: syntax error\x1b[0m" // Displayed: "Build failed: syntax error" (in red) ``` -------------------------------- ### Custom Output Directory and Build Command Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Configure a custom output directory using -build-dir and specify the build command with -build. ```bash # With custom output directory CompileDaemon -build-dir=/output/path -build="go build -o myapp" ``` -------------------------------- ### Include Specific File Types for Monitoring Source: https://github.com/githubnemo/compiledaemon/blob/master/README.md Use these options to monitor files other than the default .go and .c files, such as Makefiles or less/template files. ```bash $ CompileDaemon -include=Makefile -include="*.less" -include="*.tmpl" ``` -------------------------------- ### PollingWatcher.Watch Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Starts the polling loop in a goroutine and enters the main event processing loop. It checks file paths against inclusion/exclusion patterns and sends matching paths to the provided jobs channel. The ErrWatchedFileDeleted error is suppressed as it's an expected condition. ```APIDOC ## Watch(jobs chan<- string) ### Description Starts the polling loop in a goroutine and enters the main event processing loop. Checks file paths against inclusion/exclusion patterns and sends matching paths to the jobs channel. ErrWatchedFileDeleted is suppressed (expected condition). ### Method PollingWatcher.Watch ### Parameters #### Path Parameters - **jobs** (chan<- string) - Required - Channel receiving matched file paths ### Request Example ```go // Using polling watcher for Docker on macOS cfg := &WatcherConfig{ flagPolling: true, flagPollingInterval: 500, // Check every 500ms // ... other config } watcher, _ := NewWatcher(cfg) jobs := make(chan string) go watcher.Watch(jobs) ``` ``` -------------------------------- ### Signal Handling with Buffered Channel Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/channels-and-concurrency.md Sets up a goroutine to handle OS signals using a buffered channel. The buffer is necessary to prevent losing signals if the handler is temporarily blocked. ```go go func() { processSignalChannel := make(chan os.Signal, 1) signal.Notify(processSignalChannel, fatalSignals...) <-processSignalChannel // Block until signal log.Println(okColor("Received signal, terminating cleanly.")) if currentProcess != nil { killProcess(currentProcess) } os.Exit(0) }() ``` -------------------------------- ### Execute a Single Build Command Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Use `runBuildCommand` to execute a single command string. It handles command parsing, working directory selection, and captures output on failure. Returns an error if the command execution fails. ```go func runBuildCommand(c string) error ``` ```go // Simple command err := runBuildCommand("go build") if err != nil { log.Println("Build failed") } // Command with arguments err := runBuildCommand("go build -o bin/myapp") // Custom build script err := runBuildCommand("./scripts/build.sh") // With build directory flag // -build-dir=/project/build err := runBuildCommand("go build") // Executes in /project/build directory ``` ```go // If command fails // Logs: "Error while building:\n" followed by command output ``` -------------------------------- ### CompileDaemon Subsystem Spawning Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/builder.md Illustrates the main process spawning the builder, runner/flusher, and watcher subsystems. ```text Main spawns: ├─ builder(jobs, buildStarted, buildDone) ├─ runner(commandTemplate, buildStarted, buildSuccess) │ or flusher(buildStarted, buildSuccess) └─ watcher.Watch(jobs) Message flow: watcher → jobs → builder ├─ buildStarted → runner └─ buildDone → runner (via buildSuccess) ``` -------------------------------- ### AddFiles Method Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/watcher.md Calls the shared addFiles() function to recursively add watched directories. Returns errors from filepath.Walk() or Add(). ```go // Calls the shared addFiles() function to recursively add watched directories. // Returns: error - filepath.Walk() or Add() errors ``` -------------------------------- ### Create Communication Channels Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md Sets up unbuffered channels for inter-goroutine communication: 'jobs' for watcher to builder, 'buildStarted' for builder to runner, and 'buildSuccess' for builder to runner. ```go jobs := make(chan string) buildSuccess := make(chan bool) buildStarted := make(chan string) ``` -------------------------------- ### Multiple Build Steps Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/overview.md Configure CompileDaemon to run a sequence of build commands before executing the main command. Useful for projects with code generation or multi-stage builds. ```bash CompileDaemon \ -build="go generate ./..." \ -build="go build -o bin/app" \ -command="./bin/app" # Runs code generation, build, then app ``` -------------------------------- ### CompileDaemon Performance Tuning Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/configuration.md Explains how to adjust the debounce delay for faster builds or fewer rebuilds, and how to enable polling for improved performance on macOS with Docker. ```bash # Reduce debounce delay (faster builds) CompileDaemon -work-delay=300 ``` ```bash # Increase debounce delay (fewer false rebuilds) CompileDaemon -work-delay=1500 ``` ```bash # Use polling for Docker on macOS CompileDaemon -polling -polling-interval=500 ``` -------------------------------- ### Build System API Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/MANIFEST.txt Information about the `builder()` function, including debounce and inrush protection for build command execution. ```APIDOC ## Build System API ### Description This section covers the `builder()` function, which is responsible for executing build commands. It details the mechanisms for debounce and inrush protection to manage build triggers efficiently. ### Files - api-reference/builder.md ### Configuration - `configuration.md` (build flags) ``` -------------------------------- ### Glob List Integration with Flag Package Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/glob-list.md Shows how to use globList as a flag.Var type for command-line directory and file exclusions. The flag package calls the Set method, and Matches can be used to check against patterns. ```go func init() { var excludeDirs globList var excludeFiles globList flag.Var(&excludeDirs, "exclude-dir", "Directory to exclude") flag.Var(&excludeFiles, "exclude", "File to exclude") } // Command line: // CompileDaemon -exclude-dir=.git -exclude-dir=vendor -exclude=".#*" // Internally: // flag package calls: // excludeDirs.Set(".git") // excludeDirs.Set("vendor") // excludeFiles.Set(".#*") // Usage: // if excludeDirs.Matches(".git") { /* skip .git */ } // if excludeFiles.Matches(".#main.go") { /* skip temp file */ } ``` -------------------------------- ### Set Default Build Command Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md If no -build flags are provided, this defaults the build command to "go build". ```go if len(flagBuildCommandList.commands) == 0 { _ = flagBuildCommandList.Set("go build") } ``` -------------------------------- ### Root Directory Selection with globList Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/glob-list.md Use globList to specify the root directories to watch. This is typically set via the -directory flag. ```go var flagDirectories globList // Usage: // CompileDaemon -directory=/src -directory=/config // In code: for _, dir := range flagDirectories { // Add all matched directories } ``` -------------------------------- ### Create Watcher Configuration Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md Constructs the WatcherConfig struct using values from parsed command-line flags and the compiled file pattern. ```go cfg := &WatcherConfig{ flagVerbose: *flagVerbose, flagRecursive: *flagRecursive, flagPolling: *flagPolling, flagPollingInterval: *flagPollingInterval, flagDirectories: flagDirectories, flagExcludedDirs: flagExcludedDirs, flagExcludedFiles: flagExcludedFiles, flagIncludedFiles: flagIncludedFiles, pattern: pattern, } ``` -------------------------------- ### Minimal CompileDaemon Configuration Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Run CompileDaemon with minimal configuration, focusing solely on rebuilding. This is useful for scenarios where only the build process is required. ```bash # Minimal: just rebuild CompileDaemon ``` -------------------------------- ### Inrush Protection Order of Operations Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/channels-and-concurrency.md Illustrates how multiple file changes within the debounce window are handled to prevent race conditions and ensure a single build invocation. ```go Multiple changes arrive (within debounce window): ├─ Change 1: main.go → jobs <- main.go [timer resets] ├─ Change 2: util.go → jobs <- util.go [timer resets] ├─ Change 3: main.go → jobs <- main.go [timer resets] └─ [900ms passes] └─ Timer expires └─ build() starts (only once, with eventPath = "main.go") ``` -------------------------------- ### Enable Color for Development Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/color-and-formatting.md Enable color output for improved readability during development. This is the recommended setting for local development environments. ```bash # Development: enable color for easier reading CompileDaemon -color ``` -------------------------------- ### Add Files to Watcher Source: https://github.com/githubnemo/compiledaemon/blob/master/_autodocs/api-reference/main-function.md Recursively walks through the configured directories and adds them to the watcher. This operation can fail due to insufficient permissions, non-existent paths, or too many open files. ```go err = watcher.AddFiles() if err != nil { log.Fatal("watcher.Addfiles():", err) } ```