From d6021aaad84068c01b4e53f161d07f57b9357f43 Mon Sep 17 00:00:00 2001 From: Raymaekers Luca Date: Thu, 10 Oct 2024 19:21:30 +0200 Subject: Initial commit --- LICENSE | 19 ++++++++ go.mod | 7 +++ go.sum | 4 ++ main.go | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 LICENSE create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..33de139 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +zlib License + +Copyright (C) 2024 Luca Raymaekers + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..895dddb --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module wbr + +go 1.23.2 + +require github.com/fsnotify/fsnotify v1.7.0 + +require golang.org/x/sys v0.4.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ccd7ce9 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go new file mode 100644 index 0000000..e197b10 --- /dev/null +++ b/main.go @@ -0,0 +1,158 @@ +// [PROGRAM] will run a build command and a run command on file system changes. This is so you can +// build&run on save. +// You specify a build command and run command as flags and optionally you can filter by extension. + +package main + +import ( + "flag" + "fmt" + "os" + "os/exec" + "strings" + + "github.com/fsnotify/fsnotify" +) + +// Colors in escape sequences +var ( + Reset = "\033[0m" + BoldCyan = "\033[36m" + // Red = "\033[31m" + // Green = "\033[32m" + // Yellow = "\033[33m" + // Blue = "\033[34m" + // Magenta = "\033[35m" + // Cyan = "\033[36m" + // Gray = "\033[37m" + // White = "\033[97m" +) + +var ( + // Path in which to look for commands + Path string + // Command run for building + BuildCommand []string + // Command run after build + RunCommand []string + // Command will only run on files that have the Ext extension + Ext string +) + +func CompileRun(fileName string) { + if !strings.HasSuffix(fileName, Ext) { + return + } + + // Build the program, exit if return if there was an error + { + var buildCmd *exec.Cmd + if len(BuildCommand) > 1 { + buildCmd = exec.Command(BuildCommand[0], append(BuildCommand[1:], fileName)...) + } else { + buildCmd = exec.Command(BuildCommand[0], fileName) + } + // run the build command + out, err := buildCmd.CombinedOutput() + + if len(BuildCommand) > 1 { + fmt.Printf("\n[%s%s %s%s]\n", BoldCyan, BuildCommand[0], strings.Join(append(BuildCommand[1:], fileName), " "), Reset) + } else { + fmt.Printf("[%s%s %s %s%s]\n", BoldCyan, BuildCommand[0], BuildCommand, fileName, Reset) + } + + if len(out) > 0 { + fmt.Printf("%s", out) + } + + if err != nil { + if _, ok := err.(*exec.ExitError); ok { + return + } else if !ok { + panic(err) + } + } + } + + // There was no error in the build so we can execute the run command + { + var runCmd *exec.Cmd + if len(RunCommand) > 1 { + runCmd = exec.Command(RunCommand[0], RunCommand[1:]...) + } else { + runCmd = exec.Command(RunCommand[0]) + } + + out, err := runCmd.CombinedOutput() + if len(RunCommand) > 1 { + fmt.Printf("[%s%s %s%s]\n", BoldCyan, RunCommand[0], strings.Join(append(RunCommand[1:]), " "), Reset) + } else { + fmt.Printf("[%s%s%s]\n", BoldCyan, RunCommand[0], Reset) + + } + if len(out) > 0 { + fmt.Printf("%s", out) + } + + if err != nil { + if _, ok := err.(*exec.ExitError); ok { + return + } else if !ok { + panic(err) + } + } + } + +} + +func main() { + watcher, err := fsnotify.NewWatcher() + if err != nil { + panic(err) + } + defer watcher.Close() + + bc := flag.String("b", "", "Command to run for building") + rc := flag.String("r", "", "Command for running after build") + e := flag.String("e", "", "Filter watched files by suffix") + p := flag.String("p", ".", "Path to watch for files") + flag.Parse() + + if *bc == "" { + fmt.Println("flag is required: -b") + os.Exit(1) + } + + BuildCommand = strings.Split(*bc, " ") + RunCommand = strings.Split(*rc, " ") + Ext = *e + Path = *p + + fmt.Printf("[%swatching '%s'%s]", BoldCyan, Path, Reset) + + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + if event.Has(fsnotify.Write) { + CompileRun(event.Name) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + fmt.Println("error:", err) + } + } + }() + + err = watcher.Add(Path) + if err != nil { + panic(err) + } + + <-make(chan struct{}) +} -- cgit v1.2.3