summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormatthieu <matthieu.cneude@gmail.com>2021-04-24 11:40:41 +0200
committermatthieu <matthieu.cneude@gmail.com>2021-04-24 11:40:41 +0200
commite41eefefe8876338193b97b40c837299dfa4ebe7 (patch)
treec423f3e3e8f6383ec18c686b6bbdde791222742f
parent0b6c3b2ecc94cd48d2b9a7aa2262536df7bbf6e6 (diff)
Improve auto reloading of dashboards and add some comments in the main
run function
-rw-r--r--cmd/edit.go30
-rw-r--r--cmd/list.go30
-rw-r--r--cmd/root.go62
-rw-r--r--internal/platform/termui.go19
-rw-r--r--internal/tui.go12
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.