From ea43654872f022102caab0c649d36b70a052c967 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 9 Aug 2013 22:40:46 +0800 Subject: [PATCH 1/8] Colorful log print --- new.go | 12 +++++----- run.go | 7 +++--- util.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- watch.go | 14 ++++++------ 4 files changed, 81 insertions(+), 21 deletions(-) diff --git a/new.go b/new.go index 63ee0d9..8c5ddd2 100644 --- a/new.go +++ b/new.go @@ -40,15 +40,15 @@ func init() { func createApp(cmd *Command, args []string) { curpath, _ := os.Getwd() if len(args) != 1 { - fmt.Println("[ERRO] Argument [appname] is missing") + colorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) } gopath := os.Getenv("GOPATH") Debugf("gopath:%s", gopath) if gopath == "" { - fmt.Printf("[ERRO] $GOPATH not found\n") - fmt.Printf("[HINT] Set $GOPATH in your environment vairables\n") + colorLog("[ERRO] $GOPATH not found\n") + colorLog("[HINT] Set $GOPATH in your environment vairables\n") os.Exit(2) } haspath := false @@ -66,8 +66,8 @@ func createApp(cmd *Command, args []string) { } if !haspath { - fmt.Printf("[ERRO] Unable to create an application outside of $GOPATH(%s)\n", gopath) - fmt.Printf("[HINT] Change your work directory by `cd $GOPATH%ssrc`\n", string(path.Separator)) + colorLog("[ERRO] Unable to create an application outside of $GOPATH(%s)\n", gopath) + colorLog("[HINT] Change your work directory by `cd ($GOPATH%ssrc)`\n", string(path.Separator)) os.Exit(2) } @@ -110,7 +110,7 @@ func createApp(cmd *Command, args []string) { fmt.Println(path.Join(apppath, "main.go")) writetofile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", strings.Join(strings.Split(apppath[len(appsrcpath)+1:], string(path.Separator)), string(path.Separator)), -1)) - fmt.Println("[SUCC] New application successfully created!") + colorLog("[SUCC] New application successfully created!\n") } var appconf = `appname = {{.Appname}} diff --git a/run.go b/run.go index cc18fa0..503abf3 100644 --- a/run.go +++ b/run.go @@ -2,7 +2,6 @@ package main import ( "encoding/json" - "fmt" "os" path "path/filepath" "runtime" @@ -69,7 +68,7 @@ var conf struct { func runApp(cmd *Command, args []string) { exit := make(chan bool) if len(args) != 1 { - fmt.Println("[ERRO] Argument [appname] is missing") + colorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) } crupath, _ := os.Getwd() @@ -77,7 +76,7 @@ func runApp(cmd *Command, args []string) { err := loadConfig() if err != nil { - fmt.Println("[ERRO] Fail to parse bee.json:", err) + colorLog("[ERRO] Fail to parse bee.json[ %s ]", err) } var paths []string paths = append(paths, @@ -111,7 +110,7 @@ func loadConfig() error { } } else { defer f.Close() - fmt.Println("[INFO] Detected bee.json") + colorLog("[INFO] Detected bee.json\n") d := json.NewDecoder(f) err = d.Decode(&conf) if err != nil { diff --git a/util.go b/util.go index f8b7e13..026d8ed 100644 --- a/util.go +++ b/util.go @@ -1,9 +1,12 @@ package main -import "fmt" -import "os" -import "runtime" -import "path/filepath" +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" +) // Go is a basic promise implementation: it wraps calls a function in a goroutine // and returns a channel which will later return the function's return value. @@ -28,3 +31,61 @@ func Debugf(format string, a ...interface{}) { fmt.Fprintf(os.Stderr, fmt.Sprintf("[debug] %s:%d %s\n", file, line, format), a...) } } + +const ( + Gray = uint8(iota + 90) + Red + Green + Yellow + Blue + Magenta + //NRed = uint8(31) // Normal + EndColor = "\033[0m" +) + +// colorLog colors log and print to stdout. +// Log format: [] [ error ]. +// Level: ERRO -> red; WARN -> Magenta; SUCC -> green; others -> default. +// Content: default; path: yellow; error -> red. +// Errors have to surrounded by "[ " and " ]"(space). +func colorLog(format string, a ...interface{}) { + log := fmt.Sprintf(format, a...) + if runtime.GOOS != "windows" { + var clog string + + // Level. + i := strings.Index(log, "]") + if log[0] == '[' && i > -1 { + clog += "[" + getColorLevel(log[1:i]) + "]" + } + + log = log[i+1:] + + // Error. + log = strings.Replace(log, "[ ", fmt.Sprintf("[ \033[%dm", Red), -1) + log = strings.Replace(log, " ]", EndColor+" ]", -1) + + // Path. + log = strings.Replace(log, "(", fmt.Sprintf("(\033[%dm", Yellow), -1) + log = strings.Replace(log, ")", EndColor+")", -1) + + log = clog + log + } + + fmt.Print(log) +} + +// getColorLevel returns colored level string by given level. +func getColorLevel(level string) string { + level = strings.ToUpper(level) + switch level { + case "ERRO": + return fmt.Sprintf("\033[%dm%s\033[0m", Red, level) + case "WARN": + return fmt.Sprintf("\033[%dm%s\033[0m", Magenta, level) + case "SUCC": + return fmt.Sprintf("\033[%dm%s\033[0m", Green, level) + default: + return level + } +} diff --git a/watch.go b/watch.go index 6207e05..1ce8d64 100644 --- a/watch.go +++ b/watch.go @@ -41,14 +41,14 @@ func NewWatcher(paths []string) { // if 500ms change many times, then ignore it. // for liteide often gofmt code after save. if t.Add(time.Millisecond * 500).After(time.Now()) { - fmt.Println("[SKIP]", e.String()) + colorLog("[SKIP] %s\n", e.String()) isbuild = false } } eventTime[e.Name] = time.Now() if isbuild { - fmt.Println("[EVEN]", e) + colorLog("[EVEN] %s\n", e) go Autobuild() } case err := <-watcher.Error: @@ -57,7 +57,7 @@ func NewWatcher(paths []string) { } }() - fmt.Println("[INFO] Initializing watcher...") + colorLog("[INFO] Initializing watcher...\n") for _, path := range paths { fmt.Println(path) err = watcher.Watch(path) @@ -72,7 +72,7 @@ func Autobuild() { state.Lock() defer state.Unlock() - fmt.Println("[INFO] Start building...") + colorLog("[INFO] Start building...\n") path, _ := os.Getwd() os.Chdir(path) @@ -94,10 +94,10 @@ func Autobuild() { } if err != nil { - fmt.Println("[ERRO] ============== Build failed ===================") + colorLog("[ERRO] ============== Build failed ===================\n") return } - fmt.Println("[SUCC] Build was successful") + colorLog("[SUCC] Build was successful\n") Restart(appname) } @@ -119,7 +119,7 @@ func Restart(appname string) { } func Start(appname string) { - fmt.Println("[INFO] Restarting", appname) + colorLog("[INFO] Restarting %s ...\n", appname) if strings.Index(appname, "./") == -1 { appname = "./" + appname } From f321e15db8ba7d5ed3f86999587edf6836ec97ec Mon Sep 17 00:00:00 2001 From: Philip Nelson Date: Sun, 11 Aug 2013 17:43:00 -0700 Subject: [PATCH 2/8] Go docs advise to use strings.HasPrefix. --- new.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new.go b/new.go index 8c5ddd2..da328e5 100644 --- a/new.go +++ b/new.go @@ -58,7 +58,7 @@ func createApp(cmd *Command, args []string) { for _, wg := range wgopath { wg = path.Join(wg, "src") - if path.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { + if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { haspath = true appsrcpath = wg break From 61ed8f285b21772b1f875339e99cfe874134ecca Mon Sep 17 00:00:00 2001 From: Philip Nelson Date: Sun, 11 Aug 2013 21:38:57 -0700 Subject: [PATCH 3/8] Evaluate symlinks before comparing path. --- new.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new.go b/new.go index da328e5..b4ed4ca 100644 --- a/new.go +++ b/new.go @@ -56,7 +56,7 @@ func createApp(cmd *Command, args []string) { wgopath := path.SplitList(gopath) for _, wg := range wgopath { - wg = path.Join(wg, "src") + wg, _ = path.EvalSymlinks(path.Join(wg, "src")) if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { haspath = true From 772e5676f75efeef7fc1f73081c9834fa482aa88 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 15 Aug 2013 12:51:26 +0800 Subject: [PATCH 4/8] Fixed bug: repeat build in Mac OS, change to check file ModTime insetad of event time --- watch.go | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/watch.go b/watch.go index 1ce8d64..cba403a 100644 --- a/watch.go +++ b/watch.go @@ -14,7 +14,7 @@ import ( var ( cmd *exec.Cmd state sync.Mutex - eventTime = make(map[string]time.Time) + eventTime = make(map[string]int64) ) func NewWatcher(paths []string) { @@ -37,15 +37,23 @@ func NewWatcher(paths []string) { continue } - if t, ok := eventTime[e.Name]; ok { - // if 500ms change many times, then ignore it. - // for liteide often gofmt code after save. - if t.Add(time.Millisecond * 500).After(time.Now()) { - colorLog("[SKIP] %s\n", e.String()) - isbuild = false - } + mt := getFileModTime(e.Name) + if t := eventTime[e.Name]; mt == t { + colorLog("[SKIP] %s\n", e.String()) + isbuild = false } - eventTime[e.Name] = time.Now() + + // if t, ok := eventTime[e.Name]; ok { + // // if 500ms change many times, then ignore it. + // // for liteide often gofmt code after save. + // if t.Add(time.Millisecond * 500).After(time.Now()) { + // colorLog("[SKIP] %s\n", e.String()) + // isbuild = false + // } + // } + + eventTime[e.Name] = mt + fmt.Println(mt) if isbuild { colorLog("[EVEN] %s\n", e) @@ -68,6 +76,23 @@ func NewWatcher(paths []string) { } +// getFileModTime retuens unix timestamp of `os.File.ModTime` by given path. +func getFileModTime(path string) int64 { + f, err := os.Open(path) + if err != nil { + colorLog("[ERRO] Fail to open file[ %s ]", err) + return time.Now().Unix() + } + + fi, err := f.Stat() + if err != nil { + colorLog("[ERRO] Fail to get file information[ %s ]", err) + return time.Now().Unix() + } + + return fi.ModTime().Unix() +} + func Autobuild() { state.Lock() defer state.Unlock() From bf33c2b05c3daa979fa96f924569fbea9a8100e1 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 15 Aug 2013 12:51:48 +0800 Subject: [PATCH 5/8] Fixed bug: repeat build in Mac OS, change to check file ModTime insetad of event time --- watch.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/watch.go b/watch.go index cba403a..ece85da 100644 --- a/watch.go +++ b/watch.go @@ -43,15 +43,6 @@ func NewWatcher(paths []string) { isbuild = false } - // if t, ok := eventTime[e.Name]; ok { - // // if 500ms change many times, then ignore it. - // // for liteide often gofmt code after save. - // if t.Add(time.Millisecond * 500).After(time.Now()) { - // colorLog("[SKIP] %s\n", e.String()) - // isbuild = false - // } - // } - eventTime[e.Name] = mt fmt.Println(mt) From 5486f6ee5515280be7bcdce7f861b444da65b50a Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 15 Aug 2013 12:52:32 +0800 Subject: [PATCH 6/8] Fixed bug: repeat build in Mac OS, change to check file ModTime insetad of event time --- watch.go | 1 + 1 file changed, 1 insertion(+) diff --git a/watch.go b/watch.go index ece85da..7bf9c3e 100644 --- a/watch.go +++ b/watch.go @@ -74,6 +74,7 @@ func getFileModTime(path string) int64 { colorLog("[ERRO] Fail to open file[ %s ]", err) return time.Now().Unix() } + defer f.Close() fi, err := f.Stat() if err != nil { From a6840ebafde8defa8c1bf7ec0022625baa19962a Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 15 Aug 2013 12:53:07 +0800 Subject: [PATCH 7/8] Fixed bug: repeat build in Mac OS, change to check file ModTime insetad of event time --- watch.go | 1 - 1 file changed, 1 deletion(-) diff --git a/watch.go b/watch.go index 7bf9c3e..b640c6b 100644 --- a/watch.go +++ b/watch.go @@ -44,7 +44,6 @@ func NewWatcher(paths []string) { } eventTime[e.Name] = mt - fmt.Println(mt) if isbuild { colorLog("[EVEN] %s\n", e) From 055609f64dd526fce54d8359d80531765e8a8a9d Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 15 Aug 2013 15:24:23 +0800 Subject: [PATCH 8/8] Update color ouput --- .gitignore | 4 ++++ run.go | 3 ++- util.go | 14 ++++++++++---- watch.go | 10 ++++++---- 4 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..418384a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +bee +*.exe +*.exe~ diff --git a/run.go b/run.go index 503abf3..4fb3c97 100644 --- a/run.go +++ b/run.go @@ -68,7 +68,8 @@ var conf struct { func runApp(cmd *Command, args []string) { exit := make(chan bool) if len(args) != 1 { - colorLog("[ERRO] Argument [appname] is missing\n") + colorLog("[ERRO] Cannot start running[ %s ]\n", + "argument 'appname' is missing") os.Exit(2) } crupath, _ := os.Getwd() diff --git a/util.go b/util.go index 026d8ed..2846b97 100644 --- a/util.go +++ b/util.go @@ -62,12 +62,16 @@ func colorLog(format string, a ...interface{}) { log = log[i+1:] // Error. - log = strings.Replace(log, "[ ", fmt.Sprintf("[ \033[%dm", Red), -1) - log = strings.Replace(log, " ]", EndColor+" ]", -1) + log = strings.Replace(log, "[ ", fmt.Sprintf("[\033[%dm", Red), -1) + log = strings.Replace(log, " ]", EndColor+"]", -1) // Path. - log = strings.Replace(log, "(", fmt.Sprintf("(\033[%dm", Yellow), -1) - log = strings.Replace(log, ")", EndColor+")", -1) + log = strings.Replace(log, "( ", fmt.Sprintf("(\033[%dm", Yellow), -1) + log = strings.Replace(log, " )", EndColor+")", -1) + + // Highlights. + log = strings.Replace(log, "# ", fmt.Sprintf("\033[%dm", Gray), -1) + log = strings.Replace(log, " #", EndColor, -1) log = clog + log } @@ -79,6 +83,8 @@ func colorLog(format string, a ...interface{}) { func getColorLevel(level string) string { level = strings.ToUpper(level) switch level { + case "TRAC": + return fmt.Sprintf("\033[%dm%s\033[0m", Blue, level) case "ERRO": return fmt.Sprintf("\033[%dm%s\033[0m", Red, level) case "WARN": diff --git a/watch.go b/watch.go index b640c6b..9f05e53 100644 --- a/watch.go +++ b/watch.go @@ -20,7 +20,8 @@ var ( func NewWatcher(paths []string) { watcher, err := fsnotify.NewWatcher() if err != nil { - log.Fatal(err) + colorLog("[ERRO] Fail to create new Watcher[ %s ]\n", err) + os.Exit(2) } go func() { @@ -39,7 +40,7 @@ func NewWatcher(paths []string) { mt := getFileModTime(e.Name) if t := eventTime[e.Name]; mt == t { - colorLog("[SKIP] %s\n", e.String()) + colorLog("[SKIP] # %s #\n", e.String()) isbuild = false } @@ -57,10 +58,11 @@ func NewWatcher(paths []string) { colorLog("[INFO] Initializing watcher...\n") for _, path := range paths { - fmt.Println(path) + colorLog("[TRAC] Directory( %s )\n", path) err = watcher.Watch(path) if err != nil { - log.Fatal(err) + colorLog("[ERRO] Fail to watch directory[ %s ]\n", err) + os.Exit(2) } }