mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Merge branch 'master' into master
This commit is contained in:
commit
98d370ed94
@ -469,6 +469,13 @@
|
||||
"name": "Levi Baber",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/5819098?v=4",
|
||||
"profile": "http://researchit.las.iastate.edu",
|
||||
"contributions": []
|
||||
},
|
||||
{
|
||||
"login": "gnanderson",
|
||||
"name": "Graham Anderson",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/38514?v=4",
|
||||
"profile": "https://github.com/gnanderson",
|
||||
"contributions": [
|
||||
]
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ builds:
|
||||
goos:
|
||||
- darwin
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
|
14
CHANGELOG.md
14
CHANGELOG.md
@ -4,8 +4,22 @@
|
||||
|
||||
### ⚡️ Added
|
||||
|
||||
* DataDog module is now scrollable and interactive, by [@Seanstoppable](https://github.com/Seanstoppable)
|
||||
* Focusable hot key numbers are now assigned in a stable order, [#435](https://github.com/wtfutil/wtf/issues/435) by [@Seanstoppable](https://github.com/Seanstoppable)
|
||||
* Zendesk widget now has help text, by [@Seanstoppable](https://github.com/Seanstoppable)
|
||||
* Scrollable widget added to provide common keyboard-navigation list functionality, by [@Seanstoppable](https://github.com/Seanstoppable)
|
||||
* Logging functionality extracted out from Log module, by [@Seanstoppable](https://github.com/Seanstoppable)
|
||||
|
||||
## v0.9.2
|
||||
|
||||
### ⚡️ Added
|
||||
|
||||
* Keyboard management system for modules reworked. Now has a KeyboardWidget to simplify adding keyboard commands
|
||||
|
||||
### Fixed
|
||||
|
||||
* WTF versions are now prefixed with `v` again so module systems pick up the latest versions
|
||||
|
||||
## 0.9.1
|
||||
|
||||
### ⚡️ Added
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
[](#contributors)
|
||||
[](#contributors)
|
||||
[](https://travis-ci.com/wtfutil/wtf)
|
||||
[](https://gitter.im/wtfutil/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://twitter.com/wtfutil)
|
||||
@ -97,7 +97,7 @@ Dependency management in WTF is handled by [Go modules](https://github.com/golan
|
||||
| [<img src="https://avatars0.githubusercontent.com/u/538234?v=4" width="48px;" alt="Renán Romero"/><br /><sub><b>Renán Romero</b></sub>](http://www.romeroruiz.com)<br /> | [<img src="https://avatars1.githubusercontent.com/u/5031240?v=4" width="48px;" alt="Bastian Groß"/><br /><sub><b>Bastian Groß</b></sub>](https://github.com/sticreations)<br /> | [<img src="https://avatars1.githubusercontent.com/u/2496835?v=4" width="48px;" alt="nicholas-eden"/><br /><sub><b>nicholas-eden</b></sub>](https://github.com/nicholas-eden)<br /> | [<img src="https://avatars1.githubusercontent.com/u/279390?v=4" width="48px;" alt="Dan Rabinowitz"/><br /><sub><b>Dan Rabinowitz</b></sub>](https://github.com/danrabinowitz)<br /> | [<img src="https://avatars1.githubusercontent.com/u/6897575?v=4" width="48px;" alt="David Missmann"/><br /><sub><b>David Missmann</b></sub>](https://github.com/dvdmssmnn)<br /> | [<img src="https://avatars2.githubusercontent.com/u/882006?v=4" width="48px;" alt="Mathias Weber"/><br /><sub><b>Mathias Weber</b></sub>](https://github.com/mweb)<br /> | [<img src="https://avatars1.githubusercontent.com/u/32081703?v=4" width="48px;" alt="TheRedSpy15"/><br /><sub><b>TheRedSpy15</b></sub>](https://github.com/TheRedSpy15)<br /> |
|
||||
| [<img src="https://avatars0.githubusercontent.com/u/9569897?v=4" width="48px;" alt="Harald Nordgren"/><br /><sub><b>Harald Nordgren</b></sub>](https://www.linkedin.com/in/harald-nordgren-44778192)<br /> | [<img src="https://avatars0.githubusercontent.com/u/11583824?v=4" width="48px;" alt="Matei Alexandru Gardus"/><br /><sub><b>Matei Alexandru Gardus</b></sub>](http://stormfirefox1.github.io)<br /> | [<img src="https://avatars2.githubusercontent.com/u/1523955?v=4" width="48px;" alt="Sean Smith"/><br /><sub><b>Sean Smith</b></sub>](https://github.com/Seanstoppable)<br /> | [<img src="https://avatars1.githubusercontent.com/u/1646238?v=4" width="48px;" alt="Halil Kaskavalci"/><br /><sub><b>Halil Kaskavalci</b></sub>](http://kaskavalci.com)<br /> | [<img src="https://avatars2.githubusercontent.com/u/246715?v=4" width="48px;" alt="Johan Denoyer"/><br /><sub><b>Johan Denoyer</b></sub>](http://www.johandenoyer.fr)<br /> | [<img src="https://avatars1.githubusercontent.com/u/593516?v=4" width="48px;" alt="Jelle Vink"/><br /><sub><b>Jelle Vink</b></sub>](https://skymeyer.be)<br /> | [<img src="https://avatars1.githubusercontent.com/u/3997333?v=4" width="48px;" alt="Devin Collins"/><br /><sub><b>Devin Collins</b></sub>](http://imdevinc.com)<br /> |
|
||||
| [<img src="https://avatars3.githubusercontent.com/u/18333?v=4" width="48px;" alt="Danne Stayskal"/><br /><sub><b>Danne Stayskal</b></sub>](http://danne.stayskal.com/)<br /> | [<img src="https://avatars1.githubusercontent.com/u/2006658?v=4" width="48px;" alt="Max Beizer"/><br /><sub><b>Max Beizer</b></sub>](https://www.maxbeizer.com)<br /> | [<img src="https://avatars1.githubusercontent.com/u/194392?v=4" width="48px;" alt="E:V:A"/><br /><sub><b>E:V:A</b></sub>](http://tinyurl.com/nwmj4as)<br /> | [<img src="https://avatars0.githubusercontent.com/u/1425500?v=4" width="48px;" alt="Gabriel"/><br /><sub><b>Gabriel</b></sub>](https://github.com/GaboFDC)<br /> | [<img src="https://avatars2.githubusercontent.com/u/10111411?v=4" width="48px;" alt="Andrew Scibek"/><br /><sub><b>Andrew Scibek</b></sub>](https://github.com/AndrewScibek)<br /> | [<img src="https://avatars0.githubusercontent.com/u/29709822?v=4" width="48px;" alt="FriedCosey"/><br /><sub><b>FriedCosey</b></sub>](https://github.com/FriedCosey)<br /> | [<img src="https://avatars1.githubusercontent.com/u/3891?v=4" width="48px;" alt="Michele Gerarduzzi"/><br /><sub><b>Michele Gerarduzzi</b></sub>](https://michelegera.dev/)<br /> |
|
||||
| [<img src="https://avatars3.githubusercontent.com/u/13438569?v=4" width="48px;" alt="Jack Morris"/><br /><sub><b>Jack Morris</b></sub>](https://github.com/rudolphjacksonm)<br /> | [<img src="https://avatars0.githubusercontent.com/u/14993807?v=4" width="48px;" alt="foorb"/><br /><sub><b>foorb</b></sub>](https://github.com/foorb)<br /> | [<img src="https://avatars0.githubusercontent.com/u/5819098?v=4" width="48px;" alt="Levi Baber"/><br /><sub><b>Levi Baber</b></sub>](http://researchit.las.iastate.edu)<br /> |
|
||||
| [<img src="https://avatars3.githubusercontent.com/u/13438569?v=4" width="48px;" alt="Jack Morris"/><br /><sub><b>Jack Morris</b></sub>](https://github.com/rudolphjacksonm)<br /> | [<img src="https://avatars0.githubusercontent.com/u/14993807?v=4" width="48px;" alt="foorb"/><br /><sub><b>foorb</b></sub>](https://github.com/foorb)<br /> | [<img src="https://avatars0.githubusercontent.com/u/5819098?v=4" width="48px;" alt="Levi Baber"/><br /><sub><b>Levi Baber</b></sub>](http://researchit.las.iastate.edu)<br /> | [<img src="https://avatars0.githubusercontent.com/u/38514?v=4" width="48px;" alt="Graham Anderson"/><br /><sub><b>Graham Anderson</b></sub>](https://github.com/gnanderson)<br /> |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
## Acknowledgments
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
|
||||
goFlags "github.com/jessevdk/go-flags"
|
||||
"github.com/wtfutil/wtf/help"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
)
|
||||
|
||||
type Flags struct {
|
||||
@ -63,7 +63,7 @@ func (flags *Flags) Parse() {
|
||||
// If no config file is explicitly passed in as a param,
|
||||
// set the flag to the default config file
|
||||
if !flags.HasConfig() {
|
||||
homeDir, err := wtf.Home()
|
||||
homeDir, err := utils.Home()
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
|
@ -18,7 +18,6 @@ type Widget struct {
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -28,15 +27,12 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.unselect()
|
||||
|
||||
widget.View.SetScrollable(true)
|
||||
widget.View.SetRegions(true)
|
||||
|
||||
@ -50,22 +46,11 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
func (widget *Widget) Refresh() {
|
||||
|
||||
// The last call should always be to the display function
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
widget.View.SetWrap(false)
|
||||
|
||||
widget.View.Clear()
|
||||
widget.View.SetText("Some Text")
|
||||
widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight()
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
widget.display()
|
||||
widget.Redraw(widget.CommonSettings.Title, "Some text", false)
|
||||
}
|
111
logger/log.go
111
logger/log.go
@ -1,46 +1,21 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
)
|
||||
|
||||
const maxBufferSize int64 = 1024
|
||||
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
filePath string
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
filePath: logFilePath(),
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
return &widget
|
||||
}
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
func Log(msg string) {
|
||||
if logFileMissing() {
|
||||
if LogFileMissing() {
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(logFilePath(), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
|
||||
f, err := os.OpenFile(LogFilePath(), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
log.Fatalf("error opening file: %v", err)
|
||||
}
|
||||
@ -50,87 +25,15 @@ func Log(msg string) {
|
||||
log.Println(msg)
|
||||
}
|
||||
|
||||
// Refresh updates the onscreen contents of the widget
|
||||
func (widget *Widget) Refresh() {
|
||||
if logFileMissing() {
|
||||
return
|
||||
func LogFileMissing() bool {
|
||||
return LogFilePath() == ""
|
||||
}
|
||||
|
||||
logLines := widget.tailFile()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.CommonSettings.Title)
|
||||
widget.View.SetText(widget.contentFrom(logLines))
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) contentFrom(logLines []string) string {
|
||||
str := ""
|
||||
|
||||
for _, line := range logLines {
|
||||
chunks := strings.Split(line, " ")
|
||||
|
||||
if len(chunks) >= 4 {
|
||||
str = str + fmt.Sprintf(
|
||||
"[green]%s[white] [yellow]%s[white] %s\n",
|
||||
chunks[0],
|
||||
chunks[1],
|
||||
strings.Join(chunks[3:], " "),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func logFileMissing() bool {
|
||||
return logFilePath() == ""
|
||||
}
|
||||
|
||||
func logFilePath() string {
|
||||
dir, err := wtf.Home()
|
||||
func LogFilePath() string {
|
||||
dir, err := utils.Home()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return filepath.Join(dir, ".config", "wtf", "log.txt")
|
||||
}
|
||||
|
||||
func (widget *Widget) tailFile() []string {
|
||||
file, err := os.Open(widget.filePath)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
bufferSize := maxBufferSize
|
||||
if maxBufferSize > stat.Size() {
|
||||
bufferSize = stat.Size()
|
||||
}
|
||||
|
||||
startPos := stat.Size() - bufferSize
|
||||
|
||||
buff := make([]byte, bufferSize)
|
||||
_, err = file.ReadAt(buff, startPos)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
logLines := strings.Split(string(buff), "\n")
|
||||
|
||||
// Reverse the array of lines
|
||||
// Offset by two to account for the blank line at the end
|
||||
last := len(logLines) - 2
|
||||
for i := 0; i < len(logLines)/2; i++ {
|
||||
logLines[i], logLines[last-i] = logLines[last-i], logLines[i]
|
||||
}
|
||||
|
||||
return logLines
|
||||
}
|
||||
|
3
main.go
3
main.go
@ -18,6 +18,7 @@ import (
|
||||
"github.com/wtfutil/wtf/cfg"
|
||||
"github.com/wtfutil/wtf/flags"
|
||||
"github.com/wtfutil/wtf/maker"
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
@ -65,7 +66,7 @@ func refreshAllWidgets(widgets []wtf.Wtfable) {
|
||||
|
||||
func watchForConfigChanges(app *tview.Application, configFilePath string, grid *tview.Grid, pages *tview.Pages) {
|
||||
watch := watcher.New()
|
||||
absPath, _ := wtf.ExpandHomeDir(configFilePath)
|
||||
absPath, _ := utils.ExpandHomeDir(configFilePath)
|
||||
|
||||
// Notify write events
|
||||
watch.FilterOps(watcher.Write)
|
||||
|
@ -3,7 +3,6 @@ package maker
|
||||
import (
|
||||
"github.com/olebedev/config"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/logger"
|
||||
"github.com/wtfutil/wtf/modules/bamboohr"
|
||||
"github.com/wtfutil/wtf/modules/bargraph"
|
||||
"github.com/wtfutil/wtf/modules/circleci"
|
||||
@ -25,6 +24,7 @@ import (
|
||||
"github.com/wtfutil/wtf/modules/ipaddresses/ipinfo"
|
||||
"github.com/wtfutil/wtf/modules/jenkins"
|
||||
"github.com/wtfutil/wtf/modules/jira"
|
||||
"github.com/wtfutil/wtf/modules/logger"
|
||||
"github.com/wtfutil/wtf/modules/mercurial"
|
||||
"github.com/wtfutil/wtf/modules/nbascore"
|
||||
"github.com/wtfutil/wtf/modules/newrelic"
|
||||
@ -90,7 +90,7 @@ func MakeWidget(
|
||||
widget = cryptolive.NewWidget(app, settings)
|
||||
case "datadog":
|
||||
settings := datadog.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig)
|
||||
widget = datadog.NewWidget(app, settings)
|
||||
widget = datadog.NewWidget(app, pages, settings)
|
||||
case "gcal":
|
||||
settings := gcal.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig)
|
||||
widget = gcal.NewWidget(app, settings)
|
||||
@ -198,7 +198,7 @@ func MakeWidget(
|
||||
widget = weather.NewWidget(app, pages, settings)
|
||||
case "zendesk":
|
||||
settings := zendesk.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig)
|
||||
widget = zendesk.NewWidget(app, settings)
|
||||
widget = zendesk.NewWidget(app, pages, settings)
|
||||
default:
|
||||
settings := unknown.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig)
|
||||
widget = unknown.NewWidget(app, settings)
|
||||
|
@ -42,10 +42,7 @@ func (widget *Widget) Refresh() {
|
||||
wtf.Now().Format(wtf.DateFormat),
|
||||
)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.View.SetText(widget.contentFrom(todayItems))
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, widget.contentFrom(todayItems), false)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -11,7 +11,6 @@ type Widget struct {
|
||||
wtf.TextWidget
|
||||
*Client
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -20,7 +19,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
Client: NewClient(settings.apiKey),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -36,19 +34,17 @@ func (widget *Widget) Refresh() {
|
||||
|
||||
builds, err := widget.Client.BuildsFor()
|
||||
|
||||
title := fmt.Sprintf("%s - Builds", widget.CommonSettings.Title)
|
||||
var content string
|
||||
wrap := false
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
wrap = true
|
||||
content = err.Error()
|
||||
} else {
|
||||
widget.View.SetWrap(false)
|
||||
content = widget.contentFrom(builds)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(fmt.Sprintf("%s - Builds", widget.CommonSettings.Title))
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
widget.Redraw(title, content, wrap)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -27,5 +27,5 @@ func (widget *Widget) display(clocks []Clock, dateFormat string, timeFormat stri
|
||||
)
|
||||
}
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.Redraw(widget.CommonSettings.Title, str, false)
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
args []string
|
||||
cmd string
|
||||
settings *Settings
|
||||
@ -23,7 +22,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
args: settings.args,
|
||||
cmd: settings.cmd,
|
||||
settings: settings,
|
||||
@ -41,10 +39,7 @@ func (widget *Widget) Refresh() {
|
||||
ansiTitle := tview.TranslateANSI(widget.String())
|
||||
ansiResult := tview.TranslateANSI(result)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(ansiTitle)
|
||||
widget.View.SetText(ansiResult)
|
||||
})
|
||||
widget.Redraw(ansiTitle, ansiResult, false)
|
||||
}
|
||||
|
||||
// String returns the string representation of the widget
|
||||
|
17
modules/datadog/keyboard.go
Normal file
17
modules/datadog/keyboard.go
Normal file
@ -0,0 +1,17 @@
|
||||
package datadog
|
||||
|
||||
import (
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("/", widget.ShowHelp)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("o", widget.openItem)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyEnter, widget.openItem)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
}
|
@ -8,21 +8,43 @@ import (
|
||||
datadog "github.com/zorkian/go-datadog-api"
|
||||
)
|
||||
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
const HelpText = `
|
||||
Keyboard commands for Datadog:
|
||||
|
||||
app *tview.Application
|
||||
/: Show/hide this help window
|
||||
j: Select the next item in the list
|
||||
k: Select the previous item in the list
|
||||
|
||||
arrow down: Select the next item in the list
|
||||
arrow up: Select the previous item in the list
|
||||
|
||||
return: Open the selected issue in a browser
|
||||
`
|
||||
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
monitors []datadog.Monitor
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Render)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.HelpfulWidget.SetView(widget.View)
|
||||
|
||||
return &widget
|
||||
}
|
||||
|
||||
@ -31,26 +53,12 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
func (widget *Widget) Refresh() {
|
||||
monitors, monitorErr := widget.Monitors()
|
||||
|
||||
var content string
|
||||
if monitorErr != nil {
|
||||
widget.View.SetWrap(true)
|
||||
content = monitorErr.Error()
|
||||
} else {
|
||||
widget.View.SetWrap(false)
|
||||
content = widget.contentFrom(monitors)
|
||||
widget.monitors = nil
|
||||
widget.SetItemCount(0)
|
||||
widget.Redraw(widget.CommonSettings.Title, monitorErr.Error(), true)
|
||||
return
|
||||
}
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.View.Clear()
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) contentFrom(monitors []datadog.Monitor) string {
|
||||
var str string
|
||||
|
||||
triggeredMonitors := []datadog.Monitor{}
|
||||
|
||||
for _, monitor := range monitors {
|
||||
@ -60,13 +68,34 @@ func (widget *Widget) contentFrom(monitors []datadog.Monitor) string {
|
||||
triggeredMonitors = append(triggeredMonitors, monitor)
|
||||
}
|
||||
}
|
||||
widget.monitors = triggeredMonitors
|
||||
widget.SetItemCount(len(widget.monitors))
|
||||
|
||||
widget.Render()
|
||||
}
|
||||
|
||||
func (widget *Widget) Render() {
|
||||
content := widget.contentFrom(widget.monitors)
|
||||
widget.Redraw(widget.CommonSettings.Title, content, false)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) contentFrom(triggeredMonitors []datadog.Monitor) string {
|
||||
var str string
|
||||
|
||||
if len(triggeredMonitors) > 0 {
|
||||
str = str + fmt.Sprintf(
|
||||
" %s\n",
|
||||
"[red]Triggered Monitors[white]",
|
||||
)
|
||||
for _, triggeredMonitor := range triggeredMonitors {
|
||||
str = str + fmt.Sprintf("[red] %s\n", *triggeredMonitor.Name)
|
||||
for idx, triggeredMonitor := range triggeredMonitors {
|
||||
str = str + fmt.Sprintf(`["%d"][%s][red] %s[%s][""]`,
|
||||
idx,
|
||||
widget.RowColor(idx),
|
||||
*triggeredMonitor.Name,
|
||||
widget.RowColor(idx),
|
||||
) + "\n"
|
||||
}
|
||||
} else {
|
||||
str = str + fmt.Sprintf(
|
||||
@ -77,3 +106,12 @@ func (widget *Widget) contentFrom(monitors []datadog.Monitor) string {
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) openItem() {
|
||||
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.monitors != nil && sel < len(widget.monitors) {
|
||||
item := &widget.monitors[sel]
|
||||
wtf.OpenFile(fmt.Sprintf("https://app.datadoghq.com/monitors/%d?q=*", *item.Id))
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/wtfutil/wtf/cfg"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/calendar/v3"
|
||||
@ -30,7 +30,7 @@ import (
|
||||
func (widget *Widget) Fetch() ([]*CalEvent, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
secretPath, _ := wtf.ExpandHomeDir(widget.settings.secretFile)
|
||||
secretPath, _ := utils.ExpandHomeDir(widget.settings.secretFile)
|
||||
|
||||
b, err := ioutil.ReadFile(secretPath)
|
||||
if err != nil {
|
||||
@ -123,7 +123,7 @@ func isAuthenticated() bool {
|
||||
}
|
||||
|
||||
func (widget *Widget) authenticate() {
|
||||
secretPath, _ := wtf.ExpandHomeDir(widget.settings.secretFile)
|
||||
secretPath, _ := utils.ExpandHomeDir(widget.settings.secretFile)
|
||||
|
||||
b, err := ioutil.ReadFile(secretPath)
|
||||
if err != nil {
|
||||
|
@ -29,16 +29,12 @@ func (widget *Widget) display() {
|
||||
return
|
||||
}
|
||||
|
||||
widget.mutex.Lock()
|
||||
defer widget.mutex.Unlock()
|
||||
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.settings.common.Title))
|
||||
widget.View.SetText(widget.contentFrom(widget.calEvents))
|
||||
widget.TextWidget.Redraw(widget.settings.common.Title, widget.contentFrom(widget.calEvents), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) contentFrom(calEvents []*CalEvent) string {
|
||||
if (calEvents == nil) || (len(calEvents) == 0) {
|
||||
return ""
|
||||
return "No calendar events"
|
||||
}
|
||||
|
||||
var str string
|
||||
@ -217,7 +213,7 @@ func (widget *Widget) responseIcon(calEvent *CalEvent) string {
|
||||
|
||||
switch calEvent.ResponseFor(widget.settings.email) {
|
||||
case "accepted":
|
||||
return icon + "✔︎"
|
||||
return icon + "✔"
|
||||
case "declined":
|
||||
return icon + "✘"
|
||||
case "needsAction":
|
||||
|
@ -1,9 +1,6 @@
|
||||
package gcal
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
@ -13,8 +10,6 @@ type Widget struct {
|
||||
|
||||
app *tview.Application
|
||||
calEvents []*CalEvent
|
||||
ch chan struct{}
|
||||
mutex sync.Mutex
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -23,27 +18,21 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
ch: make(chan struct{}),
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
go updateLoop(&widget)
|
||||
|
||||
return &widget
|
||||
}
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) Disable() {
|
||||
close(widget.ch)
|
||||
widget.TextWidget.Disable()
|
||||
}
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
if isAuthenticated() {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.fetchAndDisplayEvents()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@ -61,27 +50,5 @@ func (widget *Widget) fetchAndDisplayEvents() {
|
||||
widget.calEvents = calEvents
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
func updateLoop(widget *Widget) {
|
||||
if widget.settings.textInterval == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
tick := time.NewTicker(time.Duration(widget.settings.textInterval) * time.Second)
|
||||
defer tick.Stop()
|
||||
outer:
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
case <-widget.ch:
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,11 @@ func (widget *Widget) display() {
|
||||
|
||||
project := widget.currentGerritProject()
|
||||
if project == nil {
|
||||
widget.View.SetText(fmt.Sprintf("%s", " Gerrit project data is unavailable (1)"))
|
||||
widget.Redraw(widget.CommonSettings.Title, "Gerrit project data is unavailable", true)
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s- %s", widget.CommonSettings.Title, widget.title(project))))
|
||||
title := fmt.Sprintf("%s- %s", widget.CommonSettings.Title, widget.title(project))
|
||||
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
str := widget.settings.common.SigilStr(len(widget.GerritProjects), widget.Idx, width) + "\n"
|
||||
@ -25,7 +25,7 @@ func (widget *Widget) display() {
|
||||
str = str + " [red]My Outgoing Reviews[white]\n"
|
||||
str = str + widget.displayMyOutgoingReviews(project, widget.settings.username)
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.Redraw(title, str, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) displayMyIncomingReviews(project *GerritProject, username string) string {
|
||||
|
@ -39,7 +39,6 @@ type Widget struct {
|
||||
GerritProjects []*GerritProject
|
||||
Idx int
|
||||
|
||||
app *tview.Application
|
||||
selected int
|
||||
settings *Settings
|
||||
}
|
||||
@ -56,7 +55,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
Idx: 0,
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -99,9 +97,7 @@ func (widget *Widget) Refresh() {
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(err.Error())
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
widget.gerrit = gerrit
|
||||
@ -111,10 +107,7 @@ func (widget *Widget) Refresh() {
|
||||
project.Refresh(widget.settings.username)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -9,12 +9,11 @@ import (
|
||||
func (widget *Widget) display() {
|
||||
repoData := widget.currentData()
|
||||
if repoData == nil {
|
||||
widget.View.SetText(" Git repo data is unavailable ")
|
||||
widget.Redraw(widget.CommonSettings.Title, " Git repo data is unavailable ", false)
|
||||
return
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("%s - [green]%s[white]", widget.CommonSettings.Title, repoData.Repository)
|
||||
widget.View.SetTitle(widget.ContextualTitle(title))
|
||||
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
str := widget.settings.common.SigilStr(len(widget.GitRepos), widget.Idx, width) + "\n"
|
||||
@ -25,7 +24,7 @@ func (widget *Widget) display() {
|
||||
str = str + "\n"
|
||||
str = str + widget.formatCommits(repoData.Commits)
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.Redraw(title, str, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) formatChanges(data []string) string {
|
||||
|
@ -97,9 +97,7 @@ func (widget *Widget) Refresh() {
|
||||
return widget.GitRepos[i].Path < widget.GitRepos[j].Path
|
||||
})
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
@ -125,9 +123,11 @@ func (widget *Widget) addCancelButton(form *tview.Form) {
|
||||
}
|
||||
|
||||
func (widget *Widget) modalFocus(form *tview.Form) {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
frame := widget.modalFrame(form)
|
||||
widget.pages.AddPage("modal", frame, false, true)
|
||||
widget.app.SetFocus(frame)
|
||||
})
|
||||
}
|
||||
|
||||
func (widget *Widget) modalForm(lbl, text string) *tview.Form {
|
||||
|
@ -8,13 +8,12 @@ import (
|
||||
|
||||
func (widget *Widget) display() {
|
||||
repo := widget.currentGithubRepo()
|
||||
title := fmt.Sprintf("%s - %s", widget.CommonSettings.Title, widget.title(repo))
|
||||
if repo == nil {
|
||||
widget.View.SetText(" GitHub repo data is unavailable ")
|
||||
widget.TextWidget.Redraw(title, " GitHub repo data is unavailable ", false)
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %s", widget.CommonSettings.Title, widget.title(repo))))
|
||||
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
str := widget.settings.common.SigilStr(len(widget.GithubRepos), widget.Idx, width) + "\n"
|
||||
str = str + " [red]Stats[white]\n"
|
||||
@ -26,7 +25,7 @@ func (widget *Widget) display() {
|
||||
str = str + " [red]My Pull Requests[white]\n"
|
||||
str = str + widget.displayMyPullRequests(repo, widget.settings.username)
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.TextWidget.Redraw(title, str, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) displayMyPullRequests(repo *GithubRepo, username string) string {
|
||||
|
@ -8,11 +8,11 @@ func (widget *Widget) display() {
|
||||
|
||||
project := widget.currentGitlabProject()
|
||||
if project == nil {
|
||||
widget.View.SetText(" Gitlab project data is unavailable ")
|
||||
widget.Redraw(widget.CommonSettings.Title, " Gitlab project data is unavailable ", true)
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetTitle(fmt.Sprintf("%s- %s", widget.CommonSettings.Title, widget.title(project)))
|
||||
title := fmt.Sprintf("%s- %s", widget.CommonSettings.Title, widget.title(project))
|
||||
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
str := widget.settings.common.SigilStr(len(widget.GitlabProjects), widget.Idx, width) + "\n"
|
||||
@ -24,8 +24,7 @@ func (widget *Widget) display() {
|
||||
str = str + "\n"
|
||||
str = str + " [red]My Merge Requests[white]\n"
|
||||
str = str + widget.displayMyMergeRequests(project, widget.settings.username)
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.Redraw(title, str, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) displayMyMergeRequests(project *GitlabProject, username string) string {
|
||||
|
@ -26,7 +26,6 @@ type Widget struct {
|
||||
GitlabProjects []*GitlabProject
|
||||
Idx int
|
||||
|
||||
app *tview.Application
|
||||
gitlab *glb.Client
|
||||
settings *Settings
|
||||
}
|
||||
@ -46,7 +45,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
Idx: 0,
|
||||
|
||||
app: app,
|
||||
gitlab: gitlab,
|
||||
settings: settings,
|
||||
}
|
||||
@ -68,9 +66,7 @@ func (widget *Widget) Refresh() {
|
||||
project.Refresh()
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
func (widget *Widget) Next() {
|
||||
|
@ -4,11 +4,11 @@ import "github.com/gdamore/tcell"
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("/", widget.ShowHelp)
|
||||
widget.SetKeyboardChar("j", widget.next)
|
||||
widget.SetKeyboardChar("k", widget.prev)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("r", widget.Refresh)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.next)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.prev)
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package gitter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
@ -24,11 +23,9 @@ const HelpText = `
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
app *tview.Application
|
||||
messages []Message
|
||||
selected int
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -37,20 +34,15 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
widget := Widget{
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Refresh)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.unselect()
|
||||
|
||||
widget.View.SetScrollable(true)
|
||||
widget.View.SetRegions(true)
|
||||
|
||||
widget.HelpfulWidget.SetView(widget.View)
|
||||
|
||||
return &widget
|
||||
@ -65,34 +57,25 @@ func (widget *Widget) Refresh() {
|
||||
|
||||
room, err := GetRoom(widget.settings.roomURI, widget.settings.apiToken)
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
widget.View.SetTitle(widget.CommonSettings.Title)
|
||||
widget.View.SetText(err.Error())
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
|
||||
if room == nil {
|
||||
widget.Redraw(widget.CommonSettings.Title, "No room", true)
|
||||
return
|
||||
}
|
||||
|
||||
messages, err := GetMessages(room.ID, widget.settings.numberOfMessages, widget.settings.apiToken)
|
||||
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.CommonSettings.Title)
|
||||
widget.View.SetText(err.Error())
|
||||
})
|
||||
} else {
|
||||
widget.messages = messages
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
widget.messages = messages
|
||||
widget.SetItemCount(len(messages))
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.display()
|
||||
widget.View.ScrollToEnd()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
@ -102,23 +85,21 @@ func (widget *Widget) display() {
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetWrap(true)
|
||||
widget.View.Clear()
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %s", widget.CommonSettings.Title, widget.settings.roomURI)))
|
||||
widget.View.SetText(widget.contentFrom(widget.messages))
|
||||
widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight()
|
||||
title := fmt.Sprintf("%s - %s", widget.CommonSettings.Title, widget.settings.roomURI)
|
||||
|
||||
widget.Redraw(title, widget.contentFrom(widget.messages), true)
|
||||
}
|
||||
|
||||
func (widget *Widget) contentFrom(messages []Message) string {
|
||||
var str string
|
||||
for idx, message := range messages {
|
||||
str = str + fmt.Sprintf(
|
||||
`["%d"][""][%s] [blue]%s [lightslategray]%s: [%s]%s [aqua]%s`,
|
||||
`["%d"][%s] [blue]%s [lightslategray]%s: [%s]%s [aqua]%s[""]`,
|
||||
idx,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
message.From.DisplayName,
|
||||
message.From.Username,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
message.Text,
|
||||
message.Sent.Format("Jan 02, 15:04 MST"),
|
||||
)
|
||||
@ -129,41 +110,10 @@ func (widget *Widget) contentFrom(messages []Message) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) rowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.selected) {
|
||||
return widget.settings.common.DefaultFocussedRowColor()
|
||||
}
|
||||
|
||||
return widget.settings.common.RowColor(idx)
|
||||
}
|
||||
|
||||
func (widget *Widget) next() {
|
||||
widget.selected++
|
||||
if widget.messages != nil && widget.selected >= len(widget.messages) {
|
||||
widget.selected = 0
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 && widget.messages != nil {
|
||||
widget.selected = len(widget.messages) - 1
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) openMessage() {
|
||||
sel := widget.selected
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.messages != nil && sel < len(widget.messages) {
|
||||
message := &widget.messages[widget.selected]
|
||||
message := &widget.messages[sel]
|
||||
wtf.OpenFile(message.Text)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
widget.display()
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
@ -29,7 +30,7 @@ import (
|
||||
func (widget *Widget) Fetch() ([]*sheets.ValueRange, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
secretPath, _ := wtf.ExpandHomeDir(widget.settings.secretFile)
|
||||
secretPath, _ := utils.ExpandHomeDir(widget.settings.secretFile)
|
||||
|
||||
b, err := ioutil.ReadFile(secretPath)
|
||||
if err != nil {
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -19,7 +18,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -31,9 +29,7 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
func (widget *Widget) Refresh() {
|
||||
cells, _ := widget.Fetch()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(widget.contentFrom(cells))
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, widget.contentFrom(cells), false)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -1,18 +1,17 @@
|
||||
|
||||
package hackernews
|
||||
|
||||
import "github.com/gdamore/tcell"
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("/", widget.ShowHelp)
|
||||
widget.SetKeyboardChar("j", widget.next)
|
||||
widget.SetKeyboardChar("k", widget.prev)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("o", widget.openStory)
|
||||
widget.SetKeyboardChar("r", widget.Refresh)
|
||||
widget.SetKeyboardChar("c", widget.openComments)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.next)
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyEnter, widget.openStory)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.prev)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
}
|
@ -3,7 +3,6 @@ package hackernews
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
@ -28,11 +27,9 @@ const HelpText = `
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
app *tview.Application
|
||||
stories []Story
|
||||
selected int
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -40,20 +37,15 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
widget := Widget{
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Render)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.unselect()
|
||||
|
||||
widget.View.SetScrollable(true)
|
||||
widget.View.SetRegions(true)
|
||||
|
||||
widget.HelpfulWidget.SetView(widget.View)
|
||||
|
||||
return &widget
|
||||
@ -72,10 +64,9 @@ func (widget *Widget) Refresh() {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.View.SetText(err.Error())
|
||||
} else {
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
var stories []Story
|
||||
for idx := 0; idx < widget.settings.numberOfStories; idx++ {
|
||||
story, e := GetStory(storyIds[idx])
|
||||
@ -87,38 +78,33 @@ func (widget *Widget) Refresh() {
|
||||
}
|
||||
|
||||
widget.stories = stories
|
||||
}
|
||||
widget.SetItemCount(len(stories))
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
widget.Render()
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
func (widget *Widget) Render() {
|
||||
if widget.stories == nil {
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetWrap(false)
|
||||
|
||||
widget.View.Clear()
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %sstories", widget.CommonSettings.Title, widget.settings.storyType)))
|
||||
widget.View.SetText(widget.contentFrom(widget.stories))
|
||||
widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight()
|
||||
title := fmt.Sprintf("%s - %sstories", widget.CommonSettings.Title, widget.settings.storyType)
|
||||
widget.Redraw(title, widget.contentFrom(widget.stories), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) contentFrom(stories []Story) string {
|
||||
var str string
|
||||
for idx, story := range stories {
|
||||
|
||||
u, _ := url.Parse(story.URL)
|
||||
|
||||
str = str + fmt.Sprintf(
|
||||
`["%d"][""][%s] [yellow]%d. [%s]%s [blue](%s)`,
|
||||
`["%d"][""][%s]%2d. %s [lightblue](%s)[white][""]`,
|
||||
idx,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
idx+1,
|
||||
widget.rowColor(idx),
|
||||
story.Title,
|
||||
strings.TrimPrefix(u.Host, "www."),
|
||||
)
|
||||
@ -129,49 +115,18 @@ func (widget *Widget) contentFrom(stories []Story) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) rowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.selected) {
|
||||
return widget.settings.common.DefaultFocussedRowColor()
|
||||
}
|
||||
|
||||
return widget.settings.common.RowColor(idx)
|
||||
}
|
||||
|
||||
func (widget *Widget) next() {
|
||||
widget.selected++
|
||||
if widget.stories != nil && widget.selected >= len(widget.stories) {
|
||||
widget.selected = 0
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 && widget.stories != nil {
|
||||
widget.selected = len(widget.stories) - 1
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) openStory() {
|
||||
sel := widget.selected
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.stories != nil && sel < len(widget.stories) {
|
||||
story := &widget.stories[widget.selected]
|
||||
story := &widget.stories[sel]
|
||||
wtf.OpenFile(story.URL)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) openComments() {
|
||||
sel := widget.selected
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.stories != nil && sel < len(widget.stories) {
|
||||
story := &widget.stories[widget.selected]
|
||||
story := &widget.stories[sel]
|
||||
wtf.OpenFile(fmt.Sprintf("https://news.ycombinator.com/item?id=%d", story.ID))
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
widget.display()
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
result string
|
||||
settings *Settings
|
||||
}
|
||||
@ -34,7 +33,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -46,10 +44,7 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.ipinfo()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.Clear()
|
||||
widget.View.SetText(widget.result)
|
||||
})
|
||||
widget.TextWidget.Redraw(widget.CommonSettings.Title, widget.result, false)
|
||||
}
|
||||
|
||||
//this method reads the config and calls ipinfo for ip information
|
||||
|
@ -4,13 +4,13 @@ import "github.com/gdamore/tcell"
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("/", widget.ShowHelp)
|
||||
widget.SetKeyboardChar("j", widget.next)
|
||||
widget.SetKeyboardChar("k", widget.prev)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("o", widget.openJob)
|
||||
widget.SetKeyboardChar("r", widget.Refresh)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.next)
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyEnter, widget.openJob)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.prev)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
}
|
||||
|
@ -2,8 +2,6 @@ package jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"regexp"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
@ -27,10 +25,8 @@ const HelpText = `
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
app *tview.Application
|
||||
selected int
|
||||
settings *Settings
|
||||
view *View
|
||||
}
|
||||
@ -39,20 +35,15 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
widget := Widget{
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Render)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.unselect()
|
||||
|
||||
widget.View.SetScrollable(true)
|
||||
widget.View.SetRegions(true)
|
||||
|
||||
widget.HelpfulWidget.SetView(widget.View)
|
||||
|
||||
return &widget
|
||||
@ -73,32 +64,25 @@ func (widget *Widget) Refresh() {
|
||||
widget.view = view
|
||||
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(err.Error())
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.display()
|
||||
})
|
||||
widget.SetItemCount(len(widget.view.Jobs))
|
||||
|
||||
widget.Render()
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
func (widget *Widget) Render() {
|
||||
if widget.view == nil {
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetWrap(false)
|
||||
title := fmt.Sprintf("%s: [red]%s", widget.CommonSettings.Title, widget.view.Name)
|
||||
|
||||
widget.View.Clear()
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s: [red]%s", widget.CommonSettings.Title, widget.view.Name)))
|
||||
widget.View.SetText(widget.contentFrom(widget.view))
|
||||
widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight()
|
||||
widget.Redraw(title, widget.contentFrom(widget.view), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) contentFrom(view *View) string {
|
||||
@ -108,9 +92,9 @@ func (widget *Widget) contentFrom(view *View) string {
|
||||
|
||||
if validID.MatchString(job.Name) {
|
||||
str = str + fmt.Sprintf(
|
||||
`["%d"][""][%s] [%s]%-6s[white]`,
|
||||
`["%d"][%s] [%s]%-6s[white][""]`,
|
||||
idx,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
widget.jobColor(&job),
|
||||
job.Name,
|
||||
)
|
||||
@ -122,14 +106,6 @@ func (widget *Widget) contentFrom(view *View) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) rowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.selected) {
|
||||
return widget.settings.common.DefaultFocussedRowColor()
|
||||
}
|
||||
|
||||
return widget.settings.common.RowColor(idx)
|
||||
}
|
||||
|
||||
func (widget *Widget) jobColor(job *Job) string {
|
||||
switch job.Color {
|
||||
case "blue":
|
||||
@ -142,33 +118,10 @@ func (widget *Widget) jobColor(job *Job) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) next() {
|
||||
widget.selected++
|
||||
if widget.view != nil && widget.selected >= len(widget.view.Jobs) {
|
||||
widget.selected = 0
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 && widget.view != nil {
|
||||
widget.selected = len(widget.view.Jobs) - 1
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) openJob() {
|
||||
sel := widget.selected
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.view != nil && sel < len(widget.view.Jobs) {
|
||||
job := &widget.view.Jobs[widget.selected]
|
||||
job := &widget.view.Jobs[sel]
|
||||
wtf.OpenFile(job.Url)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
widget.display()
|
||||
}
|
||||
|
@ -6,22 +6,12 @@ import (
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("/", widget.ShowHelp)
|
||||
widget.SetKeyboardChar("j", widget.selectNext)
|
||||
widget.SetKeyboardChar("k", widget.selectPrev)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("o", widget.openItem)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.selectNext)
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyEnter, widget.openItem)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.selectPrev)
|
||||
}
|
||||
|
||||
func (widget *Widget) selectNext() {
|
||||
widget.next()
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) selectPrev() {
|
||||
widget.prev()
|
||||
widget.display()
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
}
|
||||
|
@ -3,8 +3,6 @@ package jira
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
@ -25,11 +23,9 @@ const HelpText = `
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
app *tview.Application
|
||||
result *SearchResult
|
||||
selected int
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -37,20 +33,15 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
widget := Widget{
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Render)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.unselect()
|
||||
|
||||
widget.View.SetScrollable(true)
|
||||
widget.View.SetRegions(true)
|
||||
|
||||
widget.HelpfulWidget.SetView(widget.View)
|
||||
|
||||
return &widget
|
||||
@ -67,76 +58,47 @@ func (widget *Widget) Refresh() {
|
||||
|
||||
if err != nil {
|
||||
widget.result = nil
|
||||
widget.View.SetWrap(true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.CommonSettings.Title)
|
||||
widget.View.SetText(err.Error())
|
||||
})
|
||||
} else {
|
||||
widget.result = searchResult
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
widget.result = searchResult
|
||||
widget.SetItemCount(len(searchResult.Issues))
|
||||
widget.Render()
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
func (widget *Widget) Render() {
|
||||
if widget.result == nil {
|
||||
return
|
||||
}
|
||||
widget.View.SetWrap(false)
|
||||
|
||||
str := fmt.Sprintf("%s- [green]%s[white]", widget.CommonSettings.Title, widget.settings.projects)
|
||||
|
||||
widget.View.Clear()
|
||||
widget.View.SetTitle(widget.ContextualTitle(str))
|
||||
widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(widget.result)))
|
||||
widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight()
|
||||
}
|
||||
|
||||
func (widget *Widget) next() {
|
||||
widget.selected++
|
||||
if widget.result != nil && widget.selected >= len(widget.result.Issues) {
|
||||
widget.selected = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 && widget.result != nil {
|
||||
widget.selected = len(widget.result.Issues) - 1
|
||||
}
|
||||
widget.Redraw(str, widget.contentFrom(widget.result), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) openItem() {
|
||||
sel := widget.selected
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.result != nil && sel < len(widget.result.Issues) {
|
||||
issue := &widget.result.Issues[widget.selected]
|
||||
issue := &widget.result.Issues[sel]
|
||||
wtf.OpenFile(widget.settings.domain + "/browse/" + issue.Key)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
}
|
||||
|
||||
func (widget *Widget) contentFrom(searchResult *SearchResult) string {
|
||||
str := " [red]Assigned Issues[white]\n"
|
||||
|
||||
for idx, issue := range searchResult.Issues {
|
||||
fmtStr := fmt.Sprintf(
|
||||
`["%d"][""][%s] [%s]%-6s[white] [green]%-10s[white] [yellow][%s][white] [%s]%s`,
|
||||
`["%d"][%s] [%s]%-6s[white] [green]%-10s[white] [yellow][%s][white] [%s]%s[""]`,
|
||||
idx,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
widget.issueTypeColor(&issue),
|
||||
issue.IssueFields.IssueType.Name,
|
||||
issue.Key,
|
||||
issue.IssueFields.IssueStatus.IName,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
issue.IssueFields.Summary,
|
||||
)
|
||||
|
||||
@ -149,14 +111,6 @@ func (widget *Widget) contentFrom(searchResult *SearchResult) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) rowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.selected) {
|
||||
widget.settings.common.DefaultFocussedRowColor()
|
||||
}
|
||||
|
||||
return widget.settings.common.RowColor(idx)
|
||||
}
|
||||
|
||||
func (widget *Widget) issueTypeColor(issue *Issue) string {
|
||||
switch issue.IssueFields.IssueType.Name {
|
||||
case "Bug":
|
||||
|
105
modules/logger/widget.go
Normal file
105
modules/logger/widget.go
Normal file
@ -0,0 +1,105 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
log "github.com/wtfutil/wtf/logger"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
const maxBufferSize int64 = 1024
|
||||
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
filePath string
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
filePath: log.LogFilePath(),
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
return &widget
|
||||
}
|
||||
|
||||
// Refresh updates the onscreen contents of the widget
|
||||
func (widget *Widget) Refresh() {
|
||||
if log.LogFileMissing() {
|
||||
return
|
||||
}
|
||||
|
||||
logLines := widget.tailFile()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.CommonSettings.Title)
|
||||
widget.View.SetText(widget.contentFrom(logLines))
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) contentFrom(logLines []string) string {
|
||||
str := ""
|
||||
|
||||
for _, line := range logLines {
|
||||
chunks := strings.Split(line, " ")
|
||||
|
||||
if len(chunks) >= 4 {
|
||||
str = str + fmt.Sprintf(
|
||||
"[green]%s[white] [yellow]%s[white] %s\n",
|
||||
chunks[0],
|
||||
chunks[1],
|
||||
strings.Join(chunks[3:], " "),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) tailFile() []string {
|
||||
file, err := os.Open(widget.filePath)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
bufferSize := maxBufferSize
|
||||
if maxBufferSize > stat.Size() {
|
||||
bufferSize = stat.Size()
|
||||
}
|
||||
|
||||
startPos := stat.Size() - bufferSize
|
||||
|
||||
buff := make([]byte, bufferSize)
|
||||
_, err = file.ReadAt(buff, startPos)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
logLines := strings.Split(string(buff), "\n")
|
||||
|
||||
// Reverse the array of lines
|
||||
// Offset by two to account for the blank line at the end
|
||||
last := len(logLines) - 2
|
||||
for i := 0; i < len(logLines)/2; i++ {
|
||||
logLines[i], logLines[last-i] = logLines[last-i], logLines[i]
|
||||
}
|
||||
|
||||
return logLines
|
||||
}
|
@ -9,12 +9,11 @@ import (
|
||||
func (widget *Widget) display() {
|
||||
repoData := widget.currentData()
|
||||
if repoData == nil {
|
||||
widget.View.SetText(" Mercurial repo data is unavailable ")
|
||||
widget.Redraw(widget.CommonSettings.Title, " Mercurial repo data is unavailable ", false)
|
||||
return
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("%s - [green]%s[white]", widget.CommonSettings.Title, repoData.Repository)
|
||||
widget.View.SetTitle(widget.ContextualTitle(title))
|
||||
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
str := widget.settings.common.SigilStr(len(widget.Data), widget.Idx, width) + "\n"
|
||||
@ -25,7 +24,7 @@ func (widget *Widget) display() {
|
||||
str = str + "\n"
|
||||
str = str + widget.formatCommits(repoData.Commits)
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.Redraw(title, str, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) formatChanges(data []string) string {
|
||||
|
@ -71,9 +71,7 @@ func (widget *Widget) Checkout() {
|
||||
widget.pages.RemovePage("modal")
|
||||
widget.app.SetFocus(widget.View)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
|
||||
widget.Refresh()
|
||||
}
|
||||
@ -86,7 +84,6 @@ func (widget *Widget) Pull() {
|
||||
repoToPull := widget.Data[widget.Idx]
|
||||
repoToPull.pull()
|
||||
widget.Refresh()
|
||||
|
||||
}
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
@ -94,9 +91,7 @@ func (widget *Widget) Refresh() {
|
||||
|
||||
widget.Data = widget.mercurialRepos(repoPaths)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
@ -122,9 +117,11 @@ func (widget *Widget) addCancelButton(form *tview.Form) {
|
||||
}
|
||||
|
||||
func (widget *Widget) modalFocus(form *tview.Form) {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
frame := widget.modalFrame(form)
|
||||
widget.pages.AddPage("modal", frame, false, true)
|
||||
widget.app.SetFocus(frame)
|
||||
})
|
||||
}
|
||||
|
||||
func (widget *Widget) modalForm(lbl, text string) *tview.Form {
|
||||
|
@ -25,7 +25,6 @@ type Widget struct {
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
language string
|
||||
result string
|
||||
settings *Settings
|
||||
@ -40,7 +39,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -55,39 +53,32 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
}
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.nbascore()
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, widget.nbascore(), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) nbascore() {
|
||||
func (widget *Widget) nbascore() string {
|
||||
cur := time.Now().AddDate(0, 0, offset) // Go back/forward offset days
|
||||
curString := cur.Format("20060102") // Need 20060102 format to feed to api
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", "http://data.nba.net/10s/prod/v1/"+curString+"/scoreboard.json", nil)
|
||||
if err != nil {
|
||||
widget.result = err.Error()
|
||||
return
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
req.Header.Set("Accept-Language", widget.language)
|
||||
req.Header.Set("User-Agent", "curl")
|
||||
response, err := client.Do(req)
|
||||
if err != nil {
|
||||
widget.result = err.Error()
|
||||
return
|
||||
return err.Error()
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != 200 {
|
||||
widget.result = err.Error()
|
||||
return
|
||||
return err.Error()
|
||||
} // Get data from data.nba.net and check if successful
|
||||
|
||||
contents, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
widget.result = err.Error()
|
||||
return
|
||||
return err.Error()
|
||||
}
|
||||
result := map[string]interface{}{}
|
||||
json.Unmarshal(contents, &result)
|
||||
@ -146,6 +137,5 @@ func (widget *Widget) nbascore() {
|
||||
}
|
||||
allGame += fmt.Sprintf("%s%5s%v[white] %s %3s [white]vs %s%-3s %s\n", qColor, "Q", quarter, vTeam, vScore, hColor, hScore, hTeam) // Format the score and store in allgame
|
||||
}
|
||||
widget.View.SetText(allGame)
|
||||
|
||||
return allGame
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
client *Client
|
||||
settings *Settings
|
||||
}
|
||||
@ -20,7 +19,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -41,19 +39,16 @@ func (widget *Widget) Refresh() {
|
||||
}
|
||||
|
||||
var content string
|
||||
title := fmt.Sprintf("%s - [green]%s[white]", widget.CommonSettings.Title, appName)
|
||||
wrap := false
|
||||
if depErr != nil {
|
||||
widget.View.SetWrap(true)
|
||||
wrap = true
|
||||
content = depErr.Error()
|
||||
} else {
|
||||
widget.View.SetWrap(false)
|
||||
content = widget.contentFrom(deploys)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - [green]%s[white]", widget.CommonSettings.Title, appName)))
|
||||
widget.View.Clear()
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
widget.Redraw(title, content, wrap)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -19,7 +18,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -35,18 +33,15 @@ func (widget *Widget) Refresh() {
|
||||
)
|
||||
|
||||
var content string
|
||||
wrap := false
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
wrap = true
|
||||
content = err.Error()
|
||||
} else {
|
||||
widget.View.SetWrap(false)
|
||||
content = widget.contentFrom(data)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, content, wrap)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -20,7 +19,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -44,14 +42,10 @@ func (widget *Widget) Refresh() {
|
||||
incidents, err2 = GetIncidents(widget.settings.apiKey)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.View.Clear()
|
||||
})
|
||||
|
||||
var content string
|
||||
wrap := false
|
||||
if err1 != nil || err2 != nil {
|
||||
widget.View.SetWrap(true)
|
||||
wrap = true
|
||||
if err1 != nil {
|
||||
content = content + err1.Error()
|
||||
}
|
||||
@ -63,9 +57,7 @@ func (widget *Widget) Refresh() {
|
||||
content = widget.contentFrom(onCalls, incidents)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, content, wrap)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -12,7 +12,6 @@ type Widget struct {
|
||||
|
||||
Battery *Battery
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -22,7 +21,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
|
||||
Battery: NewBattery(),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -39,7 +37,5 @@ func (widget *Widget) Refresh() {
|
||||
content = content + "\n"
|
||||
content = content + widget.Battery.String()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, content, true)
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ import "github.com/gdamore/tcell"
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("/", widget.ShowHelp)
|
||||
widget.SetKeyboardChar("j", widget.next)
|
||||
widget.SetKeyboardChar("k", widget.prev)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("o", widget.openBuild)
|
||||
widget.SetKeyboardChar("r", widget.Refresh)
|
||||
widget.SetKeyboardChar("u", widget.unselect)
|
||||
widget.SetKeyboardChar("u", widget.Unselect)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.next)
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyEnter, widget.openBuild)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.prev)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
}
|
||||
|
@ -26,11 +26,9 @@ const HelpText = `
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
app *tview.Application
|
||||
items *Result
|
||||
selected int
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -39,17 +37,15 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
widget := Widget{
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Render)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.unselect()
|
||||
|
||||
widget.HelpfulWidget.SetView(widget.View)
|
||||
|
||||
return &widget
|
||||
@ -69,34 +65,30 @@ func (widget *Widget) Refresh() {
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(err.Error())
|
||||
})
|
||||
} else {
|
||||
widget.items = &items.Results
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
widget.items = &items.Results
|
||||
widget.SetItemCount(len(widget.items.Items))
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.display()
|
||||
})
|
||||
widget.Refresh()
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
func (widget *Widget) Render() {
|
||||
if widget.items == nil {
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetWrap(false)
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - %s", widget.CommonSettings.Title, widget.settings.projectName)))
|
||||
widget.View.SetText(widget.contentFrom(widget.items))
|
||||
title := fmt.Sprintf("%s - %s", widget.CommonSettings.Title, widget.settings.projectName)
|
||||
widget.Redraw(title, widget.contentFrom(widget.items), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) contentFrom(result *Result) string {
|
||||
if result == nil {
|
||||
return "No results"
|
||||
}
|
||||
var str string
|
||||
if len(result.Items) > widget.settings.count {
|
||||
result.Items = result.Items[:widget.settings.count]
|
||||
@ -105,12 +97,12 @@ func (widget *Widget) contentFrom(result *Result) string {
|
||||
|
||||
str = str + fmt.Sprintf(
|
||||
"[%s] [%s] %s [%s] %s [%s]count: %d [%s]%s\n",
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
levelColor(&item),
|
||||
item.Level,
|
||||
statusColor(&item),
|
||||
item.Title,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
item.TotalOccurrences,
|
||||
"blue",
|
||||
item.Environment,
|
||||
@ -120,14 +112,6 @@ func (widget *Widget) contentFrom(result *Result) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) rowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.selected) {
|
||||
return widget.settings.common.DefaultFocussedRowColor()
|
||||
}
|
||||
|
||||
return widget.settings.common.RowColor(idx)
|
||||
}
|
||||
|
||||
func statusColor(item *Item) string {
|
||||
switch item.Status {
|
||||
case "active":
|
||||
@ -151,27 +135,9 @@ func levelColor(item *Item) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) next() {
|
||||
widget.selected++
|
||||
if widget.items != nil && widget.selected >= len(widget.items.Items) {
|
||||
widget.selected = 0
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 && widget.items.Items != nil {
|
||||
widget.selected = len(widget.items.Items) - 1
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) openBuild() {
|
||||
if widget.selected >= 0 && widget.items != nil && widget.selected < len(widget.items.Items) {
|
||||
item := &widget.items.Items[widget.selected]
|
||||
if widget.GetSelected() >= 0 && widget.items != nil && widget.GetSelected() < len(widget.items.Items) {
|
||||
item := &widget.items.Items[widget.GetSelected()]
|
||||
|
||||
wtf.OpenFile(
|
||||
fmt.Sprintf(
|
||||
@ -184,8 +150,3 @@ func (widget *Widget) openBuild() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
widget.display()
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -19,7 +18,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -37,9 +35,7 @@ func (widget *Widget) Refresh() {
|
||||
data := NewSecurityData()
|
||||
data.Fetch()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(widget.contentFrom(data))
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, widget.contentFrom(data), false)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -21,7 +21,6 @@ type Widget struct {
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
spotigopher.Info
|
||||
spotigopher.SpotifyClient
|
||||
@ -38,7 +37,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
Info: spotigopher.Info{},
|
||||
SpotifyClient: spotifyClient,
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -63,19 +61,18 @@ func (w *Widget) refreshSpotifyInfos() error {
|
||||
}
|
||||
|
||||
func (w *Widget) Refresh() {
|
||||
w.app.QueueUpdateDraw(func() {
|
||||
w.render()
|
||||
})
|
||||
}
|
||||
|
||||
func (w *Widget) render() {
|
||||
err := w.refreshSpotifyInfos()
|
||||
w.View.Clear()
|
||||
var content string
|
||||
if err != nil {
|
||||
w.TextWidget.View.SetText(err.Error())
|
||||
content = err.Error()
|
||||
} else {
|
||||
w.TextWidget.View.SetText(w.createOutput())
|
||||
content = w.createOutput()
|
||||
}
|
||||
w.Redraw(w.CommonSettings.Title, content, true)
|
||||
}
|
||||
|
||||
func (w *Widget) createOutput() string {
|
||||
|
@ -48,7 +48,6 @@ type Widget struct {
|
||||
|
||||
Info
|
||||
|
||||
app *tview.Application
|
||||
client *spotify.Client
|
||||
clientChan chan *spotify.Client
|
||||
playerState *spotify.PlayerState
|
||||
@ -99,7 +98,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
Info: Info{},
|
||||
|
||||
app: app,
|
||||
client: client,
|
||||
clientChan: tempClientChan,
|
||||
playerState: playerState,
|
||||
@ -181,18 +179,11 @@ func (w *Widget) refreshSpotifyInfos() error {
|
||||
|
||||
// Refresh refreshes the current view of the widget
|
||||
func (w *Widget) Refresh() {
|
||||
w.app.QueueUpdateDraw(func() {
|
||||
w.render()
|
||||
})
|
||||
}
|
||||
|
||||
func (w *Widget) render() {
|
||||
err := w.refreshSpotifyInfos()
|
||||
w.View.Clear()
|
||||
if err != nil {
|
||||
w.TextWidget.View.SetText(err.Error())
|
||||
w.Redraw(w.CommonSettings.Title, err.Error(), true)
|
||||
} else {
|
||||
w.TextWidget.View.SetText(w.createOutput())
|
||||
w.Redraw(w.CommonSettings.Title, w.createOutput(), false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@ type Widget struct {
|
||||
|
||||
CurrentIcon int
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -20,7 +19,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
|
||||
CurrentIcon: 0,
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -30,9 +28,7 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(widget.animation())
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, widget.animation(), false)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -14,7 +14,6 @@ type Widget struct {
|
||||
Date string
|
||||
Version string
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
systemInfo *SystemInfo
|
||||
}
|
||||
@ -25,7 +24,6 @@ func NewWidget(app *tview.Application, date, version string, settings *Settings)
|
||||
|
||||
Date: date,
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
Version: version,
|
||||
}
|
||||
@ -36,9 +34,7 @@ func NewWidget(app *tview.Application, date, version string, settings *Settings)
|
||||
}
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(
|
||||
fmt.Sprintf(
|
||||
content := fmt.Sprintf(
|
||||
"%8s: %s\n%8s: %s\n\n%8s: %s\n%8s: %s",
|
||||
"Built",
|
||||
widget.prettyDate(),
|
||||
@ -48,9 +44,8 @@ func (widget *Widget) Refresh() {
|
||||
widget.systemInfo.ProductVersion,
|
||||
"Build",
|
||||
widget.systemInfo.BuildVersion,
|
||||
),
|
||||
)
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, content, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) prettyDate() string {
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/alecthomas/chroma/styles"
|
||||
"github.com/radovskyb/watcher"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
@ -73,16 +74,13 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
// Refresh is only called once on start-up. Its job is to display the
|
||||
// text files that first time. After that, the watcher takes over
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
title := fmt.Sprintf("[green]%s[white]", widget.CurrentSource())
|
||||
title = widget.ContextualTitle(title)
|
||||
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
text := widget.settings.common.SigilStr(len(widget.Sources), widget.Idx, width) + "\n"
|
||||
@ -93,8 +91,7 @@ func (widget *Widget) display() {
|
||||
text = text + widget.plainText()
|
||||
}
|
||||
|
||||
widget.View.SetTitle(title) // <- Writes to TextView's title
|
||||
widget.View.SetText(text) // <- Writes to TextView's text
|
||||
widget.Redraw(title, text, true)
|
||||
}
|
||||
|
||||
func (widget *Widget) fileName() string {
|
||||
@ -102,7 +99,7 @@ func (widget *Widget) fileName() string {
|
||||
}
|
||||
|
||||
func (widget *Widget) formattedText() string {
|
||||
filePath, _ := wtf.ExpandHomeDir(widget.CurrentSource())
|
||||
filePath, _ := utils.ExpandHomeDir(widget.CurrentSource())
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
@ -133,7 +130,7 @@ func (widget *Widget) formattedText() string {
|
||||
}
|
||||
|
||||
func (widget *Widget) plainText() string {
|
||||
filePath, _ := wtf.ExpandHomeDir(widget.CurrentSource())
|
||||
filePath, _ := utils.ExpandHomeDir(widget.CurrentSource())
|
||||
|
||||
fmt.Println(filePath)
|
||||
|
||||
@ -163,7 +160,7 @@ func (widget *Widget) watchForFileChanges() {
|
||||
|
||||
// Watch each textfile for changes
|
||||
for _, source := range widget.Sources {
|
||||
fullPath, err := wtf.ExpandHomeDir(source)
|
||||
fullPath, err := utils.ExpandHomeDir(source)
|
||||
if err == nil {
|
||||
if err := watch.Add(fullPath); err != nil {
|
||||
log.Fatalln(err)
|
||||
|
@ -2,7 +2,6 @@ package todo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/checklist"
|
||||
@ -34,9 +33,7 @@ func (widget *Widget) display() {
|
||||
newList.SetSelectedByItem(widget.list.SelectedItem())
|
||||
widget.SetList(newList)
|
||||
|
||||
widget.View.Clear()
|
||||
widget.View.SetText(str)
|
||||
widget.View.Highlight(strconv.Itoa(widget.list.Selected())).ScrollToHighlight()
|
||||
widget.Redraw(widget.CommonSettings.Title, str, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) formattedItemLine(idx int, item *checklist.ChecklistItem, selectedItem *checklist.ChecklistItem, maxLen int) string {
|
||||
@ -52,7 +49,7 @@ func (widget *Widget) formattedItemLine(idx int, item *checklist.ChecklistItem,
|
||||
}
|
||||
|
||||
str := fmt.Sprintf(
|
||||
`["%d"][""][%s:%s]|%s| %s[white]`,
|
||||
`["%d"][""][%s:%s]|%s| %s[white][""]`,
|
||||
idx,
|
||||
foreColor,
|
||||
backColor,
|
||||
|
@ -79,13 +79,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.load()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
title := widget.ContextualTitle(widget.CommonSettings.Title)
|
||||
widget.View.SetTitle(title)
|
||||
widget.display()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (widget *Widget) SetList(list checklist.Checklist) {
|
||||
@ -150,6 +144,10 @@ func (widget *Widget) newItem() {
|
||||
|
||||
widget.addButtons(form, saveFctn)
|
||||
widget.modalFocus(form)
|
||||
|
||||
widget.app.QueueUpdate(func() {
|
||||
widget.app.Draw()
|
||||
})
|
||||
}
|
||||
|
||||
// persist writes the todo list to Yaml file
|
||||
@ -198,10 +196,9 @@ func (widget *Widget) addSaveButton(form *tview.Form, fctn func()) {
|
||||
}
|
||||
|
||||
func (widget *Widget) modalFocus(form *tview.Form) {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
frame := widget.modalFrame(form)
|
||||
widget.pages.AddPage("modal", frame, false, true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.app.SetFocus(frame)
|
||||
})
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ func (widget *Widget) display() {
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("[green]%s[white]", proj.Project.Name)
|
||||
widget.View.SetTitle(widget.ContextualTitle(title))
|
||||
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
str := widget.settings.common.SigilStr(len(widget.projects), widget.idx, width) + "\n"
|
||||
@ -47,5 +46,5 @@ func (widget *Widget) display() {
|
||||
str = str + row + wtf.PadRow((checkWidth+len(item.Content)), (checkWidth+maxLen+1)) + "\n"
|
||||
}
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.TextWidget.Redraw(title, str, false)
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ type Widget struct {
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
idx int
|
||||
projects []*Project
|
||||
settings *Settings
|
||||
@ -44,7 +43,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -96,9 +94,7 @@ func (w *Widget) Refresh() {
|
||||
return
|
||||
}
|
||||
|
||||
w.app.QueueUpdateDraw(func() {
|
||||
w.display()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Keyboard Movement -------------------- */
|
||||
|
@ -4,13 +4,13 @@ import "github.com/gdamore/tcell"
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("/", widget.ShowHelp)
|
||||
widget.SetKeyboardChar("j", widget.next)
|
||||
widget.SetKeyboardChar("k", widget.prev)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("o", widget.openBuild)
|
||||
widget.SetKeyboardChar("r", widget.Refresh)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.next)
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyEnter, widget.openBuild)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.prev)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
}
|
||||
|
@ -25,11 +25,9 @@ const HelpText = `
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
app *tview.Application
|
||||
builds *Builds
|
||||
selected int
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -37,17 +35,15 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
widget := Widget{
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Render)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
widget.unselect()
|
||||
|
||||
widget.HelpfulWidget.SetView(widget.View)
|
||||
|
||||
return &widget
|
||||
@ -63,32 +59,23 @@ func (widget *Widget) Refresh() {
|
||||
builds, err := BuildsFor(widget.settings.apiKey, widget.settings.pro)
|
||||
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(err.Error())
|
||||
})
|
||||
} else {
|
||||
widget.builds = builds
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
return
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.display()
|
||||
})
|
||||
widget.builds = builds
|
||||
widget.SetItemCount(len(builds.Builds))
|
||||
widget.Render()
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
func (widget *Widget) Render() {
|
||||
if widget.builds == nil {
|
||||
return
|
||||
}
|
||||
|
||||
widget.View.SetWrap(false)
|
||||
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s - Builds", widget.CommonSettings.Title)))
|
||||
widget.View.SetText(widget.contentFrom(widget.builds))
|
||||
title := fmt.Sprintf("%s - Builds", widget.CommonSettings.Title)
|
||||
widget.Redraw(title, widget.contentFrom(widget.builds), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) contentFrom(builds *Builds) string {
|
||||
@ -97,12 +84,12 @@ func (widget *Widget) contentFrom(builds *Builds) string {
|
||||
|
||||
str = str + fmt.Sprintf(
|
||||
"[%s] [%s] %s-%s (%s) [%s]%s - [blue]%s\n",
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
buildColor(&build),
|
||||
build.Repository.Name,
|
||||
build.Number,
|
||||
build.Branch.Name,
|
||||
widget.rowColor(idx),
|
||||
widget.RowColor(idx),
|
||||
strings.Split(build.Commit.Message, "\n")[0],
|
||||
build.CreatedBy.Login,
|
||||
)
|
||||
@ -111,14 +98,6 @@ func (widget *Widget) contentFrom(builds *Builds) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) rowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.selected) {
|
||||
return widget.settings.common.DefaultFocussedRowColor()
|
||||
}
|
||||
|
||||
return widget.settings.common.RowColor(idx)
|
||||
}
|
||||
|
||||
func buildColor(build *Build) string {
|
||||
switch build.State {
|
||||
case "broken":
|
||||
@ -140,34 +119,11 @@ func buildColor(build *Build) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) next() {
|
||||
widget.selected++
|
||||
if widget.builds != nil && widget.selected >= len(widget.builds.Builds) {
|
||||
widget.selected = 0
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 && widget.builds != nil {
|
||||
widget.selected = len(widget.builds.Builds) - 1
|
||||
}
|
||||
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) openBuild() {
|
||||
sel := widget.selected
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.builds != nil && sel < len(widget.builds.Builds) {
|
||||
build := &widget.builds.Builds[widget.selected]
|
||||
build := &widget.builds.Builds[sel]
|
||||
travisHost := TRAVIS_HOSTS[widget.settings.pro]
|
||||
wtf.OpenFile(fmt.Sprintf("https://%s/%s/%s/%d", travisHost, build.Repository.Slug, "builds", build.ID))
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
widget.display()
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -19,7 +18,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -45,8 +43,9 @@ func (widget *Widget) Refresh() {
|
||||
var title string
|
||||
var content string
|
||||
|
||||
wrap := false
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
wrap = true
|
||||
title = widget.CommonSettings.Title
|
||||
content = err.Error()
|
||||
} else {
|
||||
@ -59,10 +58,7 @@ func (widget *Widget) Refresh() {
|
||||
content = widget.contentFrom(searchResult)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(title)
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
widget.Redraw(title, content, wrap)
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
@ -28,7 +28,6 @@ type Widget struct {
|
||||
wtf.MultiSourceWidget
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
client *Client
|
||||
idx int
|
||||
settings *Settings
|
||||
@ -42,7 +41,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
MultiSourceWidget: wtf.NewMultiSourceWidget(settings.common, "screenName", "screenNames"),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
idx: 0,
|
||||
settings: settings,
|
||||
}
|
||||
@ -67,9 +65,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
// Refresh is called on the interval and refreshes the data
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
@ -78,10 +74,10 @@ func (widget *Widget) display() {
|
||||
widget.client.screenName = widget.CurrentSource()
|
||||
tweets := widget.client.Tweets()
|
||||
|
||||
widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("Twitter - [green]@%s[white]", widget.CurrentSource())))
|
||||
title := fmt.Sprintf("Twitter - [green]@%s[white]", widget.CurrentSource())
|
||||
|
||||
if len(tweets) == 0 {
|
||||
str := fmt.Sprintf("\n\n\n%s", wtf.CenterText("[blue]No Tweets[white]", 50))
|
||||
str := fmt.Sprintf("\n\n\n%s", wtf.CenterText("[lightblue]No Tweets[white]", 50))
|
||||
widget.View.SetText(str)
|
||||
return
|
||||
}
|
||||
@ -92,7 +88,7 @@ func (widget *Widget) display() {
|
||||
str = str + widget.format(tweet)
|
||||
}
|
||||
|
||||
widget.View.SetText(str)
|
||||
widget.Redraw(title, str, true)
|
||||
}
|
||||
|
||||
// If the tweet's Username is the same as the account we're watching, no
|
||||
@ -116,7 +112,7 @@ func (widget *Widget) formatText(text string) string {
|
||||
|
||||
// @name mentions
|
||||
atRegExp := regexp.MustCompile(`@[0-9A-Za-z_]*`)
|
||||
result = atRegExp.ReplaceAllString(result, "[blue]${0}[white]")
|
||||
result = atRegExp.ReplaceAllString(result, "[lightblue]${0}[white]")
|
||||
|
||||
// HTTP(S) links
|
||||
linkRegExp := regexp.MustCompile(`http[s:\/.0-9A-Za-z]*`)
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -18,7 +17,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -28,10 +26,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.Clear()
|
||||
|
||||
content := fmt.Sprintf("Widget %s and/or type %s does not exist", widget.Name(), widget.CommonSettings.Module.Type)
|
||||
widget.View.SetText(content)
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, content, true)
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ const HelpText = `
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
teams []OnCallTeam
|
||||
settings *Settings
|
||||
}
|
||||
@ -47,19 +46,11 @@ func (widget *Widget) Refresh() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
|
||||
if err != nil {
|
||||
widget.View.SetWrap(true)
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(err.Error())
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, err.Error(), true)
|
||||
} else {
|
||||
widget.teams = teams
|
||||
widget.Redraw(widget.CommonSettings.Title, widget.contentFrom(widget.teams), true)
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
func (widget *Widget) display() {
|
||||
@ -75,6 +66,10 @@ func (widget *Widget) display() {
|
||||
func (widget *Widget) contentFrom(teams []OnCallTeam) string {
|
||||
var str string
|
||||
|
||||
if teams == nil || len(teams) == 0 {
|
||||
return "No teams specified"
|
||||
}
|
||||
|
||||
for _, team := range teams {
|
||||
if len(widget.settings.team) > 0 && widget.settings.team != team.Slug {
|
||||
continue
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
app *tview.Application
|
||||
result string
|
||||
settings *Settings
|
||||
}
|
||||
@ -21,7 +20,6 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -31,9 +29,7 @@ func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
func (widget *Widget) Refresh() {
|
||||
widget.prettyWeather()
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.SetText(widget.result)
|
||||
})
|
||||
widget.Redraw(widget.CommonSettings.Title, widget.result, false)
|
||||
}
|
||||
|
||||
//this method reads the config and calls wttr.in for pretty weather
|
||||
|
@ -9,31 +9,35 @@ import (
|
||||
)
|
||||
|
||||
func (widget *Widget) display() {
|
||||
err := ""
|
||||
if widget.apiKeyValid() == false {
|
||||
widget.View.SetText(" Environment variable WTF_OWM_API_KEY is not set")
|
||||
return
|
||||
err += " Environment variable WTF_OWM_API_KEY is not set\n"
|
||||
}
|
||||
|
||||
cityData := widget.currentData()
|
||||
if cityData == nil {
|
||||
widget.View.SetText(" Weather data is unavailable: no city data")
|
||||
return
|
||||
err += " Weather data is unavailable: no city data\n"
|
||||
}
|
||||
|
||||
if len(cityData.Weather) == 0 {
|
||||
widget.View.SetText(" Weather data is unavailable: no weather data")
|
||||
return
|
||||
err += " Weather data is unavailable: no weather data"
|
||||
}
|
||||
|
||||
widget.View.SetTitle(widget.title(cityData))
|
||||
title := widget.CommonSettings.Title
|
||||
|
||||
var content string
|
||||
if err != "" {
|
||||
content = err
|
||||
} else {
|
||||
title = widget.buildTitle(cityData)
|
||||
_, _, width, _ := widget.View.GetRect()
|
||||
content := widget.settings.common.SigilStr(len(widget.Data), widget.Idx, width) + "\n"
|
||||
content = widget.settings.common.SigilStr(len(widget.Data), widget.Idx, width) + "\n"
|
||||
content = content + widget.description(cityData) + "\n\n"
|
||||
content = content + widget.temperatures(cityData) + "\n"
|
||||
content = content + widget.sunInfo(cityData)
|
||||
}
|
||||
|
||||
widget.View.SetText(content)
|
||||
widget.Redraw(title, content, false)
|
||||
}
|
||||
|
||||
func (widget *Widget) description(cityData *owm.CurrentWeatherData) string {
|
||||
@ -69,7 +73,6 @@ func (widget *Widget) temperatures(cityData *owm.CurrentWeatherData) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (widget *Widget) title(cityData *owm.CurrentWeatherData) string {
|
||||
str := fmt.Sprintf("%s %s", widget.emojiFor(cityData), cityData.Name)
|
||||
return widget.ContextualTitle(str)
|
||||
func (widget *Widget) buildTitle(cityData *owm.CurrentWeatherData) string {
|
||||
return fmt.Sprintf("%s %s", widget.emojiFor(cityData), cityData.Name)
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ type Widget struct {
|
||||
Data []*owm.CurrentWeatherData
|
||||
Idx int
|
||||
|
||||
app *tview.Application
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
@ -40,7 +39,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
||||
|
||||
Idx: 0,
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
@ -77,9 +75,7 @@ func (widget *Widget) Refresh() {
|
||||
widget.Data = widget.Fetch(wtf.ToInts(widget.settings.cityIDs))
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
}
|
||||
|
||||
// Next displays data for the next city data in the list. If the current city is the last
|
||||
|
@ -3,22 +3,12 @@ package zendesk
|
||||
import "github.com/gdamore/tcell"
|
||||
|
||||
func (widget *Widget) initializeKeyboardControls() {
|
||||
widget.SetKeyboardChar("j", widget.selectNext)
|
||||
widget.SetKeyboardChar("k", widget.selectPrev)
|
||||
widget.SetKeyboardChar("j", widget.Next)
|
||||
widget.SetKeyboardChar("k", widget.Prev)
|
||||
widget.SetKeyboardChar("o", widget.openTicket)
|
||||
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.selectNext)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.selectPrev)
|
||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Next)
|
||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Prev)
|
||||
widget.SetKeyboardKey(tcell.KeyEnter, widget.openTicket)
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.unselect)
|
||||
}
|
||||
|
||||
func (widget *Widget) selectNext() {
|
||||
widget.next()
|
||||
widget.display()
|
||||
}
|
||||
|
||||
func (widget *Widget) selectPrev() {
|
||||
widget.prev()
|
||||
widget.display()
|
||||
widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect)
|
||||
}
|
||||
|
@ -8,27 +8,41 @@ import (
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
const HelpText = `
|
||||
Keyboard commands for Zendesk:
|
||||
|
||||
/: Show/hide this help window
|
||||
j: Select the next item in the list
|
||||
k: Select the previous item in the list
|
||||
o: Open the selected item in a browser
|
||||
|
||||
arrow down: Select the next item in the list
|
||||
arrow up: Select the previous item in the list
|
||||
|
||||
return: Open the selected item in a browser
|
||||
`
|
||||
|
||||
// A Widget represents a Zendesk widget
|
||||
type Widget struct {
|
||||
wtf.HelpfulWidget
|
||||
wtf.KeyboardWidget
|
||||
wtf.TextWidget
|
||||
wtf.ScrollableWidget
|
||||
|
||||
app *tview.Application
|
||||
result *TicketArray
|
||||
selected int
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
// NewWidget creates a new instance of a widget
|
||||
func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
HelpfulWidget: wtf.NewHelpfulWidget(app, pages, HelpText),
|
||||
KeyboardWidget: wtf.NewKeyboardWidget(),
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||
ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true),
|
||||
|
||||
app: app,
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
widget.SetRenderFunction(widget.Render)
|
||||
widget.initializeKeyboardControls()
|
||||
widget.View.SetInputCapture(widget.InputCapture)
|
||||
|
||||
@ -46,16 +60,14 @@ func (widget *Widget) Refresh() {
|
||||
widget.result = ticketArray
|
||||
}
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.display()
|
||||
})
|
||||
widget.Render()
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *Widget) display() {
|
||||
widget.View.SetTitle(fmt.Sprintf("%s (%d)", widget.CommonSettings.Title, widget.result.Count))
|
||||
widget.View.SetText(widget.textContent(widget.result.Tickets))
|
||||
func (widget *Widget) Render() {
|
||||
title := fmt.Sprintf("%s (%d)", widget.CommonSettings.Title, widget.result.Count)
|
||||
widget.Redraw(title, widget.textContent(widget.result.Tickets), false)
|
||||
}
|
||||
|
||||
func (widget *Widget) textContent(items []Ticket) string {
|
||||
@ -73,7 +85,7 @@ func (widget *Widget) textContent(items []Ticket) string {
|
||||
|
||||
func (widget *Widget) format(ticket Ticket, idx int) string {
|
||||
textColor := widget.settings.common.Colors.Background
|
||||
if idx == widget.selected {
|
||||
if idx == widget.GetSelected() {
|
||||
textColor = widget.settings.common.Colors.BorderFocused
|
||||
}
|
||||
|
||||
@ -95,29 +107,11 @@ func (widget *Widget) parseRequester(ticket Ticket) interface{} {
|
||||
return fromName
|
||||
}
|
||||
|
||||
func (widget *Widget) next() {
|
||||
widget.selected++
|
||||
if widget.result != nil && widget.selected >= len(widget.result.Tickets) {
|
||||
widget.selected = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 && widget.result != nil {
|
||||
widget.selected = len(widget.result.Tickets) - 1
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) openTicket() {
|
||||
sel := widget.selected
|
||||
sel := widget.GetSelected()
|
||||
if sel >= 0 && widget.result != nil && sel < len(widget.result.Tickets) {
|
||||
issue := &widget.result.Tickets[widget.selected]
|
||||
issue := &widget.result.Tickets[sel]
|
||||
ticketURL := fmt.Sprintf("https://%s.zendesk.com/agent/tickets/%d", widget.settings.subdomain, issue.Id)
|
||||
wtf.OpenFile(ticketURL)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Widget) unselect() {
|
||||
widget.selected = -1
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
// Copied (mostly) verbatim from https://github.com/Atrox/homedir
|
||||
|
||||
package wtf
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
@ -1,6 +1,8 @@
|
||||
package wtf
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/olebedev/config"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
@ -177,6 +179,17 @@ func (tracker *FocusTracker) focusables() []Wtfable {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort for deterministic ordering
|
||||
sort.SliceStable(focusable[:], func(i, j int) bool {
|
||||
if focusable[i].Top() < focusable[j].Top() {
|
||||
return true
|
||||
}
|
||||
if focusable[i].Top() == focusable[j].Top() {
|
||||
return focusable[i].Left() < focusable[j].Left()
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return focusable
|
||||
}
|
||||
|
||||
|
79
wtf/scrollable.go
Normal file
79
wtf/scrollable.go
Normal file
@ -0,0 +1,79 @@
|
||||
package wtf
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/cfg"
|
||||
)
|
||||
|
||||
type ScrollableWidget struct {
|
||||
TextWidget
|
||||
|
||||
selected int
|
||||
maxItems int
|
||||
RenderFunction func()
|
||||
}
|
||||
|
||||
func NewScrollableWidget(app *tview.Application, commonSettings *cfg.Common, focusable bool) ScrollableWidget {
|
||||
|
||||
widget := ScrollableWidget{
|
||||
TextWidget: NewTextWidget(app, commonSettings, focusable),
|
||||
}
|
||||
|
||||
widget.Unselect()
|
||||
widget.View.SetScrollable(true)
|
||||
widget.View.SetRegions(true)
|
||||
return widget
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) SetRenderFunction(displayFunc func()) {
|
||||
widget.RenderFunction = displayFunc
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) SetItemCount(items int) {
|
||||
widget.maxItems = items
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) GetSelected() int {
|
||||
return widget.selected
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) RowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.selected) {
|
||||
return widget.CommonSettings.DefaultFocussedRowColor()
|
||||
}
|
||||
|
||||
return widget.CommonSettings.RowColor(idx)
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) Next() {
|
||||
widget.selected++
|
||||
if widget.selected >= widget.maxItems {
|
||||
widget.selected = 0
|
||||
}
|
||||
widget.RenderFunction()
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) Prev() {
|
||||
widget.selected--
|
||||
if widget.selected < 0 {
|
||||
widget.selected = widget.maxItems - 1
|
||||
}
|
||||
widget.RenderFunction()
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) Unselect() {
|
||||
widget.selected = -1
|
||||
if widget.RenderFunction != nil {
|
||||
widget.RenderFunction()
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) Redraw(title, content string, wrap bool) {
|
||||
|
||||
widget.TextWidget.Redraw(title, content, wrap)
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.Highlight(strconv.Itoa(widget.selected)).ScrollToHighlight()
|
||||
})
|
||||
}
|
@ -13,6 +13,7 @@ type TextWidget struct {
|
||||
focusChar string
|
||||
name string
|
||||
refreshInterval int
|
||||
app *tview.Application
|
||||
|
||||
View *tview.TextView
|
||||
|
||||
@ -24,6 +25,7 @@ func NewTextWidget(app *tview.Application, commonSettings *cfg.Common, focusable
|
||||
widget := TextWidget{
|
||||
CommonSettings: commonSettings,
|
||||
|
||||
app: app,
|
||||
enabled: commonSettings.Enabled,
|
||||
focusable: focusable,
|
||||
focusChar: commonSettings.FocusChar(),
|
||||
@ -107,6 +109,16 @@ func (widget *TextWidget) TextView() *tview.TextView {
|
||||
return widget.View
|
||||
}
|
||||
|
||||
func (widget *TextWidget) Redraw(title, text string, wrap bool) {
|
||||
|
||||
widget.app.QueueUpdateDraw(func() {
|
||||
widget.View.Clear()
|
||||
widget.View.SetWrap(wrap)
|
||||
widget.View.SetTitle(widget.ContextualTitle(title))
|
||||
widget.View.SetText(text)
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *TextWidget) addView() *tview.TextView {
|
||||
@ -119,7 +131,6 @@ func (widget *TextWidget) addView() *tview.TextView {
|
||||
|
||||
view.SetBorder(true)
|
||||
view.SetDynamicColors(true)
|
||||
view.SetTitle(widget.ContextualTitle(widget.CommonSettings.Title))
|
||||
view.SetWrap(false)
|
||||
|
||||
return view
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
)
|
||||
|
||||
const SimpleDateFormat = "Jan 2"
|
||||
@ -92,7 +94,7 @@ func OpenFile(path string) {
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
filePath, _ := ExpandHomeDir(path)
|
||||
filePath, _ := utils.ExpandHomeDir(path)
|
||||
cmd := exec.Command(OpenFileUtil, filePath)
|
||||
ExecuteCommand(cmd)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user