code optimization

This commit is contained in:
alessio 2016-11-01 10:56:12 +01:00
parent 69f164ca76
commit efcd13f232
16 changed files with 512 additions and 490 deletions

View File

@ -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
}

View File

@ -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()

View File

@ -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())
}

View File

@ -1,41 +1,133 @@
package main package main
import ( 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" "gopkg.in/urfave/cli.v2"
"os" "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() { func main() {
c := &cli.App{ c := &cli.App{
Name: a.Name, Name: r.Name,
Version: a.Version, Version: r.Version,
Authors: []*cli.Author{ Authors: []*cli.Author{
{ {
Name: "Alessio Pracchia", Name: "Alessio Pracchia",
Email: "pracchia@hastega.it", Email: "pracchia@hastegit",
}, },
{ {
Name: "Daniele Conventi", Name: "Daniele Conventi",
Email: "conventi@hastega.it", Email: "conventi@hastegit",
}, },
}, },
Usage: a.Description, Usage: r.Description,
Commands: []*cli.Command{ Commands: []*cli.Command{
{ {
Name: "run", Name: "run",
Usage: "Build and watch file changes", Usage: "Build and watch file changes",
Flags: []cli.Flag{ 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"}, &cli.BoolFlag{Name: "open", Usage: "Automatically opens the web panel"},
}, },
Action: func(p *cli.Context) error { 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 { 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."}, &cli.BoolFlag{Name: "config", Value: false, Usage: "Take the defined settings if exist a Configuration file."},
}, },
Action: func(p *cli.Context) error { 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 { Before: func(c *cli.Context) error {
return app.Before(c) return before()
}, },
}, },
{ {
@ -65,7 +163,7 @@ func main() {
Aliases: []string{"a"}, Aliases: []string{"a"},
Usage: "Add another project", Usage: "Add another project",
Flags: []cli.Flag{ 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.StringFlag{Name: "path", Aliases: []string{"b"}, Value: "/", Usage: "Project base path"},
&cli.BoolFlag{Name: "build", Value: false, Usage: "Enable the build"}, &cli.BoolFlag{Name: "build", Value: false, Usage: "Enable the build"},
&cli.BoolFlag{Name: "no-run", Usage: "Disables the run"}, &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: "no-fmt", Usage: "Disables the fmt (go fmt)"},
&cli.BoolFlag{Name: "test", Value: false, Usage: "Enables the tests"}, &cli.BoolFlag{Name: "test", Value: false, Usage: "Enables the tests"},
}, },
Action: func(p *cli.Context) error { Action: func(p *cli.Context) (err error) {
return app.Handle(app.Add(p)) 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 { 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: ""}, &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: ""},
}, },
Action: func(p *cli.Context) error { 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 { Before: func(c *cli.Context) error {
return app.Before(c) return before()
}, },
}, },
{ {
@ -101,10 +205,10 @@ func main() {
Aliases: []string{"l"}, Aliases: []string{"l"},
Usage: "Projects list", Usage: "Projects list",
Action: func(p *cli.Context) error { Action: func(p *cli.Context) error {
return app.Handle(app.List(p)) return handle(r.Blueprint.List())
}, },
Before: func(c *cli.Context) error { Before: func(c *cli.Context) error {
return app.Before(c) return before()
}, },
}, },
}, },

View File

@ -413,20 +413,20 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name. // _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){ var _bindata = map[string]func() (*asset, error){
"assets/app/components/index.html": assetsAppComponentsIndexHtml, "assets/app/components/index.html": assetsAppComponentsIndexHtml,
"assets/app/components/project/index.html": assetsAppComponentsProjectIndexHtml, "assets/app/components/project/index.html": assetsAppComponentsProjectIndexHtml,
"assets/app/components/projects/index.html": assetsAppComponentsProjectsIndexHtml, "assets/app/components/projects/index.html": assetsAppComponentsProjectsIndexHtml,
"assets/assets/css/app.css": assetsAssetsCssAppCss, "assets/assets/css/app.css": assetsAssetsCssAppCss,
"assets/assets/img/svg/github-logo.svg": assetsAssetsImgSvgGithubLogoSvg, "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_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_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_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_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_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/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.js": assetsAssetsJsAllJs,
"assets/assets/js/all.min.js": assetsAssetsJsAllMinJs, "assets/assets/js/all.min.js": assetsAssetsJsAllMinJs,
"assets/index.html": assetsIndexHtml, "assets/index.html": assetsIndexHtml,
} }
// AssetDir returns the file names below a certain // AssetDir returns the file names below a certain
@ -468,40 +468,41 @@ type bintree struct {
Func func() (*asset, error) Func func() (*asset, error)
Children map[string]*bintree Children map[string]*bintree
} }
var _bintree = &bintree{nil, map[string]*bintree{ var _bintree = &bintree{nil, map[string]*bintree{
"assets": &bintree{nil, map[string]*bintree{ "assets": {nil, map[string]*bintree{
"app": &bintree{nil, map[string]*bintree{ "app": {nil, map[string]*bintree{
"components": &bintree{nil, map[string]*bintree{ "components": {nil, map[string]*bintree{
"index.html": &bintree{assetsAppComponentsIndexHtml, map[string]*bintree{}}, "index.html": {assetsAppComponentsIndexHtml, map[string]*bintree{}},
"project": &bintree{nil, map[string]*bintree{ "project": {nil, map[string]*bintree{
"index.html": &bintree{assetsAppComponentsProjectIndexHtml, map[string]*bintree{}}, "index.html": {assetsAppComponentsProjectIndexHtml, map[string]*bintree{}},
}}, }},
"projects": &bintree{nil, map[string]*bintree{ "projects": {nil, map[string]*bintree{
"index.html": &bintree{assetsAppComponentsProjectsIndexHtml, map[string]*bintree{}}, "index.html": {assetsAppComponentsProjectsIndexHtml, map[string]*bintree{}},
}}, }},
}}, }},
}}, }},
"assets": &bintree{nil, map[string]*bintree{ "assets": {nil, map[string]*bintree{
"css": &bintree{nil, map[string]*bintree{ "css": {nil, map[string]*bintree{
"app.css": &bintree{assetsAssetsCssAppCss, map[string]*bintree{}}, "app.css": {assetsAssetsCssAppCss, map[string]*bintree{}},
}}, }},
"img": &bintree{nil, map[string]*bintree{ "img": {nil, map[string]*bintree{
"svg": &bintree{nil, map[string]*bintree{ "svg": {nil, map[string]*bintree{
"github-logo.svg": &bintree{assetsAssetsImgSvgGithubLogoSvg, map[string]*bintree{}}, "github-logo.svg": {assetsAssetsImgSvgGithubLogoSvg, map[string]*bintree{}},
"ic_cached_black_48px.svg": &bintree{assetsAssetsImgSvgIc_cached_black_48pxSvg, map[string]*bintree{}}, "ic_cached_black_48px.svg": {assetsAssetsImgSvgIc_cached_black_48pxSvg, map[string]*bintree{}},
"ic_delete_sweep_black_48px.svg": &bintree{assetsAssetsImgSvgIc_delete_sweep_black_48pxSvg, map[string]*bintree{}}, "ic_delete_sweep_black_48px.svg": {assetsAssetsImgSvgIc_delete_sweep_black_48pxSvg, map[string]*bintree{}},
"ic_error_black_48px.svg": &bintree{assetsAssetsImgSvgIc_error_black_48pxSvg, map[string]*bintree{}}, "ic_error_black_48px.svg": {assetsAssetsImgSvgIc_error_black_48pxSvg, map[string]*bintree{}},
"ic_file_download_black_48px.svg": &bintree{assetsAssetsImgSvgIc_file_download_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": &bintree{assetsAssetsImgSvgIc_more_vert_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": &bintree{assetsAssetsImgSvgIc_swap_vertical_circle_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{ "js": {nil, map[string]*bintree{
"all.js": &bintree{assetsAssetsJsAllJs, map[string]*bintree{}}, "all.js": {assetsAssetsJsAllJs, map[string]*bintree{}},
"all.min.js": &bintree{assetsAssetsJsAllMinJs, 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) cannonicalName := strings.Replace(name, "\\", "/", -1)
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
} }

View File

@ -5,18 +5,20 @@ import (
"github.com/labstack/echo" "github.com/labstack/echo"
"github.com/labstack/echo/engine/standard" "github.com/labstack/echo/engine/standard"
"github.com/labstack/echo/middleware" "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" "golang.org/x/net/websocket"
"log" "log"
"net/http" "net/http"
"strconv"
"gopkg.in/urfave/cli.v2"
) )
// Server struct contains server informations // Server struct contains server informations
type Server struct { type Server struct {
Blueprint *c.Blueprint *c.Settings `yaml:"-"`
Files map[string]string *w.Blueprint `yaml:"-"`
Sync chan string Sync chan string `yaml:"-"`
Open bool
} }
func render(c echo.Context, path string, mime int) error { 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 // Server starting
func (s *Server) Start() { func (s *Server) Start(p *cli.Context) (err error) {
e := echo.New() if !p.Bool("no-server") && s.Enabled {
e.Use(middleware.Gzip()) e := echo.New()
e.Use(middleware.Gzip())
// web panel // web panel
e.GET("/", func(c echo.Context) error { e.GET("/", func(c echo.Context) error {
return render(c, "assets/index.html", 1) return render(c, "assets/index.html", 1)
}) })
e.GET("/assets/js/all.min.js", func(c echo.Context) error { e.GET("/assets/js/all.min.js", func(c echo.Context) error {
return render(c, "assets/assets/js/all.min.js", 2) return render(c, "assets/assets/js/all.min.js", 2)
}) })
e.GET("/assets/css/app.css", func(c echo.Context) error { e.GET("/assets/css/app.css", func(c echo.Context) error {
return render(c, "assets/assets/css/app.css", 3) return render(c, "assets/assets/css/app.css", 3)
}) })
e.GET("/app/components/projects/index.html", func(c echo.Context) error { e.GET("/app/components/projects/index.html", func(c echo.Context) error {
return render(c, "assets/app/components/projects/index.html", 1) return render(c, "assets/app/components/projects/index.html", 1)
}) })
e.GET("/app/components/project/index.html", func(c echo.Context) error { e.GET("/app/components/project/index.html", func(c echo.Context) error {
return render(c, "assets/app/components/project/index.html", 1) return render(c, "assets/app/components/project/index.html", 1)
}) })
e.GET("/app/components/index.html", func(c echo.Context) error { e.GET("/app/components/index.html", func(c echo.Context) error {
return render(c, "assets/app/components/index.html", 1) return render(c, "assets/app/components/index.html", 1)
}) })
e.GET("/assets/img/svg/github-logo.svg", func(c echo.Context) error { e.GET("/assets/img/svg/github-logo.svg", func(c echo.Context) error {
return render(c, "assets/assets/img/svg/github-logo.svg", 4) 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 { 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) 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 { 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) return render(c, "assets/assets/img/svg/ic_swap_vertical_circle_black_48px.svg", 4)
}) })
//websocket //websocket
//e.GET("/ws", standard.WrapHandler(s.projects())) e.GET("/ws", standard.WrapHandler(s.projects()))
e.GET("/ws", standard.WrapHandler(s.projects()))
go e.Run(standard.New(":5000")) go e.Run(standard.New(string(s.Settings.Server.Host) + ":" + strconv.Itoa(s.Settings.Server.Port)))
if s.Open { if s.Open || p.Bool("open") {
Open("http://localhost:5000") _, 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 // The WebSocket for projects list

View File

@ -3,17 +3,16 @@ package server
import ( import (
"bytes" "bytes"
"errors" "errors"
"fmt"
"io" "io"
"os/exec" "os/exec"
"runtime" "runtime"
) )
var cli map[string]string var cmd map[string]string
var stderr bytes.Buffer var stderr bytes.Buffer
func init() { func init() {
cli = map[string]string{ cmd = map[string]string{
"windows": "start", "windows": "start",
"darwin": "open", "darwin": "open",
"linux": "xdg-open", "linux": "xdg-open",
@ -21,13 +20,12 @@ func init() {
} }
func Open(url string) (io.Writer, error) { 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.") return nil, errors.New("This operating system is not supported.")
} else { } else {
cmd := exec.Command(open, url) cmd := exec.Command(open, url)
cmd.Stderr = &stderr cmd.Stderr = &stderr
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
fmt.Println(cmd.Stderr, err)
return cmd.Stderr, err return cmd.Stderr, err
} }
} }

68
settings/colors.go Normal file
View File

@ -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...)
}

View File

@ -1,4 +1,4 @@
package config package settings
import ( import (
"io/ioutil" "io/ioutil"
@ -6,25 +6,25 @@ import (
) )
// Scan return a byte stream of a given file // 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) _, err := os.Stat(file)
if err == nil { if err == nil {
content, err := ioutil.ReadFile(file) content, err := ioutil.ReadFile(file)
c.Validate(err) s.Validate(err)
return content, err return content, err
} }
return nil, err return nil, err
} }
// Write a file given a name and a byte stream // 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) err := ioutil.WriteFile(name, data, 0655)
return c.Validate(err) return s.Validate(err)
} }
// Create a new file and return its pointer // 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) 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 return out
} }

59
settings/settings.go Normal file
View File

@ -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)
}

27
settings/utils.go Normal file
View File

@ -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())
}

View File

@ -4,14 +4,13 @@ import (
"errors" "errors"
"fmt" "fmt"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"gopkg.in/yaml.v2"
"path/filepath" "path/filepath"
"strings" "strings"
) )
// Watch method adds the given paths on the Watcher // Watch method adds the given paths on the Watcher
func (h *Blueprint) Run() error { func (h *Blueprint) Run() error {
err := h.Read() err := h.check()
if err == nil { if err == nil {
// loop projects // loop projects
wg.Add(len(h.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 // 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 // Takes the values from config if wd path match with someone else
wg.Add(1) wg.Add(1)
for i := 0; i < len(h.Projects); i++ { for i := 0; i < len(h.Projects); i++ {
v := &h.Projects[i] v := &h.Projects[i]
v.parent = h v.parent = h
if params.Bool("config") { v.path = v.Path
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
}
}
}
}
go v.watching() go v.watching()
} }
wg.Wait() wg.Wait()
@ -53,16 +39,16 @@ func (h *Blueprint) Fast(params *cli.Context) error {
} }
// Add a new project // Add a new project
func (h *Blueprint) Add(params *cli.Context) error { func (h *Blueprint) Add(p *cli.Context) error {
p := Project{ project := Project{
Name: h.name(params), Name: h.name(p),
Path: filepath.Clean(params.String("path")), Path: filepath.Clean(p.String("path")),
Build: params.Bool("build"), Build: p.Bool("build"),
Bin: boolFlag(params.Bool("no-bin")), Bin: boolFlag(p.Bool("no-bin")),
Run: boolFlag(params.Bool("no-run")), Run: boolFlag(p.Bool("no-run")),
Fmt: boolFlag(params.Bool("no-fmt")), Fmt: boolFlag(p.Bool("no-fmt")),
Test: params.Bool("test"), Test: p.Bool("test"),
Params: argsParam(params), Params: argsParam(p),
Watcher: Watcher{ Watcher: Watcher{
Paths: []string{"/"}, Paths: []string{"/"},
Ignore: []string{"vendor"}, 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 return err
} }
h.Projects = append(h.Projects, p) h.Projects = append(h.Projects, project)
return nil 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 // Inserts a new project in the list
func (h *Blueprint) Insert(params *cli.Context) error { func (h *Blueprint) Insert(p *cli.Context) error {
check := h.Read() err := h.Add(p)
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 return err
} }
// Remove a project // Remove a project
func (h *Blueprint) Remove(params *cli.Context) error { func (h *Blueprint) Remove(p *cli.Context) error {
err := h.Read() for key, val := range h.Projects {
if err == nil { if p.String("name") == val.Name {
for key, val := range h.Projects { h.Projects = append(h.Projects[:key], h.Projects[key+1:]...)
if params.String("name") == val.Name { return nil
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 return errors.New("No project found.")
} }
// List of all the projects // List of all the projects
func (h *Blueprint) List() error { func (h *Blueprint) List() error {
err := h.Read() err := h.check()
if err == nil { if err == nil {
for _, val := range h.Projects { for _, val := range h.Projects {
fmt.Println(Blue("|"), Blue(strings.ToUpper(val.Name))) fmt.Println(h.Blue.Bold("|"), h.Blue.Bold(strings.ToUpper(val.Name)))
fmt.Println(MagentaS("|"), "\t", Yellow("Base Path"), ":", MagentaS(val.Path)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Base Path"), ":", h.Magenta.Regular(val.Path))
fmt.Println(MagentaS("|"), "\t", Yellow("Run"), ":", MagentaS(val.Run)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Run"), ":", h.Magenta.Regular(val.Run))
fmt.Println(MagentaS("|"), "\t", Yellow("Build"), ":", MagentaS(val.Build)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Build"), ":", h.Magenta.Regular(val.Build))
fmt.Println(MagentaS("|"), "\t", Yellow("Install"), ":", MagentaS(val.Bin)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Install"), ":", h.Magenta.Regular(val.Bin))
fmt.Println(MagentaS("|"), "\t", Yellow("Fmt"), ":", MagentaS(val.Fmt)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Fmt"), ":", h.Magenta.Regular(val.Fmt))
fmt.Println(MagentaS("|"), "\t", Yellow("Test"), ":", MagentaS(val.Test)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Test"), ":", h.Magenta.Regular(val.Test))
fmt.Println(MagentaS("|"), "\t", Yellow("Params"), ":", MagentaS(val.Params)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Params"), ":", h.Magenta.Regular(val.Params))
fmt.Println(MagentaS("|"), "\t", Yellow("Watcher"), ":") fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Watcher"), ":")
fmt.Println(MagentaS("|"), "\t\t", Yellow("After"), ":", MagentaS(val.Watcher.After)) fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("After"), ":", h.Magenta.Regular(val.Watcher.After))
fmt.Println(MagentaS("|"), "\t\t", Yellow("Before"), ":", MagentaS(val.Watcher.Before)) fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Before"), ":", h.Magenta.Regular(val.Watcher.Before))
fmt.Println(MagentaS("|"), "\t\t", Yellow("Extensions"), ":", MagentaS(val.Watcher.Exts)) fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Extensions"), ":", h.Magenta.Regular(val.Watcher.Exts))
fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths"), ":", MagentaS(val.Watcher.Paths)) fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Paths"), ":", h.Magenta.Regular(val.Watcher.Paths))
fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths ignored"), ":", MagentaS(val.Watcher.Ignore)) fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Paths ignored"), ":", h.Magenta.Regular(val.Watcher.Ignore))
fmt.Println(MagentaS("|"), "\t\t", Yellow("Watch preview"), ":", MagentaS(val.Watcher.Preview)) fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Watch preview"), ":", h.Magenta.Regular(val.Watcher.Preview))
fmt.Println(MagentaS("|"), "\t\t", Yellow("Output"), ":") fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Output"), ":")
fmt.Println(MagentaS("|"), "\t\t\t", Yellow("Cli"), ":", MagentaS(val.Watcher.Output["cli"])) fmt.Println(h.Magenta.Regular("|"), "\t\t\t", h.Yellow.Regular("Cli"), ":", h.Magenta.Regular(val.Watcher.Output["cli"]))
fmt.Println(MagentaS("|"), "\t\t\t", Yellow("File"), ":", MagentaS(val.Watcher.Output["file"])) fmt.Println(h.Magenta.Regular("|"), "\t\t\t", h.Yellow.Regular("File"), ":", h.Magenta.Regular(val.Watcher.Output["file"]))
} }
return nil
} }
return err return err
} }
// NameParam check the project name presence. If empty takes the working directory name // Check if there are projects
func (p *Blueprint) name(params *cli.Context) string { func (h *Blueprint) check() error {
var name string if len(h.Projects) > 0 {
if params.String("name") == "" && params.String("path") == "" { h.Clean()
return p.Wdir() return nil
} else if params.String("path") != "/" {
name = filepath.Base(params.String("path"))
} else { } 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 return name
} }

View File

@ -16,15 +16,14 @@ import (
// GoRun is an implementation of the bin execution // GoRun is an implementation of the bin execution
func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) error { func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) error {
var build *exec.Cmd
sync := func() { sync := func() {
p.parent.Sync <- "sync" p.parent.Sync <- "sync"
} }
var build *exec.Cmd
if len(p.Params) != 0 { 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 { } 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 build.Dir = p.base
defer func() { 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.Fatal("Failed to stop:", err)
} }
p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: "Ended"}) 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() go sync()
wr.Done() wr.Done()
}() }()
@ -42,11 +41,11 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
stderr, err := build.StderrPipe() stderr, err := build.StderrPipe()
if err != nil { if err != nil {
log.Println(Red(err.Error())) log.Println(p.Red.Bold(err.Error()))
return err return err
} }
if err := build.Start(); err != nil { if err := build.Start(); err != nil {
log.Println(Red(err.Error())) log.Println(p.Red.Bold(err.Error()))
return err return err
} }
close(runner) close(runner)
@ -66,10 +65,10 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
go sync() go sync()
if p.Watcher.Output["cli"] { 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"] { 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) f := p.Create(path)
t := time.Now() t := time.Now()
if _, err := f.WriteString(t.Format("2006-01-02 15:04:05") + " : " + output.Text() + "\r\n"); err != nil { if _, err := f.WriteString(t.Format("2006-01-02 15:04:05") + " : " + output.Text() + "\r\n"); err != nil {

View File

@ -1,8 +1,7 @@
package cli package cli
import ( import (
"github.com/fatih/color" c "github.com/tockins/realize/settings"
c "github.com/tockins/realize/config"
"log" "log"
"sync" "sync"
"time" "time"
@ -10,43 +9,35 @@ import (
var wg sync.WaitGroup 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 // Log struct
type logWriter struct{} type logWriter struct {
c.Colors
}
// Projects struct contains a projects list // Projects struct contains a projects list
type Blueprint struct { type Blueprint struct {
c.Config *c.Settings `yaml:"-"`
Projects []Project `yaml:"projects,omitempty"` Projects []Project `yaml:"projects,omitempty"`
Files map[string]string `yaml:"-"` Sync chan string `yaml:"-"`
Sync chan string `yaml:"-"`
} }
// Project defines the informations of a single project // Project defines the informations of a single project
type Project struct { type Project struct {
c.Config c.Settings `yaml:"-"`
LastChangedOn time.Time `yaml:"-"` LastChangedOn time.Time `yaml:"-"`
base string base string
Name string `yaml:"app_name,omitempty"` Name string `yaml:"name,omitempty"`
Path string `yaml:"app_path,omitempty"` Path string `yaml:"path,omitempty"`
Run bool `yaml:"app_run,omitempty"` Run bool `yaml:"run,omitempty"`
Bin bool `yaml:"app_bin,omitempty"` Bin bool `yaml:"bin,omitempty"`
Build bool `yaml:"app_build,omitempty"` Build bool `yaml:"build,omitempty"`
Fmt bool `yaml:"app_fmt,omitempty"` Fmt bool `yaml:"fmt,omitempty"`
Test bool `yaml:"app_test,omitempty"` Test bool `yaml:"test,omitempty"`
Params []string `yaml:"app_params,omitempty"` Params []string `yaml:"params,omitempty"`
Watcher Watcher `yaml:"app_watcher,omitempty"` Watcher Watcher `yaml:"watcher,omitempty"`
Buffer Buffer `yaml:"-"` Buffer Buffer `yaml:"-"`
parent *Blueprint parent *Blueprint
path string
} }
// Watcher struct defines the livereload's logic // Watcher struct defines the livereload's logic

View File

@ -4,7 +4,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"strings"
"time" "time"
) )
@ -49,29 +48,7 @@ func inArray(str string, list []string) bool {
return false 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 // Cewrites the log timestamp
func (writer logWriter) Write(bytes []byte) (int, error) { func (w logWriter) Write(bytes []byte) (int, error) {
return fmt.Print(YellowS("[") + time.Now().Format("15:04:05") + YellowS("]") + string(bytes)) return fmt.Print(w.Yellow.Regular("[") + time.Now().Format("15:04:05") + w.Yellow.Regular("]") + string(bytes))
} }

View File

@ -19,29 +19,28 @@ import (
func (p *Project) watching() { func (p *Project) watching() {
var wr sync.WaitGroup var wr sync.WaitGroup
var watcher *fsnotify.Watcher var watcher *fsnotify.Watcher
sync := func() { sync := func() {
p.parent.Sync <- "sync" p.parent.Sync <- "sync"
} }
watcher, err := fsnotify.NewWatcher() watcher, err := fsnotify.NewWatcher()
if err != nil { 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) channel, exit := make(chan bool, 1), make(chan bool, 1)
if err != nil { 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() { end := func() {
watcher.Close() watcher.Close()
wg.Done() wg.Done()
} }
defer end() defer end()
p.path = p.Path
p.cmd(exit) p.cmd(exit)
err = p.walks(watcher) err = p.walks(watcher)
if err != nil { 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 return
} }
@ -69,7 +68,7 @@ func (p *Project) watching() {
if event.Name[:i] != "" && inArray(ext, p.Watcher.Exts) { 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}) p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + event.Name[:i] + ext})
go sync() 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 // stop and run again
if p.Run { if p.Run {
close(channel) close(channel)
@ -87,7 +86,7 @@ func (p *Project) watching() {
} }
} }
case err := <-watcher.Errors: case err := <-watcher.Errors:
log.Println(Red(err.Error())) log.Println(p.Red.Bold(err.Error()))
case <-exit: case <-exit:
return return
} }
@ -97,22 +96,22 @@ func (p *Project) watching() {
// Install calls an implementation of the "go install" // Install calls an implementation of the "go install"
func (p *Project) install(channel chan bool, wr *sync.WaitGroup) { func (p *Project) install(channel chan bool, wr *sync.WaitGroup) {
if p.Bin { if p.Bin {
log.Println(pname(p.Name, 1), ":", "Installing..") log.Println(p.pname(p.Name, 1), ":", "Installing..")
start := time.Now() start := time.Now()
if std, err := p.GoInstall(); err != nil { 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() wr.Done()
} else { } 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 { if p.Run {
runner := make(chan bool, 1) runner := make(chan bool, 1)
log.Println(pname(p.Name, 1), ":", "Running..") log.Println(p.pname(p.Name, 1), ":", "Running..")
start = time.Now() start = time.Now()
go p.GoRun(channel, runner, wr) go p.GoRun(channel, runner, wr)
for { for {
select { select {
case <-runner: 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 return
} }
} }
@ -125,12 +124,12 @@ func (p *Project) install(channel chan bool, wr *sync.WaitGroup) {
// Build calls an implementation of the "go build" // Build calls an implementation of the "go build"
func (p *Project) build() { func (p *Project) build() {
if p.Build { if p.Build {
log.Println(pname(p.Name, 1), ":", "Building..") log.Println(p.pname(p.Name, 1), ":", "Building..")
start := time.Now() start := time.Now()
if std, err := p.GoBuild(); err != nil { 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 { } 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 return
} }
@ -141,7 +140,7 @@ func (p *Project) build() {
func (p *Project) fmt(path string) error { func (p *Project) fmt(path string) error {
if p.Fmt { if p.Fmt {
if _, err := p.GoFmt(path); err != nil { 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 return nil
@ -154,7 +153,7 @@ func (p *Project) cmd(exit chan bool) {
cast := func(commands []string) { cast := func(commands []string) {
if errs := p.Cmd(commands); errs != nil { if errs := p.Cmd(commands); errs != nil {
for _, err := range errs { 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 { func (p *Project) test(path string) error {
if p.Test { if p.Test {
if _, err := p.GoTest(path); err != nil { 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 return nil
@ -195,7 +194,7 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error {
if !p.ignore(path) { 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 (info.IsDir() && len(filepath.Ext(path)) == 0 && !strings.HasPrefix(path, ".")) && !strings.Contains(path, "/.") || (inArray(filepath.Ext(path), p.Watcher.Exts)) {
if p.Watcher.Preview { 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 { if err = watcher.Add(path); err != nil {
return filepath.SkipDir return filepath.SkipDir
@ -221,26 +220,26 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error {
return nil return nil
} }
if p.Path == "." || p.Path == "/" { if p.path == "." || p.path == "/" {
p.base = wd p.base = wd
p.Path = p.Wdir() p.path = p.Wdir()
} else if filepath.IsAbs(p.Path) { } else if filepath.IsAbs(p.path) {
p.base = p.Path p.base = p.path
} else { } else {
p.base = filepath.Join(wd, p.Path) p.base = filepath.Join(wd, p.path)
} }
for _, dir := range p.Watcher.Paths { for _, dir := range p.Watcher.Paths {
base := filepath.Join(p.base, dir) base := filepath.Join(p.base, dir)
if _, err := os.Stat(base); err == nil { if _, err := os.Stat(base); err == nil {
if err := filepath.Walk(base, walk); err != nil { if err := filepath.Walk(base, walk); err != nil {
log.Println(Red(err.Error())) log.Println(p.Red.Bold(err.Error()))
} }
} else { } else {
return errors.New(base + " path doesn't exist") 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 return nil
} }
@ -261,3 +260,25 @@ func (p *Project) routines(channel chan bool, wr *sync.WaitGroup) {
go p.install(channel, wr) go p.install(channel, wr)
wr.Wait() 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
}