diff --git a/main.go b/main.go index 43abbe6..e6c027d 100644 --- a/main.go +++ b/main.go @@ -11,7 +11,7 @@ import ( func main() { - app := r.Info() + app := r.App handle := func(err error) error { if err != nil { @@ -50,8 +50,7 @@ func main() { Name: "run", Usage: "Build and watch file changes", Action: func(p *cli.Context) error { - y := r.New(p) - return handle(y.Watch()) + return handle(app.Blueprint.Run()) }, Before: func(c *cli.Context) error { header() @@ -60,7 +59,7 @@ func main() { }, { Name: "fast", - Usage: "Build and watch file changes for a single project without any config file", + Usage: "Build and watch file changes for a single project without any Configuration file", Flags: []cli.Flag{ &cli.StringFlag{Name: "path", Aliases: []string{"b"}, Value: "", Usage: "Project base path"}, &cli.BoolFlag{Name: "build", Value: false, Usage: "Enables the build"}, @@ -68,11 +67,11 @@ func main() { &cli.BoolFlag{Name: "no-bin", Usage: "Disables the installation"}, &cli.BoolFlag{Name: "no-fmt", Usage: "Disables the fmt (go fmt)"}, &cli.BoolFlag{Name: "test", Value: false, Usage: "Enable the tests"}, - &cli.BoolFlag{Name: "config", Value: false, Usage: "Take the defined settings if exist a config file."}, + &cli.BoolFlag{Name: "Configuration", Value: false, Usage: "Take the defined settings if exist a Configuration file."}, }, Action: func(p *cli.Context) error { - y := r.New(p) - return handle(y.Fast(p)) + app.Blueprint.Add(p) + return handle(app.Blueprint.Fast(p)) }, Before: func(c *cli.Context) error { header() @@ -81,11 +80,11 @@ func main() { }, { Name: "add", - Category: "config", + Category: "Configuration", Aliases: []string{"a"}, Usage: "Add another project", Flags: []cli.Flag{ - &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: r.WorkingDir(), Usage: "Project name"}, + &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: app.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"}, @@ -94,8 +93,7 @@ func main() { &cli.BoolFlag{Name: "test", Value: false, Usage: "Enable the tests"}, }, Action: func(p *cli.Context) error { - y := r.New(p) - return handle(y.Add(p)) + return handle(app.Blueprint.Insert(p)) }, Before: func(c *cli.Context) error { header() @@ -104,15 +102,14 @@ func main() { }, { Name: "remove", - Category: "config", + Category: "Configuration", Aliases: []string{"r"}, Usage: "Remove a project", Flags: []cli.Flag{ &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: ""}, }, Action: func(p *cli.Context) error { - y := r.New(p) - return handle(y.Remove(p)) + return handle(app.Blueprint.Remove(p)) }, Before: func(c *cli.Context) error { header() @@ -121,12 +118,11 @@ func main() { }, { Name: "list", - Category: "config", + Category: "Configuration", Aliases: []string{"l"}, Usage: "Projects list", Action: func(p *cli.Context) error { - y := r.New(p) - return handle(y.List()) + return handle(app.Blueprint.List()) }, Before: func(c *cli.Context) error { header() diff --git a/realize/app.go b/realize/app.go index b659f46..879fb9c 100644 --- a/realize/app.go +++ b/realize/app.go @@ -1,21 +1,12 @@ package realize import ( - "fmt" "github.com/fatih/color" "log" "sync" - "syscall" - "time" ) -// Default values and info -const ( - AppName = "Realize" - AppVersion = "v1.0" - AppDescription = "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths" - AppFile = "realize.config.yaml" -) +var App Realize var wg sync.WaitGroup @@ -46,47 +37,19 @@ var MagentaS = color.New(color.FgMagenta).SprintFunc() // Magenta color bold var Magenta = color.New(color.FgMagenta, color.Bold).SprintFunc() -// WatcherIgnores is an array of default ignored paths -var watcherIgnores = []string{"vendor", "bin"} - -// WatcherExts is an array of default exts -var watcherExts = []string{".go"} - -// WatcherPaths is an array of default watched paths -var watcherPaths = []string{"/"} - -type logWriter struct{} - -// App struct contains the informations about realize -type App struct { - Name, Version, Description, Author, Email string -} - -// Custom log timestamp +// Initialize the application func init() { + App = Realize{ + Name: "Realize", + Version: "1.0", + Description: "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths", + Limit: 10000, + } + App.Blueprint.files = map[string]string{ + "config": "r.config.yaml", + "output": "r.output.log", + } + App.limit() log.SetFlags(0) log.SetOutput(new(logWriter)) - - // increases the files limit - var rLimit syscall.Rlimit - rLimit.Max = 10000 - rLimit.Cur = 10000 - err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) - if err != nil { - fmt.Println(Red("Error Setting Rlimit "), err) - } -} - -// Info returns the general informations about Realize -func Info() *App { - return &App{ - Name: AppName, - Version: AppVersion, - Description: AppDescription, - } -} - -// 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)) } diff --git a/realize/blueprint.go b/realize/blueprint.go new file mode 100644 index 0000000..88e2433 --- /dev/null +++ b/realize/blueprint.go @@ -0,0 +1,225 @@ +package realize + +import ( + "errors" + "fmt" + "gopkg.in/urfave/cli.v2" + "gopkg.in/yaml.v2" + "log" + "os" + "path/filepath" + "strings" + "syscall" + "time" +) + +// App struct contains the informations about realize +type Realize struct { + Name, Description, Author, Email string + Version string `yaml:"version,omitempty"` + Limit uint64 + Blueprint Blueprint +} + +// Projects struct contains a projects list +type Blueprint struct { + Projects []Project `yaml:"projects,omitempty"` + files map[string]string +} + +// Project defines the informations of a single project +type Project struct { + reload time.Time + 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"` +} + +// Wdir returns the name last element of the working directory path +func (r *Realize) Wdir() string { + dir, err := os.Getwd() + if err != nil { + log.Fatal(Red(err)) + } + return filepath.Base(dir) +} + +// Limit defines the max number of watched files +func (r *Realize) limit() { + // increases the files limit + var rLimit syscall.Rlimit + rLimit.Max = r.Limit + rLimit.Cur = r.Limit + err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) + if err != nil { + fmt.Println(Red("Error Setting Rlimit "), err) + } +} + +// Watch method adds the given paths on the Watcher +func (h *Blueprint) Run() error { + err := h.Read() + if err == nil { + // loop projects + wg.Add(len(h.Projects)) + for k := range h.Projects { + go h.Projects[k].watching() + } + wg.Wait() + return nil + } + return err +} + +// Fast method run a project from his working directory without makes a config file +func (h *Blueprint) Fast(params *cli.Context) error { + fast := h.Projects[0] + // Takes the values from config if wd path match with someone else + if params.Bool("config") { + if err := h.Read(); err == nil { + for _, val := range h.Projects { + if fast.Path == val.Path { + fast = val + } + } + } + } + wg.Add(1) + go fast.watching() + wg.Wait() + return nil +} + +// Add a new project +func (h *Blueprint) Add(params *cli.Context) error { + p := Project{ + Name: nameFlag(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), + Watcher: Watcher{ + Paths: []string{"/"}, + Ignore: []string{"vendor"}, + Exts: []string{".go"}, + Output: map[string]bool{ + "cli": true, + "file": false, + }, + }, + } + if _, err := duplicates(p, h.Projects); err != nil { + return err + } + h.Projects = append(h.Projects, p) + return nil +} + +// Clean duplicate projects +func (h *Blueprint) Clean() { + arr := h.Projects + for key, val := range arr { + if _, err := duplicates(val, arr[key+1:]); err != nil { + h.Projects = append(arr[:key], arr[key+1:]...) + break + } + } +} + +// Read, Check and remove duplicates from the config file +func (h *Blueprint) Read() error { + content, err := read(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 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")) + } + } + 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 + } + } + return errors.New("No project found") + } + return err +} + +// List of all the projects +func (h *Blueprint) List() error { + err := h.Read() + 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"])) + } + } + return err +} diff --git a/realize/config.go b/realize/config.go deleted file mode 100644 index 726a0ff..0000000 --- a/realize/config.go +++ /dev/null @@ -1,219 +0,0 @@ -package realize - -import ( - "errors" - "fmt" - "gopkg.in/urfave/cli.v2" - "gopkg.in/yaml.v2" - "io/ioutil" - "log" - "os" - "path/filepath" - "strings" -) - -// Config struct contains the general informations about a project -type Config struct { - file string - Version string `yaml:"version,omitempty"` - Projects []Project -} - -// New method puts the cli params in the struct -func New(params *cli.Context) *Config { - return &Config{ - file: AppFile, - Version: AppVersion, - Projects: []Project{ - { - Name: nameFlag(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), - Watcher: Watcher{ - Paths: watcherPaths, - Ignore: watcherIgnores, - Exts: watcherExts, - }, - }, - }, - } -} - -// argsParam parse one by one the given argumentes -func argsParam(params *cli.Context) []string { - argsN := params.NArg() - if argsN > 0 { - var args []string - for i := 0; i <= argsN-1; i++ { - args = append(args, params.Args().Get(i)) - } - return args - } - return nil -} - -// NameParam check the project name presence. If empty takes the working directory name -func nameFlag(params *cli.Context) string { - var name string - if params.String("name") == "" && params.String("path") == "" { - return WorkingDir() - } else if params.String("path") != "/" { - name = filepath.Base(params.String("path")) - } else { - name = params.String("name") - } - return name -} - -// BoolParam is used to check the presence of a bool flag -func boolFlag(b bool) bool { - if b { - return false - } - return true -} - -// WorkingDir returns the last element of the working dir path -func WorkingDir() string { - dir, err := os.Getwd() - if err != nil { - log.Fatal(Red(err)) - } - return filepath.Base(dir) -} - -// Duplicates check projects with same name or same combinations of main/path -func Duplicates(value Project, arr []Project) (Project, error) { - for _, val := range arr { - if value.Path == val.Path || value.Name == val.Name { - return val, errors.New("There is a duplicate of '" + val.Name + "'. Check your config file!") - } - } - return Project{}, nil -} - -// Clean duplicate projects -func (h *Config) Clean() { - arr := h.Projects - for key, val := range arr { - if _, err := Duplicates(val, arr[key+1:]); err != nil { - h.Projects = append(arr[:key], arr[key+1:]...) - break - } - } -} - -// Read, Check and remove duplicates from the config file -func (h *Config) Read() error { - _, err := os.Stat(h.file) - if err == nil { - file, err := ioutil.ReadFile(h.file) - if err == nil { - if len(h.Projects) > 0 { - err = yaml.Unmarshal(file, h) - if err == nil { - h.Clean() - } - return err - } - return errors.New("There are no projects") - } - return h.Create() - } - return err -} - -// Create and unmarshal yaml config file -func (h *Config) Create() error { - y, err := yaml.Marshal(h) - if err != nil { - return err - } - return ioutil.WriteFile(h.file, y, 0655) -} - -// Add another project -func (h *Config) Add(params *cli.Context) error { - err := h.Read() - if err == nil { - new := Project{ - Name: nameFlag(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), - Watcher: Watcher{ - Paths: watcherPaths, - Exts: watcherExts, - Ignore: watcherIgnores, - }, - } - if _, err := Duplicates(new, h.Projects); err != nil { - return err - } - h.Projects = append(h.Projects, new) - err = h.Create() - if err == nil { - fmt.Println(Green("Your project was successfully added")) - } - return err - } - err = h.Create() - if err == nil { - fmt.Println(Green("The config file was successfully created")) - } - return err -} - -// Remove a project in list -func (h *Config) 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 - } - } - return errors.New("No project found") - } - return err -} - -// List of projects -func (h *Config) List() error { - err := h.Read() - 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)) - } - return nil - } - return err -} diff --git a/realize/project.go b/realize/execute.go similarity index 81% rename from realize/project.go rename to realize/execute.go index de1896e..aded846 100644 --- a/realize/project.go +++ b/realize/execute.go @@ -12,21 +12,6 @@ import ( "time" ) -// The Project struct defines the informations about a project -type Project struct { - reload time.Time - 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"` -} - // GoRun is an implementation of the bin execution func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) error { @@ -51,7 +36,6 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) // Read stdout and stderr in same var outputs := io.MultiReader(stdout, stderr) - if err != nil { log.Println(Red(err.Error())) return err @@ -67,7 +51,17 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) for in.Scan() { select { default: - log.Println(pname(p.Name, 3), ":", BlueS(in.Text())) + if p.Watcher.Output["cli"] { + log.Println(pname(p.Name, 3), ":", BlueS(in.Text())) + } + if p.Watcher.Output["file"] { + path := filepath.Join(p.base, App.Blueprint.files["output"]) + f := create(path) + t := time.Now() + if _, err := f.WriteString(t.Format("2006-01-02 15:04:05") + " : " + in.Text() + "\r\n"); err != nil { + log.Fatal(err) + } + } } } close(stop) diff --git a/realize/utils.go b/realize/utils.go new file mode 100644 index 0000000..b0a7ea3 --- /dev/null +++ b/realize/utils.go @@ -0,0 +1,130 @@ +package realize + +import ( + "errors" + "fmt" + "gopkg.in/urfave/cli.v2" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" + "time" +) + +// Read a file given a name and return its byte stream +func read(file string) ([]byte, error) { + _, err := os.Stat(file) + if err == nil { + content, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + return content, err + } + return nil, err + +} + +// Write a file given a name and a byte stream +func write(name string, data []byte) error { + err := ioutil.WriteFile(name, data, 0655) + if err != nil { + log.Fatal(err) + return err + } + return nil +} + +// Create a new file and return its pointer +func create(file string) *os.File { + out, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0655) + if err != nil { + log.Fatal(err) + } + return out +} + +// argsParam parse one by one the given argumentes +func argsParam(params *cli.Context) []string { + argsN := params.NArg() + if argsN > 0 { + var args []string + for i := 0; i <= argsN-1; i++ { + args = append(args, params.Args().Get(i)) + } + return args + } + return nil +} + +// NameParam check the project name presence. If empty takes the working directory name +func nameFlag(params *cli.Context) string { + var name string + if params.String("name") == "" && params.String("path") == "" { + return App.Wdir() + } else if params.String("path") != "/" { + name = filepath.Base(params.String("path")) + } else { + name = params.String("name") + } + return name +} + +// BoolParam is used to check the presence of a bool flag +func boolFlag(b bool) bool { + if b { + return false + } + return true +} + +// Duplicates check projects with same name or same combinations of main/path +func duplicates(value Project, arr []Project) (Project, error) { + for _, val := range arr { + if value.Path == val.Path || value.Name == val.Name { + return val, errors.New("There is a duplicate of '" + val.Name + "'. Check your config file!") + } + } + return Project{}, nil +} + +// check if a string is inArray +func inArray(str string, list []string) bool { + for _, v := range list { + if v == str { + return true + } + } + 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 +} + +// Log struct +type logWriter struct{} + +// 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)) +} diff --git a/realize/watcher.go b/realize/watcher.go index 343633b..6e8df4f 100644 --- a/realize/watcher.go +++ b/realize/watcher.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "github.com/fsnotify/fsnotify" - "gopkg.in/urfave/cli.v2" "log" "math/big" "os" @@ -17,46 +16,13 @@ import ( // The Watcher struct defines the livereload's logic type Watcher struct { // different before and after on re-run? - Before []string `yaml:"before,omitempty"` - After []string `yaml:"after,omitempty"` - Paths []string `yaml:"paths,omitempty"` - Ignore []string `yaml:"ignore_paths,omitempty"` - Exts []string `yaml:"exts,omitempty"` - Preview bool `yaml:"preview,omitempty"` -} - -// Watch method adds the given paths on the Watcher -func (h *Config) Watch() error { - err := h.Read() - if err == nil { - // loop projects - wg.Add(len(h.Projects)) - for k := range h.Projects { - go h.Projects[k].watching() - } - wg.Wait() - return nil - } - return err -} - -// Fast method run a project from his working directory without makes a config file -func (h *Config) Fast(params *cli.Context) error { - fast := h.Projects[0] - // Takes the values from config if wd path match with someone else - if params.Bool("config") { - if err := h.Read(); err == nil { - for _, val := range h.Projects { - if fast.Path == val.Path { - fast = val - } - } - } - } - wg.Add(1) - go fast.watching() - wg.Wait() - return nil + Before []string `yaml:"before,omitempty"` + After []string `yaml:"after,omitempty"` + Paths []string `yaml:"paths,omitempty"` + Ignore []string `yaml:"ignore_paths,omitempty"` + Exts []string `yaml:"exts,omitempty"` + Preview bool `yaml:"preview,omitempty"` + Output map[string]bool `yaml:"output,omitempty"` } // Watching method is the main core. It manages the livereload and the watching @@ -84,7 +50,7 @@ func (p *Project) watching() { fmt.Println(pname(p.Name, 1), ":", Red(err.Error())) return } - go routines(p, channel, &wr) + go p.routines(channel, &wr) p.reload = time.Now().Truncate(time.Second) // waiting for an event @@ -117,7 +83,7 @@ func (p *Project) watching() { if err != nil { log.Fatal(Red(err)) } else { - go routines(p, channel, &wr) + go p.routines(channel, &wr) p.reload = time.Now().Truncate(time.Second) } } @@ -230,7 +196,7 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error { if p.Path == "." || p.Path == "/" { p.base = wd - p.Path = WorkingDir() + p.Path = App.Wdir() } else if filepath.IsAbs(p.Path) { p.base = p.Path } else { @@ -247,7 +213,7 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error { return errors.New(base + " path doesn't exist") } } - fmt.Println(Red("Watching: "), pname(p.Name, 1), Magenta(files), "file/s", Magenta(folders), "folder/s") + fmt.Println(Red("Watching"), ":", pname(p.Name, 1), Magenta(files), "file/s", Magenta(folders), "folder/s") return nil } @@ -262,41 +228,9 @@ func (p *Project) ignore(str string) bool { } // Routines launches the following methods: run, build, fmt, install -func routines(p *Project, channel chan bool, wr *sync.WaitGroup) { +func (p *Project) routines(channel chan bool, wr *sync.WaitGroup) { wr.Add(1) go p.build() go p.install(channel, wr) wr.Wait() } - -// check if a string is inArray -func inArray(str string, list []string) bool { - for _, v := range list { - if v == str { - return true - } - } - 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 -}