From efcd13f2320a487ef42d3aaadc4a8f9c2f4224fb Mon Sep 17 00:00:00 2001 From: alessio Date: Tue, 1 Nov 2016 10:56:12 +0100 Subject: [PATCH] code optimization --- app/main.go | 139 ------------------------------ config/config.go | 18 ---- config/utils.go | 27 ------ realize.go | 144 ++++++++++++++++++++++++++----- server/bindata.go | 76 ++++++++--------- server/main.go | 92 ++++++++++---------- server/open.go | 8 +- settings/colors.go | 68 +++++++++++++++ {config => settings}/io.go | 14 ++-- settings/settings.go | 59 +++++++++++++ settings/utils.go | 27 ++++++ watcher/cmd.go | 168 ++++++++++++++----------------------- watcher/exec.go | 17 ++-- watcher/main.go | 45 ++++------ watcher/utils.go | 27 +----- watcher/watcher.go | 73 ++++++++++------ 16 files changed, 512 insertions(+), 490 deletions(-) delete mode 100644 app/main.go delete mode 100644 config/config.go delete mode 100644 config/utils.go create mode 100644 settings/colors.go rename {config => settings}/io.go (64%) create mode 100644 settings/settings.go create mode 100644 settings/utils.go diff --git a/app/main.go b/app/main.go deleted file mode 100644 index 397fe9b..0000000 --- a/app/main.go +++ /dev/null @@ -1,139 +0,0 @@ -package app - -import ( - "fmt" - w "github.com/tockins/realize/watcher" - c "github.com/tockins/realize/config" - s "github.com/tockins/realize/server" - "gopkg.in/urfave/cli.v2" - "log" - "os" - "syscall" -) - -const ( - Name = "Realize" - Version = "1.1" - Description = "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths" - Limit = 10000 - Config = "R.config.yaml" - Output = "R.output.log" - Host = "Web server listening on localhost:5000" -) - -var R Realize - -// Realize struct contains the general app informations -type Realize struct { - c.Config - Name, Description, Author, Email, Host string - Version string - Limit uint64 - Blueprint w.Blueprint - Server s.Server - Files map[string]string - Sync chan string -} - -// Application initialization -func init() { - R = Realize{ - Name: Name, - Version: Version, - Description: Description, - Host: Host, - Limit: Limit, - Files: map[string]string{ - "config": Config, - "output": Output, - }, - Sync: make(chan string), - } - R.Blueprint = w.Blueprint{ - Config: R.Config, - Files: R.Files, - Sync: R.Sync, - } - R.Server = s.Server{ - Blueprint: &R.Blueprint, - Files: R.Files, - Sync: R.Sync, - } - R.limit() -} - -// Flimit defines the max number of watched files -func (r *Realize) limit() { - var rLimit syscall.Rlimit - rLimit.Max = R.Limit - rLimit.Cur = R.Limit - err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) - if err != nil { - log.Fatal(w.Red("Error Setting Rlimit "), err) - } -} - -func (r *Realize) Red(s string) string { - return w.Red(s) -} - -func (r *Realize) Blue(s string) string { - return w.Blue(s) -} - -func (r *Realize) BlueS(s string) string { - return w.BlueS(s) -} - -func (r *Realize) Dir() string { - return r.Wdir() -} - -func (r *Realize) Serve(p *cli.Context) { - if !p.Bool("no-server") { - fmt.Println(R.Red(R.Host) + "\n") - R.Server.Open = p.Bool("open") - R.Server.Start() - } -} - -func (r *Realize) Run(p *cli.Context) error { - R.Serve(p) - return R.Blueprint.Run() -} - -func (r *Realize) Fast(p *cli.Context) error { - R.Blueprint.Add(p) - R.Serve(p) - return R.Blueprint.Fast(p) -} - -func (r *Realize) Add(p *cli.Context) error { - return R.Blueprint.Insert(p) -} - -func (r *Realize) Remove(p *cli.Context) error { - return R.Blueprint.Insert(p) -} - -func (r *Realize) List(p *cli.Context) error { - return R.Blueprint.List() -} - -func (r *Realize) Before(p *cli.Context) error { - fmt.Println(R.Blue(R.Name) + " - " + R.Blue(R.Version)) - fmt.Println(R.BlueS(R.Description) + "\n") - gopath := os.Getenv("GOPATH") - if gopath == "" { - log.Fatal(R.Red("$GOPATH isn't set up properly")) - } - return nil -} - -func (r *Realize) Handle(err error) error { - if err != nil { - fmt.Println(R.Red(err.Error())) - return nil - } - return nil -} diff --git a/config/config.go b/config/config.go deleted file mode 100644 index 1f38cea..0000000 --- a/config/config.go +++ /dev/null @@ -1,18 +0,0 @@ -package config - -import ( - "github.com/fatih/color" -) - -type Config struct{} - -var Red, Blue, Yellow, Magenta = color.New(color.FgRed).SprintFunc(), - color.New(color.FgBlue).SprintFunc(), - color.New(color.FgYellow).SprintFunc(), - color.New(color.FgMagenta).SprintFunc() - -var GreenB, RedB, BlueB, YellowB, MagentaB = color.New(color.FgGreen, color.Bold).SprintFunc(), - color.New(color.FgRed, color.Bold).SprintFunc(), - color.New(color.FgBlue, color.Bold).SprintFunc(), - color.New(color.FgYellow, color.Bold).SprintFunc(), - color.New(color.FgMagenta, color.Bold).SprintFunc() diff --git a/config/utils.go b/config/utils.go deleted file mode 100644 index 8fcd207..0000000 --- a/config/utils.go +++ /dev/null @@ -1,27 +0,0 @@ -package config - -import ( - "log" - "os" - "path/filepath" -) - -func (c *Config) Wdir() string { - dir, err := os.Getwd() - c.Validate(err) - return filepath.Base(dir) -} - -func (c *Config) Validate(err error) error { - if err != nil { - log.Fatal(Red(err)) - } - return nil -} - -func (c *Config) Fatal(msg string, err error){ - if(msg != "") { - log.Fatal(Red(msg), err.Error()) - } - log.Fatal(err.Error()) -} diff --git a/realize.go b/realize.go index b53c41f..a468c91 100644 --- a/realize.go +++ b/realize.go @@ -1,41 +1,133 @@ package main import ( - a "github.com/tockins/realize/app" + "errors" + "fmt" + s "github.com/tockins/realize/server" + c "github.com/tockins/realize/settings" + w "github.com/tockins/realize/watcher" "gopkg.in/urfave/cli.v2" "os" ) -var app a.Realize +const ( + name = "Realize" + version = "1.2" + description = "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths" + config = "realize.yaml" + output = "realize.log" + host = "localhost" + port = 5000 + server = true + open = false +) +var r realize + +// Realize struct contains the general app informations +type realize struct { + c.Settings `yaml:"settings,omitempty"` + Name, Description, Author, Email, Host, Version string `yaml:"-"` + Sync chan string `yaml:"-"` + Blueprint w.Blueprint `yaml:"-"` + Server s.Server `yaml:"-"` + Projects *[]w.Project `yaml:"projects"` +} + +// Realize struct initialization +func init() { + r = realize{ + Name: name, + Version: version, + Description: description, + Sync: make(chan string), + Settings: c.Settings{ + Config: c.Config{ + Flimit: 0, + }, + Resources: c.Resources{ + Config: config, + Output: output, + }, + Server: c.Server{ + Enabled: server, + Open: open, + Host: host, + Port: port, + }, + }, + } + r.Blueprint = w.Blueprint{ + Settings: &r.Settings, + Sync: r.Sync, + } + r.Server = s.Server{ + Blueprint: &r.Blueprint, + Settings: &r.Settings, + Sync: r.Sync, + } + r.Projects = &r.Blueprint.Projects + + // read if exist + r.Read(&r) + + // increase the file limit + if r.Config.Flimit != 0 { + r.Flimit() + } +} + +// Before of every exec of a cli method +func before() error { + fmt.Println(r.Blue.Bold(name) + " - " + r.Blue.Bold(version)) + fmt.Println(r.Blue.Regular(description) + "\n") + gopath := os.Getenv("GOPATH") + if gopath == "" { + return handle(errors.New("$GOPATH isn't set up properly")) + } + return nil +} + +// Handle errors +func handle(err error) error { + if err != nil { + fmt.Println(r.Red.Bold(err.Error())) + os.Exit(1) + } + return nil +} + +// Cli commands func main() { c := &cli.App{ - Name: a.Name, - Version: a.Version, + Name: r.Name, + Version: r.Version, Authors: []*cli.Author{ { Name: "Alessio Pracchia", - Email: "pracchia@hastega.it", + Email: "pracchia@hastegit", }, { Name: "Daniele Conventi", - Email: "conventi@hastega.it", + Email: "conventi@hastegit", }, }, - Usage: a.Description, + Usage: r.Description, Commands: []*cli.Command{ { Name: "run", Usage: "Build and watch file changes", Flags: []cli.Flag{ - &cli.BoolFlag{Name: "no-server", Usage: "Enable the web panel"}, + &cli.BoolFlag{Name: "no-server", Usage: "Disables the web panel"}, &cli.BoolFlag{Name: "open", Usage: "Automatically opens the web panel"}, }, Action: func(p *cli.Context) error { - return app.Handle(app.Run(p)) + handle(r.Server.Start(p)) + handle(r.Blueprint.Run()) + return nil }, Before: func(c *cli.Context) error { - return app.Before(c) + return before() }, }, { @@ -53,10 +145,16 @@ func main() { &cli.BoolFlag{Name: "config", Value: false, Usage: "Take the defined settings if exist a Configuration file."}, }, Action: func(p *cli.Context) error { - return app.Handle(app.Fast(p)) + if !p.Bool("config") { + r.Blueprint.Projects = r.Blueprint.Projects[:0] + } + handle(r.Blueprint.Add(p)) + handle(r.Server.Start(p)) + handle(r.Blueprint.Fast(p)) + return nil }, Before: func(c *cli.Context) error { - return app.Before(c) + return before() }, }, { @@ -65,7 +163,7 @@ func main() { Aliases: []string{"a"}, Usage: "Add another project", Flags: []cli.Flag{ - &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: app.Dir(), Usage: "Project name"}, + &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: r.Wdir(), Usage: "Project name"}, &cli.StringFlag{Name: "path", Aliases: []string{"b"}, Value: "/", Usage: "Project base path"}, &cli.BoolFlag{Name: "build", Value: false, Usage: "Enable the build"}, &cli.BoolFlag{Name: "no-run", Usage: "Disables the run"}, @@ -73,11 +171,14 @@ func main() { &cli.BoolFlag{Name: "no-fmt", Usage: "Disables the fmt (go fmt)"}, &cli.BoolFlag{Name: "test", Value: false, Usage: "Enables the tests"}, }, - Action: func(p *cli.Context) error { - return app.Handle(app.Add(p)) + Action: func(p *cli.Context) (err error) { + handle(r.Blueprint.Insert(p)) + handle(r.Record(r)) + fmt.Println(r.Green.Bold("Your project was successfully added")) + return nil }, Before: func(c *cli.Context) error { - return app.Before(c) + return before() }, }, { @@ -89,10 +190,13 @@ func main() { &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: ""}, }, Action: func(p *cli.Context) error { - return app.Handle(app.Remove(p)) + handle(r.Blueprint.Remove(p)) + handle(r.Record(r)) + fmt.Println(r.Green.Bold("Your project was successfully removed.")) + return nil }, Before: func(c *cli.Context) error { - return app.Before(c) + return before() }, }, { @@ -101,10 +205,10 @@ func main() { Aliases: []string{"l"}, Usage: "Projects list", Action: func(p *cli.Context) error { - return app.Handle(app.List(p)) + return handle(r.Blueprint.List()) }, Before: func(c *cli.Context) error { - return app.Before(c) + return before() }, }, }, diff --git a/server/bindata.go b/server/bindata.go index 6855616..6d1673f 100644 --- a/server/bindata.go +++ b/server/bindata.go @@ -413,20 +413,20 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "assets/app/components/index.html": assetsAppComponentsIndexHtml, - "assets/app/components/project/index.html": assetsAppComponentsProjectIndexHtml, - "assets/app/components/projects/index.html": assetsAppComponentsProjectsIndexHtml, - "assets/assets/css/app.css": assetsAssetsCssAppCss, - "assets/assets/img/svg/github-logo.svg": assetsAssetsImgSvgGithubLogoSvg, - "assets/assets/img/svg/ic_cached_black_48px.svg": assetsAssetsImgSvgIc_cached_black_48pxSvg, - "assets/assets/img/svg/ic_delete_sweep_black_48px.svg": assetsAssetsImgSvgIc_delete_sweep_black_48pxSvg, - "assets/assets/img/svg/ic_error_black_48px.svg": assetsAssetsImgSvgIc_error_black_48pxSvg, - "assets/assets/img/svg/ic_file_download_black_48px.svg": assetsAssetsImgSvgIc_file_download_black_48pxSvg, - "assets/assets/img/svg/ic_more_vert_black_48px.svg": assetsAssetsImgSvgIc_more_vert_black_48pxSvg, + "assets/app/components/index.html": assetsAppComponentsIndexHtml, + "assets/app/components/project/index.html": assetsAppComponentsProjectIndexHtml, + "assets/app/components/projects/index.html": assetsAppComponentsProjectsIndexHtml, + "assets/assets/css/app.css": assetsAssetsCssAppCss, + "assets/assets/img/svg/github-logo.svg": assetsAssetsImgSvgGithubLogoSvg, + "assets/assets/img/svg/ic_cached_black_48px.svg": assetsAssetsImgSvgIc_cached_black_48pxSvg, + "assets/assets/img/svg/ic_delete_sweep_black_48px.svg": assetsAssetsImgSvgIc_delete_sweep_black_48pxSvg, + "assets/assets/img/svg/ic_error_black_48px.svg": assetsAssetsImgSvgIc_error_black_48pxSvg, + "assets/assets/img/svg/ic_file_download_black_48px.svg": assetsAssetsImgSvgIc_file_download_black_48pxSvg, + "assets/assets/img/svg/ic_more_vert_black_48px.svg": assetsAssetsImgSvgIc_more_vert_black_48pxSvg, "assets/assets/img/svg/ic_swap_vertical_circle_black_48px.svg": assetsAssetsImgSvgIc_swap_vertical_circle_black_48pxSvg, - "assets/assets/js/all.js": assetsAssetsJsAllJs, - "assets/assets/js/all.min.js": assetsAssetsJsAllMinJs, - "assets/index.html": assetsIndexHtml, + "assets/assets/js/all.js": assetsAssetsJsAllJs, + "assets/assets/js/all.min.js": assetsAssetsJsAllMinJs, + "assets/index.html": assetsIndexHtml, } // AssetDir returns the file names below a certain @@ -468,40 +468,41 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ - "assets": &bintree{nil, map[string]*bintree{ - "app": &bintree{nil, map[string]*bintree{ - "components": &bintree{nil, map[string]*bintree{ - "index.html": &bintree{assetsAppComponentsIndexHtml, map[string]*bintree{}}, - "project": &bintree{nil, map[string]*bintree{ - "index.html": &bintree{assetsAppComponentsProjectIndexHtml, map[string]*bintree{}}, + "assets": {nil, map[string]*bintree{ + "app": {nil, map[string]*bintree{ + "components": {nil, map[string]*bintree{ + "index.html": {assetsAppComponentsIndexHtml, map[string]*bintree{}}, + "project": {nil, map[string]*bintree{ + "index.html": {assetsAppComponentsProjectIndexHtml, map[string]*bintree{}}, }}, - "projects": &bintree{nil, map[string]*bintree{ - "index.html": &bintree{assetsAppComponentsProjectsIndexHtml, map[string]*bintree{}}, + "projects": {nil, map[string]*bintree{ + "index.html": {assetsAppComponentsProjectsIndexHtml, map[string]*bintree{}}, }}, }}, }}, - "assets": &bintree{nil, map[string]*bintree{ - "css": &bintree{nil, map[string]*bintree{ - "app.css": &bintree{assetsAssetsCssAppCss, map[string]*bintree{}}, + "assets": {nil, map[string]*bintree{ + "css": {nil, map[string]*bintree{ + "app.css": {assetsAssetsCssAppCss, map[string]*bintree{}}, }}, - "img": &bintree{nil, map[string]*bintree{ - "svg": &bintree{nil, map[string]*bintree{ - "github-logo.svg": &bintree{assetsAssetsImgSvgGithubLogoSvg, map[string]*bintree{}}, - "ic_cached_black_48px.svg": &bintree{assetsAssetsImgSvgIc_cached_black_48pxSvg, map[string]*bintree{}}, - "ic_delete_sweep_black_48px.svg": &bintree{assetsAssetsImgSvgIc_delete_sweep_black_48pxSvg, map[string]*bintree{}}, - "ic_error_black_48px.svg": &bintree{assetsAssetsImgSvgIc_error_black_48pxSvg, map[string]*bintree{}}, - "ic_file_download_black_48px.svg": &bintree{assetsAssetsImgSvgIc_file_download_black_48pxSvg, map[string]*bintree{}}, - "ic_more_vert_black_48px.svg": &bintree{assetsAssetsImgSvgIc_more_vert_black_48pxSvg, map[string]*bintree{}}, - "ic_swap_vertical_circle_black_48px.svg": &bintree{assetsAssetsImgSvgIc_swap_vertical_circle_black_48pxSvg, map[string]*bintree{}}, + "img": {nil, map[string]*bintree{ + "svg": {nil, map[string]*bintree{ + "github-logo.svg": {assetsAssetsImgSvgGithubLogoSvg, map[string]*bintree{}}, + "ic_cached_black_48px.svg": {assetsAssetsImgSvgIc_cached_black_48pxSvg, map[string]*bintree{}}, + "ic_delete_sweep_black_48px.svg": {assetsAssetsImgSvgIc_delete_sweep_black_48pxSvg, map[string]*bintree{}}, + "ic_error_black_48px.svg": {assetsAssetsImgSvgIc_error_black_48pxSvg, map[string]*bintree{}}, + "ic_file_download_black_48px.svg": {assetsAssetsImgSvgIc_file_download_black_48pxSvg, map[string]*bintree{}}, + "ic_more_vert_black_48px.svg": {assetsAssetsImgSvgIc_more_vert_black_48pxSvg, map[string]*bintree{}}, + "ic_swap_vertical_circle_black_48px.svg": {assetsAssetsImgSvgIc_swap_vertical_circle_black_48pxSvg, map[string]*bintree{}}, }}, }}, - "js": &bintree{nil, map[string]*bintree{ - "all.js": &bintree{assetsAssetsJsAllJs, map[string]*bintree{}}, - "all.min.js": &bintree{assetsAssetsJsAllMinJs, map[string]*bintree{}}, + "js": {nil, map[string]*bintree{ + "all.js": {assetsAssetsJsAllJs, map[string]*bintree{}}, + "all.min.js": {assetsAssetsJsAllMinJs, map[string]*bintree{}}, }}, }}, - "index.html": &bintree{assetsIndexHtml, map[string]*bintree{}}, + "index.html": {assetsIndexHtml, map[string]*bintree{}}, }}, }} @@ -551,4 +552,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/server/main.go b/server/main.go index e9db68c..0a748dc 100644 --- a/server/main.go +++ b/server/main.go @@ -5,18 +5,20 @@ import ( "github.com/labstack/echo" "github.com/labstack/echo/engine/standard" "github.com/labstack/echo/middleware" - c "github.com/tockins/realize/watcher" + c "github.com/tockins/realize/settings" + w "github.com/tockins/realize/watcher" "golang.org/x/net/websocket" "log" "net/http" + "strconv" + "gopkg.in/urfave/cli.v2" ) // Server struct contains server informations type Server struct { - Blueprint *c.Blueprint - Files map[string]string - Sync chan string - Open bool + *c.Settings `yaml:"-"` + *w.Blueprint `yaml:"-"` + Sync chan string `yaml:"-"` } func render(c echo.Context, path string, mime int) error { @@ -46,46 +48,52 @@ func render(c echo.Context, path string, mime int) error { } // Server starting -func (s *Server) Start() { - e := echo.New() - e.Use(middleware.Gzip()) +func (s *Server) Start(p *cli.Context) (err error) { + if !p.Bool("no-server") && s.Enabled { + e := echo.New() + e.Use(middleware.Gzip()) - // web panel - e.GET("/", func(c echo.Context) error { - return render(c, "assets/index.html", 1) - }) - e.GET("/assets/js/all.min.js", func(c echo.Context) error { - return render(c, "assets/assets/js/all.min.js", 2) - }) - e.GET("/assets/css/app.css", func(c echo.Context) error { - return render(c, "assets/assets/css/app.css", 3) - }) - e.GET("/app/components/projects/index.html", func(c echo.Context) error { - return render(c, "assets/app/components/projects/index.html", 1) - }) - e.GET("/app/components/project/index.html", func(c echo.Context) error { - return render(c, "assets/app/components/project/index.html", 1) - }) - e.GET("/app/components/index.html", func(c echo.Context) error { - return render(c, "assets/app/components/index.html", 1) - }) - e.GET("/assets/img/svg/github-logo.svg", func(c echo.Context) error { - return render(c, "assets/assets/img/svg/github-logo.svg", 4) - }) - e.GET("/assets/img/svg/ic_error_black_48px.svg", func(c echo.Context) error { - return render(c, "assets/assets/img/svg/ic_error_black_48px.svg", 4) - }) - e.GET("/assets/img/svg/ic_swap_vertical_circle_black_48px.svg", func(c echo.Context) error { - return render(c, "assets/assets/img/svg/ic_swap_vertical_circle_black_48px.svg", 4) - }) + // web panel + e.GET("/", func(c echo.Context) error { + return render(c, "assets/index.html", 1) + }) + e.GET("/assets/js/all.min.js", func(c echo.Context) error { + return render(c, "assets/assets/js/all.min.js", 2) + }) + e.GET("/assets/css/app.css", func(c echo.Context) error { + return render(c, "assets/assets/css/app.css", 3) + }) + e.GET("/app/components/projects/index.html", func(c echo.Context) error { + return render(c, "assets/app/components/projects/index.html", 1) + }) + e.GET("/app/components/project/index.html", func(c echo.Context) error { + return render(c, "assets/app/components/project/index.html", 1) + }) + e.GET("/app/components/index.html", func(c echo.Context) error { + return render(c, "assets/app/components/index.html", 1) + }) + e.GET("/assets/img/svg/github-logo.svg", func(c echo.Context) error { + return render(c, "assets/assets/img/svg/github-logo.svg", 4) + }) + e.GET("/assets/img/svg/ic_error_black_48px.svg", func(c echo.Context) error { + return render(c, "assets/assets/img/svg/ic_error_black_48px.svg", 4) + }) + e.GET("/assets/img/svg/ic_swap_vertical_circle_black_48px.svg", func(c echo.Context) error { + return render(c, "assets/assets/img/svg/ic_swap_vertical_circle_black_48px.svg", 4) + }) - //websocket - //e.GET("/ws", standard.WrapHandler(s.projects())) - e.GET("/ws", standard.WrapHandler(s.projects())) - go e.Run(standard.New(":5000")) - if s.Open { - Open("http://localhost:5000") + //websocket + e.GET("/ws", standard.WrapHandler(s.projects())) + + go e.Run(standard.New(string(s.Settings.Server.Host) + ":" + strconv.Itoa(s.Settings.Server.Port))) + if s.Open || p.Bool("open") { + _, err = Open("http://" + string(s.Settings.Server.Host) + ":" + strconv.Itoa(s.Settings.Server.Port)) + if err != nil { + return err + } + } } + return nil } // The WebSocket for projects list diff --git a/server/open.go b/server/open.go index 4ac6a04..9d1f48d 100644 --- a/server/open.go +++ b/server/open.go @@ -3,17 +3,16 @@ package server import ( "bytes" "errors" - "fmt" "io" "os/exec" "runtime" ) -var cli map[string]string +var cmd map[string]string var stderr bytes.Buffer func init() { - cli = map[string]string{ + cmd = map[string]string{ "windows": "start", "darwin": "open", "linux": "xdg-open", @@ -21,13 +20,12 @@ func init() { } func Open(url string) (io.Writer, error) { - if open, err := cli[runtime.GOOS]; !err { + if open, err := cmd[runtime.GOOS]; !err { return nil, errors.New("This operating system is not supported.") } else { cmd := exec.Command(open, url) cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - fmt.Println(cmd.Stderr, err) return cmd.Stderr, err } } diff --git a/settings/colors.go b/settings/colors.go new file mode 100644 index 0000000..8f65462 --- /dev/null +++ b/settings/colors.go @@ -0,0 +1,68 @@ +package settings + +import ( + "github.com/fatih/color" +) + +type Colors struct { + Red + Blue + Yellow + Magenta + Green +} +type Red struct{} +type Blue struct{} +type Yellow struct{} +type Magenta struct{} +type Green struct{} + +func (c Red) Regular(t ...interface{}) string { + r := color.New(color.FgRed).SprintFunc() + return r(t...) +} + +func (c Red) Bold(t ...interface{}) string { + r := color.New(color.FgRed, color.Bold).SprintFunc() + return r(t...) +} + +func (c Blue) Regular(t ...interface{}) string { + r := color.New(color.FgBlue).SprintFunc() + return r(t...) +} + +func (c Blue) Bold(t ...interface{}) string { + r := color.New(color.FgBlue, color.Bold).SprintFunc() + return r(t...) +} + +func (c Yellow) Regular(t ...interface{}) string { + r := color.New(color.FgYellow).SprintFunc() + return r(t...) +} + +func (c Yellow) Bold(t ...interface{}) string { + r := color.New(color.FgYellow, color.Bold).SprintFunc() + return r(t...) +} + +func (c Magenta) Regular(t ...interface{}) string { + r := color.New(color.FgMagenta).SprintFunc() + return r(t...) +} + +func (c Magenta) Bold(t ...interface{}) string { + r := color.New(color.FgMagenta, color.Bold).SprintFunc() + return r(t...) +} + +func (c Green) Regular(t ...interface{}) string { + r := color.New(color.FgGreen).SprintFunc() + return r(t...) +} + +func (c Green) Bold(t ...interface{}) string { + r := color.New(color.FgGreen, color.Bold).SprintFunc() + return r(t...) +} diff --git a/config/io.go b/settings/io.go similarity index 64% rename from config/io.go rename to settings/io.go index 80bc0e1..02b9e6d 100644 --- a/config/io.go +++ b/settings/io.go @@ -1,4 +1,4 @@ -package config +package settings import ( "io/ioutil" @@ -6,25 +6,25 @@ import ( ) // Scan return a byte stream of a given file -func (c *Config) Stream(file string) ([]byte, error) { +func (s Settings) Stream(file string) ([]byte, error) { _, err := os.Stat(file) if err == nil { content, err := ioutil.ReadFile(file) - c.Validate(err) + s.Validate(err) return content, err } return nil, err } // Write a file given a name and a byte stream -func (c *Config) Write(name string, data []byte) error { +func (s Settings) Write(name string, data []byte) error { err := ioutil.WriteFile(name, data, 0655) - return c.Validate(err) + return s.Validate(err) } // Create a new file and return its pointer -func (c *Config) Create(file string) *os.File { +func (s Settings) Create(file string) *os.File { out, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0655) - c.Validate(err) + s.Validate(err) return out } diff --git a/settings/settings.go b/settings/settings.go new file mode 100644 index 0000000..fde20e8 --- /dev/null +++ b/settings/settings.go @@ -0,0 +1,59 @@ +package settings + +import ( + "gopkg.in/yaml.v2" + "syscall" +) + +type Settings struct { + Colors `yaml:"-"` + Resources `yaml:"resources,omitempty"` + Server `yaml:"server,omitempty"` + Config `yaml:"config,omitempty"` +} + +type Config struct { + Flimit uint64 `yaml:"flimit,omitempty"` +} + +type Server struct { + Enabled bool `yaml:"enable,omitempty"` + Open bool `yaml:"open,omitempty"` + Host string `yaml:"host,omitempty"` + Port int `yaml:"port,omitempty"` +} + +type Resources struct { + Config string `yaml:"config,omitempty"` + Output string `yaml:"output,omitempty"` +} + +// Flimit defines the max number of watched files +func (s *Settings) Flimit() { + var rLimit syscall.Rlimit + rLimit.Max = s.Config.Flimit + rLimit.Cur = s.Config.Flimit + err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) + if err != nil { + s.Fatal("Error Setting Rlimit", err) + } +} + +// Read from the configuration file +func (s *Settings) Read(out interface{}) error { + content, err := s.Stream(s.Resources.Config) + if err == nil { + err = yaml.Unmarshal(content, out) + return err + } + return err +} + +// Record create and unmarshal the yaml config file +func (h *Settings) Record(out interface{}) error { + y, err := yaml.Marshal(out) + if err != nil { + return err + } + return h.Write(h.Resources.Config, y) +} diff --git a/settings/utils.go b/settings/utils.go new file mode 100644 index 0000000..a030559 --- /dev/null +++ b/settings/utils.go @@ -0,0 +1,27 @@ +package settings + +import ( + "log" + "os" + "path/filepath" +) + +func (s Settings) Wdir() string { + dir, err := os.Getwd() + s.Validate(err) + return filepath.Base(dir) +} + +func (s Settings) Validate(err error) error { + if err != nil { + s.Fatal("", err) + } + return nil +} + +func (s Settings) Fatal(msg string, err error) { + if msg != "" { + log.Fatal(s.Red.Regular(msg), err.Error()) + } + log.Fatal(err.Error()) +} diff --git a/watcher/cmd.go b/watcher/cmd.go index aaa555e..92b428f 100644 --- a/watcher/cmd.go +++ b/watcher/cmd.go @@ -4,14 +4,13 @@ import ( "errors" "fmt" "gopkg.in/urfave/cli.v2" - "gopkg.in/yaml.v2" "path/filepath" "strings" ) // Watch method adds the given paths on the Watcher func (h *Blueprint) Run() error { - err := h.Read() + err := h.check() if err == nil { // loop projects wg.Add(len(h.Projects)) @@ -26,26 +25,13 @@ func (h *Blueprint) Run() error { } // Fast method run a project from his working directory without makes a config file -func (h *Blueprint) Fast(params *cli.Context) error { +func (h *Blueprint) Fast(p *cli.Context) error { // Takes the values from config if wd path match with someone else wg.Add(1) for i := 0; i < len(h.Projects); i++ { v := &h.Projects[i] v.parent = h - if params.Bool("config") { - if err := h.Read(); err == nil { - for l := 0; l < len(h.Projects); l++ { - l := &h.Projects[l] - if l.Path == "/" { - l.Path = "." - l.parent = v.parent - } - if v.Path == l.Path { - v = l - } - } - } - } + v.path = v.Path go v.watching() } wg.Wait() @@ -53,16 +39,16 @@ func (h *Blueprint) Fast(params *cli.Context) error { } // Add a new project -func (h *Blueprint) Add(params *cli.Context) error { - p := Project{ - Name: h.name(params), - Path: filepath.Clean(params.String("path")), - Build: params.Bool("build"), - Bin: boolFlag(params.Bool("no-bin")), - Run: boolFlag(params.Bool("no-run")), - Fmt: boolFlag(params.Bool("no-fmt")), - Test: params.Bool("test"), - Params: argsParam(params), +func (h *Blueprint) Add(p *cli.Context) error { + project := Project{ + Name: h.name(p), + Path: filepath.Clean(p.String("path")), + Build: p.Bool("build"), + Bin: boolFlag(p.Bool("no-bin")), + Run: boolFlag(p.Bool("no-run")), + Fmt: boolFlag(p.Bool("no-fmt")), + Test: p.Bool("test"), + Params: argsParam(p), Watcher: Watcher{ Paths: []string{"/"}, Ignore: []string{"vendor"}, @@ -73,10 +59,10 @@ func (h *Blueprint) Add(params *cli.Context) error { }, }, } - if _, err := duplicates(p, h.Projects); err != nil { + if _, err := duplicates(project, h.Projects); err != nil { return err } - h.Projects = append(h.Projects, p) + h.Projects = append(h.Projects, project) return nil } @@ -91,103 +77,71 @@ func (h *Blueprint) Clean() { } } -// Read, Check and remove duplicates from the config file -func (h *Blueprint) Read() error { - content, err := h.Stream(h.Files["config"]) - if err == nil { - err = yaml.Unmarshal(content, h) - if err == nil { - if len(h.Projects) > 0 { - h.Clean() - return nil - } - return errors.New("There are no projects!") - } - return err - } - return err -} - -// Create and unmarshal yaml config file -func (h *Blueprint) Create() error { - y, err := yaml.Marshal(h) - if err != nil { - return err - } - return h.Write(h.Files["config"], y) -} - // Inserts a new project in the list -func (h *Blueprint) Insert(params *cli.Context) error { - check := h.Read() - err := h.Add(params) - if err == nil { - err = h.Create() - if check == nil && err == nil { - fmt.Println(Green("Your project was successfully added")) - } else { - fmt.Println(Green("The config file was successfully created")) - } - } +func (h *Blueprint) Insert(p *cli.Context) error { + err := h.Add(p) return err } // Remove a project -func (h *Blueprint) Remove(params *cli.Context) error { - err := h.Read() - if err == nil { - for key, val := range h.Projects { - if params.String("name") == val.Name { - h.Projects = append(h.Projects[:key], h.Projects[key+1:]...) - err = h.Create() - if err == nil { - fmt.Println(Green("Your project was successfully removed")) - } - return err - } +func (h *Blueprint) Remove(p *cli.Context) error { + for key, val := range h.Projects { + if p.String("name") == val.Name { + h.Projects = append(h.Projects[:key], h.Projects[key+1:]...) + return nil } - return errors.New("No project found") } - return err + return errors.New("No project found.") } // List of all the projects func (h *Blueprint) List() error { - err := h.Read() + err := h.check() if err == nil { for _, val := range h.Projects { - fmt.Println(Blue("|"), Blue(strings.ToUpper(val.Name))) - fmt.Println(MagentaS("|"), "\t", Yellow("Base Path"), ":", MagentaS(val.Path)) - fmt.Println(MagentaS("|"), "\t", Yellow("Run"), ":", MagentaS(val.Run)) - fmt.Println(MagentaS("|"), "\t", Yellow("Build"), ":", MagentaS(val.Build)) - fmt.Println(MagentaS("|"), "\t", Yellow("Install"), ":", MagentaS(val.Bin)) - fmt.Println(MagentaS("|"), "\t", Yellow("Fmt"), ":", MagentaS(val.Fmt)) - fmt.Println(MagentaS("|"), "\t", Yellow("Test"), ":", MagentaS(val.Test)) - fmt.Println(MagentaS("|"), "\t", Yellow("Params"), ":", MagentaS(val.Params)) - fmt.Println(MagentaS("|"), "\t", Yellow("Watcher"), ":") - fmt.Println(MagentaS("|"), "\t\t", Yellow("After"), ":", MagentaS(val.Watcher.After)) - fmt.Println(MagentaS("|"), "\t\t", Yellow("Before"), ":", MagentaS(val.Watcher.Before)) - fmt.Println(MagentaS("|"), "\t\t", Yellow("Extensions"), ":", MagentaS(val.Watcher.Exts)) - fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths"), ":", MagentaS(val.Watcher.Paths)) - fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths ignored"), ":", MagentaS(val.Watcher.Ignore)) - fmt.Println(MagentaS("|"), "\t\t", Yellow("Watch preview"), ":", MagentaS(val.Watcher.Preview)) - fmt.Println(MagentaS("|"), "\t\t", Yellow("Output"), ":") - fmt.Println(MagentaS("|"), "\t\t\t", Yellow("Cli"), ":", MagentaS(val.Watcher.Output["cli"])) - fmt.Println(MagentaS("|"), "\t\t\t", Yellow("File"), ":", MagentaS(val.Watcher.Output["file"])) + fmt.Println(h.Blue.Bold("|"), h.Blue.Bold(strings.ToUpper(val.Name))) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Base Path"), ":", h.Magenta.Regular(val.Path)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Run"), ":", h.Magenta.Regular(val.Run)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Build"), ":", h.Magenta.Regular(val.Build)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Install"), ":", h.Magenta.Regular(val.Bin)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Fmt"), ":", h.Magenta.Regular(val.Fmt)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Test"), ":", h.Magenta.Regular(val.Test)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Params"), ":", h.Magenta.Regular(val.Params)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Watcher"), ":") + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("After"), ":", h.Magenta.Regular(val.Watcher.After)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Before"), ":", h.Magenta.Regular(val.Watcher.Before)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Extensions"), ":", h.Magenta.Regular(val.Watcher.Exts)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Paths"), ":", h.Magenta.Regular(val.Watcher.Paths)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Paths ignored"), ":", h.Magenta.Regular(val.Watcher.Ignore)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Watch preview"), ":", h.Magenta.Regular(val.Watcher.Preview)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Output"), ":") + fmt.Println(h.Magenta.Regular("|"), "\t\t\t", h.Yellow.Regular("Cli"), ":", h.Magenta.Regular(val.Watcher.Output["cli"])) + fmt.Println(h.Magenta.Regular("|"), "\t\t\t", h.Yellow.Regular("File"), ":", h.Magenta.Regular(val.Watcher.Output["file"])) } + return nil } return err } -// NameParam check the project name presence. If empty takes the working directory name -func (p *Blueprint) name(params *cli.Context) string { - var name string - if params.String("name") == "" && params.String("path") == "" { - return p.Wdir() - } else if params.String("path") != "/" { - name = filepath.Base(params.String("path")) +// Check if there are projects +func (h *Blueprint) check() error { + if len(h.Projects) > 0 { + h.Clean() + return nil } else { - name = params.String("name") + return errors.New("There are no projects. The config file is empty.") + } +} + +// NameParam check the project name presence. If empty takes the working directory name +func (h *Blueprint) name(p *cli.Context) string { + var name string + if p.String("name") == "" && p.String("path") == "" { + return h.Wdir() + } else if p.String("path") != "/" { + name = filepath.Base(p.String("path")) + } else { + name = p.String("name") } return name } diff --git a/watcher/exec.go b/watcher/exec.go index d86f40d..906e62c 100644 --- a/watcher/exec.go +++ b/watcher/exec.go @@ -16,15 +16,14 @@ import ( // GoRun is an implementation of the bin execution func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) error { + var build *exec.Cmd sync := func() { p.parent.Sync <- "sync" } - - var build *exec.Cmd if len(p.Params) != 0 { - build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.Path)), p.Params...) + build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path)), p.Params...) } else { - build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.Path))) + build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path))) } build.Dir = p.base defer func() { @@ -33,7 +32,7 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) p.Fatal("Failed to stop:", err) } p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: "Ended"}) - log.Println(pname(p.Name, 2), ":", RedS("Ended")) + log.Println(p.pname(p.Name, 2), ":", p.Red.Regular("Ended")) go sync() wr.Done() }() @@ -42,11 +41,11 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) stderr, err := build.StderrPipe() if err != nil { - log.Println(Red(err.Error())) + log.Println(p.Red.Bold(err.Error())) return err } if err := build.Start(); err != nil { - log.Println(Red(err.Error())) + log.Println(p.Red.Bold(err.Error())) return err } close(runner) @@ -66,10 +65,10 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) go sync() if p.Watcher.Output["cli"] { - log.Println(pname(p.Name, 3), ":", BlueS(output.Text())) + log.Println(p.pname(p.Name, 3), ":", p.Blue.Regular(output.Text())) } if p.Watcher.Output["file"] { - path := filepath.Join(p.base, p.parent.Files["output"]) + path := filepath.Join(p.base, p.parent.Resources.Output) f := p.Create(path) t := time.Now() if _, err := f.WriteString(t.Format("2006-01-02 15:04:05") + " : " + output.Text() + "\r\n"); err != nil { diff --git a/watcher/main.go b/watcher/main.go index 944a2a4..8d18342 100644 --- a/watcher/main.go +++ b/watcher/main.go @@ -1,8 +1,7 @@ package cli import ( - "github.com/fatih/color" - c "github.com/tockins/realize/config" + c "github.com/tockins/realize/settings" "log" "sync" "time" @@ -10,43 +9,35 @@ import ( var wg sync.WaitGroup -var Green, Red, RedS, Blue, BlueS, Yellow, YellowS, Magenta, MagentaS = color.New(color.FgGreen, color.Bold).SprintFunc(), - color.New(color.FgRed, color.Bold).SprintFunc(), - color.New(color.FgRed).SprintFunc(), - color.New(color.FgBlue, color.Bold).SprintFunc(), - color.New(color.FgBlue).SprintFunc(), - color.New(color.FgYellow, color.Bold).SprintFunc(), - color.New(color.FgYellow).SprintFunc(), - color.New(color.FgMagenta, color.Bold).SprintFunc(), - color.New(color.FgMagenta).SprintFunc() - // Log struct -type logWriter struct{} +type logWriter struct { + c.Colors +} // Projects struct contains a projects list type Blueprint struct { - c.Config - Projects []Project `yaml:"projects,omitempty"` - Files map[string]string `yaml:"-"` - Sync chan string `yaml:"-"` + *c.Settings `yaml:"-"` + Projects []Project `yaml:"projects,omitempty"` + Sync chan string `yaml:"-"` } // Project defines the informations of a single project type Project struct { - c.Config + c.Settings `yaml:"-"` LastChangedOn time.Time `yaml:"-"` base string - Name string `yaml:"app_name,omitempty"` - Path string `yaml:"app_path,omitempty"` - Run bool `yaml:"app_run,omitempty"` - Bin bool `yaml:"app_bin,omitempty"` - Build bool `yaml:"app_build,omitempty"` - Fmt bool `yaml:"app_fmt,omitempty"` - Test bool `yaml:"app_test,omitempty"` - Params []string `yaml:"app_params,omitempty"` - Watcher Watcher `yaml:"app_watcher,omitempty"` + Name string `yaml:"name,omitempty"` + Path string `yaml:"path,omitempty"` + Run bool `yaml:"run,omitempty"` + Bin bool `yaml:"bin,omitempty"` + Build bool `yaml:"build,omitempty"` + Fmt bool `yaml:"fmt,omitempty"` + Test bool `yaml:"test,omitempty"` + Params []string `yaml:"params,omitempty"` + Watcher Watcher `yaml:"watcher,omitempty"` Buffer Buffer `yaml:"-"` parent *Blueprint + path string } // Watcher struct defines the livereload's logic diff --git a/watcher/utils.go b/watcher/utils.go index a466284..4e8d98e 100644 --- a/watcher/utils.go +++ b/watcher/utils.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "gopkg.in/urfave/cli.v2" - "strings" "time" ) @@ -49,29 +48,7 @@ func inArray(str string, list []string) bool { return false } -// Defines the colors scheme for the project name -func pname(name string, color int) string { - switch color { - case 1: - name = Yellow("[") + strings.ToUpper(name) + Yellow("]") - break - case 2: - name = Yellow("[") + Red(strings.ToUpper(name)) + Yellow("]") - break - case 3: - name = Yellow("[") + Blue(strings.ToUpper(name)) + Yellow("]") - break - case 4: - name = Yellow("[") + Magenta(strings.ToUpper(name)) + Yellow("]") - break - case 5: - name = Yellow("[") + Green(strings.ToUpper(name)) + Yellow("]") - break - } - return name -} - // Cewrites the log timestamp -func (writer logWriter) Write(bytes []byte) (int, error) { - return fmt.Print(YellowS("[") + time.Now().Format("15:04:05") + YellowS("]") + string(bytes)) +func (w logWriter) Write(bytes []byte) (int, error) { + return fmt.Print(w.Yellow.Regular("[") + time.Now().Format("15:04:05") + w.Yellow.Regular("]") + string(bytes)) } diff --git a/watcher/watcher.go b/watcher/watcher.go index 71736a4..4b6b1dc 100644 --- a/watcher/watcher.go +++ b/watcher/watcher.go @@ -19,29 +19,28 @@ import ( func (p *Project) watching() { var wr sync.WaitGroup var watcher *fsnotify.Watcher - sync := func() { p.parent.Sync <- "sync" } - watcher, err := fsnotify.NewWatcher() if err != nil { - log.Println(strings.ToUpper(pname(p.Name, 1)), ":", Red(err.Error())) + log.Println(strings.ToUpper(p.pname(p.Name, 1)), ":", p.Red.Bold(err.Error())) } channel, exit := make(chan bool, 1), make(chan bool, 1) if err != nil { - log.Println(pname(p.Name, 1), ":", Red(err.Error())) + log.Println(p.pname(p.Name, 1), ":", p.Red.Bold(err.Error())) } end := func() { watcher.Close() wg.Done() } defer end() + p.path = p.Path p.cmd(exit) err = p.walks(watcher) if err != nil { - fmt.Println(pname(p.Name, 1), ":", Red(err.Error())) + fmt.Println(p.pname(p.Name, 1), ":", p.Red.Bold(err.Error())) return } @@ -69,7 +68,7 @@ func (p *Project) watching() { if event.Name[:i] != "" && inArray(ext, p.Watcher.Exts) { p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + event.Name[:i] + ext}) go sync() - fmt.Println(pname(p.Name, 4), Magenta(strings.ToUpper(ext[1:])+" changed"), Magenta(event.Name[:i]+ext)) + fmt.Println(p.pname(p.Name, 4), p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(event.Name[:i]+ext)) // stop and run again if p.Run { close(channel) @@ -87,7 +86,7 @@ func (p *Project) watching() { } } case err := <-watcher.Errors: - log.Println(Red(err.Error())) + log.Println(p.Red.Bold(err.Error())) case <-exit: return } @@ -97,22 +96,22 @@ func (p *Project) watching() { // Install calls an implementation of the "go install" func (p *Project) install(channel chan bool, wr *sync.WaitGroup) { if p.Bin { - log.Println(pname(p.Name, 1), ":", "Installing..") + log.Println(p.pname(p.Name, 1), ":", "Installing..") start := time.Now() if std, err := p.GoInstall(); err != nil { - log.Println(pname(p.Name, 1), ":", fmt.Sprint(Red(err)), std) + log.Println(p.pname(p.Name, 1), ":", fmt.Sprint(p.Red.Bold(err)), std) wr.Done() } else { - log.Println(pname(p.Name, 5), ":", Green("Installed")+" after", MagentaS(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s")) + log.Println(p.pname(p.Name, 5), ":", p.Green.Regular("Installed")+" after", p.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s")) if p.Run { runner := make(chan bool, 1) - log.Println(pname(p.Name, 1), ":", "Running..") + log.Println(p.pname(p.Name, 1), ":", "Running..") start = time.Now() go p.GoRun(channel, runner, wr) for { select { case <-runner: - log.Println(pname(p.Name, 5), ":", Green("Has been run")+" after", MagentaS(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s")) + log.Println(p.pname(p.Name, 5), ":", p.Green.Regular("Has been run")+" after", p.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s")) return } } @@ -125,12 +124,12 @@ func (p *Project) install(channel chan bool, wr *sync.WaitGroup) { // Build calls an implementation of the "go build" func (p *Project) build() { if p.Build { - log.Println(pname(p.Name, 1), ":", "Building..") + log.Println(p.pname(p.Name, 1), ":", "Building..") start := time.Now() if std, err := p.GoBuild(); err != nil { - log.Println(pname(p.Name, 1), ":", fmt.Sprint(Red(err)), std) + log.Println(p.pname(p.Name, 1), ":", fmt.Sprint(p.Red.Bold(err)), std) } else { - log.Println(pname(p.Name, 5), ":", Green("Builded")+" after", MagentaS(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s")) + log.Println(p.pname(p.Name, 5), ":", p.Green.Regular("Builded")+" after", p.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s")) } return } @@ -141,7 +140,7 @@ func (p *Project) build() { func (p *Project) fmt(path string) error { if p.Fmt { if _, err := p.GoFmt(path); err != nil { - log.Println(pname(p.Name, 1), Red("There are some GoFmt errors in "), ":", Magenta(path)) + log.Println(p.pname(p.Name, 1), p.Red.Bold("There are some GoFmt errors in "), ":", p.Magenta.Bold(path)) } } return nil @@ -154,7 +153,7 @@ func (p *Project) cmd(exit chan bool) { cast := func(commands []string) { if errs := p.Cmd(commands); errs != nil { for _, err := range errs { - log.Println(pname(p.Name, 2), Red(err)) + log.Println(p.pname(p.Name, 2), p.Red.Bold(err)) } } } @@ -180,7 +179,7 @@ func (p *Project) cmd(exit chan bool) { func (p *Project) test(path string) error { if p.Test { if _, err := p.GoTest(path); err != nil { - log.Println(pname(p.Name, 1), Red("Go Test fails in "), ":", Magenta(path)) + log.Println(p.pname(p.Name, 1), p.Red.Bold("Go Test fails in "), ":", p.Magenta.Bold(path)) } } return nil @@ -195,7 +194,7 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error { if !p.ignore(path) { if (info.IsDir() && len(filepath.Ext(path)) == 0 && !strings.HasPrefix(path, ".")) && !strings.Contains(path, "/.") || (inArray(filepath.Ext(path), p.Watcher.Exts)) { if p.Watcher.Preview { - fmt.Println(pname(p.Name, 1), ":", path) + fmt.Println(p.pname(p.Name, 1), ":", path) } if err = watcher.Add(path); err != nil { return filepath.SkipDir @@ -221,26 +220,26 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error { return nil } - if p.Path == "." || p.Path == "/" { + if p.path == "." || p.path == "/" { p.base = wd - p.Path = p.Wdir() - } else if filepath.IsAbs(p.Path) { - p.base = p.Path + p.path = p.Wdir() + } else if filepath.IsAbs(p.path) { + p.base = p.path } else { - p.base = filepath.Join(wd, p.Path) + p.base = filepath.Join(wd, p.path) } for _, dir := range p.Watcher.Paths { base := filepath.Join(p.base, dir) if _, err := os.Stat(base); err == nil { if err := filepath.Walk(base, walk); err != nil { - log.Println(Red(err.Error())) + log.Println(p.Red.Bold(err.Error())) } } else { return errors.New(base + " path doesn't exist") } } - fmt.Println(pname(p.Name, 1), Red("Watching"), Magenta(files), "file/s", Magenta(folders), "folder/s") + fmt.Println(p.pname(p.Name, 1), p.Red.Bold("Watching"), p.Magenta.Bold(files), "file/s", p.Magenta.Bold(folders), "folder/s") return nil } @@ -261,3 +260,25 @@ func (p *Project) routines(channel chan bool, wr *sync.WaitGroup) { go p.install(channel, wr) wr.Wait() } + +// Defines the colors scheme for the project name +func (p *Project) pname(name string, color int) string { + switch color { + case 1: + name = p.Yellow.Regular("[") + strings.ToUpper(name) + p.Yellow.Regular("]") + break + case 2: + name = p.Yellow.Regular("[") + p.Red.Bold(strings.ToUpper(name)) + p.Yellow.Regular("]") + break + case 3: + name = p.Yellow.Regular("[") + p.Blue.Bold(strings.ToUpper(name)) + p.Yellow.Regular("]") + break + case 4: + name = p.Yellow.Regular("[") + p.Magenta.Bold(strings.ToUpper(name)) + p.Yellow.Regular("]") + break + case 5: + name = p.Yellow.Regular("[") + p.Green.Bold(strings.ToUpper(name)) + p.Yellow.Regular("]") + break + } + return name +}