aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymaekers Luca <raymaekers.luca@gmail.com>2024-10-10 19:21:30 +0200
committerRaymaekers Luca <raymaekers.luca@gmail.com>2024-10-10 19:21:30 +0200
commitd6021aaad84068c01b4e53f161d07f57b9357f43 (patch)
treee373b7e12d5c604dc773b0843a68daed08ad7ad8
Initial commit
-rw-r--r--LICENSE19
-rw-r--r--go.mod7
-rw-r--r--go.sum4
-rw-r--r--main.go158
4 files changed, 188 insertions, 0 deletions
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{})
+}