diff options
author | matthieu <matthieu.cneude@gmail.com> | 2021-04-24 11:40:41 +0200 |
---|---|---|
committer | matthieu <matthieu.cneude@gmail.com> | 2021-04-24 11:40:41 +0200 |
commit | e41eefefe8876338193b97b40c837299dfa4ebe7 (patch) | |
tree | c423f3e3e8f6383ec18c686b6bbdde791222742f | |
parent | 0b6c3b2ecc94cd48d2b9a7aa2262536df7bbf6e6 (diff) |
Improve auto reloading of dashboards and add some comments in the main
run function
-rw-r--r-- | cmd/edit.go | 30 | ||||
-rw-r--r-- | cmd/list.go | 30 | ||||
-rw-r--r-- | cmd/root.go | 62 | ||||
-rw-r--r-- | internal/platform/termui.go | 19 | ||||
-rw-r--r-- | internal/tui.go | 12 |
5 files changed, 107 insertions, 46 deletions
diff --git a/cmd/edit.go b/cmd/edit.go index ef5308c..b28e6c2 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -5,6 +5,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" "github.com/spf13/cobra" ) @@ -26,8 +27,18 @@ func editCmd() *cobra.Command { } func edit(args []string) { - // TODO make it work for every OS - cmd := exec.Command(os.ExpandEnv(editor), filepath.Join(dashPath(), args[0])) + file := findConfigFile(args[0]) + if file == "" { + fmt.Fprintf(os.Stdout, "The config %s doesn't exist", args[0]) + return + } else { + editDashboard(os.ExpandEnv(editor), filepath.Join(dashPath(), file)) + } +} + +// TODO add that to the gokit/cmd. +func editDashboard(editor string, config string) { + cmd := exec.Command(editor, config) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout err := cmd.Run() @@ -35,3 +46,18 @@ func edit(args []string) { fmt.Println(err) } } + +func findConfigFile(search string) string { + fs := getConfigFiles() + for _, v := range fs { + s := strings.Split(v.Name(), ".") + if search == s[0] || search == v.Name() { + fmt.Println(s[0]) + fmt.Println(v.Name()) + fmt.Println(search) + return v.Name() + } + } + + return "" +} diff --git a/cmd/list.go b/cmd/list.go index 61b8398..c7557e9 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -1,5 +1,7 @@ package cmd +// TODO to test + import ( "bufio" "fmt" @@ -30,7 +32,6 @@ func listCmd() *cobra.Command { return listCmd } -// TODO to refactor and TEST func runList() { var err error path := dashPath() @@ -46,6 +47,21 @@ func runList() { } } + fs := getConfigFiles() + for _, f := range fs { + s := strings.Split(f.Name(), ".") + // TODO erk to refactor + if !f.IsDir() && len(s) > 1 && (s[1] == "json" || s[1] == "toml" || s[1] == "yaml" || s[1] == "yml") { + if extension { + fmt.Fprintln(os.Stdout, f.Name()) + } else { + fmt.Fprintln(os.Stdout, s[0]) + } + } + } +} + +func getConfigFiles() []fs.FileInfo { homeFiles, err := ioutil.ReadDir(dashPath()) if err != nil { log.Fatal(err) @@ -70,17 +86,7 @@ func runList() { } } - for _, f := range fs { - s := strings.Split(f.Name(), ".") - // TODO erk to refactor - if !f.IsDir() && len(s) > 1 && (s[1] == "json" || s[1] == "toml" || s[1] == "yaml" || s[1] == "yml") { - if extension { - fmt.Fprintln(os.Stdout, f.Name()) - } else { - fmt.Fprintln(os.Stdout, s[0]) - } - } - } + return fs } func isDashboard(fileInfo fs.FileInfo, path string) (fs.FileInfo, bool) { diff --git a/cmd/root.go b/cmd/root.go index 668ecc8..8fa59eb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -24,7 +24,7 @@ var ( Short: "DevDash is a highly configurable terminal dashboard for developers and creators", Long: `DevDash is a highly flexible terminal dashboard for developers and creators, which allows you to gather and refresh the data you really need from Google Analytics, Google Search Console, Github, TravisCI, and more.`, Run: func(cmd *cobra.Command, args []string) { - run(args) + run() }, } ) @@ -47,41 +47,52 @@ func Execute() { } } -func run(args []string) { +// run the dashboard. +func run() { termui, err := platform.NewTermUI(debug) if err != nil { fmt.Println(err) } + // Create the TUI. tui := internal.NewTUI(termui) defer tui.Close() - if file == "" && len(args) > 0 { - file = args[0] - } - + // Map dashboard config to a struct Config. cfg, file := mapConfig(file) + + // Passing a time.Time to this channel reload the entire dashboard. hotReload := make(chan time.Time) + + // Add keystrokes to reload and quit tui.AddKHotReload(cfg.KHotReload(), hotReload) tui.AddKQuit(cfg.KQuit()) + // Passing a bool to this channel stop the automatic reload of the dashboard. + stopAutoReload := make(chan bool) + autoReload(cfg.RefreshTime(), stopAutoReload, hotReload) + editor := os.Getenv("EDITOR") if cfg.General.Editor != "" { editor = cfg.General.Editor } - tui.AddKEdit(cfg.KEdit(), hotReload, file, editor) - // first display - build(file, tui) - - ticker := time.NewTicker(time.Duration(cfg.RefreshTime()) * time.Second) + // Add keystroke (managed by TUI) to edit the configuration in a CLI editor. + // Wrap edit config in lambda to defer the execution. + tui.AddKEdit( + cfg.KEdit(), + func() { + stopReload(stopAutoReload) + editDashboard(editor, file) + hotReload <- time.Now() + autoReload(cfg.RefreshTime(), stopAutoReload, hotReload) + }, + ) - go func() { - for { - hotReload <- <-ticker.C - } - }() + // First display. + build(file, tui) + // Automatic reload go func() { for hr := range hotReload { tui.HotReload() @@ -95,6 +106,25 @@ func run(args []string) { tui.Loop() } +func autoReload(refresh int64, stopAutoReload <-chan bool, hotReload chan<- time.Time) { + go func() { + ticker := time.NewTicker(time.Duration(refresh) * time.Second) + defer ticker.Stop() + for { + select { + case <-stopAutoReload: + return + case tick := <-ticker.C: + hotReload <- tick + } + } + }() +} + +func stopReload(stopAutoReload chan<- bool) { + stopAutoReload <- true +} + // build every services present in the configuration func build(file string, tui *internal.Tui) { cfg, _ := mapConfig(file) diff --git a/internal/platform/termui.go b/internal/platform/termui.go index f8796f8..a41a003 100644 --- a/internal/platform/termui.go +++ b/internal/platform/termui.go @@ -2,8 +2,6 @@ package platform import ( "fmt" - "os" - "os/exec" "time" "github.com/Phantas0s/termui" @@ -222,23 +220,18 @@ func (*termUI) KQuit(key string) { func (t *termUI) KHotReload(key string, c chan<- time.Time) { termui.Handle(fmt.Sprintf("/sys/kbd/%s", key), func(e termui.Event) { go func() { + // TODO wrap that into a function and pass it till here c <- time.Now() }() }) } -func (t *termUI) KEdit(key string, c chan<- time.Time, config string, editor string) { +// Key to edit a dashboard config. +// Need to stop the hot reload while editing the file. +// Automatically reload the dashboad after the edit is done. +func (t *termUI) KEdit(key string, editDashboard func()) { termui.Handle(fmt.Sprintf("/sys/kbd/%s", key), func(e termui.Event) { - cmd := exec.Command(os.ExpandEnv(editor), config) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - err := cmd.Run() - if err != nil { - fmt.Println(err) - } - - // Hot reload when command complete - c <- time.Now() + editDashboard() }) } diff --git a/internal/tui.go b/internal/tui.go index cf786c9..1273067 100644 --- a/internal/tui.go +++ b/internal/tui.go @@ -161,7 +161,10 @@ type drawer interface { type keyManager interface { KQuit(key string) KHotReload(key string, c chan<- time.Time) - KEdit(key string, c chan<- time.Time, config string, editor string) + KEdit( + key string, + editDashboard func(), + ) } type looper interface { @@ -526,8 +529,11 @@ func (t *Tui) AddKHotReload(key string, c chan<- time.Time) { t.instance.KHotReload(key, c) } -func (t *Tui) AddKEdit(key string, c chan<- time.Time, config string, editor string) { - t.instance.KEdit(key, c, config, editor) +func (t *Tui) AddKEdit( + key string, + editDashboard func(), +) { + t.instance.KEdit(key, editDashboard) } // Loop the TUI to receive events. |