func shouldWatch(path string) bool {
	for _, r := range exclude {
		if r.MatchString(path) {
			log.Println("exclude:", path)
			return false
		}
	}
	for _, r := range include {
		if r.MatchString(path) {
			return true
		}
	}
	return false
}
shouldWatch determines if we should watch the given
path based on the include and exclude regexps.
package main
import (
	"fmt"
	"go/parser"
	"go/token"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/codegangsta/cli"
	"github.com/howeyc/fsnotify"
	"github.com/kballard/go-shellquote"
)
var (
	wpaths       = make(map[string]string)
	include      []*regexp.Regexp
	exclude      []*regexp.Regexp
	includeFiles []*regexp.Regexp
	excludeFiles []*regexp.Regexp
)
func run(c *cli.Context, cmderr chan error) (*exec.Cmd, error) {
	if len(c.Args()) > 0 {
		log.Printf("Running program...\n")
		args := shellquote.Join(c.Args()...)
		if len(args) > 2 {
			if args[0] == '\'' || args[0] == '"' {
				args = args[1:]
			}
			if args[len(args)-1] == '\'' || args[len(args)-1] == '"' {
				args = args[:len(args)-1]
			}
		}
		cmd := exec.Command(os.ExpandEnv(c.String("shell")), "-c", args)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Start()
		if err != nil {
			return nil, err
		}
		go func() {
			cmderr <- cmd.Wait()
		}()
		return cmd, nil
	} else {
		log.Println("Detected code change")
	}
	return nil, nil
}
func shouldRerun(name string) (ret bool) {
	ret = false
	ret = !strings.HasPrefix(filepath.Base(name), ".")
	if !ret {
		return
	}
	for _, r := range excludeFiles {
		if r.MatchString(name) {
			ret = false
			return
		}
	}
	for _, r := range includeFiles {
		if r.MatchString(name) {
			ret = true
			return
		}
	}
	return false
}
func watcher(c *cli.Context) {
	log.Println("Running watcher")
	var wg sync.WaitGroup
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	cmderr := make(chan error)
	wg.Add(1)
	go func() {
		defer wg.Done()
		cmd, err := run(c, cmderr)
		if err != nil {
			log.Println(err)
		}
		for {
			select {
			case ev := <-watcher.Event:
			LOOP:
				for {
					select {
					case <-watcher.Event:
						continue LOOP
					case <-time.After(300 * time.Millisecond):
						break LOOP
					}
				}
				if ev.IsModify() || ev.IsCreate() {
					if shouldRerun(ev.Name) {
						if cmd != nil && cmd.Process != nil {
							select {
							case e := <-cmderr:
								if e != nil {
									log.Println(e)
								}
							default:
								log.Printf("Killing program...\n")
								if cmd.Process.Signal(os.Interrupt) != nil {
									if runtime.GOOS == "windows" {
										exec.Command("TASKKILL", "/F", "/T", "/PID", fmt.Sprintf("%d", cmd.Process.Pid)).Run()
									} else {
										cmd.Process.Kill()
									}
								}
								<-cmderr
							}
						}
						cmd, err = run(c, cmderr)
						if err != nil {
							log.Println(err)
						}
					}
				}
			case <-watcher.Error:
			}
		}
	}()
	for _, value := range wpaths {
		err = watcher.Watch(value)
		if err != nil {
			log.Fatal(err)
		}
	}
	wg.Wait()
}
func which(pkg string, location string) string {
	for _, top := range strings.Split(os.Getenv("GOPATH"), ":") {
		dir := top + "/" + location + "/" + pkg
		_, err := os.Stat(dir)
		if err == nil {
			return dir
		}
		p := err.(*os.PathError)
		if !os.IsNotExist(p.Err) {
			log.Print(err)
		}
	}
	return ""
}