diff --git a/.gitignore b/.gitignore index 4135fa0b..8f9f6635 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ gcal/client_secret.json gspreadsheets/client_secret.json profile.pdf report.* +.vscode # All things node node_modules/ diff --git a/cfg/common_settings.go b/cfg/common_settings.go new file mode 100644 index 00000000..8d7a8c39 --- /dev/null +++ b/cfg/common_settings.go @@ -0,0 +1,91 @@ +package cfg + +import ( + "github.com/olebedev/config" +) + +type Colors struct { + Background string + BorderFocusable string + BorderFocused string + BorderNormal string + Checked string + HighlightFore string + HighlightBack string + Text string + Title string +} + +type Module struct { + ConfigKey string + Name string +} + +type Position struct { + Height int + Left int + Top int + Width int +} + +type Sigils struct { + CheckedIcon string + UncheckedIcon string +} + +type Common struct { + Colors + Module + Position + Sigils + + Enabled bool + FocusChar int + RefreshInterval int + Title string +} + +func NewCommonSettingsFromYAML(name, configKey string, ymlConfig *config.Config) *Common { + colorsPath := "wtf.colors" + modulePath := "wtf.mods." + configKey + positionPath := "wtf.mods." + configKey + ".position" + sigilsPath := "wtf.sigils" + + common := Common{ + Colors: Colors{ + Background: ymlConfig.UString(modulePath+".colors.background", ymlConfig.UString(colorsPath+".background", "black")), + BorderFocusable: ymlConfig.UString(colorsPath+".border.focusable", "red"), + BorderFocused: ymlConfig.UString(colorsPath+".border.focused", "orange"), + BorderNormal: ymlConfig.UString(colorsPath+".border.normal", "gray"), + Checked: ymlConfig.UString(colorsPath+".checked", "white"), + HighlightFore: ymlConfig.UString(colorsPath+".highlight.fore", "black"), + HighlightBack: ymlConfig.UString(colorsPath+".highlight.back", "green"), + Text: ymlConfig.UString(modulePath+".colors.text", ymlConfig.UString(colorsPath+".text", "white")), + Title: ymlConfig.UString(modulePath+".colors.title", ymlConfig.UString(colorsPath+".title", "white")), + }, + + Module: Module{ + ConfigKey: configKey, + Name: name, + }, + + Position: Position{ + Height: ymlConfig.UInt(positionPath + ".height"), + Left: ymlConfig.UInt(positionPath + ".left"), + Top: ymlConfig.UInt(positionPath + ".top"), + Width: ymlConfig.UInt(positionPath + ".width"), + }, + + Sigils: Sigils{ + CheckedIcon: ymlConfig.UString(sigilsPath+".checkedIcon", "x"), + UncheckedIcon: ymlConfig.UString(sigilsPath+".uncheckedIcon", " "), + }, + + Enabled: ymlConfig.UBool(modulePath+".enabled", false), + FocusChar: ymlConfig.UInt(modulePath+".focusChar", -1), + RefreshInterval: ymlConfig.UInt(modulePath+".refreshInterval", 300), + Title: ymlConfig.UString(modulePath+".title", name), + } + + return &common +} diff --git a/cfg/config_files.go b/cfg/config_files.go index dac769e1..4bb00582 100644 --- a/cfg/config_files.go +++ b/cfg/config_files.go @@ -1,13 +1,14 @@ package cfg import ( + "errors" "fmt" "io/ioutil" "os" + "os/user" + "path/filepath" "github.com/olebedev/config" - "github.com/wtfutil/wtf/logger" - "github.com/wtfutil/wtf/wtf" ) // ConfigDirV1 defines the path to the first version of configuration. Do not use this @@ -21,8 +22,8 @@ const ConfigDirV2 = "~/.config/wtf/" // MigrateOldConfig copies any existing configuration from the old location // to the new, XDG-compatible location func MigrateOldConfig() { - srcDir, _ := wtf.ExpandHomeDir(ConfigDirV1) - destDir, _ := wtf.ExpandHomeDir(ConfigDirV2) + srcDir, _ := expandHomeDir(ConfigDirV1) + destDir, _ := expandHomeDir(ConfigDirV2) // If the old config directory doesn't exist, do not move if _, err := os.Stat(srcDir); os.IsNotExist(err) { @@ -38,15 +39,13 @@ func MigrateOldConfig() { err := Copy(srcDir, destDir) if err != nil { panic(err) - } else { - logger.Log(fmt.Sprintf("Copied old config from %s to %s", srcDir, destDir)) } // Delete the old directory if the new one exists if _, err := os.Stat(destDir); err == nil { err := os.RemoveAll(srcDir) if err != nil { - logger.Log(err.Error()) + fmt.Println(err) } } } @@ -55,7 +54,7 @@ func MigrateOldConfig() { // ConfigDir returns the absolute path to the configuration directory func ConfigDir() (string, error) { - configDir, err := wtf.ExpandHomeDir(ConfigDirV2) + configDir, err := expandHomeDir(ConfigDirV2) if err != nil { return "", err } @@ -123,7 +122,7 @@ func CreateFile(fileName string) (string, error) { // LoadConfigFile loads the config.yml file to configure the app func LoadConfigFile(filePath string) *config.Config { - absPath, _ := wtf.ExpandHomeDir(filePath) + absPath, _ := expandHomeDir(filePath) cfg, err := config.ParseYamlFile(absPath) if err != nil { @@ -199,3 +198,43 @@ const simpleConfig = `wtf: width: 1 refreshInterval: 30 ` + +/* -------------------- Unexported Functions -------------------- */ + +// Expand expands the path to include the home directory if the path +// is prefixed with `~`. If it isn't prefixed with `~`, the path is +// returned as-is. +func expandHomeDir(path string) (string, error) { + if len(path) == 0 { + return path, nil + } + + if path[0] != '~' { + return path, nil + } + + if len(path) > 1 && path[1] != '/' && path[1] != '\\' { + return "", errors.New("cannot expand user-specific home dir") + } + + dir, err := home() + if err != nil { + return "", err + } + + return filepath.Join(dir, path[1:]), nil +} + +// Dir returns the home directory for the executing user. +// An error is returned if a home directory cannot be detected. +func home() (string, error) { + currentUser, err := user.Current() + if err != nil { + return "", err + } + if currentUser.HomeDir == "" { + return "", errors.New("cannot find user-specific home dir") + } + + return currentUser.HomeDir, nil +} diff --git a/checklist/checklist.go b/checklist/checklist.go index af55b03c..7e293878 100644 --- a/checklist/checklist.go +++ b/checklist/checklist.go @@ -3,14 +3,18 @@ package checklist // Checklist is a module for creating generic checklist implementations // See 'Todo' for an implementation example type Checklist struct { - Selected int - Items []*ChecklistItem + + checkedIcon string + selected int + uncheckedIcon string } -func NewChecklist() Checklist { +func NewChecklist(checkedIcon, uncheckedIcon string) Checklist { list := Checklist{ - Selected: -1, + checkedIcon: checkedIcon, + selected: -1, + uncheckedIcon: uncheckedIcon, } return list @@ -20,12 +24,14 @@ func NewChecklist() Checklist { // Add creates a new item in the checklist func (list *Checklist) Add(checked bool, text string) { - item := ChecklistItem{ - Checked: checked, - Text: text, - } + item := NewChecklistItem( + checked, + text, + list.checkedIcon, + list.uncheckedIcon, + ) - list.Items = append([]*ChecklistItem{&item}, list.Items...) + list.Items = append([]*ChecklistItem{item}, list.Items...) } // CheckedItems returns a slice of all the checked items @@ -43,7 +49,7 @@ func (list *Checklist) CheckedItems() []*ChecklistItem { // Delete removes the selected item from the checklist func (list *Checklist) Delete() { - list.Items = append(list.Items[:list.Selected], list.Items[list.Selected+1:]...) + list.Items = append(list.Items[:list.selected], list.Items[list.selected+1:]...) list.Prev() } @@ -53,18 +59,18 @@ func (list *Checklist) Demote() { return } - j := list.Selected + 1 + j := list.selected + 1 if j >= len(list.Items) { j = 0 } - list.Swap(list.Selected, j) - list.Selected = j + list.Swap(list.selected, j) + list.selected = j } // IsSelectable returns true if the checklist has selectable items, false if it does not func (list *Checklist) IsSelectable() bool { - return list.Selected >= 0 && list.Selected < len(list.Items) + return list.selected >= 0 && list.selected < len(list.Items) } // IsUnselectable returns true if the checklist has no selectable items, false if it does @@ -74,9 +80,9 @@ func (list *Checklist) IsUnselectable() bool { // Next selects the next item in the checklist func (list *Checklist) Next() { - list.Selected = list.Selected + 1 - if list.Selected >= len(list.Items) { - list.Selected = 0 + list.selected = list.selected + 1 + if list.selected >= len(list.Items) { + list.selected = 0 } } @@ -95,9 +101,9 @@ func (list *Checklist) LongestLine() int { // Prev selects the previous item in the checklist func (list *Checklist) Prev() { - list.Selected = list.Selected - 1 - if list.Selected < 0 { - list.Selected = len(list.Items) - 1 + list.selected = list.selected - 1 + if list.selected < 0 { + list.selected = len(list.Items) - 1 } } @@ -107,13 +113,17 @@ func (list *Checklist) Promote() { return } - j := list.Selected - 1 + j := list.selected - 1 if j < 0 { j = len(list.Items) - 1 } - list.Swap(list.Selected, j) - list.Selected = j + list.Swap(list.selected, j) + list.selected = j +} + +func (list *Checklist) Selected() int { + return list.selected } // SelectedItem returns the currently-selected checklist item or nil if no item is selected @@ -122,13 +132,13 @@ func (list *Checklist) SelectedItem() *ChecklistItem { return nil } - return list.Items[list.Selected] + return list.Items[list.selected] } func (list *Checklist) SetSelectedByItem(selectableItem *ChecklistItem) { for idx, item := range list.Items { if item == selectableItem { - list.Selected = idx + list.selected = idx break } } @@ -158,7 +168,7 @@ func (list *Checklist) UncheckedItems() []*ChecklistItem { // Unselect removes the current select such that no item is selected func (list *Checklist) Unselect() { - list.Selected = -1 + list.selected = -1 } // Update sets the text of the currently-selected item to the provided text diff --git a/checklist/checklist_item.go b/checklist/checklist_item.go index 70d0ae6f..40cfafb8 100644 --- a/checklist/checklist_item.go +++ b/checklist/checklist_item.go @@ -1,23 +1,36 @@ package checklist -import ( - "github.com/wtfutil/wtf/wtf" -) +import () // ChecklistItem is a module for creating generic checklist implementations // See 'Todo' for an implementation example type ChecklistItem struct { - Checked bool - Text string + Checked bool + CheckedIcon string + Text string + UncheckedIcon string +} + +func NewChecklistItem(checked bool, text string, checkedIcon, uncheckedIcon string) *ChecklistItem { + item := &ChecklistItem{ + Checked: checked, + CheckedIcon: checkedIcon, + Text: text, + UncheckedIcon: uncheckedIcon, + } + + return item } // CheckMark returns the string used to indicate a ChecklistItem is checked or unchecked func (item *ChecklistItem) CheckMark() string { + item.ensureItemIcons() + if item.Checked { - return wtf.Config.UString("wtf.mods.todo.checkedIcon", "x") + return item.CheckedIcon } - return " " + return item.UncheckedIcon } // Toggle changes the checked state of the ChecklistItem @@ -25,3 +38,15 @@ func (item *ChecklistItem) CheckMark() string { func (item *ChecklistItem) Toggle() { item.Checked = !item.Checked } + +/* -------------------- Unexported Functions -------------------- */ + +func (item *ChecklistItem) ensureItemIcons() { + if item.CheckedIcon == "" { + item.CheckedIcon = "x" + } + + if item.UncheckedIcon == "" { + item.UncheckedIcon = " " + } +} diff --git a/generator/textwidget.tpl b/generator/textwidget.tpl index 3bed5c5c..e3ebd214 100644 --- a/generator/textwidget.tpl +++ b/generator/textwidget.tpl @@ -16,12 +16,16 @@ const HelpText = ` type Widget struct { wtf.HelpfulWidget wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), TextWidget: wtf.NewTextWidget(app, "{{(Title .Name)}}", "{{(Lower .Name)}}", true), + + settings: settings, } widget.HelpfulWidget.SetView(widget.View) diff --git a/logger/log.go b/logger/log.go index 0e40dc0d..7b4b88cd 100644 --- a/logger/log.go +++ b/logger/log.go @@ -2,7 +2,6 @@ package logger import ( "fmt" - //"io/ioutil" "log" "os" "path/filepath" @@ -18,13 +17,15 @@ type Widget struct { wtf.TextWidget filePath string + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Logs", "logger", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), filePath: logFilePath(), + settings: settings, } return &widget diff --git a/logger/settings.go b/logger/settings.go new file mode 100644 index 00000000..ba61ce9e --- /dev/null +++ b/logger/settings.go @@ -0,0 +1,20 @@ +package logger + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "logger" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/main.go b/main.go index a9f92bbd..be978e2a 100644 --- a/main.go +++ b/main.go @@ -151,7 +151,7 @@ func watchForConfigChanges(app *tview.Application, configFilePath string, grid * loadConfigFile(absPath) widgets := makeWidgets(app, pages) - validateWidgets(widgets) + wtf.ValidateWidgets(widgets) initializeFocusTracker(app, widgets) @@ -182,97 +182,142 @@ func makeWidget(app *tview.Application, pages *tview.Pages, widgetName string) w // Always in alphabetical order switch widgetName { case "bamboohr": - widget = bamboohr.NewWidget(app) + settings := bamboohr.NewSettingsFromYAML("BambooHR", wtf.Config) + widget = bamboohr.NewWidget(app, settings) case "bargraph": widget = bargraph.NewWidget(app) case "bittrex": - widget = bittrex.NewWidget(app) + settings := bittrex.NewSettingsFromYAML("Bittrex", wtf.Config) + widget = bittrex.NewWidget(app, settings) case "blockfolio": - widget = blockfolio.NewWidget(app) + settings := blockfolio.NewSettingsFromYAML("Blockfolio", wtf.Config) + widget = blockfolio.NewWidget(app, settings) case "circleci": - widget = circleci.NewWidget(app) + settings := circleci.NewSettingsFromYAML("CircleCI", wtf.Config) + widget = circleci.NewWidget(app, settings) case "clocks": - widget = clocks.NewWidget(app) + settings := clocks.NewSettingsFromYAML("Clocks", wtf.Config) + widget = clocks.NewWidget(app, settings) case "cmdrunner": - widget = cmdrunner.NewWidget(app) + settings := cmdrunner.NewSettingsFromYAML("CmdRunner", wtf.Config) + widget = cmdrunner.NewWidget(app, settings) case "cryptolive": - widget = cryptolive.NewWidget(app) + settings := cryptolive.NewSettingsFromYAML("CryptoLive", wtf.Config) + widget = cryptolive.NewWidget(app, settings) case "datadog": - widget = datadog.NewWidget(app) + settings := datadog.NewSettingsFromYAML("DataDog", wtf.Config) + widget = datadog.NewWidget(app, settings) case "gcal": - widget = gcal.NewWidget(app) + settings := gcal.NewSettingsFromYAML("Calendar", wtf.Config) + widget = gcal.NewWidget(app, settings) case "gerrit": - widget = gerrit.NewWidget(app, pages) + settings := gerrit.NewSettingsFromYAML("Gerrit", wtf.Config) + widget = gerrit.NewWidget(app, pages, settings) case "git": - widget = git.NewWidget(app, pages) + settings := git.NewSettingsFromYAML("Git", wtf.Config) + widget = git.NewWidget(app, pages, settings) case "github": - widget = github.NewWidget(app, pages) + settings := github.NewSettingsFromYAML("GitHub", wtf.Config) + widget = github.NewWidget(app, pages, settings) case "gitlab": - widget = gitlab.NewWidget(app, pages) + settings := gitlab.NewSettingsFromYAML("GitLab", wtf.Config) + widget = gitlab.NewWidget(app, pages, settings) case "gitter": - widget = gitter.NewWidget(app, pages) + settings := gitter.NewSettingsFromYAML("Gitter", wtf.Config) + widget = gitter.NewWidget(app, pages, settings) case "gspreadsheets": - widget = gspreadsheets.NewWidget(app) + settings := gspreadsheets.NewSettingsFromYAML("Google Spreadsheets", wtf.Config) + widget = gspreadsheets.NewWidget(app, settings) case "hackernews": - widget = hackernews.NewWidget(app, pages) + settings := hackernews.NewSettingsFromYAML("HackerNews", wtf.Config) + widget = hackernews.NewWidget(app, pages, settings) case "ipapi": - widget = ipapi.NewWidget(app) + settings := ipapi.NewSettingsFromYAML("IPAPI", wtf.Config) + widget = ipapi.NewWidget(app, settings) case "ipinfo": - widget = ipinfo.NewWidget(app) + settings := ipinfo.NewSettingsFromYAML("IPInfo", wtf.Config) + widget = ipinfo.NewWidget(app, settings) case "jenkins": - widget = jenkins.NewWidget(app, pages) + settings := jenkins.NewSettingsFromYAML("Jenkins", wtf.Config) + widget = jenkins.NewWidget(app, pages, settings) case "jira": - widget = jira.NewWidget(app, pages) + settings := jira.NewSettingsFromYAML("Jira", wtf.Config) + widget = jira.NewWidget(app, pages, settings) case "logger": - widget = logger.NewWidget(app) + settings := logger.NewSettingsFromYAML("Log", wtf.Config) + widget = logger.NewWidget(app, settings) case "mercurial": - widget = mercurial.NewWidget(app, pages) + settings := mercurial.NewSettingsFromYAML("Mercurial", wtf.Config) + widget = mercurial.NewWidget(app, pages, settings) case "nbascore": - widget = nbascore.NewWidget(app, pages) + settings := nbascore.NewSettingsFromYAML("NBA Score", wtf.Config) + widget = nbascore.NewWidget(app, pages, settings) case "newrelic": - widget = newrelic.NewWidget(app) + settings := newrelic.NewSettingsFromYAML("NewRelic", wtf.Config) + widget = newrelic.NewWidget(app, settings) case "opsgenie": - widget = opsgenie.NewWidget(app) + settings := opsgenie.NewSettingsFromYAML("OpsGenie", wtf.Config) + widget = opsgenie.NewWidget(app, settings) case "pagerduty": - widget = pagerduty.NewWidget(app) + settings := pagerduty.NewSettingsFromYAML("PagerDuty", wtf.Config) + widget = pagerduty.NewWidget(app, settings) case "power": - widget = power.NewWidget(app) + settings := power.NewSettingsFromYAML("Power", wtf.Config) + widget = power.NewWidget(app, settings) case "prettyweather": - widget = prettyweather.NewWidget(app) + settings := prettyweather.NewSettingsFromYAML("Pretty Weather", wtf.Config) + widget = prettyweather.NewWidget(app, settings) case "resourceusage": - widget = resourceusage.NewWidget(app) - case "security": - widget = security.NewWidget(app) - case "status": - widget = status.NewWidget(app) - case "system": - widget = system.NewWidget(app, date, version) - case "spotify": - widget = spotify.NewWidget(app, pages) - case "spotifyweb": - widget = spotifyweb.NewWidget(app, pages) - case "textfile": - widget = textfile.NewWidget(app, pages) - case "todo": - widget = todo.NewWidget(app, pages) - case "todoist": - widget = todoist.NewWidget(app, pages) - case "travisci": - widget = travisci.NewWidget(app, pages) + settings := resourceusage.NewSettingsFromYAML("Resource Usage", wtf.Config) + widget = resourceusage.NewWidget(app, settings) case "rollbar": - widget = rollbar.NewWidget(app, pages) + settings := rollbar.NewSettingsFromYAML("Rollbar", wtf.Config) + widget = rollbar.NewWidget(app, pages, settings) + case "security": + settings := security.NewSettingsFromYAML("Security", wtf.Config) + widget = security.NewWidget(app, settings) + case "spotify": + settings := spotify.NewSettingsFromYAML("Spotify", wtf.Config) + widget = spotify.NewWidget(app, pages, settings) + case "spotifyweb": + settings := spotifyweb.NewSettingsFromYAML("Spotify Web", wtf.Config) + widget = spotifyweb.NewWidget(app, pages, settings) + case "status": + settings := status.NewSettingsFromYAML("Status", wtf.Config) + widget = status.NewWidget(app, settings) + case "system": + settings := system.NewSettingsFromYAML("System", wtf.Config) + widget = system.NewWidget(app, date, version, settings) + case "textfile": + settings := textfile.NewSettingsFromYAML("Textfile", wtf.Config) + widget = textfile.NewWidget(app, pages, settings) + case "todo": + settings := todo.NewSettingsFromYAML("Todo", wtf.Config) + widget = todo.NewWidget(app, pages, settings) + case "todoist": + settings := todoist.NewSettingsFromYAML("Todoist", wtf.Config) + widget = todoist.NewWidget(app, pages, settings) + case "travisci": + settings := travisci.NewSettingsFromYAML("TravisCI", wtf.Config) + widget = travisci.NewWidget(app, pages, settings) case "trello": - widget = trello.NewWidget(app) + settings := trello.NewSettingsFromYAML("Trello", wtf.Config) + widget = trello.NewWidget(app, settings) case "twitter": - widget = twitter.NewWidget(app, pages) + settings := twitter.NewSettingsFromYAML("Twitter", wtf.Config) + widget = twitter.NewWidget(app, pages, settings) case "victorops": - widget = victorops.NewWidget(app) + settings := victorops.NewSettingsFromYAML("VictorOps - OnCall", wtf.Config) + widget = victorops.NewWidget(app, settings) case "weather": - widget = weather.NewWidget(app, pages) + settings := weather.NewSettingsFromYAML("Weather", wtf.Config) + widget = weather.NewWidget(app, pages, settings) case "zendesk": - widget = zendesk.NewWidget(app) + settings := zendesk.NewSettingsFromYAML("Zendesk", wtf.Config) + widget = zendesk.NewWidget(app, settings) default: - widget = unknown.NewWidget(app, widgetName) + settings := unknown.NewSettingsFromYAML(widgetName, wtf.Config) + widget = unknown.NewWidget(app, widgetName, settings) } return widget @@ -297,15 +342,15 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) []wtf.Wtfable { return widgets } -// Check that all the loaded widgets are valid for display -func validateWidgets(widgets []wtf.Wtfable) { - for _, widget := range widgets { - if widget.Enabled() && !widget.IsPositionable() { - errStr := fmt.Sprintf("Widget config has invalid values: %s", widget.Key()) - log.Fatalln(errStr) - } - } -} +// // Check that all the loaded widgets are valid for display +// func validateWidgets(widgets []wtf.Wtfable) { +// for _, widget := range widgets { +// if widget.Enabled() && !widget.IsPositionable() { +// errStr := fmt.Sprintf("Widget config has invalid values: %s", widget.Key()) +// log.Fatalln(errStr) +// } +// } +// } /* -------------------- Main -------------------- */ @@ -331,7 +376,7 @@ func main() { pages := tview.NewPages() widgets := makeWidgets(app, pages) - validateWidgets(widgets) + wtf.ValidateWidgets(widgets) initializeFocusTracker(app, widgets) diff --git a/modules/bamboohr/settings.go b/modules/bamboohr/settings.go new file mode 100644 index 00000000..a8a61d0e --- /dev/null +++ b/modules/bamboohr/settings.go @@ -0,0 +1,30 @@ +package bamboohr + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "bamboohr" + +type Settings struct { + common *cfg.Common + + apiKey string + subdomain string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_BAMBOO_HR_TOKEN")), + subdomain: localConfig.UString("subdomain", os.Getenv("WTF_BAMBOO_HR_SUBDOMAIN")), + } + + return &settings +} diff --git a/modules/bamboohr/widget.go b/modules/bamboohr/widget.go index a757e40a..c132a719 100644 --- a/modules/bamboohr/widget.go +++ b/modules/bamboohr/widget.go @@ -2,19 +2,24 @@ package bamboohr import ( "fmt" - "os" "github.com/rivo/tview" "github.com/wtfutil/wtf/wtf" ) +const APIURI = "https://api.bamboohr.com/api/gateway.php" + type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "BambooHR", "bamboohr", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -23,17 +28,12 @@ func NewWidget(app *tview.Application) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - apiKey := wtf.Config.UString( - "wtf.mods.bamboohr.apiKey", - os.Getenv("WTF_BAMBOO_HR_TOKEN"), + client := NewClient( + APIURI, + widget.settings.apiKey, + widget.settings.subdomain, ) - subdomain := wtf.Config.UString( - "wtf.mods.bamboohr.subdomain", - os.Getenv("WTF_BAMBOO_HR_SUBDOMAIN"), - ) - - client := NewClient("https://api.bamboohr.com/api/gateway.php", apiKey, subdomain) todayItems := client.Away( "timeOff", wtf.Now().Format(wtf.DateFormat), diff --git a/modules/circleci/settings.go b/modules/circleci/settings.go new file mode 100644 index 00000000..59a74056 --- /dev/null +++ b/modules/circleci/settings.go @@ -0,0 +1,28 @@ +package circleci + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "circleci" + +type Settings struct { + common *cfg.Common + + apiKey string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_CIRCLE_API_KEY")), + } + + return &settings +} diff --git a/modules/circleci/widget.go b/modules/circleci/widget.go index 7806d074..4016a25e 100644 --- a/modules/circleci/widget.go +++ b/modules/circleci/widget.go @@ -2,7 +2,6 @@ package circleci import ( "fmt" - "os" "github.com/rivo/tview" "github.com/wtfutil/wtf/wtf" @@ -11,19 +10,16 @@ import ( type Widget struct { wtf.TextWidget *Client + + settings *Settings } -const apiEnvKey = "WTF_CIRCLE_API_KEY" - -func NewWidget(app *tview.Application) *Widget { - apiKey := wtf.Config.UString( - "wtf.mods.circleci.apiKey", - os.Getenv(apiEnvKey), - ) - +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "CircleCI", "circleci", false), - Client: NewClient(apiKey), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + Client: NewClient(settings.apiKey), + + settings: settings, } return &widget diff --git a/modules/clocks/clock_collection.go b/modules/clocks/clock_collection.go index 6ca8f0c8..754a3f4c 100644 --- a/modules/clocks/clock_collection.go +++ b/modules/clocks/clock_collection.go @@ -3,16 +3,14 @@ package clocks import ( "sort" "time" - - "github.com/wtfutil/wtf/wtf" ) type ClockCollection struct { Clocks []Clock } -func (clocks *ClockCollection) Sorted() []Clock { - if "chronological" == wtf.Config.UString("wtf.mods.clocks.sort", "alphabetical") { +func (clocks *ClockCollection) Sorted(sortOrder string) []Clock { + if sortOrder == "chronological" { clocks.SortedChronologically() } else { clocks.SortedAlphabetically() diff --git a/modules/clocks/display.go b/modules/clocks/display.go index 0516e197..9448aa06 100644 --- a/modules/clocks/display.go +++ b/modules/clocks/display.go @@ -2,8 +2,6 @@ package clocks import ( "fmt" - - "github.com/wtfutil/wtf/wtf" ) func (widget *Widget) display(clocks []Clock, dateFormat string, timeFormat string) { @@ -14,9 +12,15 @@ func (widget *Widget) display(clocks []Clock, dateFormat string, timeFormat stri str := "" for idx, clock := range clocks { + rowColor := widget.settings.colors.rows.odd + + if idx%2 == 0 { + rowColor = widget.settings.colors.rows.even + } + str = str + fmt.Sprintf( " [%s]%-12s %-10s %7s[white]\n", - wtf.RowColor("clocks", idx), + rowColor, clock.Label, clock.Time(timeFormat), clock.Date(dateFormat), diff --git a/modules/clocks/setting.go b/modules/clocks/setting.go new file mode 100644 index 00000000..08297cc8 --- /dev/null +++ b/modules/clocks/setting.go @@ -0,0 +1,44 @@ +package clocks + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" + "github.com/wtfutil/wtf/wtf" +) + +const configKey = "clocks" + +type colors struct { + rows struct { + even string + odd string + } +} + +type Settings struct { + colors + common *cfg.Common + + dateFormat string + timeFormat string + locations map[string]interface{} + sort string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + dateFormat: localConfig.UString("dateFormat", wtf.SimpleDateFormat), + timeFormat: localConfig.UString("timeFormat", wtf.SimpleTimeFormat), + locations: localConfig.UMap("locations"), + sort: localConfig.UString("sort"), + } + + settings.colors.rows.even = localConfig.UString("colors.rows.even", "white") + settings.colors.rows.odd = localConfig.UString("colors.rows.odd", "blue") + + return &settings +} diff --git a/modules/clocks/widget.go b/modules/clocks/widget.go index 38d19ac0..e65cb584 100644 --- a/modules/clocks/widget.go +++ b/modules/clocks/widget.go @@ -14,17 +14,19 @@ type Widget struct { clockColl ClockCollection dateFormat string timeFormat string + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "World Clocks", "clocks", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, + dateFormat: settings.dateFormat, + timeFormat: settings.timeFormat, } - widget.clockColl = widget.buildClockCollection(wtf.Config.UMap("wtf.mods.clocks.locations")) - - widget.dateFormat = wtf.Config.UString("wtf.mods.clocks.dateFormat", wtf.SimpleDateFormat) - widget.timeFormat = wtf.Config.UString("wtf.mods.clocks.timeFormat", wtf.SimpleTimeFormat) + widget.clockColl = widget.buildClockCollection(settings.locations) return &widget } @@ -32,7 +34,7 @@ func NewWidget(app *tview.Application) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - widget.display(widget.clockColl.Sorted(), widget.dateFormat, widget.timeFormat) + widget.display(widget.clockColl.Sorted(widget.settings.sort), widget.dateFormat, widget.timeFormat) } /* -------------------- Unexported Functions -------------------- */ diff --git a/modules/cmdrunner/settings.go b/modules/cmdrunner/settings.go new file mode 100644 index 00000000..8c979a2a --- /dev/null +++ b/modules/cmdrunner/settings.go @@ -0,0 +1,29 @@ +package cmdrunner + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" + "github.com/wtfutil/wtf/wtf" +) + +const configKey = "cmdrunner" + +type Settings struct { + common *cfg.Common + + args []string + cmd string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + args: wtf.ToStrs(localConfig.UList("args")), + cmd: localConfig.UString("cmd"), + } + + return &settings +} diff --git a/modules/cmdrunner/widget.go b/modules/cmdrunner/widget.go index 2c812db9..edb6fa13 100644 --- a/modules/cmdrunner/widget.go +++ b/modules/cmdrunner/widget.go @@ -12,17 +12,19 @@ import ( type Widget struct { wtf.TextWidget - args []string - cmd string - result string + args []string + cmd string + result string + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "CmdRunner", "cmdrunner", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), - args: wtf.ToStrs(wtf.Config.UList("wtf.mods.cmdrunner.args")), - cmd: wtf.Config.UString("wtf.mods.cmdrunner.cmd"), + args: settings.args, + cmd: settings.cmd, + settings: settings, } widget.View.SetWrap(true) @@ -33,8 +35,8 @@ func NewWidget(app *tview.Application) *Widget { func (widget *Widget) Refresh() { widget.execute() - title := tview.TranslateANSI(wtf.Config.UString("wtf.mods.cmdrunner.title", widget.String())) - widget.View.SetTitle(title) + widget.CommonSettings.Title = widget.String() + widget.View.SetTitle(tview.TranslateANSI(widget.CommonSettings.Title)) widget.View.SetText(widget.result) } diff --git a/modules/cryptoexchanges/bittrex/display.go b/modules/cryptoexchanges/bittrex/display.go index 3c8fa6e4..cb8b5001 100644 --- a/modules/cryptoexchanges/bittrex/display.go +++ b/modules/cryptoexchanges/bittrex/display.go @@ -12,14 +12,21 @@ func (widget *Widget) display() { return } - widget.View.SetText(summaryText(&widget.summaryList, &widget.TextColors)) + summaryText := widget.summaryText(&widget.summaryList) + widget.View.SetText(summaryText) } -func summaryText(list *summaryList, colors *TextColors) string { +func (widget *Widget) summaryText(list *summaryList) string { str := "" for _, baseCurrency := range list.items { - str += fmt.Sprintf(" [%s]%s[%s] (%s)\n\n", colors.base.displayName, baseCurrency.displayName, colors.base.name, baseCurrency.name) + str += fmt.Sprintf( + " [%s]%s[%s] (%s)\n\n", + widget.settings.colors.base.displayName, + baseCurrency.displayName, + widget.settings.colors.base.name, + baseCurrency.name, + ) resultTemplate := template.New("bittrex") @@ -38,9 +45,9 @@ func summaryText(list *summaryList, colors *TextColors) string { ) strTemplate.Execute(writer, map[string]string{ - "nameColor": colors.market.name, - "fieldColor": colors.market.field, - "valueColor": colors.market.value, + "nameColor": widget.settings.colors.market.name, + "fieldColor": widget.settings.colors.market.field, + "valueColor": widget.settings.colors.market.value, "mName": marketCurrency.name, "High": marketCurrency.High, "Low": marketCurrency.Low, diff --git a/modules/cryptoexchanges/bittrex/settings.go b/modules/cryptoexchanges/bittrex/settings.go new file mode 100644 index 00000000..78f7aeb8 --- /dev/null +++ b/modules/cryptoexchanges/bittrex/settings.go @@ -0,0 +1,64 @@ +package bittrex + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "bittrex" + +type colors struct { + base struct { + name string + displayName string + } + market struct { + name string + field string + value string + } +} + +type currency struct { + displayName string + market []interface{} +} + +type summary struct { + currencies map[string]*currency +} + +type Settings struct { + colors + common *cfg.Common + summary +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + settings.colors.base.name = localConfig.UString("colors.base.name") + settings.colors.base.displayName = localConfig.UString("colors.base.displayName") + + settings.colors.market.name = localConfig.UString("colors.market.name") + settings.colors.market.field = localConfig.UString("colors.market.field") + settings.colors.market.value = localConfig.UString("colors.market.value") + + settings.summary.currencies = make(map[string]*currency) + for key, val := range localConfig.UMap("summary") { + coercedVal := val.(map[string]interface{}) + + currency := ¤cy{ + displayName: coercedVal["displayName"].(string), + market: coercedVal["market"].([]interface{}), + } + + settings.summary.currencies[key] = currency + } + + return &settings +} diff --git a/modules/cryptoexchanges/bittrex/widget.go b/modules/cryptoexchanges/bittrex/widget.go index ed11d2d7..49949389 100644 --- a/modules/cryptoexchanges/bittrex/widget.go +++ b/modules/cryptoexchanges/bittrex/widget.go @@ -11,69 +11,48 @@ import ( "github.com/wtfutil/wtf/wtf" ) -type TextColors struct { - base struct { - name string - displayName string - } - market struct { - name string - field string - value string - } -} - var ok = true var errorText = "" -var baseURL = "https://bittrex.com/api/v1.1/public/getmarketsummary" +const baseURL = "https://bittrex.com/api/v1.1/public/getmarketsummary" // Widget define wtf widget to register widget later type Widget struct { wtf.TextWidget + + settings *Settings summaryList - TextColors } // NewWidget Make new instance of widget -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Bittrex", "bittrex", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, summaryList: summaryList{}, } ok = true errorText = "" - widget.config() widget.setSummaryList() return &widget } -func (widget *Widget) config() { - widget.TextColors.base.name = wtf.Config.UString("wtf.mods.bittrex.colors.base.name", "red") - widget.TextColors.base.displayName = wtf.Config.UString("wtf.mods.bittrex.colors.base.displayName", "grey") - widget.TextColors.market.name = wtf.Config.UString("wtf.mods.bittrex.colors.market.name", "red") - widget.TextColors.market.field = wtf.Config.UString("wtf.mods.bittrex.colors.market.field", "coral") - widget.TextColors.market.value = wtf.Config.UString("wtf.mods.bittrex.colors.market.value", "white") -} - func (widget *Widget) setSummaryList() { - sCurrencies, _ := wtf.Config.Map("wtf.mods.bittrex.summary") - for baseCurrencyName := range sCurrencies { - displayName, _ := wtf.Config.String("wtf.mods.bittrex.summary." + baseCurrencyName + ".displayName") - mCurrencyList := makeSummaryMarketList(baseCurrencyName) - widget.summaryList.addSummaryItem(baseCurrencyName, displayName, mCurrencyList) + for symbol, currency := range widget.settings.summary.currencies { + mCurrencyList := widget.makeSummaryMarketList(symbol, currency.market) + widget.summaryList.addSummaryItem(symbol, currency.displayName, mCurrencyList) } } -func makeSummaryMarketList(currencyName string) []*mCurrency { +func (widget *Widget) makeSummaryMarketList(currencySymbol string, market []interface{}) []*mCurrency { mCurrencyList := []*mCurrency{} - configMarketList, _ := wtf.Config.List("wtf.mods.bittrex.summary." + currencyName + ".market") - for _, mCurrencyName := range configMarketList { - mCurrencyList = append(mCurrencyList, makeMarketCurrency(mCurrencyName.(string))) + for _, marketSymbol := range market { + mCurrencyList = append(mCurrencyList, makeMarketCurrency(marketSymbol.(string))) } return mCurrencyList diff --git a/modules/cryptoexchanges/blockfolio/settings.go b/modules/cryptoexchanges/blockfolio/settings.go new file mode 100644 index 00000000..958e0635 --- /dev/null +++ b/modules/cryptoexchanges/blockfolio/settings.go @@ -0,0 +1,35 @@ +package blockfolio + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "blockfolio" + +type colors struct { + name string + grows string + drop string +} + +type Settings struct { + colors + common *cfg.Common + + deviceToken string + displayHoldings bool +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + deviceToken: localConfig.UString("device_token"), + displayHoldings: localConfig.UBool("displayHoldings", true), + } + + return &settings +} diff --git a/modules/cryptoexchanges/blockfolio/widget.go b/modules/cryptoexchanges/blockfolio/widget.go index 3c116c88..27f8e5fe 100644 --- a/modules/cryptoexchanges/blockfolio/widget.go +++ b/modules/cryptoexchanges/blockfolio/widget.go @@ -15,12 +15,15 @@ type Widget struct { wtf.TextWidget device_token string + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Blockfolio", "blockfolio", false), - device_token: wtf.Config.UString("wtf.mods.blockfolio.device_token"), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + device_token: settings.deviceToken, + settings: settings, } return &widget @@ -36,31 +39,50 @@ func (widget *Widget) Refresh() { return } - widget.View.SetText(contentFrom(positions)) + content := widget.contentFrom(positions) + widget.View.SetText(content) } /* -------------------- Unexported Functions -------------------- */ -func contentFrom(positions *AllPositionsResponse) string { +func (widget *Widget) contentFrom(positions *AllPositionsResponse) string { res := "" - colorName := wtf.Config.UString("wtf.mods.blockfolio.colors.name") - colorGrows := wtf.Config.UString("wtf.mods.blockfolio.colors.grows") - colorDrop := wtf.Config.UString("wtf.mods.blockfolio.colors.drop") - displayHoldings := wtf.Config.UBool("wtf.mods.blockfolio.displayHoldings") - var totalFiat float32 - totalFiat = 0.0 + totalFiat := float32(0.0) + for i := 0; i < len(positions.PositionList); i++ { - colorForChange := colorGrows + colorForChange := widget.settings.colors.grows + if positions.PositionList[i].TwentyFourHourPercentChangeFiat <= 0 { - colorForChange = colorDrop + colorForChange = widget.settings.colors.drop } + totalFiat += positions.PositionList[i].HoldingValueFiat - if displayHoldings { - res = res + fmt.Sprintf("[%s]%-6s - %5.2f ([%s]%.3fk [%s]%.2f%s)\n", colorName, positions.PositionList[i].Coin, positions.PositionList[i].Quantity, colorForChange, positions.PositionList[i].HoldingValueFiat/1000, colorForChange, positions.PositionList[i].TwentyFourHourPercentChangeFiat, "%") + + if widget.settings.displayHoldings { + res = res + fmt.Sprintf( + "[%s]%-6s - %5.2f ([%s]%.3fk [%s]%.2f%s)\n", + widget.settings.colors.name, + positions.PositionList[i].Coin, + positions.PositionList[i].Quantity, + colorForChange, + positions.PositionList[i].HoldingValueFiat/1000, + colorForChange, + positions.PositionList[i].TwentyFourHourPercentChangeFiat, + "%", + ) } else { - res = res + fmt.Sprintf("[%s]%-6s - %5.2f ([%s]%.2f%s)\n", colorName, positions.PositionList[i].Coin, positions.PositionList[i].Quantity, colorForChange, positions.PositionList[i].TwentyFourHourPercentChangeFiat, "%") + res = res + fmt.Sprintf( + "[%s]%-6s - %5.2f ([%s]%.2f%s)\n", + widget.settings.colors.name, + positions.PositionList[i].Coin, + positions.PositionList[i].Quantity, + colorForChange, + positions.PositionList[i].TwentyFourHourPercentChangeFiat, + "%", + ) } } - if displayHoldings { + + if widget.settings.displayHoldings { res = res + fmt.Sprintf("\n[%s]Total value: $%.3fk", "green", totalFiat/1000) } diff --git a/modules/cryptoexchanges/cryptolive/price/settings.go b/modules/cryptoexchanges/cryptolive/price/settings.go new file mode 100644 index 00000000..3f39dca6 --- /dev/null +++ b/modules/cryptoexchanges/cryptolive/price/settings.go @@ -0,0 +1,77 @@ +package price + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "cryptolive" + +type colors struct { + from struct { + name string + displayName string + } + to struct { + name string + price string + } + top struct { + from struct { + name string + displayName string + } + to struct { + name string + field string + value string + } + } +} + +type currency struct { + displayName string + to []interface{} +} + +type Settings struct { + colors + common *cfg.Common + currencies map[string]*currency +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + settings.colors.from.name = localConfig.UString("colors.from.name") + settings.colors.from.displayName = localConfig.UString("colors.from.displayName") + + settings.colors.to.name = localConfig.UString("colors.to.name") + settings.colors.to.price = localConfig.UString("colors.to.price") + + settings.colors.top.from.name = localConfig.UString("colors.top.from.name") + settings.colors.top.from.displayName = localConfig.UString("colors.top.from.displayName") + + settings.colors.top.to.name = localConfig.UString("colors.top.to.name") + settings.colors.top.to.field = localConfig.UString("colors.top.to.field") + settings.colors.top.to.value = localConfig.UString("colors.top.to.value") + + settings.currencies = make(map[string]*currency) + + for key, val := range localConfig.UMap("currencies") { + coercedVal := val.(map[string]interface{}) + + currency := ¤cy{ + displayName: coercedVal["displayName"].(string), + to: coercedVal["to"].([]interface{}), + } + + settings.currencies[key] = currency + } + + return &settings +} diff --git a/modules/cryptoexchanges/cryptolive/price/widget.go b/modules/cryptoexchanges/cryptolive/price/widget.go index 4984f70e..faada9c1 100644 --- a/modules/cryptoexchanges/cryptolive/price/widget.go +++ b/modules/cryptoexchanges/cryptolive/price/widget.go @@ -6,8 +6,6 @@ import ( "net/http" "sync" "time" - - "github.com/wtfutil/wtf/wtf" ) var baseURL = "https://min-api.cryptocompare.com/data/price" @@ -16,6 +14,7 @@ var ok = true // Widget define wtf widget to register widget later type Widget struct { *list + settings *Settings Result string @@ -23,8 +22,10 @@ type Widget struct { } // NewWidget Make new instance of widget -func NewWidget() *Widget { - widget := Widget{} +func NewWidget(settings *Settings) *Widget { + widget := Widget{ + settings: settings, + } widget.setList() @@ -32,16 +33,12 @@ func NewWidget() *Widget { } func (widget *Widget) setList() { - currenciesMap, _ := wtf.Config.Map("wtf.mods.cryptolive.currencies") - widget.list = &list{} - for currency := range currenciesMap { - displayName, _ := wtf.Config.String("wtf.mods.cryptolive.currencies." + currency + ".displayName") - toList := getToList(currency) - widget.list.addItem(currency, displayName, toList) + for symbol, currency := range widget.settings.currencies { + toList := widget.getToList(symbol) + widget.list.addItem(symbol, currency.displayName, toList) } - } /* -------------------- Exported Functions -------------------- */ @@ -66,16 +63,23 @@ func (widget *Widget) Refresh(wg *sync.WaitGroup) { func (widget *Widget) display() { str := "" - var ( - fromNameColor = wtf.Config.UString("wtf.mods.cryptolive.colors.from.name", "coral") - fromDisplayNameColor = wtf.Config.UString("wtf.mods.cryptolive.colors.from.displayName", "grey") - toNameColor = wtf.Config.UString("wtf.mods.cryptolive.colors.to.name", "white") - toPriceColor = wtf.Config.UString("wtf.mods.cryptolive.colors.to.price", "green") - ) + for _, item := range widget.list.items { - str += fmt.Sprintf(" [%s]%s[%s] (%s)\n", fromNameColor, item.displayName, fromDisplayNameColor, item.name) + str += fmt.Sprintf( + " [%s]%s[%s] (%s)\n", + widget.settings.colors.from.name, + item.displayName, + widget.settings.colors.from.name, + item.name, + ) for _, toItem := range item.to { - str += fmt.Sprintf("\t[%s]%s: [%s]%f\n", toNameColor, toItem.name, toPriceColor, toItem.price) + str += fmt.Sprintf( + "\t[%s]%s: [%s]%f\n", + widget.settings.colors.to.name, + toItem.name, + widget.settings.colors.to.price, + toItem.price, + ) } str += "\n" } @@ -83,12 +87,10 @@ func (widget *Widget) display() { widget.Result = fmt.Sprintf("\n%s", str) } -func getToList(fromName string) []*toCurrency { - toNames, _ := wtf.Config.List("wtf.mods.cryptolive.currencies." + fromName + ".to") - +func (widget *Widget) getToList(symbol string) []*toCurrency { var toList []*toCurrency - for _, to := range toNames { + for _, to := range widget.settings.currencies[symbol].to { toList = append(toList, &toCurrency{ name: to.(string), price: 0, diff --git a/modules/cryptoexchanges/cryptolive/settings.go b/modules/cryptoexchanges/cryptolive/settings.go new file mode 100644 index 00000000..1ecc7049 --- /dev/null +++ b/modules/cryptoexchanges/cryptolive/settings.go @@ -0,0 +1,75 @@ +package cryptolive + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" + "github.com/wtfutil/wtf/modules/cryptoexchanges/cryptolive/price" + "github.com/wtfutil/wtf/modules/cryptoexchanges/cryptolive/toplist" +) + +const configKey = "cryptolive" + +type colors struct { + from struct { + name string + displayName string + } + to struct { + name string + price string + } + top struct { + from struct { + name string + displayName string + } + to struct { + name string + field string + value string + } + } +} + +type Settings struct { + colors + common *cfg.Common + + currencies map[string]interface{} + top map[string]interface{} + + priceSettings *price.Settings + toplistSettings *toplist.Settings +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + currencies, _ := localConfig.Map("currencies") + top, _ := localConfig.Map("top") + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + currencies: currencies, + top: top, + + priceSettings: price.NewSettingsFromYAML(name, ymlConfig), + toplistSettings: toplist.NewSettingsFromYAML(name, ymlConfig), + } + + settings.colors.from.name = localConfig.UString("colors.from.name") + settings.colors.from.displayName = localConfig.UString("colors.from.displayName") + + settings.colors.to.name = localConfig.UString("colors.to.name") + settings.colors.to.price = localConfig.UString("colors.to.price") + + settings.colors.top.from.name = localConfig.UString("colors.top.from.name") + settings.colors.top.from.displayName = localConfig.UString("colors.top.from.displayName") + + settings.colors.top.to.name = localConfig.UString("colors.top.to.name") + settings.colors.top.to.field = localConfig.UString("colors.top.to.field") + settings.colors.top.to.value = localConfig.UString("colors.top.to.value") + + return &settings +} diff --git a/modules/cryptoexchanges/cryptolive/toplist/display.go b/modules/cryptoexchanges/cryptolive/toplist/display.go index 53d6da16..f8950b95 100644 --- a/modules/cryptoexchanges/cryptolive/toplist/display.go +++ b/modules/cryptoexchanges/cryptolive/toplist/display.go @@ -7,49 +7,54 @@ func (widget *Widget) display() { for _, fromCurrency := range widget.list.items { str += fmt.Sprintf( "[%s]%s [%s](%s)\n", - widget.colors.from.displayName, + widget.settings.colors.from.displayName, fromCurrency.displayName, - widget.colors.from.name, + widget.settings.colors.from.name, fromCurrency.name, ) - str += makeToListText(fromCurrency.to, widget.colors) + str += widget.makeToListText(fromCurrency.to) } widget.Result = str } -func makeToListText(toList []*tCurrency, colors textColors) string { +func (widget *Widget) makeToListText(toList []*tCurrency) string { str := "" for _, toCurrency := range toList { - str += makeToText(toCurrency, colors) + str += widget.makeToText(toCurrency) } return str } -func makeToText(toCurrency *tCurrency, colors textColors) string { +func (widget *Widget) makeToText(toCurrency *tCurrency) string { str := "" - str += fmt.Sprintf(" [%s]%s\n", colors.to.name, toCurrency.name) + str += fmt.Sprintf( + " [%s]%s\n", + widget.settings.colors.to.name, + toCurrency.name, + ) + for _, info := range toCurrency.info { - str += makeInfoText(info, colors) + str += widget.makeInfoText(info) str += "\n\n" } return str } -func makeInfoText(info tInfo, colors textColors) string { +func (widget *Widget) makeInfoText(info tInfo) string { return fmt.Sprintf( " [%s]Exchange: [%s]%s\n", - colors.to.field, - colors.to.value, + widget.settings.colors.top.to.field, + widget.settings.colors.top.to.value, info.exchange, ) + fmt.Sprintf( " [%s]Volume(24h): [%s]%f-[%s]%f", - colors.to.field, - colors.to.value, + widget.settings.colors.top.to.field, + widget.settings.colors.top.to.value, info.volume24h, - colors.to.value, + widget.settings.colors.top.to.value, info.volume24hTo, ) } diff --git a/modules/cryptoexchanges/cryptolive/toplist/settings.go b/modules/cryptoexchanges/cryptolive/toplist/settings.go new file mode 100644 index 00000000..8c250c44 --- /dev/null +++ b/modules/cryptoexchanges/cryptolive/toplist/settings.go @@ -0,0 +1,96 @@ +package toplist + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "cryptolive" + +type colors struct { + from struct { + name string + displayName string + } + to struct { + name string + price string + } + top struct { + from struct { + name string + displayName string + } + to struct { + name string + field string + value string + } + } +} + +type currency struct { + displayName string + limit int + to []interface{} +} + +type Settings struct { + colors + common *cfg.Common + currencies map[string]*currency + top map[string]*currency +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + settings.colors.from.name = localConfig.UString("colors.from.name") + settings.colors.from.displayName = localConfig.UString("colors.from.displayName") + + settings.colors.to.name = localConfig.UString("colors.to.name") + settings.colors.to.price = localConfig.UString("colors.to.price") + + settings.colors.top.from.name = localConfig.UString("colors.top.from.name") + settings.colors.top.from.displayName = localConfig.UString("colors.top.from.displayName") + + settings.colors.top.to.name = localConfig.UString("colors.top.to.name") + settings.colors.top.to.field = localConfig.UString("colors.top.to.field") + settings.colors.top.to.value = localConfig.UString("colors.top.to.value") + + settings.currencies = make(map[string]*currency) + + for key, val := range localConfig.UMap("currencies") { + coercedVal := val.(map[string]interface{}) + + limit, _ := coercedVal["limit"].(int) + + currency := ¤cy{ + displayName: coercedVal["displayName"].(string), + limit: limit, + to: coercedVal["to"].([]interface{}), + } + + settings.currencies[key] = currency + } + + for key, val := range localConfig.UMap("top") { + coercedVal := val.(map[string]interface{}) + + limit, _ := coercedVal["limit"].(int) + + currency := ¤cy{ + displayName: coercedVal["displayName"].(string), + limit: limit, + to: coercedVal["to"].([]interface{}), + } + + settings.currencies[key] = currency + } + + return &settings +} diff --git a/modules/cryptoexchanges/cryptolive/toplist/widget.go b/modules/cryptoexchanges/cryptolive/toplist/widget.go index 5c433fec..58eafd3f 100644 --- a/modules/cryptoexchanges/cryptolive/toplist/widget.go +++ b/modules/cryptoexchanges/cryptolive/toplist/widget.go @@ -7,62 +7,43 @@ import ( "os" "sync" "time" - - "github.com/wtfutil/wtf/wtf" ) var baseURL = "https://min-api.cryptocompare.com/data/top/exchanges" -type textColors struct { - from struct { - name string - displayName string - } - to struct { - name string - field string - value string - } -} - // Widget Toplist Widget type Widget struct { Result string RefreshInterval int - list *cList - - colors textColors + list *cList + settings *Settings } // NewWidget Make new toplist widget -func NewWidget() *Widget { - widget := Widget{} +func NewWidget(settings *Settings) *Widget { + widget := Widget{ + settings: settings, + } widget.list = &cList{} widget.setList() - widget.config() return &widget } func (widget *Widget) setList() { - currenciesMap, _ := wtf.Config.Map("wtf.mods.cryptolive.top") - - for fromCurrency := range currenciesMap { - displayName := wtf.Config.UString("wtf.mods.cryptolive.top."+fromCurrency+".displayName", "") - limit := wtf.Config.UInt("wtf.mods.cryptolive.top."+fromCurrency+".limit", 1) - widget.list.addItem(fromCurrency, displayName, limit, makeToList(fromCurrency, limit)) + for symbol, currency := range widget.settings.top { + toList := widget.makeToList(symbol, currency.limit) + widget.list.addItem(symbol, currency.displayName, currency.limit, toList) } } -func makeToList(fCurrencyName string, limit int) (list []*tCurrency) { - toList, _ := wtf.Config.List("wtf.mods.cryptolive.top." + fCurrencyName + ".to") - - for _, toCurrency := range toList { +func (widget *Widget) makeToList(symbol string, limit int) (list []*tCurrency) { + for _, to := range widget.settings.top[symbol].to { list = append(list, &tCurrency{ - name: toCurrency.(string), + name: to.(string), info: make([]tInfo, limit), }) } @@ -70,15 +51,6 @@ func makeToList(fCurrencyName string, limit int) (list []*tCurrency) { return } -func (widget *Widget) config() { - // set colors - widget.colors.from.name = wtf.Config.UString("wtf.mods.cryptolive.colors.top.from.name", "coral") - widget.colors.from.displayName = wtf.Config.UString("wtf.mods.cryptolive.colors.top.from.displayName", "grey") - widget.colors.to.name = wtf.Config.UString("wtf.mods.cryptolive.colors.top.to.name", "red") - widget.colors.to.field = wtf.Config.UString("wtf.mods.cryptolive.colors.top.to.field", "white") - widget.colors.to.value = wtf.Config.UString("wtf.mods.cryptolive.colors.top.to.value", "value") -} - /* -------------------- Exported Functions -------------------- */ // Refresh & update after interval time diff --git a/modules/cryptoexchanges/cryptolive/widget.go b/modules/cryptoexchanges/cryptolive/widget.go index 1671bfb2..c16c4dcf 100644 --- a/modules/cryptoexchanges/cryptolive/widget.go +++ b/modules/cryptoexchanges/cryptolive/widget.go @@ -13,16 +13,20 @@ import ( // Widget define wtf widget to register widget later type Widget struct { wtf.TextWidget + priceWidget *price.Widget toplistWidget *toplist.Widget + settings *Settings } // NewWidget Make new instance of widget -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "CryptoLive", "cryptolive", false), - priceWidget: price.NewWidget(), - toplistWidget: toplist.NewWidget(), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + priceWidget: price.NewWidget(settings.priceSettings), + toplistWidget: toplist.NewWidget(settings.toplistSettings), + settings: settings, } widget.priceWidget.RefreshInterval = widget.RefreshInterval() diff --git a/modules/datadog/client.go b/modules/datadog/client.go index d9d4e238..ce9a2406 100644 --- a/modules/datadog/client.go +++ b/modules/datadog/client.go @@ -1,34 +1,23 @@ package datadog import ( - "os" - "github.com/wtfutil/wtf/wtf" datadog "github.com/zorkian/go-datadog-api" ) // Monitors returns a list of newrelic monitors -func Monitors() ([]datadog.Monitor, error) { - client := datadog.NewClient(apiKey(), applicationKey()) +func (widget *Widget) Monitors() ([]datadog.Monitor, error) { + client := datadog.NewClient( + widget.settings.apiKey, + widget.settings.applicationKey, + ) - monitors, err := client.GetMonitorsByTags(wtf.ToStrs(wtf.Config.UList("wtf.mods.datadog.monitors.tags"))) + tags := wtf.ToStrs(widget.settings.tags) + + monitors, err := client.GetMonitorsByTags(tags) if err != nil { return nil, err } return monitors, nil } - -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.datadog.apiKey", - os.Getenv("WTF_DATADOG_API_KEY"), - ) -} - -func applicationKey() string { - return wtf.Config.UString( - "wtf.mods.datadog.applicationKey", - os.Getenv("WTF_DATADOG_APPLICATION_KEY"), - ) -} diff --git a/modules/datadog/settings.go b/modules/datadog/settings.go new file mode 100644 index 00000000..f7f05f79 --- /dev/null +++ b/modules/datadog/settings.go @@ -0,0 +1,32 @@ +package datadog + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "datadog" + +type Settings struct { + common *cfg.Common + + apiKey string + applicationKey string + tags []interface{} +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_DATADOG_API_KEY")), + applicationKey: localConfig.UString("applicationKey", os.Getenv("WTF_DATADOG_APPLICATION_KEY")), + tags: localConfig.UList("monitors.tags"), + } + + return &settings +} diff --git a/modules/datadog/widget.go b/modules/datadog/widget.go index 5ed2f9b9..7b97b40d 100644 --- a/modules/datadog/widget.go +++ b/modules/datadog/widget.go @@ -10,11 +10,15 @@ import ( type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Datadog", "datadog", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -23,7 +27,7 @@ func NewWidget(app *tview.Application) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - monitors, monitorErr := Monitors() + monitors, monitorErr := widget.Monitors() widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s", widget.Name()))) widget.View.Clear() diff --git a/modules/gcal/client.go b/modules/gcal/client.go index 06f6ccd1..ee475af5 100644 --- a/modules/gcal/client.go +++ b/modules/gcal/client.go @@ -27,10 +27,10 @@ import ( /* -------------------- Exported Functions -------------------- */ -func Fetch() ([]*CalEvent, error) { +func (widget *Widget) Fetch() ([]*CalEvent, error) { ctx := context.Background() - secretPath, _ := wtf.ExpandHomeDir(wtf.Config.UString("wtf.mods.gcal.secretFile")) + secretPath, _ := wtf.ExpandHomeDir(widget.settings.secretFile) b, err := ioutil.ReadFile(secretPath) if err != nil { @@ -48,13 +48,13 @@ func Fetch() ([]*CalEvent, error) { return nil, err } - calendarIds, err := getCalendarIdList(srv) + calendarIds, err := widget.getCalendarIdList(srv) // Get calendar events var events calendar.Events startTime := fromMidnight().Format(time.RFC3339) - eventLimit := int64(wtf.Config.UInt("wtf.mods.gcal.eventCount", 10)) + eventLimit := int64(widget.settings.eventCount) for _, calendarId := range calendarIds { calendarEvents, err := srv.Events.List(calendarId).ShowDeleted(false).TimeMin(startTime).MaxResults(eventLimit).SingleEvents(true).OrderBy("startTime").Do() @@ -122,13 +122,12 @@ func isAuthenticated() bool { return err == nil } -func authenticate() { - filename := wtf.Config.UString("wtf.mods.gcal.secretFile") - secretPath, _ := wtf.ExpandHomeDir(filename) +func (widget *Widget) authenticate() { + secretPath, _ := wtf.ExpandHomeDir(widget.settings.secretFile) b, err := ioutil.ReadFile(secretPath) if err != nil { - log.Fatalf("Unable to read secret file. %v", filename) + log.Fatalf("Unable to read secret file. %v", widget.settings.secretFile) } config, err := google.ConfigFromJSON(b, calendar.CalendarReadonlyScope) @@ -188,9 +187,9 @@ func saveToken(file string, token *oauth2.Token) { json.NewEncoder(f).Encode(token) } -func getCalendarIdList(srv *calendar.Service) ([]string, error) { +func (widget *Widget) getCalendarIdList(srv *calendar.Service) ([]string, error) { // Return single calendar if settings specify we should - if !wtf.Config.UBool("wtf.mods.gcal.multiCalendar", false) { + if !widget.settings.multiCalendar { id, err := srv.CalendarList.Get("primary").Do() if err != nil { return nil, err diff --git a/modules/gcal/display.go b/modules/gcal/display.go index af2b34c2..749fa81b 100644 --- a/modules/gcal/display.go +++ b/modules/gcal/display.go @@ -32,7 +32,7 @@ func (widget *Widget) display() { widget.mutex.Lock() defer widget.mutex.Unlock() - widget.View.SetTitle(widget.ContextualTitle(widget.Name())) + widget.View.SetTitle(widget.ContextualTitle(widget.settings.common.Title)) widget.View.SetText(widget.contentFrom(widget.calEvents)) } @@ -44,8 +44,8 @@ func (widget *Widget) contentFrom(calEvents []*CalEvent) string { var str string var prevEvent *CalEvent - if !wtf.Config.UBool("wtf.mods.gcal.showDeclined", false) { - calEvents = removeDeclined(calEvents) + if !widget.settings.showDeclined { + calEvents = widget.removeDeclined(calEvents) } for _, calEvent := range calEvents { @@ -101,7 +101,7 @@ func (widget *Widget) dayDivider(event, prevEvent *CalEvent) string { if !eventStartDay.Equal(prevStartDay) { return fmt.Sprintf("[%s::b]", - wtf.Config.UString("wtf.mods.gcal.colors.day", "forestgreen")) + + widget.settings.colors.day) + event.Start().Format(wtf.FullDateFormat) + "\n" } @@ -111,10 +111,10 @@ func (widget *Widget) dayDivider(event, prevEvent *CalEvent) string { func (widget *Widget) descriptionColor(calEvent *CalEvent) string { if calEvent.Past() { - return wtf.Config.UString("wtf.mods.gcal.colors.past", "gray") + return widget.settings.colors.past } - return wtf.Config.UString("wtf.mods.gcal.colors.description", "white") + return widget.settings.colors.description } func (widget *Widget) eventSummary(calEvent *CalEvent, conflict bool) string { @@ -123,13 +123,13 @@ func (widget *Widget) eventSummary(calEvent *CalEvent, conflict bool) string { if calEvent.Now() { summary = fmt.Sprintf( "%s %s", - wtf.Config.UString("wtf.mods.gcal.currentIcon", "🔸"), + widget.settings.currentIcon, summary, ) } if conflict { - return fmt.Sprintf("%s %s", wtf.Config.UString("wtf.mods.gcal.conflictIcon", "🚨"), summary) + return fmt.Sprintf("%s %s", widget.settings.conflictIcon, summary) } return summary @@ -170,9 +170,9 @@ func (widget *Widget) timeUntil(calEvent *CalEvent) string { } func (widget *Widget) titleColor(calEvent *CalEvent) string { - color := wtf.Config.UString("wtf.mods.gcal.colors.title", "white") + color := widget.settings.colors.title - for _, untypedArr := range wtf.Config.UList("wtf.mods.gcal.colors.highlights") { + for _, untypedArr := range widget.settings.highlights { highlightElements := wtf.ToStrs(untypedArr.([]interface{})) match, _ := regexp.MatchString( @@ -186,14 +186,14 @@ func (widget *Widget) titleColor(calEvent *CalEvent) string { } if calEvent.Past() { - color = wtf.Config.UString("wtf.mods.gcal.colors.past", "gray") + color = widget.settings.colors.past } return color } func (widget *Widget) location(calEvent *CalEvent) string { - if wtf.Config.UBool("wtf.mods.gcal.displayLocation", true) == false { + if widget.settings.withLocation == false { return "" } @@ -209,13 +209,13 @@ func (widget *Widget) location(calEvent *CalEvent) string { } func (widget *Widget) responseIcon(calEvent *CalEvent) string { - if false == wtf.Config.UBool("wtf.mods.gcal.displayResponseStatus", true) { + if widget.settings.displayResponseStatus == false { return "" } icon := "[gray]" - switch calEvent.ResponseFor(wtf.Config.UString("wtf.mods.gcal.email")) { + switch calEvent.ResponseFor(widget.settings.email) { case "accepted": return icon + "✔︎" case "declined": @@ -229,10 +229,10 @@ func (widget *Widget) responseIcon(calEvent *CalEvent) string { } } -func removeDeclined(events []*CalEvent) []*CalEvent { +func (widget *Widget) removeDeclined(events []*CalEvent) []*CalEvent { var ret []*CalEvent for _, e := range events { - if e.ResponseFor(wtf.Config.UString("wtf.mods.gcal.email")) != "declined" { + if e.ResponseFor(widget.settings.email) != "declined" { ret = append(ret, e) } } diff --git a/modules/gcal/settings.go b/modules/gcal/settings.go new file mode 100644 index 00000000..1c04d8a6 --- /dev/null +++ b/modules/gcal/settings.go @@ -0,0 +1,59 @@ +package gcal + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "gcal" + +type colors struct { + day string + description string + past string + title string + + highlights []interface{} +} + +type Settings struct { + colors + common *cfg.Common + + conflictIcon string + currentIcon string + displayResponseStatus bool + email string + eventCount int + multiCalendar bool + secretFile string + showDeclined bool + textInterval int + withLocation bool +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + conflictIcon: localConfig.UString("conflictIcon", "🚨"), + currentIcon: localConfig.UString("currentIcon", "🔸"), + displayResponseStatus: localConfig.UBool("displayResponseStatus", true), + email: localConfig.UString("email", ""), + eventCount: localConfig.UInt("eventCount", 10), + multiCalendar: localConfig.UBool("multiCalendar", false), + secretFile: localConfig.UString("secretFile", ""), + showDeclined: localConfig.UBool("showDeclined", false), + textInterval: localConfig.UInt("textInterval", 30), + withLocation: localConfig.UBool("withLocation", true), + } + + settings.colors.day = localConfig.UString("colors.day", "forestgreen") + settings.colors.description = localConfig.UString("colors.description", "white") + settings.colors.past = localConfig.UString("colors.past", "gray") + settings.colors.title = localConfig.UString("colors.title", "white") + + return &settings +} diff --git a/modules/gcal/widget.go b/modules/gcal/widget.go index 5095a0d8..ecc40cd7 100644 --- a/modules/gcal/widget.go +++ b/modules/gcal/widget.go @@ -11,17 +11,20 @@ import ( type Widget struct { wtf.TextWidget + app *tview.Application calEvents []*CalEvent ch chan struct{} mutex sync.Mutex - app *tview.Application + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Calendar", "gcal", true), - ch: make(chan struct{}), - app: app, + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + app: app, + ch: make(chan struct{}), + settings: settings, } go updateLoop(&widget) @@ -41,14 +44,14 @@ func (widget *Widget) Refresh() { widget.fetchAndDisplayEvents() return } - widget.app.Suspend(authenticate) + widget.app.Suspend(widget.authenticate) widget.Refresh() } /* -------------------- Unexported Functions -------------------- */ func (widget *Widget) fetchAndDisplayEvents() { - calEvents, err := Fetch() + calEvents, err := widget.Fetch() if err != nil { widget.calEvents = []*CalEvent{} } else { @@ -58,12 +61,11 @@ func (widget *Widget) fetchAndDisplayEvents() { } func updateLoop(widget *Widget) { - interval := wtf.Config.UInt("wtf.mods.gcal.textInterval", 30) - if interval == 0 { + if widget.settings.textInterval == 0 { return } - tick := time.NewTicker(time.Duration(interval) * time.Second) + tick := time.NewTicker(time.Duration(widget.settings.textInterval) * time.Second) defer tick.Stop() outer: for { diff --git a/modules/gerrit/display.go b/modules/gerrit/display.go index 770c3231..fc320013 100644 --- a/modules/gerrit/display.go +++ b/modules/gerrit/display.go @@ -21,10 +21,10 @@ func (widget *Widget) display() { str = str + widget.displayStats(project) str = str + "\n" str = str + " [red]Open Incoming Reviews[white]\n" - str = str + widget.displayMyIncomingReviews(project, wtf.Config.UString("wtf.mods.gerrit.username")) + str = str + widget.displayMyIncomingReviews(project, widget.settings.username) str = str + "\n" str = str + " [red]My Outgoing Reviews[white]\n" - str = str + widget.displayMyOutgoingReviews(project, wtf.Config.UString("wtf.mods.gerrit.username")) + str = str + widget.displayMyOutgoingReviews(project, widget.settings.username) widget.View.SetText(str) } diff --git a/modules/gerrit/gerrit_repo.go b/modules/gerrit/gerrit_repo.go index dbe58889..b171da1f 100644 --- a/modules/gerrit/gerrit_repo.go +++ b/modules/gerrit/gerrit_repo.go @@ -2,7 +2,6 @@ package gerrit import ( glb "github.com/andygrunwald/go-gerrit" - "github.com/wtfutil/wtf/wtf" ) type GerritProject struct { @@ -25,8 +24,7 @@ func NewGerritProject(path string, gerrit *glb.Client) *GerritProject { } // Refresh reloads the gerrit data via the Gerrit API -func (project *GerritProject) Refresh() { - username := wtf.Config.UString("wtf.mods.gerrit.username") +func (project *GerritProject) Refresh(username string) { project.Changes, _ = project.loadChanges() project.ReviewCount = project.countReviews(project.Changes) diff --git a/modules/gerrit/settings.go b/modules/gerrit/settings.go new file mode 100644 index 00000000..dff7080a --- /dev/null +++ b/modules/gerrit/settings.go @@ -0,0 +1,47 @@ +package gerrit + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +type colors struct { + rows struct { + even string + odd string + } +} + +const configKey = "gerrit" + +type Settings struct { + colors + common *cfg.Common + + domain string + password string + projects []interface{} + username string + verifyServerCertificate bool +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + domain: localConfig.UString("domain", ""), + password: localConfig.UString("password", os.Getenv("WTF_GERRIT_PASSWORD")), + projects: localConfig.UList("projects"), + username: localConfig.UString("username", ""), + verifyServerCertificate: localConfig.UBool("verifyServerCertificate", true), + } + + settings.colors.rows.even = localConfig.UString("colors.rows.even", "white") + settings.colors.rows.odd = localConfig.UString("colors.rows.odd", "blue") + + return &settings +} diff --git a/modules/gerrit/widget.go b/modules/gerrit/widget.go index 6fcdaee9..15afa32c 100644 --- a/modules/gerrit/widget.go +++ b/modules/gerrit/widget.go @@ -4,7 +4,6 @@ import ( "crypto/tls" "fmt" "net/http" - "os" "regexp" glb "github.com/andygrunwald/go-gerrit" @@ -40,18 +39,20 @@ type Widget struct { GerritProjects []*GerritProject Idx int selected int + settings *Settings } var ( GerritURLPattern = regexp.MustCompile(`^(http|https)://(.*)$`) ) -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Gerrit", "gerrit", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), - Idx: 0, + Idx: 0, + settings: settings, } widget.HelpfulWidget.SetView(widget.View) @@ -65,31 +66,27 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - baseURL := wtf.Config.UString("wtf.mods.gerrit.domain") - username := wtf.Config.UString("wtf.mods.gerrit.username") - - password := wtf.Config.UString( - "wtf.mods.gerrit.password", - os.Getenv("WTF_GERRIT_PASSWORD"), - ) - - verifyServerCertificate := wtf.Config.UBool("wtf.mods.gerrit.verifyServerCertificate", true) - - httpClient := &http.Client{Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: !verifyServerCertificate, + httpClient := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: !widget.settings.verifyServerCertificate, + }, + Proxy: http.ProxyFromEnvironment, }, - Proxy: http.ProxyFromEnvironment, - }, } - gerritUrl := baseURL - submatches := GerritURLPattern.FindAllStringSubmatch(baseURL, -1) + gerritUrl := widget.settings.domain + submatches := GerritURLPattern.FindAllStringSubmatch(widget.settings.domain, -1) if len(submatches) > 0 && len(submatches[0]) > 2 { submatch := submatches[0] gerritUrl = fmt.Sprintf( - "%s://%s:%s@%s", submatch[1], username, password, submatch[2]) + "%s://%s:%s@%s", + submatch[1], + widget.settings.username, + widget.settings.password, + submatch[2], + ) } gerrit, err := glb.NewClient(gerritUrl, httpClient) if err != nil { @@ -99,10 +96,10 @@ func (widget *Widget) Refresh() { return } widget.gerrit = gerrit - widget.GerritProjects = widget.buildProjectCollection(wtf.Config.UList("wtf.mods.gerrit.projects")) + widget.GerritProjects = widget.buildProjectCollection(widget.settings.projects) for _, project := range widget.GerritProjects { - project.Refresh() + project.Refresh(widget.settings.username) } widget.display() @@ -159,7 +156,7 @@ func (widget *Widget) openReview() { } else { change = project.OutgoingReviews[sel-len(project.IncomingReviews)] } - wtf.OpenFile(fmt.Sprintf("%s/%s/%d", wtf.Config.UString("wtf.mods.gerrit.domain"), "#/c", change.Number)) + wtf.OpenFile(fmt.Sprintf("%s/%s/%d", widget.settings.domain, "#/c", change.Number)) } } diff --git a/modules/git/git_repo.go b/modules/git/git_repo.go index a402d988..b53e6ed4 100644 --- a/modules/git/git_repo.go +++ b/modules/git/git_repo.go @@ -16,12 +16,12 @@ type GitRepo struct { Path string } -func NewGitRepo(repoPath string) *GitRepo { +func NewGitRepo(repoPath string, commitCount int, commitFormat, dateFormat string) *GitRepo { repo := GitRepo{Path: repoPath} repo.Branch = repo.branch() repo.ChangedFiles = repo.changedFiles() - repo.Commits = repo.commits() + repo.Commits = repo.commits(commitCount, commitFormat, dateFormat) repo.Repository = strings.TrimSpace(repo.repository()) return &repo @@ -49,13 +49,9 @@ func (repo *GitRepo) changedFiles() []string { return data } -func (repo *GitRepo) commits() []string { - numStr := fmt.Sprintf("-n %d", wtf.Config.UInt("wtf.mods.git.commitCount", 10)) - - dateFormat := wtf.Config.UString("wtf.mods.git.dateFormat", "%b %d, %Y") +func (repo *GitRepo) commits(commitCount int, commitFormat, dateFormat string) []string { dateStr := fmt.Sprintf("--date=format:\"%s\"", dateFormat) - - commitFormat := wtf.Config.UString("wtf.mods.git.commitFormat", "[forestgreen]%h [white]%s [grey]%an on %cd[white]") + numStr := fmt.Sprintf("-n %d", commitCount) commitStr := fmt.Sprintf("--pretty=format:\"%s\"", commitFormat) arg := []string{repo.gitDir(), repo.workTree(), "log", dateStr, numStr, commitStr} diff --git a/modules/git/settings.go b/modules/git/settings.go new file mode 100644 index 00000000..a99c85a1 --- /dev/null +++ b/modules/git/settings.go @@ -0,0 +1,32 @@ +package git + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "git" + +type Settings struct { + common *cfg.Common + + commitCount int + commitFormat string + dateFormat string + repositories []interface{} +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + commitCount: localConfig.UInt("commitCount", 10), + commitFormat: localConfig.UString("commitFormat", "[forestgreen]%h [white]%s [grey]%an on %cd[white]"), + dateFormat: localConfig.UString("dateFormat", "%b %d, %Y"), + repositories: localConfig.UList("repositories"), + } + + return &settings +} diff --git a/modules/git/widget.go b/modules/git/widget.go index b94550e1..f63952c7 100644 --- a/modules/git/widget.go +++ b/modules/git/widget.go @@ -32,19 +32,22 @@ type Widget struct { wtf.MultiSourceWidget wtf.TextWidget - app *tview.Application GitRepos []*GitRepo + + app *tview.Application pages *tview.Pages + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - MultiSourceWidget: wtf.NewMultiSourceWidget("git", "repository", "repositories"), - TextWidget: wtf.NewTextWidget(app, "Git", "git", true), + MultiSourceWidget: wtf.NewMultiSourceWidget(settings.common.ConfigKey, "repository", "repositories"), + TextWidget: wtf.NewTextWidget(app, settings.common, true), - app: app, - pages: pages, + app: app, + pages: pages, + settings: settings, } widget.LoadSources() @@ -83,7 +86,7 @@ func (widget *Widget) Pull() { } func (widget *Widget) Refresh() { - repoPaths := wtf.ToStrs(wtf.Config.UList("wtf.mods.git.repositories")) + repoPaths := wtf.ToStrs(widget.settings.repositories) widget.GitRepos = widget.gitRepos(repoPaths) sort.Slice(widget.GitRepos, func(i, j int) bool { @@ -164,10 +167,16 @@ func (widget *Widget) gitRepos(repoPaths []string) []*GitRepo { for _, repoPath := range repoPaths { if strings.HasSuffix(repoPath, "/") { - repos = append(repos, findGitRepositories(make([]*GitRepo, 0), repoPath)...) + repos = append(repos, widget.findGitRepositories(make([]*GitRepo, 0), repoPath)...) } else { - repo := NewGitRepo(repoPath) + repo := NewGitRepo( + repoPath, + widget.settings.commitCount, + widget.settings.commitFormat, + widget.settings.dateFormat, + ) + repos = append(repos, repo) } } @@ -175,7 +184,7 @@ func (widget *Widget) gitRepos(repoPaths []string) []*GitRepo { return repos } -func findGitRepositories(repositories []*GitRepo, directory string) []*GitRepo { +func (widget *Widget) findGitRepositories(repositories []*GitRepo, directory string) []*GitRepo { directory = strings.TrimSuffix(directory, "/") files, err := ioutil.ReadDir(directory) @@ -188,16 +197,24 @@ func findGitRepositories(repositories []*GitRepo, directory string) []*GitRepo { for _, file := range files { if file.IsDir() { path = directory + "/" + file.Name() + if file.Name() == ".git" { path = strings.TrimSuffix(path, "/.git") - repo := NewGitRepo(path) + + repo := NewGitRepo( + path, + widget.settings.commitCount, + widget.settings.commitFormat, + widget.settings.dateFormat, + ) + repositories = append(repositories, repo) continue } if file.Name() == "vendor" || file.Name() == "node_modules" { continue } - repositories = findGitRepositories(repositories, path) + repositories = widget.findGitRepositories(repositories, path) } } diff --git a/modules/github/display.go b/modules/github/display.go index 556f38a3..1819efa2 100644 --- a/modules/github/display.go +++ b/modules/github/display.go @@ -21,16 +21,16 @@ func (widget *Widget) display() { str = str + widget.displayStats(repo) str = str + "\n" str = str + " [red]Open Review Requests[white]\n" - str = str + widget.displayMyReviewRequests(repo, wtf.Config.UString("wtf.mods.github.username")) + str = str + widget.displayMyReviewRequests(repo, widget.settings.username) str = str + "\n" str = str + " [red]My Pull Requests[white]\n" - str = str + widget.displayMyPullRequests(repo, wtf.Config.UString("wtf.mods.github.username")) + str = str + widget.displayMyPullRequests(repo, widget.settings.username) widget.View.SetText(str) } func (widget *Widget) displayMyPullRequests(repo *GithubRepo, username string) string { - prs := repo.myPullRequests(username) + prs := repo.myPullRequests(username, widget.settings.enableStatus) if len(prs) == 0 { return " [grey]none[white]\n" @@ -38,7 +38,7 @@ func (widget *Widget) displayMyPullRequests(repo *GithubRepo, username string) s str := "" for _, pr := range prs { - str = str + fmt.Sprintf(" %s[green]%4d[white] %s\n", mergeString(pr), *pr.Number, *pr.Title) + str = str + fmt.Sprintf(" %s[green]%4d[white] %s\n", widget.mergeString(pr), *pr.Number, *pr.Title) } return str @@ -74,10 +74,6 @@ func (widget *Widget) title(repo *GithubRepo) string { return fmt.Sprintf("[green]%s - %s[white]", repo.Owner, repo.Name) } -func showStatus() bool { - return wtf.Config.UBool("wtf.mods.github.enableStatus", false) -} - var mergeIcons = map[string]string{ "dirty": "[red]![white] ", "clean": "[green]✔[white] ", @@ -85,8 +81,8 @@ var mergeIcons = map[string]string{ "blocked": "[red]✖[white] ", } -func mergeString(pr *github.PullRequest) string { - if !showStatus() { +func (widget *Widget) mergeString(pr *github.PullRequest) string { + if !widget.settings.enableStatus { return "" } if str, ok := mergeIcons[pr.GetMergeableState()]; ok { diff --git a/modules/github/github_repo.go b/modules/github/github_repo.go index 1860de61..65636795 100644 --- a/modules/github/github_repo.go +++ b/modules/github/github_repo.go @@ -3,7 +3,6 @@ package github import ( "context" "net/http" - "os" ghb "github.com/google/go-github/github" "github.com/wtfutil/wtf/wtf" @@ -21,13 +20,15 @@ type GithubRepo struct { RemoteRepo *ghb.Repository } -func NewGithubRepo(name, owner string) *GithubRepo { +func NewGithubRepo(name, owner, apiKey, baseURL, uploadURL string) *GithubRepo { repo := GithubRepo{ Name: name, Owner: owner, - } - repo.loadAPICredentials() + apiKey: apiKey, + baseURL: baseURL, + uploadURL: uploadURL, + } return &repo } @@ -94,25 +95,8 @@ func (repo *GithubRepo) githubClient() (*ghb.Client, error) { return ghb.NewClient(oauthClient), nil } -func (repo *GithubRepo) loadAPICredentials() { - repo.apiKey = wtf.Config.UString( - "wtf.mods.github.apiKey", - os.Getenv("WTF_GITHUB_TOKEN"), - ) - - repo.baseURL = wtf.Config.UString( - "wtf.mods.github.baseURL", - os.Getenv("WTF_GITHUB_BASE_URL"), - ) - - repo.uploadURL = wtf.Config.UString( - "wtf.mods.github.uploadURL", - os.Getenv("WTF_GITHUB_UPLOAD_URL"), - ) -} - // myPullRequests returns a list of pull requests created by username on this repo -func (repo *GithubRepo) myPullRequests(username string) []*ghb.PullRequest { +func (repo *GithubRepo) myPullRequests(username string, showStatus bool) []*ghb.PullRequest { prs := []*ghb.PullRequest{} for _, pr := range repo.PullRequests { @@ -123,7 +107,7 @@ func (repo *GithubRepo) myPullRequests(username string) []*ghb.PullRequest { } } - if showStatus() { + if showStatus { prs = repo.individualPRs(prs) } diff --git a/modules/github/settings.go b/modules/github/settings.go new file mode 100644 index 00000000..dfe9bf96 --- /dev/null +++ b/modules/github/settings.go @@ -0,0 +1,38 @@ +package github + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "github" + +type Settings struct { + common *cfg.Common + + apiKey string + baseURL string + enableStatus bool + repositories map[string]interface{} + uploadURL string + username string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_GITHUB_TOKEN")), + baseURL: localConfig.UString("baseURL", os.Getenv("WTF_GITHUB_BASE_URL")), + enableStatus: localConfig.UBool("enableStatus", false), + repositories: localConfig.UMap("repositories"), + uploadURL: localConfig.UString("uploadURL", os.Getenv("WTF_GITHUB_UPLOAD_URL")), + username: localConfig.UString("username"), + } + + return &settings +} diff --git a/modules/github/widget.go b/modules/github/widget.go index 2bafc598..8021183b 100644 --- a/modules/github/widget.go +++ b/modules/github/widget.go @@ -26,17 +26,19 @@ type Widget struct { GithubRepos []*GithubRepo Idx int + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "GitHub", "github", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), - Idx: 0, + Idx: 0, + settings: settings, } - widget.GithubRepos = widget.buildRepoCollection(wtf.Config.UMap("wtf.mods.github.repositories")) + widget.GithubRepos = widget.buildRepoCollection(widget.settings.repositories) widget.HelpfulWidget.SetView(widget.View) widget.View.SetInputCapture(widget.keyboardIntercept) @@ -78,7 +80,14 @@ func (widget *Widget) buildRepoCollection(repoData map[string]interface{}) []*Gi githubRepos := []*GithubRepo{} for name, owner := range repoData { - repo := NewGithubRepo(name, owner.(string)) + repo := NewGithubRepo( + name, + owner.(string), + widget.settings.apiKey, + widget.settings.baseURL, + widget.settings.uploadURL, + ) + githubRepos = append(githubRepos, repo) } diff --git a/modules/gitlab/display.go b/modules/gitlab/display.go index 3899d7f2..51cdfcc9 100644 --- a/modules/gitlab/display.go +++ b/modules/gitlab/display.go @@ -21,10 +21,10 @@ func (widget *Widget) display() { str = str + widget.displayStats(project) str = str + "\n" str = str + " [red]Open Approval Requests[white]\n" - str = str + widget.displayMyApprovalRequests(project, wtf.Config.UString("wtf.mods.gitlab.username")) + str = str + widget.displayMyApprovalRequests(project, widget.settings.username) str = str + "\n" str = str + " [red]My Merge Requests[white]\n" - str = str + widget.displayMyMergeRequests(project, wtf.Config.UString("wtf.mods.gitlab.username")) + str = str + widget.displayMyMergeRequests(project, widget.settings.username) widget.View.SetText(str) } diff --git a/modules/gitlab/settings.go b/modules/gitlab/settings.go new file mode 100644 index 00000000..1db314da --- /dev/null +++ b/modules/gitlab/settings.go @@ -0,0 +1,34 @@ +package gitlab + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "gitlab" + +type Settings struct { + common *cfg.Common + + apiKey string + domain string + projects map[string]interface{} + username string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_GITLAB_TOKEN")), + domain: localConfig.UString("domain"), + projects: localConfig.UMap("projects"), + username: localConfig.UString("username"), + } + + return &settings +} diff --git a/modules/gitlab/widget.go b/modules/gitlab/widget.go index 8001e84f..bbeb8f4e 100644 --- a/modules/gitlab/widget.go +++ b/modules/gitlab/widget.go @@ -1,8 +1,6 @@ package gitlab import ( - "os" - "github.com/gdamore/tcell" "github.com/rivo/tview" "github.com/wtfutil/wtf/wtf" @@ -25,15 +23,15 @@ type Widget struct { wtf.HelpfulWidget wtf.TextWidget - gitlab *glb.Client - GitlabProjects []*GitlabProject Idx int + gitlab *glb.Client + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { - baseURL := wtf.Config.UString("wtf.mods.gitlab.domain") - gitlab := glb.NewClient(nil, apiKey()) +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { + baseURL := settings.domain + gitlab := glb.NewClient(nil, settings.apiKey) if baseURL != "" { gitlab.SetBaseURL(baseURL) @@ -41,14 +39,14 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Gitlab", "gitlab", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), - gitlab: gitlab, - - Idx: 0, + Idx: 0, + gitlab: gitlab, + settings: settings, } - widget.GitlabProjects = widget.buildProjectCollection(wtf.Config.UMap("wtf.mods.gitlab.projects")) + widget.GitlabProjects = widget.buildProjectCollection(settings.projects) widget.HelpfulWidget.SetView(widget.View) widget.View.SetInputCapture(widget.keyboardIntercept) @@ -86,13 +84,6 @@ func (widget *Widget) Prev() { /* -------------------- Unexported Functions -------------------- */ -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.gitlab.apiKey", - os.Getenv("WTF_GITLAB_TOKEN"), - ) -} - func (widget *Widget) buildProjectCollection(projectData map[string]interface{}) []*GitlabProject { gitlabProjects := []*GitlabProject{} diff --git a/modules/gitter/client.go b/modules/gitter/client.go index f3d635c2..0eec0343 100644 --- a/modules/gitter/client.go +++ b/modules/gitter/client.go @@ -5,18 +5,16 @@ import ( "encoding/json" "fmt" "github.com/wtfutil/wtf/logger" - "github.com/wtfutil/wtf/wtf" "io" "io/ioutil" "net/http" - "os" "strconv" ) -func GetMessages(roomId string, numberOfMessages int) ([]Message, error) { +func GetMessages(roomId string, numberOfMessages int, apiToken string) ([]Message, error) { var messages []Message - resp, err := apiRequest("rooms/" + roomId + "/chatMessages?limit=" + strconv.Itoa(numberOfMessages)) + resp, err := apiRequest("rooms/"+roomId+"/chatMessages?limit="+strconv.Itoa(numberOfMessages), apiToken) if err != nil { return nil, err } @@ -26,10 +24,10 @@ func GetMessages(roomId string, numberOfMessages int) ([]Message, error) { return messages, nil } -func GetRoom(roomUri string) (*Room, error) { +func GetRoom(roomUri, apiToken string) (*Room, error) { var rooms Rooms - resp, err := apiRequest("rooms?q=" + roomUri) + resp, err := apiRequest("rooms?q="+roomUri, apiToken) if err != nil { return nil, err } @@ -52,9 +50,9 @@ var ( apiBaseURL = "https://api.gitter.im/v1/" ) -func apiRequest(path string) (*http.Response, error) { +func apiRequest(path, apiToken string) (*http.Response, error) { req, err := http.NewRequest("GET", apiBaseURL+path, nil) - bearer := fmt.Sprintf("Bearer %s", apiToken()) + bearer := fmt.Sprintf("Bearer %s", apiToken) req.Header.Add("Authorization", bearer) httpClient := &http.Client{} @@ -86,10 +84,3 @@ func parseJson(obj interface{}, text io.Reader) { } } } - -func apiToken() string { - return wtf.Config.UString( - "wtf.mods.gitter.apiToken", - os.Getenv("WTF_GITTER_API_TOKEN"), - ) -} diff --git a/modules/gitter/settings.go b/modules/gitter/settings.go new file mode 100644 index 00000000..6cb70eca --- /dev/null +++ b/modules/gitter/settings.go @@ -0,0 +1,32 @@ +package gitter + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "gitter" + +type Settings struct { + common *cfg.Common + + apiToken string + numberOfMessages int + roomURI string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiToken: localConfig.UString("apiToken", os.Getenv("WTF_GITTER_API_TOKEN")), + numberOfMessages: localConfig.UInt("numberOfMessages", 10), + roomURI: localConfig.UString("roomUri", "wtfutil/Lobby"), + } + + return &settings +} diff --git a/modules/gitter/widget.go b/modules/gitter/widget.go index 89dbb03a..3411e67f 100644 --- a/modules/gitter/widget.go +++ b/modules/gitter/widget.go @@ -26,12 +26,15 @@ type Widget struct { messages []Message selected int + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Gitter", "gitter", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.HelpfulWidget.SetView(widget.View) @@ -51,7 +54,7 @@ func (widget *Widget) Refresh() { return } - room, err := GetRoom(wtf.Config.UString("wtf.mods.gitter.roomUri", "wtfutil/Lobby")) + room, err := GetRoom(widget.settings.roomURI, widget.settings.apiToken) if err != nil { widget.View.SetWrap(true) widget.View.SetTitle(widget.Name()) @@ -63,7 +66,7 @@ func (widget *Widget) Refresh() { return } - messages, err := GetMessages(room.ID, wtf.Config.UInt("wtf.mods.gitter.numberOfMessages", 10)) + messages, err := GetMessages(room.ID, widget.settings.numberOfMessages, widget.settings.apiToken) if err != nil { widget.View.SetWrap(true) @@ -86,7 +89,7 @@ func (widget *Widget) display() { widget.View.SetWrap(true) widget.View.Clear() - widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %s", widget.Name(), wtf.Config.UString("wtf.mods.gitter.roomUri", "wtfutil/Lobby")))) + widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %s", widget.Name(), widget.settings.roomURI))) widget.View.SetText(widget.contentFrom(widget.messages)) widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight() } diff --git a/modules/gspreadsheets/client.go b/modules/gspreadsheets/client.go index 12b6caf0..929f9748 100644 --- a/modules/gspreadsheets/client.go +++ b/modules/gspreadsheets/client.go @@ -26,10 +26,10 @@ import ( /* -------------------- Exported Functions -------------------- */ -func Fetch() ([]*sheets.ValueRange, error) { +func (widget *Widget) Fetch() ([]*sheets.ValueRange, error) { ctx := context.Background() - secretPath, _ := wtf.ExpandHomeDir(wtf.Config.UString("wtf.mods.gspreadsheets.secretFile")) + secretPath, _ := wtf.ExpandHomeDir(widget.settings.secretFile) b, err := ioutil.ReadFile(secretPath) if err != nil { @@ -51,14 +51,13 @@ func Fetch() ([]*sheets.ValueRange, error) { return nil, err } - cells := wtf.ToStrs(wtf.Config.UList("wtf.mods.gspreadsheets.cells.addresses")) - documentId := wtf.Config.UString("wtf.mods.gspreadsheets.sheetId") + cells := wtf.ToStrs(widget.settings.cellAddresses) addresses := strings.Join(cells[:], ";") responses := make([]*sheets.ValueRange, len(cells)) for i := 0; i < len(cells); i++ { - resp, err := srv.Spreadsheets.Values.Get(documentId, cells[i]).Do() + resp, err := srv.Spreadsheets.Values.Get(widget.settings.sheetID, cells[i]).Do() if err != nil { log.Fatalf("Error fetching cells %s", addresses) return nil, err diff --git a/modules/gspreadsheets/settings.go b/modules/gspreadsheets/settings.go new file mode 100644 index 00000000..20f9ae4a --- /dev/null +++ b/modules/gspreadsheets/settings.go @@ -0,0 +1,38 @@ +package gspreadsheets + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "gspreadsheets" + +type colors struct { + values string +} + +type Settings struct { + colors + common *cfg.Common + + cellAddresses []interface{} + cellNames []interface{} + secretFile string + sheetID string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + cellNames: localConfig.UList("cells.names"), + secretFile: localConfig.UString("secretFile"), + sheetID: localConfig.UString("sheetId"), + } + + settings.colors.values = localConfig.UString("colors.values", "green") + + return &settings +} diff --git a/modules/gspreadsheets/widget.go b/modules/gspreadsheets/widget.go index c2d9a5ba..f723cec0 100644 --- a/modules/gspreadsheets/widget.go +++ b/modules/gspreadsheets/widget.go @@ -10,11 +10,15 @@ import ( type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Google Spreadsheets", "gspreadsheets", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -23,7 +27,7 @@ func NewWidget(app *tview.Application) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - cells, _ := Fetch() + cells, _ := widget.Fetch() widget.View.SetText(widget.contentFrom(cells)) } @@ -35,12 +39,11 @@ func (widget *Widget) contentFrom(valueRanges []*sheets.ValueRange) string { return "error 1" } - valuesColor := wtf.Config.UString("wtf.mods.gspreadsheets.colors.values", "green") res := "" - cells := wtf.ToStrs(wtf.Config.UList("wtf.mods.gspreadsheets.cells.names")) + cells := wtf.ToStrs(widget.settings.cellNames) for i := 0; i < len(valueRanges); i++ { - res = res + fmt.Sprintf("%s\t[%s]%s\n", cells[i], valuesColor, valueRanges[i].Values[0][0]) + res = res + fmt.Sprintf("%s\t[%s]%s\n", cells[i], widget.settings.colors.values, valueRanges[i].Values[0][0]) } return res diff --git a/modules/hackernews/settings.go b/modules/hackernews/settings.go new file mode 100644 index 00000000..a0154493 --- /dev/null +++ b/modules/hackernews/settings.go @@ -0,0 +1,28 @@ +package hackernews + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "hackernews" + +type Settings struct { + common *cfg.Common + + numberOfStories int + storyType string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + numberOfStories: localConfig.UInt("numberOfStories", 10), + storyType: localConfig.UString("storyType", "top"), + } + + return &settings +} diff --git a/modules/hackernews/widget.go b/modules/hackernews/widget.go index be19ab36..d9798d25 100644 --- a/modules/hackernews/widget.go +++ b/modules/hackernews/widget.go @@ -32,12 +32,15 @@ type Widget struct { stories []Story selected int + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Hacker News", "hackernews", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.HelpfulWidget.SetView(widget.View) @@ -57,7 +60,7 @@ func (widget *Widget) Refresh() { return } - storyIds, err := GetStories(wtf.Config.UString("wtf.mods.hackernews.storyType", "top")) + storyIds, err := GetStories(widget.settings.storyType) if storyIds == nil { return } @@ -68,8 +71,7 @@ func (widget *Widget) Refresh() { widget.View.SetText(err.Error()) } else { var stories []Story - numberOfStoriesToDisplay := wtf.Config.UInt("wtf.mods.hackernews.numberOfStories", 10) - for idx := 0; idx < numberOfStoriesToDisplay; idx++ { + for idx := 0; idx < widget.settings.numberOfStories; idx++ { story, e := GetStory(storyIds[idx]) if e != nil { panic(e) @@ -94,7 +96,7 @@ func (widget *Widget) display() { widget.View.SetWrap(false) widget.View.Clear() - widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %sstories", widget.Name(), wtf.Config.UString("wtf.mods.hackernews.storyType", "top")))) + widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %sstories", widget.Name(), widget.settings.storyType))) widget.View.SetText(widget.contentFrom(widget.stories)) widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight() } diff --git a/modules/ipaddresses/ipapi/settings.go b/modules/ipaddresses/ipapi/settings.go new file mode 100644 index 00000000..54ba0afc --- /dev/null +++ b/modules/ipaddresses/ipapi/settings.go @@ -0,0 +1,31 @@ +package ipapi + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "ipapi" + +type colors struct { + name string + value string +} + +type Settings struct { + colors + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + settings.colors.name = localConfig.UString("colors.name", "red") + settings.colors.value = localConfig.UString("colors.value", "white") + + return &settings +} diff --git a/modules/ipaddresses/ipapi/widget.go b/modules/ipaddresses/ipapi/widget.go index 8a9bfc48..24d6b1fd 100644 --- a/modules/ipaddresses/ipapi/widget.go +++ b/modules/ipaddresses/ipapi/widget.go @@ -15,10 +15,9 @@ import ( // Widget widget struct type Widget struct { wtf.TextWidget - result string - colors struct { - name, value string - } + + result string + settings *Settings } type ipinfo struct { @@ -37,15 +36,15 @@ type ipinfo struct { } // NewWidget constructor -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "IPInfo", "ipapi", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } widget.View.SetWrap(false) - widget.config() - return &widget } @@ -80,13 +79,6 @@ func (widget *Widget) ipinfo() { widget.setResult(&info) } -// read module configs -func (widget *Widget) config() { - nameColor, valueColor := wtf.Config.UString("wtf.mods.ipinfo.colors.name", "red"), wtf.Config.UString("wtf.mods.ipinfo.colors.value", "white") - widget.colors.name = nameColor - widget.colors.value = valueColor -} - func (widget *Widget) setResult(info *ipinfo) { resultTemplate, _ := template.New("ipinfo_result").Parse( formatableText("IP Address", "Ip") + @@ -104,8 +96,8 @@ func (widget *Widget) setResult(info *ipinfo) { resultBuffer := new(bytes.Buffer) resultTemplate.Execute(resultBuffer, map[string]string{ - "nameColor": widget.colors.name, - "valueColor": widget.colors.value, + "nameColor": widget.settings.colors.name, + "valueColor": widget.settings.colors.value, "Ip": info.Query, "ISP": info.ISP, "AS": info.AS, diff --git a/modules/ipaddresses/ipinfo/settings.go b/modules/ipaddresses/ipinfo/settings.go new file mode 100644 index 00000000..23ee349d --- /dev/null +++ b/modules/ipaddresses/ipinfo/settings.go @@ -0,0 +1,31 @@ +package ipinfo + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "ipinfo" + +type colors struct { + name string + value string +} + +type Settings struct { + colors + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + settings.colors.name = localConfig.UString("colors.name", "red") + settings.colors.value = localConfig.UString("colors.value", "white") + + return &settings +} diff --git a/modules/ipaddresses/ipinfo/widget.go b/modules/ipaddresses/ipinfo/widget.go index 7ee92a4b..0f282519 100644 --- a/modules/ipaddresses/ipinfo/widget.go +++ b/modules/ipaddresses/ipinfo/widget.go @@ -13,10 +13,9 @@ import ( type Widget struct { wtf.TextWidget - result string - colors struct { - name, value string - } + + result string + settings *Settings } type ipinfo struct { @@ -30,15 +29,15 @@ type ipinfo struct { Organization string `json:"org"` } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "IPInfo", "ipinfo", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } widget.View.SetWrap(false) - widget.config() - return &widget } @@ -75,12 +74,6 @@ func (widget *Widget) ipinfo() { widget.setResult(&info) } -// read module configs -func (widget *Widget) config() { - widget.colors.name = wtf.Config.UString("wtf.mods.ipinfo.colors.name", "white") - widget.colors.value = wtf.Config.UString("wtf.mods.ipinfo.colors.value", "white") -} - func (widget *Widget) setResult(info *ipinfo) { resultTemplate, _ := template.New("ipinfo_result").Parse( formatableText("IP", "Ip") + @@ -95,8 +88,8 @@ func (widget *Widget) setResult(info *ipinfo) { resultBuffer := new(bytes.Buffer) resultTemplate.Execute(resultBuffer, map[string]string{ - "nameColor": widget.colors.name, - "valueColor": widget.colors.value, + "nameColor": widget.settings.colors.name, + "valueColor": widget.settings.colors.value, "Ip": info.Ip, "Hostname": info.Hostname, "City": info.City, diff --git a/modules/jenkins/client.go b/modules/jenkins/client.go index 97105c86..7d7cfeb0 100644 --- a/modules/jenkins/client.go +++ b/modules/jenkins/client.go @@ -9,11 +9,9 @@ import ( "net/http" "net/url" "strings" - - "github.com/wtfutil/wtf/wtf" ) -func Create(jenkinsURL string, username string, apiKey string) (*View, error) { +func (widget *Widget) Create(jenkinsURL string, username string, apiKey string) (*View, error) { const apiSuffix = "api/json?pretty=true" parsedSuffix, err := url.Parse(apiSuffix) if err != nil { @@ -29,10 +27,9 @@ func Create(jenkinsURL string, username string, apiKey string) (*View, error) { req, _ := http.NewRequest("GET", jenkinsAPIURL.String(), nil) req.SetBasicAuth(username, apiKey) - verifyServerCertificate := wtf.Config.UBool("wtf.mods.jenkins.verifyServerCertificate", true) httpClient := &http.Client{Transport: &http.Transport{ TLSClientConfig: &tls.Config{ - InsecureSkipVerify: !verifyServerCertificate, + InsecureSkipVerify: !widget.settings.verifyServerCertificate, }, Proxy: http.ProxyFromEnvironment, }, diff --git a/modules/jenkins/settings.go b/modules/jenkins/settings.go new file mode 100644 index 00000000..6a132a66 --- /dev/null +++ b/modules/jenkins/settings.go @@ -0,0 +1,38 @@ +package jenkins + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "jenkins" + +type Settings struct { + common *cfg.Common + + apiKey string + jobNameRegex string + successBallColor string + url string + user string + verifyServerCertificate bool +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_JENKINS_API_KEY")), + jobNameRegex: localConfig.UString("jobNameRegex", ".*"), + successBallColor: localConfig.UString("successBallColor", "blue"), + url: localConfig.UString("url"), + user: localConfig.UString("user"), + verifyServerCertificate: localConfig.UBool("verifyServerCertificate", true), + } + + return &settings +} diff --git a/modules/jenkins/widget.go b/modules/jenkins/widget.go index 25ddfdbe..145c397b 100644 --- a/modules/jenkins/widget.go +++ b/modules/jenkins/widget.go @@ -2,12 +2,12 @@ package jenkins import ( "fmt" - "regexp" + "strconv" + "github.com/gdamore/tcell" "github.com/rivo/tview" "github.com/wtfutil/wtf/wtf" - "os" - "strconv" + "regexp" ) const HelpText = ` @@ -28,14 +28,17 @@ type Widget struct { wtf.HelpfulWidget wtf.TextWidget - view *View selected int + settings *Settings + view *View } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Jenkins", "jenkins", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.HelpfulWidget.SetView(widget.View) @@ -55,10 +58,10 @@ func (widget *Widget) Refresh() { return } - view, err := Create( - wtf.Config.UString("wtf.mods.jenkins.url"), - wtf.Config.UString("wtf.mods.jenkins.user"), - widget.apiKey(), + view, err := widget.Create( + widget.settings.url, + widget.settings.user, + widget.settings.apiKey, ) widget.view = view @@ -86,18 +89,11 @@ func (widget *Widget) display() { widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight() } -func (widget *Widget) apiKey() string { - return wtf.Config.UString( - "wtf.mods.jenkins.apiKey", - os.Getenv("WTF_JENKINS_API_KEY"), - ) -} - func (widget *Widget) contentFrom(view *View) string { var str string for idx, job := range view.Jobs { - regex := wtf.Config.UString("wtf.mods.jenkins.jobNameRegex", ".*") - var validID = regexp.MustCompile(regex) + var validID = regexp.MustCompile(widget.settings.jobNameRegex) + if validID.MatchString(job.Name) { str = str + fmt.Sprintf( `["%d"][""][%s] [%s]%-6s[white]`, @@ -126,12 +122,7 @@ func (widget *Widget) jobColor(job *Job) string { switch job.Color { case "blue": // Override color if successBallColor boolean param provided in config - ballColor := wtf.Config.UString("wtf.mods.jenkins.successBallColor", "blue") - if ballColor != "blue" { - return ballColor - } else { - return "blue" - } + return widget.settings.successBallColor case "red": return "red" default: diff --git a/modules/jira/client.go b/modules/jira/client.go index df639251..15818076 100644 --- a/modules/jira/client.go +++ b/modules/jira/client.go @@ -9,13 +9,10 @@ import ( "io/ioutil" "net/http" "net/url" - "os" "strings" - - "github.com/wtfutil/wtf/wtf" ) -func IssuesFor(username string, projects []string, jql string) (*SearchResult, error) { +func (widget *Widget) IssuesFor(username string, projects []string, jql string) (*SearchResult, error) { query := []string{} var projQuery = getProjectQuery(projects) @@ -37,7 +34,7 @@ func IssuesFor(username string, projects []string, jql string) (*SearchResult, e url := fmt.Sprintf("/rest/api/2/search?%s", v.Encode()) - resp, err := jiraRequest(url) + resp, err := widget.jiraRequest(url) if err != nil { return &SearchResult{}, err } @@ -54,26 +51,18 @@ func buildJql(key string, value string) string { /* -------------------- Unexported Functions -------------------- */ -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.jira.apiKey", - os.Getenv("WTF_JIRA_API_KEY"), - ) -} - -func jiraRequest(path string) (*http.Response, error) { - url := fmt.Sprintf("%s%s", wtf.Config.UString("wtf.mods.jira.domain"), path) +func (widget *Widget) jiraRequest(path string) (*http.Response, error) { + url := fmt.Sprintf("%s%s", widget.settings.domain, path) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } - req.SetBasicAuth(wtf.Config.UString("wtf.mods.jira.email"), apiKey()) + req.SetBasicAuth(widget.settings.email, widget.settings.apiKey) - verifyServerCertificate := wtf.Config.UBool("wtf.mods.jira.verifyServerCertificate", true) httpClient := &http.Client{Transport: &http.Transport{ TLSClientConfig: &tls.Config{ - InsecureSkipVerify: !verifyServerCertificate, + InsecureSkipVerify: !widget.settings.verifyServerCertificate, }, Proxy: http.ProxyFromEnvironment, }, diff --git a/modules/jira/settings.go b/modules/jira/settings.go new file mode 100644 index 00000000..a55cc597 --- /dev/null +++ b/modules/jira/settings.go @@ -0,0 +1,76 @@ +package jira + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "jira" + +type colors struct { + rows struct { + even string + odd string + } +} + +type Settings struct { + colors + common *cfg.Common + + apiKey string + domain string + email string + jql string + projects []string + username string + verifyServerCertificate bool +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_JIRA_API_KEY")), + domain: localConfig.UString("domain"), + email: localConfig.UString("email"), + jql: localConfig.UString("jql"), + username: localConfig.UString("username"), + verifyServerCertificate: localConfig.UBool("verifyServerCertificate", true), + } + + settings.colors.rows.even = localConfig.UString("colors.even", "lightblue") + settings.colors.rows.odd = localConfig.UString("colors.odd", "white") + + settings.projects = settings.arrayifyProjects(localConfig) + + return &settings +} + +/* -------------------- Unexported functions -------------------- */ + +// arrayifyProjects figures out if we're dealing with a single project or an array of projects +func (settings *Settings) arrayifyProjects(localConfig *config.Config) []string { + projects := []string{} + + // Single project + project, err := localConfig.String("project") + if err == nil { + projects = append(projects, project) + return projects + } + + // Array of projects + projectList := localConfig.UList("project") + for _, projectName := range projectList { + if project, ok := projectName.(string); ok { + projects = append(projects, project) + } + } + + return projects +} diff --git a/modules/jira/widget.go b/modules/jira/widget.go index ef260a12..91047552 100644 --- a/modules/jira/widget.go +++ b/modules/jira/widget.go @@ -28,12 +28,15 @@ type Widget struct { result *SearchResult selected int + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Jira", "jira", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.HelpfulWidget.SetView(widget.View) @@ -48,10 +51,10 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - searchResult, err := IssuesFor( - wtf.Config.UString("wtf.mods.jira.username"), - getProjects(), - wtf.Config.UString("wtf.mods.jira.jql", ""), + searchResult, err := widget.IssuesFor( + widget.settings.username, + widget.settings.projects, + widget.settings.jql, ) if err != nil { @@ -74,7 +77,7 @@ func (widget *Widget) display() { } widget.View.SetWrap(false) - str := fmt.Sprintf("%s- [green]%s[white]", widget.Name(), wtf.Config.UString("wtf.mods.jira.project")) + str := fmt.Sprintf("%s- [green]%s[white]", widget.Name(), widget.settings.projects) widget.View.Clear() widget.View.SetTitle(widget.ContextualTitle(str)) @@ -100,7 +103,7 @@ func (widget *Widget) openItem() { sel := widget.selected if sel >= 0 && widget.result != nil && sel < len(widget.result.Issues) { issue := &widget.result.Issues[widget.selected] - wtf.OpenFile(wtf.Config.UString("wtf.mods.jira.domain") + "/browse/" + issue.Key) + wtf.OpenFile(widget.settings.domain + "/browse/" + issue.Key) } } @@ -137,7 +140,12 @@ func (widget *Widget) rowColor(idx int) string { if widget.View.HasFocus() && (idx == widget.selected) { return wtf.DefaultFocussedRowColor() } - return wtf.RowColor("jira", idx) + + if idx%2 == 0 { + return widget.settings.colors.rows.even + } + + return widget.settings.colors.rows.odd } func (widget *Widget) issueTypeColor(issue *Issue) string { @@ -153,24 +161,6 @@ func (widget *Widget) issueTypeColor(issue *Issue) string { } } -func getProjects() []string { - // see if project is set to a single string - configPath := "wtf.mods.jira.project" - singleProject, err := wtf.Config.String(configPath) - if err == nil { - return []string{singleProject} - } - // else, assume list - projList := wtf.Config.UList(configPath) - var ret []string - for _, proj := range projList { - if str, ok := proj.(string); ok { - ret = append(ret, str) - } - } - return ret -} - func (widget *Widget) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { switch string(event.Rune()) { case "/": diff --git a/modules/mercurial/hg_repo.go b/modules/mercurial/hg_repo.go index 27774c96..ae53a21f 100644 --- a/modules/mercurial/hg_repo.go +++ b/modules/mercurial/hg_repo.go @@ -19,13 +19,13 @@ type MercurialRepo struct { Path string } -func NewMercurialRepo(repoPath string) *MercurialRepo { +func NewMercurialRepo(repoPath string, commitCount int, commitFormat string) *MercurialRepo { repo := MercurialRepo{Path: repoPath} repo.Branch = strings.TrimSpace(repo.branch()) repo.Bookmark = strings.TrimSpace(repo.bookmark()) repo.ChangedFiles = repo.changedFiles() - repo.Commits = repo.commits() + repo.Commits = repo.commits(commitCount, commitFormat) repo.Repository = strings.TrimSpace(repo.Path) return &repo @@ -61,10 +61,8 @@ func (repo *MercurialRepo) changedFiles() []string { return data } -func (repo *MercurialRepo) commits() []string { - numStr := fmt.Sprintf("-l %d", wtf.Config.UInt("wtf.mods.mercurial.commitCount", 10)) - - commitFormat := wtf.Config.UString("wtf.mods.mercurial.commitFormat", "[forestgreen]{rev}:{phase} [white]{desc|firstline|strip} [grey]{author|person} {date|age}[white]") +func (repo *MercurialRepo) commits(commitCount int, commitFormat string) []string { + numStr := fmt.Sprintf("-l %d", commitCount) commitStr := fmt.Sprintf("--template=\"%s\n\"", commitFormat) arg := []string{"log", repo.repoPath(), numStr, commitStr} diff --git a/modules/mercurial/settings.go b/modules/mercurial/settings.go new file mode 100644 index 00000000..b21f366e --- /dev/null +++ b/modules/mercurial/settings.go @@ -0,0 +1,30 @@ +package mercurial + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "mercurial" + +type Settings struct { + common *cfg.Common + + commitCount int + commitFormat string + repositories []interface{} +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + commitCount: localConfig.UInt("commitCount", 10), + commitFormat: localConfig.UString("commitFormat", "[forestgreen]{rev}:{phase} [white]{desc|firstline|strip} [grey]{author|person} {date|age}[white]"), + repositories: localConfig.UList("repositories"), + } + + return &settings +} diff --git a/modules/mercurial/widget.go b/modules/mercurial/widget.go index 2947fef7..cffe384b 100644 --- a/modules/mercurial/widget.go +++ b/modules/mercurial/widget.go @@ -28,19 +28,21 @@ type Widget struct { wtf.MultiSourceWidget wtf.TextWidget - app *tview.Application - Data []*MercurialRepo - pages *tview.Pages + app *tview.Application + Data []*MercurialRepo + pages *tview.Pages + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - MultiSourceWidget: wtf.NewMultiSourceWidget("mercurial", "repository", "repositories"), - TextWidget: wtf.NewTextWidget(app, "Mercurial", "mercurial", true), + MultiSourceWidget: wtf.NewMultiSourceWidget(settings.common.ConfigKey, "repository", "repositories"), + TextWidget: wtf.NewTextWidget(app, settings.common, true), - app: app, - pages: pages, + app: app, + pages: pages, + settings: settings, } widget.LoadSources() @@ -79,7 +81,7 @@ func (widget *Widget) Pull() { } func (widget *Widget) Refresh() { - repoPaths := wtf.ToStrs(wtf.Config.UList("wtf.mods.mercurial.repositories")) + repoPaths := wtf.ToStrs(widget.settings.repositories) widget.Data = widget.mercurialRepos(repoPaths) widget.display() @@ -156,7 +158,7 @@ func (widget *Widget) mercurialRepos(repoPaths []string) []*MercurialRepo { repos := []*MercurialRepo{} for _, repoPath := range repoPaths { - repo := NewMercurialRepo(repoPath) + repo := NewMercurialRepo(repoPath, widget.settings.commitCount, widget.settings.commitFormat) repos = append(repos, repo) } diff --git a/modules/nbascore/settings.go b/modules/nbascore/settings.go new file mode 100644 index 00000000..245c0ff0 --- /dev/null +++ b/modules/nbascore/settings.go @@ -0,0 +1,20 @@ +package nbascore + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "nbascore" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/nbascore/widget.go b/modules/nbascore/widget.go index 242decb9..d506fcee 100644 --- a/modules/nbascore/widget.go +++ b/modules/nbascore/widget.go @@ -22,22 +22,23 @@ const HelpText = ` type Widget struct { wtf.HelpfulWidget wtf.TextWidget - app *tview.Application - pages *tview.Pages + language string result string + settings *Settings } var offset = 0 -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "NBA Score", "nbascore", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.HelpfulWidget.SetView(widget.View) - widget.TextWidget.RefreshInt = 15 widget.View.SetInputCapture(widget.keyboardIntercept) widget.View.SetScrollable(true) diff --git a/modules/newrelic/settings.go b/modules/newrelic/settings.go new file mode 100644 index 00000000..92a5eb54 --- /dev/null +++ b/modules/newrelic/settings.go @@ -0,0 +1,32 @@ +package newrelic + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "newrelic" + +type Settings struct { + common *cfg.Common + + apiKey string + applicationID int + deployCount int +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_NEW_RELIC_API_KEY")), + applicationID: localConfig.UInt("applicationID"), + deployCount: localConfig.UInt("deployCount", 5), + } + + return &settings +} diff --git a/modules/newrelic/widget.go b/modules/newrelic/widget.go index 591426c5..73c24039 100644 --- a/modules/newrelic/widget.go +++ b/modules/newrelic/widget.go @@ -2,7 +2,6 @@ package newrelic import ( "fmt" - "os" "github.com/rivo/tview" "github.com/wtfutil/wtf/wtf" @@ -11,15 +10,20 @@ import ( type Widget struct { wtf.TextWidget - client *Client + + client *Client + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "New Relic", "newrelic", false), - client: NewClient(apiKey(), wtf.Config.UInt("wtf.mods.newrelic.applicationId")), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } + widget.client = NewClient(widget.settings.apiKey, widget.settings.applicationID) + return &widget } @@ -81,7 +85,7 @@ func (widget *Widget) contentFrom(deploys []nr.ApplicationDeployment) string { revisions = append(revisions, deploy.Revision) - if len(revisions) == wtf.Config.UInt("wtf.mods.newrelic.deployCount", 5) { + if len(revisions) == widget.settings.deployCount { break } } @@ -89,10 +93,3 @@ func (widget *Widget) contentFrom(deploys []nr.ApplicationDeployment) string { return str } - -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.newrelic.apiKey", - os.Getenv("WTF_NEW_RELIC_API_KEY"), - ) -} diff --git a/modules/opsgenie/client.go b/modules/opsgenie/client.go index 4e56bec9..928ad57e 100644 --- a/modules/opsgenie/client.go +++ b/modules/opsgenie/client.go @@ -4,9 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "os" - - "github.com/wtfutil/wtf/wtf" ) type OnCallResponse struct { @@ -29,11 +26,12 @@ type Parent struct { /* -------------------- Exported Functions -------------------- */ -func Fetch(scheduleIdentifierType string, schedules []string) ([]*OnCallResponse, error) { +func (widget *Widget) Fetch(scheduleIdentifierType string, schedules []string) ([]*OnCallResponse, error) { agregatedResponses := []*OnCallResponse{} + for _, sched := range schedules { scheduleUrl := fmt.Sprintf("https://api.opsgenie.com/v2/schedules/%s/on-calls?scheduleIdentifierType=%s&flat=true", sched, scheduleIdentifierType) - response, err := opsGenieRequest(scheduleUrl, apiKey()) + response, err := opsGenieRequest(scheduleUrl, widget.settings.apiKey) agregatedResponses = append(agregatedResponses, response) if err != nil { return nil, err @@ -44,13 +42,6 @@ func Fetch(scheduleIdentifierType string, schedules []string) ([]*OnCallResponse /* -------------------- Unexported Functions -------------------- */ -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.opsgenie.apiKey", - os.Getenv("WTF_OPS_GENIE_API_KEY"), - ) -} - func opsGenieRequest(url string, apiKey string) (*OnCallResponse, error) { req, err := http.NewRequest("GET", url, nil) if err != nil { diff --git a/modules/opsgenie/settings.go b/modules/opsgenie/settings.go new file mode 100644 index 00000000..3da2c2e8 --- /dev/null +++ b/modules/opsgenie/settings.go @@ -0,0 +1,57 @@ +package opsgenie + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "opsgenie" + +type Settings struct { + common *cfg.Common + + apiKey string + displayEmpty bool + schedule []string + scheduleIdentifierType string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_OPS_GENIE_API_KEY")), + displayEmpty: localConfig.UBool("displayEmpty", true), + scheduleIdentifierType: localConfig.UString("scheduleIdentifierType", "id"), + } + + settings.schedule = settings.arrayifySchedules(localConfig) + + return &settings +} + +// arrayifySchedules figures out if we're dealing with a single project or an array of projects +func (settings *Settings) arrayifySchedules(localConfig *config.Config) []string { + schedules := []string{} + + // Single schedule + schedule, err := localConfig.String("schedule") + if err == nil { + schedules = append(schedules, schedule) + return schedules + } + + // Array of schedules + scheduleList := localConfig.UList("schedule") + for _, scheduleName := range scheduleList { + if schedule, ok := scheduleName.(string); ok { + schedules = append(schedules, schedule) + } + } + + return schedules +} diff --git a/modules/opsgenie/widget.go b/modules/opsgenie/widget.go index 717c5f34..d6d34b2a 100644 --- a/modules/opsgenie/widget.go +++ b/modules/opsgenie/widget.go @@ -10,11 +10,15 @@ import ( type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "OpsGenie", "opsgenie", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -23,10 +27,11 @@ func NewWidget(app *tview.Application) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - data, err := Fetch( - wtf.Config.UString("wtf.mods.opsgenie.scheduleIdentifierType"), - getSchedules(), + data, err := widget.Fetch( + widget.settings.scheduleIdentifierType, + widget.settings.schedule, ) + widget.View.SetTitle(widget.ContextualTitle(widget.Name())) var content string @@ -43,31 +48,11 @@ func (widget *Widget) Refresh() { /* -------------------- Unexported Functions -------------------- */ -func getSchedules() []string { - // see if schedule is set to a single string - configPath := "wtf.mods.opsgenie.schedule" - singleSchedule, err := wtf.Config.String(configPath) - if err == nil { - return []string{singleSchedule} - } - // else, assume list - scheduleList := wtf.Config.UList(configPath) - var ret []string - for _, schedule := range scheduleList { - if str, ok := schedule.(string); ok { - ret = append(ret, str) - } - } - return ret -} - func (widget *Widget) contentFrom(onCallResponses []*OnCallResponse) string { str := "" - displayEmpty := wtf.Config.UBool("wtf.mods.opsgenie.displayEmpty", true) - for _, data := range onCallResponses { - if (len(data.OnCallData.Recipients) == 0) && (displayEmpty == false) { + if (len(data.OnCallData.Recipients) == 0) && (widget.settings.displayEmpty == false) { continue } diff --git a/modules/pagerduty/client.go b/modules/pagerduty/client.go index d8f28421..aa8766b9 100644 --- a/modules/pagerduty/client.go +++ b/modules/pagerduty/client.go @@ -1,16 +1,14 @@ package pagerduty import ( - "os" "time" "github.com/PagerDuty/go-pagerduty" - "github.com/wtfutil/wtf/wtf" ) // GetOnCalls returns a list of people currently on call -func GetOnCalls() ([]pagerduty.OnCall, error) { - client := pagerduty.NewClient(apiKey()) +func GetOnCalls(apiKey string) ([]pagerduty.OnCall, error) { + client := pagerduty.NewClient(apiKey) var results []pagerduty.OnCall @@ -38,8 +36,8 @@ func GetOnCalls() ([]pagerduty.OnCall, error) { } // GetIncidents returns a list of people currently on call -func GetIncidents() ([]pagerduty.Incident, error) { - client := pagerduty.NewClient(apiKey()) +func GetIncidents(apiKey string) ([]pagerduty.Incident, error) { + client := pagerduty.NewClient(apiKey) var results []pagerduty.Incident @@ -64,10 +62,3 @@ func GetIncidents() ([]pagerduty.Incident, error) { return results, nil } - -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.pagerduty.apiKey", - os.Getenv("WTF_PAGERDUTY_API_KEY"), - ) -} diff --git a/modules/pagerduty/settings.go b/modules/pagerduty/settings.go new file mode 100644 index 00000000..473bc403 --- /dev/null +++ b/modules/pagerduty/settings.go @@ -0,0 +1,34 @@ +package pagerduty + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "pagerduty" + +type Settings struct { + common *cfg.Common + + apiKey string + escalationFilter []interface{} + showIncidents bool + showSchedules bool +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_PAGERDUTY_API_KEY")), + escalationFilter: localConfig.UList("escalationFilter"), + showIncidents: localConfig.UBool("showIncidents", true), + showSchedules: localConfig.UBool("showSchedules", true), + } + + return &settings +} diff --git a/modules/pagerduty/widget.go b/modules/pagerduty/widget.go index 469abbdb..4db3f72b 100644 --- a/modules/pagerduty/widget.go +++ b/modules/pagerduty/widget.go @@ -11,11 +11,15 @@ import ( type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "PagerDuty", "pagerduty", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -30,12 +34,12 @@ func (widget *Widget) Refresh() { var err1 error var err2 error - if wtf.Config.UBool("wtf.mods.pagerduty.showSchedules", true) { - onCalls, err1 = GetOnCalls() + if widget.settings.showSchedules { + onCalls, err1 = GetOnCalls(widget.settings.apiKey) } - if wtf.Config.UBool("wtf.mods.pagerduty.showIncidents") { - incidents, err2 = GetIncidents() + if widget.settings.showIncidents { + incidents, err2 = GetIncidents(widget.settings.apiKey) } widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s", widget.Name()))) @@ -75,15 +79,14 @@ func (widget *Widget) contentFrom(onCalls []pagerduty.OnCall, incidents []pagerd tree := make(map[string][]pagerduty.OnCall) - filtering := wtf.Config.UList("wtf.mods.pagerduty.escalationFilter") filter := make(map[string]bool) - for _, item := range filtering { + for _, item := range widget.settings.escalationFilter { filter[item.(string)] = true } for _, onCall := range onCalls { key := onCall.EscalationPolicy.Summary - if len(filtering) == 0 || filter[key] { + if len(widget.settings.escalationFilter) == 0 || filter[key] { tree[key] = append(tree[key], onCall) } } diff --git a/modules/power/settings.go b/modules/power/settings.go new file mode 100644 index 00000000..bae89013 --- /dev/null +++ b/modules/power/settings.go @@ -0,0 +1,22 @@ +package power + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "power" + +type Settings struct { + common *cfg.Common + + filePath string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/power/widget.go b/modules/power/widget.go index ee091df3..db25265e 100644 --- a/modules/power/widget.go +++ b/modules/power/widget.go @@ -10,13 +10,16 @@ import ( type Widget struct { wtf.TextWidget - Battery *Battery + Battery *Battery + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Power", "power", false), - Battery: NewBattery(), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + Battery: NewBattery(), + settings: settings, } widget.View.SetWrap(true) diff --git a/modules/resourceusage/settings.go b/modules/resourceusage/settings.go new file mode 100644 index 00000000..d5f4ae29 --- /dev/null +++ b/modules/resourceusage/settings.go @@ -0,0 +1,20 @@ +package resourceusage + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "resourceusage" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/resourceusage/widget.go b/modules/resourceusage/widget.go index f4991c35..ed7d1a2f 100644 --- a/modules/resourceusage/widget.go +++ b/modules/resourceusage/widget.go @@ -17,12 +17,16 @@ var ok = true // Widget define wtf widget to register widget later type Widget struct { wtf.BarGraph + + settings *Settings } // NewWidget Make new instance of widget -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - BarGraph: wtf.NewBarGraph(app, "Resource Usage", "resourceusage", false), + BarGraph: wtf.NewBarGraph(app, settings.common.Name, settings.common.ConfigKey, false), + + settings: settings, } widget.View.SetWrap(false) diff --git a/modules/rollbar/client.go b/modules/rollbar/client.go index 751f79f7..90337ae3 100644 --- a/modules/rollbar/client.go +++ b/modules/rollbar/client.go @@ -8,17 +8,14 @@ import ( "io/ioutil" "net/http" "net/url" - - "github.com/wtfutil/wtf/wtf" ) -func CurrentActiveItems() (*ActiveItems, error) { +func CurrentActiveItems(accessToken, assignedToName string, activeOnly bool) (*ActiveItems, error) { items := &ActiveItems{} - accessToken := wtf.Config.UString("wtf.mods.rollbar.accessToken", "") rollbarAPIURL.Host = "api.rollbar.com" rollbarAPIURL.Path = "/api/1/items" - resp, err := rollbarItemRequest(accessToken) + resp, err := rollbarItemRequest(accessToken, assignedToName, activeOnly) if err != nil { return items, err } @@ -34,13 +31,11 @@ var ( rollbarAPIURL = &url.URL{Scheme: "https"} ) -func rollbarItemRequest(accessToken string) (*http.Response, error) { +func rollbarItemRequest(accessToken, assignedToName string, activeOnly bool) (*http.Response, error) { params := url.Values{} params.Add("access_token", accessToken) - userName := wtf.Config.UString("wtf.mods.rollbar.assignedToName", "") - params.Add("assigned_user", userName) - active := wtf.Config.UBool("wtf.mods.rollbar.activeOnly", false) - if active { + params.Add("assigned_user", assignedToName) + if activeOnly { params.Add("status", "active") } diff --git a/modules/rollbar/settings.go b/modules/rollbar/settings.go new file mode 100644 index 00000000..7f24774d --- /dev/null +++ b/modules/rollbar/settings.go @@ -0,0 +1,36 @@ +package rollbar + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "rollbar" + +type Settings struct { + common *cfg.Common + + accessToken string + activeOnly bool + assignedToName string + count int + projectName string + projectOwner string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + accessToken: localConfig.UString("accessToken"), + activeOnly: localConfig.UBool("activeOnly", false), + assignedToName: localConfig.UString("assignedToName"), + count: localConfig.UInt("count", 10), + projectName: localConfig.UString("projectName", "Items"), + projectOwner: localConfig.UString("projectOwner"), + } + + return &settings +} diff --git a/modules/rollbar/widget.go b/modules/rollbar/widget.go index e1f34204..985b7079 100644 --- a/modules/rollbar/widget.go +++ b/modules/rollbar/widget.go @@ -29,13 +29,17 @@ type Widget struct { items *Result selected int + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Rollbar", "rollbar", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } + widget.HelpfulWidget.SetView(widget.View) widget.unselect() @@ -51,7 +55,11 @@ func (widget *Widget) Refresh() { return } - items, err := CurrentActiveItems() + items, err := CurrentActiveItems( + widget.settings.accessToken, + widget.settings.assignedToName, + widget.settings.activeOnly, + ) if err != nil { widget.View.SetWrap(true) @@ -72,16 +80,14 @@ func (widget *Widget) display() { } widget.View.SetWrap(false) - projectName := wtf.Config.UString("wtf.mods.rollbar.projectName", "Items") - widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %s", widget.Name(), projectName))) + widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %s", widget.Name(), widget.settings.projectName))) widget.View.SetText(widget.contentFrom(widget.items)) } func (widget *Widget) contentFrom(result *Result) string { var str string - count := wtf.Config.UInt("wtf.mods.rollbar.count", 10) - if len(result.Items) > count { - result.Items = result.Items[:count] + if len(result.Items) > widget.settings.count { + result.Items = result.Items[:widget.settings.count] } for idx, item := range result.Items { @@ -151,12 +157,18 @@ func (widget *Widget) prev() { } func (widget *Widget) openBuild() { - sel := widget.selected - projectOwner := wtf.Config.UString("wtf.mods.rollbar.projectOwner", "") - projectName := wtf.Config.UString("wtf.mods.rollbar.projectName", "") - if sel >= 0 && widget.items != nil && sel < len(widget.items.Items) { + if widget.selected >= 0 && widget.items != nil && widget.selected < len(widget.items.Items) { item := &widget.items.Items[widget.selected] - wtf.OpenFile(fmt.Sprintf("https://rollbar.com/%s/%s/%s/%d", projectOwner, projectName, "items", item.ID)) + + wtf.OpenFile( + fmt.Sprintf( + "https://rollbar.com/%s/%s/%s/%d", + widget.settings.projectOwner, + widget.settings.projectName, + "items", + item.ID, + ), + ) } } diff --git a/modules/security/settings.go b/modules/security/settings.go new file mode 100644 index 00000000..45e86f4f --- /dev/null +++ b/modules/security/settings.go @@ -0,0 +1,20 @@ +package security + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "security" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/security/widget.go b/modules/security/widget.go index 2bd39415..b656ab71 100644 --- a/modules/security/widget.go +++ b/modules/security/widget.go @@ -10,11 +10,15 @@ import ( type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Security", "security", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -48,12 +52,10 @@ func (widget *Widget) contentFrom(data *SecurityData) string { str = str + "\n" str = str + " [red]Users[white]\n" - str = str + fmt.Sprintf(" %s", strings.Join(data.LoggedInUsers, "\n ")) - str = str + "\n" + str = str + fmt.Sprintf(" %s", strings.Join(data.LoggedInUsers, "\n ")) + str = str + "\n\n" str = str + " [red]DNS[white]\n" - //str = str + fmt.Sprintf(" %8s: [%s]%-3s[white] %-16s\n", "Enabled", widget.labelColor(data.FirewallEnabled), data.FirewallEnabled, data.DnsAt(0)) - //str = str + fmt.Sprintf(" %8s: [%s]%-3s[white] %-16s\n", "Stealth", widget.labelColor(data.FirewallStealth), data.FirewallStealth, data.DnsAt(1)) str = str + fmt.Sprintf(" %12s\n", data.DnsAt(0)) str = str + fmt.Sprintf(" %12s\n", data.DnsAt(1)) str = str + "\n" diff --git a/modules/spotify/settings.go b/modules/spotify/settings.go new file mode 100644 index 00000000..50ed6be5 --- /dev/null +++ b/modules/spotify/settings.go @@ -0,0 +1,20 @@ +package spotify + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "spotify" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/spotify/widget.go b/modules/spotify/widget.go index c6b4aadb..b35c0838 100644 --- a/modules/spotify/widget.go +++ b/modules/spotify/widget.go @@ -20,20 +20,26 @@ const HelpText = ` type Widget struct { wtf.HelpfulWidget wtf.TextWidget - spotigopher.SpotifyClient + + settings *Settings spotigopher.Info + spotigopher.SpotifyClient } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { spotifyClient := spotigopher.NewClient() widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Spotify", "spotify", true), - SpotifyClient: spotifyClient, + TextWidget: wtf.NewTextWidget(app, settings.common, true), + Info: spotigopher.Info{}, + SpotifyClient: spotifyClient, + settings: settings, } + + widget.settings.common.RefreshInterval = 5 + widget.HelpfulWidget.SetView(widget.View) - widget.TextWidget.RefreshInt = 5 widget.View.SetInputCapture(widget.captureInput) widget.View.SetWrap(true) widget.View.SetWordWrap(true) diff --git a/modules/spotifyweb/settings.go b/modules/spotifyweb/settings.go new file mode 100644 index 00000000..63b0539a --- /dev/null +++ b/modules/spotifyweb/settings.go @@ -0,0 +1,32 @@ +package spotifyweb + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "spotifyweb" + +type Settings struct { + common *cfg.Common + + callbackPort string + clientID string + secretKey string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + callbackPort: localConfig.UString("callbackPort", "8080"), + clientID: localConfig.UString("clientID", os.Getenv("SPOTIFY_ID")), + secretKey: localConfig.UString("secretKey", os.Getenv("SPOTIFY_SECRET")), + } + + return &settings +} diff --git a/modules/spotifyweb/widget.go b/modules/spotifyweb/widget.go index 02723ffc..fe91efde 100644 --- a/modules/spotifyweb/widget.go +++ b/modules/spotifyweb/widget.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "net/http" - "os" "time" "github.com/gdamore/tcell" @@ -47,10 +46,12 @@ type Info struct { type Widget struct { wtf.HelpfulWidget wtf.TextWidget + Info - clientChan chan *spotify.Client client *spotify.Client + clientChan chan *spotify.Client playerState *spotify.PlayerState + settings *Settings } var ( @@ -79,27 +80,12 @@ func authHandler(w http.ResponseWriter, r *http.Request) { tempClientChan <- &client } -func clientID() string { - return wtf.Config.UString( - "wtf.mods.spotifyweb.clientID", - os.Getenv("SPOTIFY_ID"), - ) -} - -func secretKey() string { - return wtf.Config.UString( - "wtf.mods.spotifyweb.secretKey", - os.Getenv("SPOTIFY_SECRET"), - ) -} - // NewWidget creates a new widget for WTF -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { - callbackPort = wtf.Config.UString("wtf.mods.spotifyweb.callbackPort", "8080") - redirectURI = "http://localhost:" + callbackPort + "/callback" +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { + redirectURI = "http://localhost:" + settings.callbackPort + "/callback" auth = spotify.NewAuthenticator(redirectURI, spotify.ScopeUserReadCurrentlyPlaying, spotify.ScopeUserReadPlaybackState, spotify.ScopeUserModifyPlaybackState) - auth.SetAuthInfo(clientID(), secretKey()) + auth.SetAuthInfo(settings.clientID, settings.secretKey) authURL = auth.AuthURL(state) var client *spotify.Client @@ -107,11 +93,13 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "SpotifyWeb", "spotifyweb", true), - Info: Info{}, - clientChan: tempClientChan, - client: client, - playerState: playerState, + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + Info: Info{}, + client: client, + clientChan: tempClientChan, + playerState: playerState, + settings: settings, } http.HandleFunc("/callback", authHandler) @@ -147,8 +135,9 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { // If inconvenient, I'll remove this option and save the URL in a file or some other method. wtf.OpenFile(`"` + authURL + `"`) + widget.settings.common.RefreshInterval = 5 + widget.HelpfulWidget.SetView(widget.View) - widget.TextWidget.RefreshInt = 5 widget.View.SetInputCapture(widget.captureInput) widget.View.SetWrap(true) widget.View.SetWordWrap(true) diff --git a/modules/status/settings.go b/modules/status/settings.go new file mode 100644 index 00000000..9083f5b2 --- /dev/null +++ b/modules/status/settings.go @@ -0,0 +1,20 @@ +package status + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "status" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/status/widget.go b/modules/status/widget.go index 9af4c26b..e9a07650 100644 --- a/modules/status/widget.go +++ b/modules/status/widget.go @@ -9,12 +9,15 @@ type Widget struct { wtf.TextWidget CurrentIcon int + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Status", "status", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + CurrentIcon: 0, + settings: settings, } return &widget diff --git a/modules/system/settings.go b/modules/system/settings.go new file mode 100644 index 00000000..c748a0b2 --- /dev/null +++ b/modules/system/settings.go @@ -0,0 +1,20 @@ +package system + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "system" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/system/widget.go b/modules/system/widget.go index 063930f7..4bf5b32d 100644 --- a/modules/system/widget.go +++ b/modules/system/widget.go @@ -11,17 +11,19 @@ import ( type Widget struct { wtf.TextWidget - systemInfo *SystemInfo Date string Version string + settings *Settings + systemInfo *SystemInfo } -func NewWidget(app *tview.Application, date, version string) *Widget { +func NewWidget(app *tview.Application, date, version string, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "System", "system", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), - Date: date, - Version: version, + Date: date, + settings: settings, + Version: version, } widget.systemInfo = NewSystemInfo() diff --git a/modules/textfile/settings.go b/modules/textfile/settings.go new file mode 100644 index 00000000..ee692249 --- /dev/null +++ b/modules/textfile/settings.go @@ -0,0 +1,30 @@ +package textfile + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "textfile" + +type Settings struct { + common *cfg.Common + + filePaths []interface{} + format bool + formatStyle string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + filePaths: localConfig.UList("filePaths"), + format: localConfig.UBool("format", false), + formatStyle: localConfig.UString("formatStyle", "vim"), + } + + return &settings +} diff --git a/modules/textfile/widget.go b/modules/textfile/widget.go index 6125681b..c0d01778 100644 --- a/modules/textfile/widget.go +++ b/modules/textfile/widget.go @@ -34,23 +34,25 @@ type Widget struct { wtf.HelpfulWidget wtf.MultiSourceWidget wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - MultiSourceWidget: wtf.NewMultiSourceWidget("textfile", "filePath", "filePaths"), - TextWidget: wtf.NewTextWidget(app, "TextFile", "textfile", true), + MultiSourceWidget: wtf.NewMultiSourceWidget(settings.common.ConfigKey, "filePath", "filePaths"), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } // Don't use a timer for this widget, watch for filesystem changes instead - widget.RefreshInt = 0 - - widget.LoadSources() - widget.SetDisplayFunction(widget.display) + widget.settings.common.RefreshInterval = 0 widget.HelpfulWidget.SetView(widget.View) - + widget.LoadSources() + widget.SetDisplayFunction(widget.display) widget.View.SetWrap(true) widget.View.SetWordWrap(true) widget.View.SetInputCapture(widget.keyboardIntercept) @@ -76,16 +78,14 @@ func (widget *Widget) display() { text := wtf.SigilStr(len(widget.Sources), widget.Idx, widget.View) + "\n" - if wtf.Config.UBool("wtf.mods.textfile.format", false) { + if widget.settings.format { text = text + widget.formattedText() } else { text = text + widget.plainText() } - //widget.View.Lock() widget.View.SetTitle(title) // <- Writes to TextView's title widget.View.SetText(text) // <- Writes to TextView's text - //widget.View.Unlock() } func (widget *Widget) fileName() string { @@ -105,7 +105,7 @@ func (widget *Widget) formattedText() string { lexer = lexers.Fallback } - style := styles.Get(wtf.Config.UString("wtf.mods.textfile.formatStyle", "vim")) + style := styles.Get(widget.settings.formatStyle) if style == nil { style = styles.Fallback } diff --git a/modules/todo/display.go b/modules/todo/display.go index 684a9dee..2471438c 100644 --- a/modules/todo/display.go +++ b/modules/todo/display.go @@ -13,7 +13,10 @@ const checkWidth = 4 func (widget *Widget) display() { str := "" - newList := checklist.NewChecklist() + newList := checklist.NewChecklist( + widget.settings.common.Sigils.CheckedIcon, + widget.settings.common.Sigils.UncheckedIcon, + ) offset := 0 @@ -33,19 +36,19 @@ func (widget *Widget) display() { widget.View.Clear() widget.View.SetText(str) - widget.View.Highlight(strconv.Itoa(widget.list.Selected)).ScrollToHighlight() + widget.View.Highlight(strconv.Itoa(widget.list.Selected())).ScrollToHighlight() } func (widget *Widget) formattedItemLine(idx int, item *checklist.ChecklistItem, selectedItem *checklist.ChecklistItem, maxLen int) string { - foreColor, backColor := "white", wtf.Config.UString("wtf.colors.background", "black") + foreColor, backColor := widget.settings.common.Colors.Text, widget.settings.common.Colors.Background if item.Checked { - foreColor = wtf.Config.UString("wtf.colors.checked", "white") + foreColor = widget.settings.common.Colors.Checked } if widget.View.HasFocus() && (item == selectedItem) { - foreColor = wtf.Config.UString("wtf.colors.highlight.fore", "black") - backColor = wtf.Config.UString("wtf.colors.highlight.back", "orange") + foreColor = widget.settings.common.Colors.HighlightFore + backColor = widget.settings.common.Colors.HighlightBack } str := fmt.Sprintf( diff --git a/modules/todo/settings.go b/modules/todo/settings.go new file mode 100644 index 00000000..1cf6eeb4 --- /dev/null +++ b/modules/todo/settings.go @@ -0,0 +1,26 @@ +package todo + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "todo" + +type Settings struct { + common *cfg.Common + + filePath string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + filePath: localConfig.UString("filename"), + } + + return &settings +} diff --git a/modules/todo/widget.go b/modules/todo/widget.go index 5f0abeba..51367b38 100644 --- a/modules/todo/widget.go +++ b/modules/todo/widget.go @@ -40,19 +40,21 @@ type Widget struct { wtf.TextWidget app *tview.Application + settings *Settings filePath string list checklist.Checklist pages *tview.Pages } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Todo", "todo", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), app: app, - filePath: wtf.Config.UString("wtf.mods.todo.filename"), - list: checklist.NewChecklist(), + settings: settings, + filePath: settings.filePath, + list: checklist.NewChecklist(settings.common.Sigils.CheckedIcon, settings.common.Sigils.UncheckedIcon), pages: pages, } @@ -191,7 +193,10 @@ func (widget *Widget) load() { filePath := fmt.Sprintf("%s/%s", confDir, widget.filePath) fileData, _ := wtf.ReadFileBytes(filePath) + yaml.Unmarshal(fileData, &widget.list) + + widget.setItemChecks() } func (widget *Widget) newItem() { @@ -225,6 +230,15 @@ func (widget *Widget) persist() { } } +// setItemChecks rolls through the checklist and ensures that all checklist +// items have the correct checked/unchecked icon per the user's preferences +func (widget *Widget) setItemChecks() { + for _, item := range widget.list.Items { + item.CheckedIcon = widget.settings.common.CheckedIcon + item.UncheckedIcon = widget.settings.common.UncheckedIcon + } +} + /* -------------------- Modal Form -------------------- */ func (widget *Widget) addButtons(form *tview.Form, saveFctn func()) { @@ -255,11 +269,8 @@ func (widget *Widget) modalFocus(form *tview.Form) { } func (widget *Widget) modalForm(lbl, text string) *tview.Form { - form := tview.NewForm(). - SetFieldBackgroundColor(wtf.ColorFor(wtf.Config.UString("wtf.colors.background", "black"))) - - form.SetButtonsAlign(tview.AlignCenter). - SetButtonTextColor(wtf.ColorFor(wtf.Config.UString("wtf.colors.text", "white"))) + form := tview.NewForm().SetFieldBackgroundColor(wtf.ColorFor(widget.settings.common.Colors.Background)) + form.SetButtonsAlign(tview.AlignCenter).SetButtonTextColor(wtf.ColorFor(widget.settings.common.Colors.Text)) form.AddInputField(lbl, text, 60, nil, nil) diff --git a/modules/todoist/display.go b/modules/todoist/display.go index 0352b6e6..56c5be64 100644 --- a/modules/todoist/display.go +++ b/modules/todoist/display.go @@ -24,11 +24,11 @@ func (widget *Widget) display() { maxLen := proj.LongestLine() for index, item := range proj.tasks { - foreColor, backColor := "white", wtf.Config.UString("wtf.colors.background", "black") + foreColor, backColor := widget.settings.common.Colors.Text, widget.settings.common.Colors.Background if index == proj.index { - foreColor = wtf.Config.UString("wtf.colors.highlight.fore", "black") - backColor = wtf.Config.UString("wtf.colors.highlight.back", "orange") + foreColor = widget.settings.common.Colors.HighlightFore + backColor = widget.settings.common.Colors.HighlightBack } row := fmt.Sprintf( @@ -46,6 +46,5 @@ func (widget *Widget) display() { str = str + row + wtf.PadRow((checkWidth+len(item.Content)), (checkWidth+maxLen+1)) + "\n" } - //widget.View.Clear() widget.View.SetText(str) } diff --git a/modules/todoist/settings.go b/modules/todoist/settings.go new file mode 100644 index 00000000..54979d11 --- /dev/null +++ b/modules/todoist/settings.go @@ -0,0 +1,30 @@ +package todoist + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "todoist" + +type Settings struct { + common *cfg.Common + + apiKey string + projects []interface{} +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_TODOIST_TOKEN")), + projects: localConfig.UList("projects"), + } + + return &settings +} diff --git a/modules/todoist/widget.go b/modules/todoist/widget.go index e59d4751..0a57c22e 100644 --- a/modules/todoist/widget.go +++ b/modules/todoist/widget.go @@ -1,8 +1,6 @@ package todoist import ( - "os" - "github.com/darkSasori/todoist" "github.com/gdamore/tcell" "github.com/rivo/tview" @@ -31,18 +29,21 @@ type Widget struct { wtf.HelpfulWidget wtf.TextWidget - projects []*Project idx int + projects []*Project + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Todoist", "todoist", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.loadAPICredentials() - widget.projects = loadProjects() + widget.loadProjects() widget.HelpfulWidget.SetView(widget.View) widget.View.SetInputCapture(widget.keyboardIntercept) @@ -169,21 +170,18 @@ func (w *Widget) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { } func (widget *Widget) loadAPICredentials() { - todoist.Token = wtf.Config.UString( - "wtf.mods.todoist.apiKey", - os.Getenv("WTF_TODOIST_TOKEN"), - ) + todoist.Token = widget.settings.apiKey } -func loadProjects() []*Project { +func (widget *Widget) loadProjects() { projects := []*Project{} - for _, id := range wtf.Config.UList("wtf.mods.todoist.projects") { + for _, id := range widget.settings.projects { proj := NewProject(id.(int)) projects = append(projects, proj) } - return projects + widget.projects = projects } func (w *Widget) vimBindings(event *tcell.EventKey) tcell.Key { diff --git a/modules/travisci/client.go b/modules/travisci/client.go index a37a0d7b..0434fcfd 100644 --- a/modules/travisci/client.go +++ b/modules/travisci/client.go @@ -8,9 +8,6 @@ import ( "io/ioutil" "net/http" "net/url" - "os" - - "github.com/wtfutil/wtf/wtf" ) var TRAVIS_HOSTS = map[bool]string{ @@ -18,13 +15,12 @@ var TRAVIS_HOSTS = map[bool]string{ true: "travis-ci.com", } -func BuildsFor() (*Builds, error) { +func BuildsFor(apiKey string, pro bool) (*Builds, error) { builds := &Builds{} - pro := wtf.Config.UBool("wtf.mods.travisci.pro", false) travisAPIURL.Host = "api." + TRAVIS_HOSTS[pro] - resp, err := travisRequest("builds") + resp, err := travisRequest(apiKey, "builds") if err != nil { return builds, err } @@ -40,7 +36,7 @@ var ( travisAPIURL = &url.URL{Scheme: "https", Path: "/"} ) -func travisRequest(path string) (*http.Response, error) { +func travisRequest(apiKey string, path string) (*http.Response, error) { params := url.Values{} params.Add("limit", "10") @@ -51,7 +47,7 @@ func travisRequest(path string) (*http.Response, error) { req.Header.Add("Content-Type", "application/json") req.Header.Add("Travis-API-Version", "3") - bearer := fmt.Sprintf("token %s", apiToken()) + bearer := fmt.Sprintf("token %s", apiKey) req.Header.Add("Authorization", bearer) if err != nil { return nil, err @@ -70,13 +66,6 @@ func travisRequest(path string) (*http.Response, error) { return resp, nil } -func apiToken() string { - return wtf.Config.UString( - "wtf.mods.travisci.apiKey", - os.Getenv("WTF_TRAVIS_API_TOKEN"), - ) -} - func parseJson(obj interface{}, text io.Reader) { jsonStream, err := ioutil.ReadAll(text) if err != nil { diff --git a/modules/travisci/settings.go b/modules/travisci/settings.go new file mode 100644 index 00000000..b9660748 --- /dev/null +++ b/modules/travisci/settings.go @@ -0,0 +1,30 @@ +package travisci + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "travisci" + +type Settings struct { + common *cfg.Common + + apiKey string + pro bool +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_TRAVIS_API_TOKEN")), + pro: localConfig.UBool("pro", false), + } + + return &settings +} diff --git a/modules/travisci/widget.go b/modules/travisci/widget.go index 8844fcaf..1265c176 100644 --- a/modules/travisci/widget.go +++ b/modules/travisci/widget.go @@ -28,12 +28,15 @@ type Widget struct { builds *Builds selected int + settings *Settings } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "TravisCI", "travisci", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.HelpfulWidget.SetView(widget.View) @@ -51,7 +54,7 @@ func (widget *Widget) Refresh() { return } - builds, err := BuildsFor() + builds, err := BuildsFor(widget.settings.apiKey, widget.settings.pro) if err != nil { widget.View.SetWrap(true) @@ -147,7 +150,7 @@ func (widget *Widget) openBuild() { sel := widget.selected if sel >= 0 && widget.builds != nil && sel < len(widget.builds.Builds) { build := &widget.builds.Builds[widget.selected] - travisHost := TRAVIS_HOSTS[wtf.Config.UBool("wtf.mods.travisci.pro", false)] + travisHost := TRAVIS_HOSTS[widget.settings.pro] wtf.OpenFile(fmt.Sprintf("https://%s/%s/%s/%d", travisHost, build.Repository.Slug, "builds", build.ID)) } } diff --git a/modules/trello/client.go b/modules/trello/client.go index 3252eb57..f61f9968 100644 --- a/modules/trello/client.go +++ b/modules/trello/client.go @@ -4,11 +4,10 @@ import ( "fmt" "github.com/adlio/trello" - "github.com/wtfutil/wtf/wtf" ) -func GetCards(client *trello.Client, lists map[string]string) (*SearchResult, error) { - boardID, err := getBoardID(client) +func GetCards(client *trello.Client, username string, boardName string, lists map[string]string) (*SearchResult, error) { + boardID, err := getBoardID(client, username, boardName) if err != nil { return nil, err } @@ -43,8 +42,8 @@ func GetCards(client *trello.Client, lists map[string]string) (*SearchResult, er return searchResult, nil } -func getBoardID(client *trello.Client) (string, error) { - member, err := client.GetMember(wtf.Config.UString("wtf.mods.trello.username"), trello.Defaults()) +func getBoardID(client *trello.Client, username, boardName string) (string, error) { + member, err := client.GetMember(username, trello.Defaults()) if err != nil { return "", err } @@ -55,12 +54,12 @@ func getBoardID(client *trello.Client) (string, error) { } for _, board := range boards { - if board.Name == wtf.Config.UString("wtf.mods.trello.board") { + if board.Name == boardName { return board.ID, nil } } - return "", fmt.Errorf("could not find board with name %s", wtf.Config.UString("wtf.mods.trello.board")) + return "", fmt.Errorf("could not find board with name %s", boardName) } func getListIDs(client *trello.Client, boardID string, lists map[string]string) (map[string]string, error) { diff --git a/modules/trello/settings.go b/modules/trello/settings.go new file mode 100644 index 00000000..f7c39df4 --- /dev/null +++ b/modules/trello/settings.go @@ -0,0 +1,58 @@ +package trello + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "trello" + +type Settings struct { + common *cfg.Common + + accessToken string + apiKey string + board string + list map[string]string + username string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + accessToken: localConfig.UString("accessToken", os.Getenv("WTF_TRELLO_ACCESS_TOKEN")), + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_TRELLO_APP_KEY")), + board: localConfig.UString("board"), + username: localConfig.UString("username"), + } + + settings.list = mapifyList(localConfig) + + return &settings +} + +func mapifyList(localConfig *config.Config) map[string]string { + lists := make(map[string]string) + + // Single list + list, err := localConfig.String("list") + if err == nil { + lists[list] = "" + return lists + } + + // Array of lists + listList := localConfig.UList("project") + for _, listName := range listList { + if list, ok := listName.(string); ok { + lists[list] = "" + } + } + + return lists +} diff --git a/modules/trello/widget.go b/modules/trello/widget.go index 61ddf0cc..fd79984f 100644 --- a/modules/trello/widget.go +++ b/modules/trello/widget.go @@ -2,7 +2,6 @@ package trello import ( "fmt" - "os" "github.com/adlio/trello" "github.com/rivo/tview" @@ -11,11 +10,15 @@ import ( type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Trello", "trello", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -25,12 +28,17 @@ func NewWidget(app *tview.Application) *Widget { func (widget *Widget) Refresh() { client := trello.NewClient( - widget.apiKey(), - widget.accessToken(), + widget.settings.apiKey, + widget.settings.accessToken, ) // Get the cards - searchResult, err := GetCards(client, getLists()) + searchResult, err := GetCards( + client, + widget.settings.username, + widget.settings.board, + widget.settings.list, + ) var content string if err != nil { @@ -43,7 +51,7 @@ func (widget *Widget) Refresh() { fmt.Sprintf( "[white]%s: [green]%s ", widget.Name(), - wtf.Config.UString("wtf.mods.trello.board"), + widget.settings.board, ), ) content = widget.contentFrom(searchResult) @@ -54,20 +62,6 @@ func (widget *Widget) Refresh() { /* -------------------- Unexported Functions -------------------- */ -func (widget *Widget) accessToken() string { - return wtf.Config.UString( - "wtf.mods.trello.accessToken", - os.Getenv("WTF_TRELLO_ACCESS_TOKEN"), - ) -} - -func (widget *Widget) apiKey() string { - return wtf.Config.UString( - "wtf.mods.trello.apiKey", - os.Getenv("WTF_TRELLO_APP_KEY"), - ) -} - func (widget *Widget) contentFrom(searchResult *SearchResult) string { str := "" @@ -81,22 +75,3 @@ func (widget *Widget) contentFrom(searchResult *SearchResult) string { return str } - -func getLists() map[string]string { - list := make(map[string]string) - // see if project is set to a single string - configPath := "wtf.mods.trello.list" - singleList, err := wtf.Config.String(configPath) - if err == nil { - list[singleList] = "" - return list - } - // else, assume list - multiList := wtf.Config.UList(configPath) - for _, proj := range multiList { - if str, ok := proj.(string); ok { - list[str] = "" - } - } - return list -} diff --git a/modules/twitter/client.go b/modules/twitter/client.go index e03a6a9c..affe0a20 100644 --- a/modules/twitter/client.go +++ b/modules/twitter/client.go @@ -3,10 +3,7 @@ package twitter import ( "encoding/json" "fmt" - "os" "strconv" - - "github.com/wtfutil/wtf/wtf" ) /* NOTE: Currently single application ONLY @@ -22,15 +19,14 @@ type Client struct { } // NewClient creates and returns a new Twitter client -func NewClient() *Client { +func NewClient(settings *Settings) *Client { client := Client{ - apiBase: "https://api.twitter.com/1.1/", - count: wtf.Config.UInt("wtf.mods.twitter.count", 5), - screenName: "", + apiBase: "https://api.twitter.com/1.1/", + count: settings.count, + screenName: "", + bearerToken: settings.bearerToken, } - client.loadAPICredentials() - return &client } @@ -65,10 +61,3 @@ func (client *Client) tweets() (tweets []Tweet, err error) { return } - -func (client *Client) loadAPICredentials() { - client.bearerToken = wtf.Config.UString( - "wtf.mods.twitter.bearerToken", - os.Getenv("WTF_TWITTER_BEARER_TOKEN"), - ) -} diff --git a/modules/twitter/request.go b/modules/twitter/request.go index ec5406d3..e20a306c 100644 --- a/modules/twitter/request.go +++ b/modules/twitter/request.go @@ -13,8 +13,7 @@ func Request(bearerToken string, apiURL string) ([]byte, error) { } // Expected authorization format for single-application twitter dev accounts - req.Header.Add("Authorization", - fmt.Sprintf("Bearer %s", bearerToken)) + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", bearerToken)) client := &http.Client{} resp, err := client.Do(req) diff --git a/modules/twitter/settings.go b/modules/twitter/settings.go new file mode 100644 index 00000000..487fdb30 --- /dev/null +++ b/modules/twitter/settings.go @@ -0,0 +1,32 @@ +package twitter + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "twitter" + +type Settings struct { + common *cfg.Common + + bearerToken string + count int + screenNames []interface{} +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + bearerToken: localConfig.UString("bearerToken", os.Getenv("WTF_TWITTER_BEARER_TOKEN")), + count: localConfig.UInt("count", 5), + screenNames: localConfig.UList("screenName"), + } + + return &settings +} diff --git a/modules/twitter/widget.go b/modules/twitter/widget.go index afdefa7e..b2056932 100644 --- a/modules/twitter/widget.go +++ b/modules/twitter/widget.go @@ -27,18 +27,20 @@ type Widget struct { wtf.MultiSourceWidget wtf.TextWidget - client *Client - idx int - sources []string + client *Client + idx int + settings *Settings + sources []string } -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - MultiSourceWidget: wtf.NewMultiSourceWidget("twitter", "screenName", "screenNames"), - TextWidget: wtf.NewTextWidget(app, "Twitter", "twitter", true), + MultiSourceWidget: wtf.NewMultiSourceWidget(settings.common.ConfigKey, "screenName", "screenNames"), + TextWidget: wtf.NewTextWidget(app, settings.common, true), - idx: 0, + idx: 0, + settings: settings, } widget.HelpfulWidget.SetView(widget.View) @@ -46,7 +48,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { widget.LoadSources() widget.SetDisplayFunction(widget.display) - widget.client = NewClient() + widget.client = NewClient(settings) widget.View.SetBorderPadding(1, 1, 1, 1) widget.View.SetWrap(true) @@ -163,6 +165,4 @@ func (widget *Widget) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { default: return event } - - return event } diff --git a/modules/unknown/settings.go b/modules/unknown/settings.go new file mode 100644 index 00000000..20a53e6c --- /dev/null +++ b/modules/unknown/settings.go @@ -0,0 +1,20 @@ +package unknown + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "unkown" + +type Settings struct { + common *cfg.Common +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + } + + return &settings +} diff --git a/modules/unknown/widget.go b/modules/unknown/widget.go index 88653d90..053c9bad 100644 --- a/modules/unknown/widget.go +++ b/modules/unknown/widget.go @@ -9,11 +9,15 @@ import ( type Widget struct { wtf.TextWidget + + settings *Settings } -func NewWidget(app *tview.Application, name string) *Widget { +func NewWidget(app *tview.Application, name string, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, name, name, false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -22,7 +26,6 @@ func NewWidget(app *tview.Application, name string) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s", widget.Name()))) widget.View.Clear() diff --git a/modules/victorops/client.go b/modules/victorops/client.go index 8c952e28..06069313 100644 --- a/modules/victorops/client.go +++ b/modules/victorops/client.go @@ -4,34 +4,20 @@ import ( "encoding/json" "fmt" "net/http" - "os" "strings" "github.com/wtfutil/wtf/logger" - "github.com/wtfutil/wtf/wtf" ) // Fetch gets the current oncall users -func Fetch() ([]OnCallTeam, error) { +func Fetch(apiID, apiKey string) ([]OnCallTeam, error) { scheduleURL := "https://api.victorops.com/api-public/v1/oncall/current" - response, err := victorOpsRequest(scheduleURL, apiID(), apiKey()) + response, err := victorOpsRequest(scheduleURL, apiID, apiKey) + return response, err } /* ---------------- Unexported Functions ---------------- */ -func apiID() string { - return wtf.Config.UString( - "wtf.mods.victorops.apiID", - os.Getenv("WTF_VICTOROPS_API_ID"), - ) -} - -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.victorops.apiKey", - os.Getenv("WTF_VICTOROPS_API_KEY"), - ) -} func victorOpsRequest(url string, apiID string, apiKey string) ([]OnCallTeam, error) { req, err := http.NewRequest("GET", url, nil) diff --git a/modules/victorops/settings.go b/modules/victorops/settings.go new file mode 100644 index 00000000..07cdb864 --- /dev/null +++ b/modules/victorops/settings.go @@ -0,0 +1,32 @@ +package victorops + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "victorops" + +type Settings struct { + common *cfg.Common + + apiID string + apiKey string + team string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiID: localConfig.UString("apiID", os.Getenv("WTF_VICTOROPS_API_ID")), + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_VICTOROPS_API_KEY")), + team: localConfig.UString("team"), + } + + return &settings +} diff --git a/modules/victorops/widget.go b/modules/victorops/widget.go index a4de256f..a3e0fcdb 100644 --- a/modules/victorops/widget.go +++ b/modules/victorops/widget.go @@ -19,13 +19,15 @@ const HelpText = ` // Widget contains text info type Widget struct { wtf.TextWidget - teams []OnCallTeam + + teams []OnCallTeam + settings *Settings } // NewWidget creates a new widget -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "VictorOps - OnCall", "victorops", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), } widget.View.SetScrollable(true) @@ -40,7 +42,7 @@ func (widget *Widget) Refresh() { return } - teams, err := Fetch() + teams, err := Fetch(widget.settings.apiID, widget.settings.apiKey) widget.View.SetTitle(widget.ContextualTitle(widget.Name())) if err != nil { @@ -64,10 +66,10 @@ func (widget *Widget) display() { } func (widget *Widget) contentFrom(teams []OnCallTeam) string { - teamToDisplay := wtf.Config.UString("wtf.mods.victorops.team") var str string + for _, team := range teams { - if len(teamToDisplay) > 0 && teamToDisplay != team.Slug { + if len(widget.settings.team) > 0 && widget.settings.team != team.Slug { continue } diff --git a/modules/weatherservices/prettyweather/settings.go b/modules/weatherservices/prettyweather/settings.go new file mode 100644 index 00000000..55e99818 --- /dev/null +++ b/modules/weatherservices/prettyweather/settings.go @@ -0,0 +1,32 @@ +package prettyweather + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "prettyweather" + +type Settings struct { + common *cfg.Common + + city string + unit string + view string + language string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + city: localConfig.UString("city", "Barcelona"), + language: localConfig.UString("language", "en"), + unit: localConfig.UString("unit", "m"), + view: localConfig.UString("view", "0"), + } + + return &settings +} diff --git a/modules/weatherservices/prettyweather/widget.go b/modules/weatherservices/prettyweather/widget.go index eb1963a7..3107db35 100644 --- a/modules/weatherservices/prettyweather/widget.go +++ b/modules/weatherservices/prettyweather/widget.go @@ -11,16 +11,16 @@ import ( type Widget struct { wtf.TextWidget + result string - unit string - city string - view string - language string + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Pretty Weather", "prettyweather", false), + TextWidget: wtf.NewTextWidget(app, settings.common, false), + + settings: settings, } return &widget @@ -35,17 +35,18 @@ func (widget *Widget) Refresh() { //this method reads the config and calls wttr.in for pretty weather func (widget *Widget) prettyWeather() { client := &http.Client{} - widget.unit = wtf.Config.UString("wtf.mods.prettyweather.unit", "m") - widget.city = wtf.Config.UString("wtf.mods.prettyweather.city", "") - widget.view = wtf.Config.UString("wtf.mods.prettyweather.view", "0") - widget.language = wtf.Config.UString("wtf.mods.prettyweather.language", "en") - req, err := http.NewRequest("GET", "https://wttr.in/"+widget.city+"?"+widget.view+"?"+widget.unit, nil) + + city := widget.settings.city + unit := widget.settings.unit + view := widget.settings.view + + req, err := http.NewRequest("GET", "https://wttr.in/"+city+"?"+view+"?"+unit, nil) if err != nil { widget.result = err.Error() return } - req.Header.Set("Accept-Language", widget.language) + req.Header.Set("Accept-Language", widget.settings.language) req.Header.Set("User-Agent", "curl") response, err := client.Do(req) if err != nil { @@ -61,6 +62,5 @@ func (widget *Widget) prettyWeather() { return } - //widget.result = strings.TrimSpace(string(contents)) widget.result = strings.TrimSpace(wtf.ASCIItoTviewColors(string(contents))) } diff --git a/modules/weatherservices/weather/display.go b/modules/weatherservices/weather/display.go index 12b6119d..929e4b57 100644 --- a/modules/weatherservices/weather/display.go +++ b/modules/weatherservices/weather/display.go @@ -9,7 +9,6 @@ import ( ) func (widget *Widget) display() { - if widget.apiKeyValid() == false { widget.View.SetText(" Environment variable WTF_OWM_API_KEY is not set") return @@ -54,19 +53,17 @@ func (widget *Widget) sunInfo(cityData *owm.CurrentWeatherData) string { } func (widget *Widget) temperatures(cityData *owm.CurrentWeatherData) string { - tempUnit := wtf.Config.UString("wtf.mods.weather.tempUnit", "C") - - str := fmt.Sprintf("%8s: %4.1f° %s\n", "High", cityData.Main.TempMax, tempUnit) + str := fmt.Sprintf("%8s: %4.1f° %s\n", "High", cityData.Main.TempMax, widget.settings.tempUnit) str = str + fmt.Sprintf( "%8s: [%s]%4.1f° %s[white]\n", "Current", - wtf.Config.UString("wtf.mods.weather.colors.current", "green"), + widget.settings.colors.current, cityData.Main.Temp, - tempUnit, + widget.settings.tempUnit, ) - str = str + fmt.Sprintf("%8s: %4.1f° %s\n", "Low", cityData.Main.TempMin, tempUnit) + str = str + fmt.Sprintf("%8s: %4.1f° %s\n", "Low", cityData.Main.TempMin, widget.settings.tempUnit) return str } diff --git a/modules/weatherservices/weather/settings.go b/modules/weatherservices/weather/settings.go new file mode 100644 index 00000000..e35b5480 --- /dev/null +++ b/modules/weatherservices/weather/settings.go @@ -0,0 +1,41 @@ +package weather + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "weather" + +type colors struct { + current string +} + +type Settings struct { + colors + common *cfg.Common + + apiKey string + cityIDs []interface{} + language string + tempUnit string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("WTF_OWM_API_KEY")), + cityIDs: localConfig.UList("cityids"), + language: localConfig.UString("language", "EN"), + tempUnit: localConfig.UString("tempUnit", "C"), + } + + settings.colors.current = localConfig.UString("colors.current", "green") + + return &settings +} diff --git a/modules/weatherservices/weather/widget.go b/modules/weatherservices/weather/widget.go index b7dba99e..c4017b36 100644 --- a/modules/weatherservices/weather/widget.go +++ b/modules/weatherservices/weather/widget.go @@ -1,8 +1,6 @@ package weather import ( - "os" - owm "github.com/briandowns/openweathermap" "github.com/gdamore/tcell" "github.com/rivo/tview" @@ -25,22 +23,24 @@ type Widget struct { wtf.HelpfulWidget wtf.TextWidget - APIKey string - Data []*owm.CurrentWeatherData - Idx int + // APIKey string + Data []*owm.CurrentWeatherData + Idx int + settings *Settings } // NewWidget creates and returns a new instance of the weather Widget. -func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { - configKey := "weather" +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText), - TextWidget: wtf.NewTextWidget(app, "Weather", configKey, true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), - Idx: 0, + Idx: 0, + settings: settings, } - widget.loadAPICredentials() + // widget.loadAPICredentials() + // widget.APIKey widget.HelpfulWidget.SetView(widget.View) widget.View.SetInputCapture(widget.keyboardIntercept) @@ -57,7 +57,7 @@ func (widget *Widget) Fetch(cityIDs []int) []*owm.CurrentWeatherData { data := []*owm.CurrentWeatherData{} for _, cityID := range cityIDs { - result, err := widget.currentWeather(widget.APIKey, cityID) + result, err := widget.currentWeather(cityID) if err == nil { data = append(data, result) } @@ -70,7 +70,7 @@ func (widget *Widget) Fetch(cityIDs []int) []*owm.CurrentWeatherData { // widget's view for rendering func (widget *Widget) Refresh() { if widget.apiKeyValid() { - widget.Data = widget.Fetch(wtf.ToInts(wtf.Config.UList("wtf.mods.weather.cityids", widget.defaultCityCodes()))) + widget.Data = widget.Fetch(wtf.ToInts(widget.settings.cityIDs)) } widget.display() @@ -101,11 +101,11 @@ func (widget *Widget) Prev() { /* -------------------- Unexported Functions -------------------- */ func (widget *Widget) apiKeyValid() bool { - if widget.APIKey == "" { + if widget.settings.apiKey == "" { return false } - if len(widget.APIKey) != 32 { + if len(widget.settings.apiKey) != 32 { return false } @@ -124,11 +124,11 @@ func (widget *Widget) currentData() *owm.CurrentWeatherData { return widget.Data[widget.Idx] } -func (widget *Widget) currentWeather(apiKey string, cityCode int) (*owm.CurrentWeatherData, error) { +func (widget *Widget) currentWeather(cityCode int) (*owm.CurrentWeatherData, error) { weather, err := owm.NewCurrent( - wtf.Config.UString("wtf.mods.weather.tempUnit", "C"), - wtf.Config.UString("wtf.mods.weather.language", "EN"), - apiKey, + widget.settings.tempUnit, + widget.settings.language, + widget.settings.apiKey, ) if err != nil { return nil, err @@ -142,17 +142,6 @@ func (widget *Widget) currentWeather(apiKey string, cityCode int) (*owm.CurrentW return weather, nil } -func (widget *Widget) defaultCityCodes() []interface{} { - defaultArr := []int{3370352} - - var defaults = make([]interface{}, len(defaultArr)) - for i, d := range defaultArr { - defaults[i] = d - } - - return defaults -} - func (widget *Widget) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { switch string(event.Rune()) { case "/": @@ -177,12 +166,3 @@ func (widget *Widget) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { return event } } - -// loadAPICredentials loads the API authentication credentials for this module -// First checks to see if they're in the config file. If not, checks the ENV var -func (widget *Widget) loadAPICredentials() { - widget.APIKey = wtf.Config.UString( - "wtf.mods.weather.apiKey", - os.Getenv("WTF_OWM_API_KEY"), - ) -} diff --git a/modules/zendesk/client.go b/modules/zendesk/client.go index e093a7e5..9bdbd564 100644 --- a/modules/zendesk/client.go +++ b/modules/zendesk/client.go @@ -6,9 +6,6 @@ import ( "io/ioutil" "log" "net/http" - "os" - - "github.com/wtfutil/wtf/wtf" ) type Resource struct { @@ -16,34 +13,20 @@ type Resource struct { Raw string } -func apiKey() string { - return wtf.Config.UString( - "wtf.mods.zendesk.apiKey", - os.Getenv("ZENDESK_API"), - ) -} - -func subdomain() string { - return wtf.Config.UString( - "wtf.mods.zendesk.subdomain", - os.Getenv("ZENDESK_SUBDOMAIN"), - ) -} - func errHandler(err error) { if err != nil { log.Print(err) } } -func api(key string, meth string, path string, params string) (*Resource, error) { +func (widget *Widget) api(meth string, path string, params string) (*Resource, error) { trn := &http.Transport{} client := &http.Client{ Transport: trn, } - baseURL := fmt.Sprintf("https://%v.zendesk.com/api/v2", subdomain()) + baseURL := fmt.Sprintf("https://%v.zendesk.com/api/v2", widget.settings.subdomain) URL := baseURL + "/tickets.json?sort_by=status" req, err := http.NewRequest(meth, URL, bytes.NewBufferString(params)) @@ -53,9 +36,8 @@ func api(key string, meth string, path string, params string) (*Resource, error) req.Header.Add("Content-Type", "application/json") - username := wtf.Config.UString("wtf.mods.zendesk.username") - apiUser := fmt.Sprintf("%v/token", username) - req.SetBasicAuth(apiUser, key) + apiUser := fmt.Sprintf("%v/token", widget.settings.username) + req.SetBasicAuth(apiUser, widget.settings.apiKey) resp, err := client.Do(req) if err != nil { @@ -70,5 +52,4 @@ func api(key string, meth string, path string, params string) (*Resource, error) } return &Resource{Response: &resp, Raw: string(data)}, nil - } diff --git a/modules/zendesk/settings.go b/modules/zendesk/settings.go new file mode 100644 index 00000000..f70fe09f --- /dev/null +++ b/modules/zendesk/settings.go @@ -0,0 +1,34 @@ +package zendesk + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const configKey = "zendesk" + +type Settings struct { + common *cfg.Common + + apiKey string + status string + subdomain string + username string +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config) *Settings { + localConfig, _ := ymlConfig.Get("wtf.mods." + configKey) + + settings := Settings{ + common: cfg.NewCommonSettingsFromYAML(name, configKey, ymlConfig), + + apiKey: localConfig.UString("apiKey", os.Getenv("ZENDESK_API")), + status: localConfig.UString("status"), + subdomain: localConfig.UString("subdomain", os.Getenv("ZENDESK_SUBDOMAIN")), + username: localConfig.UString("username"), + } + + return &settings +} diff --git a/modules/zendesk/tickets.go b/modules/zendesk/tickets.go index a5ba7575..6bc3bbfa 100644 --- a/modules/zendesk/tickets.go +++ b/modules/zendesk/tickets.go @@ -45,7 +45,7 @@ type Ticket struct { Fields interface{} `json:"fields"` } -func listTickets(pag ...string) (*TicketArray, error) { +func (widget *Widget) listTickets(pag ...string) (*TicketArray, error) { TicketStruct := &TicketArray{} @@ -55,7 +55,7 @@ func listTickets(pag ...string) (*TicketArray, error) { } else { path = pag[0] } - resource, err := api(apiKey(), "GET", path, "") + resource, err := widget.api("GET", path, "") if err != nil { return nil, err } @@ -66,14 +66,14 @@ func listTickets(pag ...string) (*TicketArray, error) { } -func newTickets(ticketStatus string) (*TicketArray, error) { +func (widget *Widget) newTickets() (*TicketArray, error) { newTicketArray := &TicketArray{} - tickets, err := listTickets() + tickets, err := widget.listTickets(widget.settings.apiKey) if err != nil { log.Fatal(err) } for _, Ticket := range tickets.Tickets { - if Ticket.Status == ticketStatus && Ticket.Status != "closed" && Ticket.Status != "solved" { + if Ticket.Status == widget.settings.status && Ticket.Status != "closed" && Ticket.Status != "solved" { newTicketArray.Tickets = append(newTicketArray.Tickets, Ticket) } } diff --git a/modules/zendesk/widget.go b/modules/zendesk/widget.go index 153a954f..11c06efa 100644 --- a/modules/zendesk/widget.go +++ b/modules/zendesk/widget.go @@ -14,11 +14,14 @@ type Widget struct { result *TicketArray selected int + settings *Settings } -func NewWidget(app *tview.Application) *Widget { +func NewWidget(app *tview.Application, settings *Settings) *Widget { widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Zendesk", "zendesk", true), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, } widget.View.SetInputCapture(widget.keyboardIntercept) @@ -28,8 +31,7 @@ func NewWidget(app *tview.Application) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - ticketStatus := wtf.Config.UString("wtf.mods.zendesk.status") - ticketArray, err := newTickets(ticketStatus) + ticketArray, err := widget.newTickets() ticketArray.Count = len(ticketArray.Tickets) if err != nil { log.Fatal(err) @@ -61,13 +63,13 @@ func (widget *Widget) textContent(items []Ticket) string { } func (widget *Widget) format(ticket Ticket, idx int) string { - var str string - requesterName := widget.parseRequester(ticket) - textColor := wtf.Config.UString("wtf.colors.background", "green") + textColor := widget.settings.common.Colors.Background if idx == widget.selected { - textColor = wtf.Config.UString("wtf.colors.background", "orange") + textColor = widget.settings.common.Colors.BorderFocused } - str = fmt.Sprintf(" [%s:]%d - %s\n %s\n\n", textColor, ticket.Id, requesterName, ticket.Subject) + + requesterName := widget.parseRequester(ticket) + str := fmt.Sprintf(" [%s:]%d - %s\n %s\n\n", textColor, ticket.Id, requesterName, ticket.Subject) return str } @@ -102,7 +104,7 @@ func (widget *Widget) openTicket() { sel := widget.selected if sel >= 0 && widget.result != nil && sel < len(widget.result.Tickets) { issue := &widget.result.Tickets[widget.selected] - ticketUrl := fmt.Sprintf("https://%s.zendesk.com/agent/tickets/%d", subdomain(), issue.Id) + ticketUrl := fmt.Sprintf("https://%s.zendesk.com/agent/tickets/%d", widget.settings.subdomain, issue.Id) wtf.OpenFile(ticketUrl) } } diff --git a/wtf/text_widget.go b/wtf/text_widget.go index 74ead21f..845c4645 100644 --- a/wtf/text_widget.go +++ b/wtf/text_widget.go @@ -5,44 +5,49 @@ import ( "github.com/olebedev/config" "github.com/rivo/tview" + "github.com/wtfutil/wtf/cfg" ) var Config *config.Config type TextWidget struct { - enabled bool - focusable bool - focusChar string - key string - name string + enabled bool + focusable bool + focusChar string + key string + name string + refreshInterval int - RefreshInt int - View *tview.TextView + View *tview.TextView + CommonSettings *cfg.Common Position } -func NewTextWidget(app *tview.Application, name string, configKey string, focusable bool) TextWidget { - focusCharValue := Config.UInt(fmt.Sprintf("wtf.mods.%s.focusChar", configKey), -1) - focusChar := string('0' + focusCharValue) - if focusCharValue == -1 { +func NewTextWidget(app *tview.Application, commonSettings *cfg.Common, focusable bool) TextWidget { + configKey := commonSettings.ConfigKey + + focusChar := string('0' + commonSettings.FocusChar) + if commonSettings.FocusChar == -1 { focusChar = "" } widget := TextWidget{ - enabled: Config.UBool(fmt.Sprintf("wtf.mods.%s.enabled", configKey), false), - focusable: focusable, - focusChar: focusChar, - key: configKey, - name: Config.UString(fmt.Sprintf("wtf.mods.%s.title", configKey), name), - RefreshInt: Config.UInt(fmt.Sprintf("wtf.mods.%s.refreshInterval", configKey)), + CommonSettings: commonSettings, + + enabled: commonSettings.Enabled, + focusable: focusable, + focusChar: focusChar, + key: commonSettings.ConfigKey, + name: commonSettings.Name, + refreshInterval: commonSettings.RefreshInterval, } widget.Position = NewPosition( - Config.UInt(fmt.Sprintf("wtf.mods.%s.position.top", configKey)), - Config.UInt(fmt.Sprintf("wtf.mods.%s.position.left", configKey)), - Config.UInt(fmt.Sprintf("wtf.mods.%s.position.width", configKey)), - Config.UInt(fmt.Sprintf("wtf.mods.%s.position.height", configKey)), + commonSettings.Position.Top, + commonSettings.Position.Left, + commonSettings.Position.Width, + commonSettings.Position.Height, ) widget.addView(app, configKey) @@ -54,10 +59,10 @@ func NewTextWidget(app *tview.Application, name string, configKey string, focusa func (widget *TextWidget) BorderColor() string { if widget.Focusable() { - return Config.UString("wtf.colors.border.focusable", "red") + return widget.CommonSettings.Colors.BorderFocusable } - return Config.UString("wtf.colors.border.normal", "gray") + return widget.CommonSettings.Colors.BorderNormal } func (widget *TextWidget) ContextualTitle(defaultStr string) string { @@ -103,13 +108,17 @@ func (widget *TextWidget) Name() string { } func (widget *TextWidget) RefreshInterval() int { - return widget.RefreshInt + return widget.refreshInterval } func (widget *TextWidget) SetFocusChar(char string) { widget.focusChar = char } +func (widget *TextWidget) String() string { + return widget.name +} + func (widget *TextWidget) TextView() *tview.TextView { return widget.View } @@ -119,34 +128,19 @@ func (widget *TextWidget) TextView() *tview.TextView { func (widget *TextWidget) addView(app *tview.Application, configKey string) { view := tview.NewTextView() - view.SetBackgroundColor(ColorFor( - Config.UString(fmt.Sprintf("wtf.mods.%s.colors.background", configKey), - Config.UString("wtf.colors.background", "black"), - ), - )) - - view.SetTextColor(ColorFor( - Config.UString( - fmt.Sprintf("wtf.mods.%s.colors.text", configKey), - Config.UString("wtf.colors.text", "white"), - ), - )) - - view.SetTitleColor(ColorFor( - Config.UString( - fmt.Sprintf("wtf.mods.%s.colors.title", configKey), - Config.UString("wtf.colors.title", "white"), - ), - )) + view.SetBackgroundColor(ColorFor(widget.CommonSettings.Colors.Background)) + view.SetBorderColor(ColorFor(widget.BorderColor())) + view.SetTextColor(ColorFor(widget.CommonSettings.Colors.Text)) + view.SetTitleColor(ColorFor(widget.CommonSettings.Colors.Title)) view.SetBorder(true) - view.SetBorderColor(ColorFor(widget.BorderColor())) + view.SetDynamicColors(true) + view.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title)) + view.SetWrap(false) + view.SetChangedFunc(func() { app.Draw() }) - view.SetDynamicColors(true) - view.SetTitle(widget.ContextualTitle(widget.name)) - view.SetWrap(false) widget.View = view } diff --git a/wtf/utils.go b/wtf/utils.go index 234788d6..49726e8b 100644 --- a/wtf/utils.go +++ b/wtf/utils.go @@ -5,9 +5,8 @@ import ( "io/ioutil" "os/exec" "regexp" - "strings" - //"sync" "runtime" + "strings" "github.com/rivo/tview" ) @@ -96,17 +95,17 @@ func NamesFromEmails(emails []string) []string { // OpenFile opens the file defined in `path` via the operating system func OpenFile(path string) { - if (strings.HasPrefix(path,"http://"))||(strings.HasPrefix(path,"https://")) { + if (strings.HasPrefix(path, "http://")) || (strings.HasPrefix(path, "https://")) { switch runtime.GOOS { - case "linux": - exec.Command("xdg-open", path).Start() - case "windows": - exec.Command("rundll32", "url.dll,FileProtocolHandler", path).Start() - case "darwin": - exec.Command("open", path).Start() - default: + case "linux": + exec.Command("xdg-open", path).Start() + case "windows": + exec.Command("rundll32", "url.dll,FileProtocolHandler", path).Start() + case "darwin": + exec.Command("open", path).Start() + default: } - }else { + } else { filePath, _ := ExpandHomeDir(path) openFileUtil := Config.UString("wtf.openFileUtil", "open") cmd := exec.Command(openFileUtil, filePath) @@ -136,10 +135,7 @@ func ReadFileBytes(filePath string) ([]byte, error) { } func RightAlignFormat(view *tview.TextView) string { - //mutex := &sync.Mutex{} - //mutex.Lock() _, _, w, _ := view.GetInnerRect() - //mutex.Unlock() return fmt.Sprintf("%%%ds", w-1) } @@ -169,6 +165,18 @@ func SigilStr(len, pos int, view *tview.TextView) string { return sigils } +/* -------------------- Map Conversion -------------------- */ + +func MapToStrs(aMap map[string]interface{}) map[string]string { + results := make(map[string]string) + + for key, val := range aMap { + results[key] = val.(string) + } + + return results +} + /* -------------------- Slice Conversion -------------------- */ func ToInts(slice []interface{}) []int { diff --git a/wtf/widget_validator.go b/wtf/widget_validator.go new file mode 100644 index 00000000..9483db28 --- /dev/null +++ b/wtf/widget_validator.go @@ -0,0 +1,21 @@ +package wtf + +import ( + "fmt" + "log" +) + +// Check that all the loaded widgets are valid for display +func ValidateWidgets(widgets []Wtfable) (bool, error) { + result := true + var err error + + for _, widget := range widgets { + if widget.Enabled() && !widget.IsPositionable() { + errStr := fmt.Sprintf("Widget config has invalid values: %s", widget.Key()) + log.Fatalln(errStr) + } + } + + return result, err +} diff --git a/wtf/wtfable.go b/wtf/wtfable.go index 86e33121..aad2b78c 100644 --- a/wtf/wtfable.go +++ b/wtf/wtfable.go @@ -9,15 +9,15 @@ type Wtfable interface { Scheduler BorderColor() string - Focusable() bool FocusChar() string + Focusable() bool Key() string Name() string SetFocusChar(string) TextView() *tview.TextView - Top() int - Left() int - Width() int Height() int + Left() int + Top() int + Width() int } diff --git a/wtf_tests/colors_test.go b/wtf_tests/colors_test.go index 8f7ddea6..baec66ac 100644 --- a/wtf_tests/colors_test.go +++ b/wtf_tests/colors_test.go @@ -7,7 +7,7 @@ import ( . "github.com/wtfutil/wtf/wtf" ) -func TestASCIItoTviewColors(t *testing.T) { +func Test_ASCIItoTviewColors(t *testing.T) { Equal(t, "", ASCIItoTviewColors("")) Equal(t, "cat", ASCIItoTviewColors("cat")) Equal(t, "[38;5;226mcat/[-]", ASCIItoTviewColors("[38;5;226mcat/"))