aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go158
1 files changed, 158 insertions, 0 deletions
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{})
+}