mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Merge branch 'master' into githubmultisource
This commit is contained in:
commit
85014a4ded
@ -7,7 +7,6 @@ builds:
|
|||||||
goos:
|
goos:
|
||||||
- darwin
|
- darwin
|
||||||
- linux
|
- linux
|
||||||
- windows
|
|
||||||
goarch:
|
goarch:
|
||||||
- 386
|
- 386
|
||||||
- amd64
|
- amd64
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## v0.10.0
|
||||||
|
|
||||||
### ⚡️ Added
|
### ⚡️ Added
|
||||||
|
|
||||||
* DataDog module is now scrollable and interactive, by [@Seanstoppable](https://github.com/Seanstoppable)
|
* DataDog module is now scrollable and interactive, by [@Seanstoppable](https://github.com/Seanstoppable)
|
||||||
|
@ -53,21 +53,6 @@ func (list *Checklist) Delete() {
|
|||||||
list.Prev()
|
list.Prev()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Demote moves the selected item down in the checklist
|
|
||||||
func (list *Checklist) Demote() {
|
|
||||||
if list.IsUnselectable() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
j := list.selected + 1
|
|
||||||
if j >= len(list.Items) {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Swap(list.selected, j)
|
|
||||||
list.selected = j
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSelectable returns true if the checklist has selectable items, false if it does not
|
// IsSelectable returns true if the checklist has selectable items, false if it does not
|
||||||
func (list *Checklist) IsSelectable() bool {
|
func (list *Checklist) IsSelectable() bool {
|
||||||
return list.selected >= 0 && list.selected < len(list.Items)
|
return list.selected >= 0 && list.selected < len(list.Items)
|
||||||
@ -78,14 +63,6 @@ func (list *Checklist) IsUnselectable() bool {
|
|||||||
return !list.IsSelectable()
|
return !list.IsSelectable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next selects the next item in the checklist
|
|
||||||
func (list *Checklist) Next() {
|
|
||||||
list.selected = list.selected + 1
|
|
||||||
if list.selected >= len(list.Items) {
|
|
||||||
list.selected = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LongestLine returns the length of the longest checklist item's text
|
// LongestLine returns the length of the longest checklist item's text
|
||||||
func (list *Checklist) LongestLine() int {
|
func (list *Checklist) LongestLine() int {
|
||||||
maxLen := 0
|
maxLen := 0
|
||||||
@ -99,29 +76,6 @@ func (list *Checklist) LongestLine() int {
|
|||||||
return maxLen
|
return maxLen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prev selects the previous item in the checklist
|
|
||||||
func (list *Checklist) Prev() {
|
|
||||||
list.selected = list.selected - 1
|
|
||||||
if list.selected < 0 {
|
|
||||||
list.selected = len(list.Items) - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Promote moves the selected item up in the checklist
|
|
||||||
func (list *Checklist) Promote() {
|
|
||||||
if list.IsUnselectable() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
j := list.selected - 1
|
|
||||||
if j < 0 {
|
|
||||||
j = len(list.Items) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Swap(list.selected, j)
|
|
||||||
list.selected = j
|
|
||||||
}
|
|
||||||
|
|
||||||
func (list *Checklist) Selected() int {
|
func (list *Checklist) Selected() int {
|
||||||
return list.selected
|
return list.selected
|
||||||
}
|
}
|
||||||
@ -182,6 +136,54 @@ func (list *Checklist) Update(text string) {
|
|||||||
item.Text = text
|
item.Text = text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------- Item Movement -------------------- */
|
||||||
|
|
||||||
|
// Prev selects the previous item UP in the checklist
|
||||||
|
func (list *Checklist) Prev() {
|
||||||
|
list.selected = list.selected - 1
|
||||||
|
if list.selected < 0 {
|
||||||
|
list.selected = len(list.Items) - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next selects the next item DOWN in the checklist
|
||||||
|
func (list *Checklist) Next() {
|
||||||
|
list.selected = list.selected + 1
|
||||||
|
if list.selected >= len(list.Items) {
|
||||||
|
list.selected = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Promote moves the selected item UP in the checklist
|
||||||
|
func (list *Checklist) Promote() {
|
||||||
|
if list.IsUnselectable() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
k := list.selected - 1
|
||||||
|
if k < 0 {
|
||||||
|
k = len(list.Items) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Swap(list.selected, k)
|
||||||
|
list.selected = k
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demote moves the selected item DOWN in the checklist
|
||||||
|
func (list *Checklist) Demote() {
|
||||||
|
if list.IsUnselectable() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
j := list.selected + 1
|
||||||
|
if j >= len(list.Items) {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Swap(list.selected, j)
|
||||||
|
list.selected = j
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------- Sort Interface -------------------- */
|
/* -------------------- Sort Interface -------------------- */
|
||||||
|
|
||||||
func (list *Checklist) Len() int {
|
func (list *Checklist) Len() int {
|
||||||
|
@ -216,25 +216,3 @@ func (widget *Widget) findGitRepositories(repositories []*GitRepo, directory str
|
|||||||
|
|
||||||
return repositories
|
return repositories
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *Widget) Next() {
|
|
||||||
widget.Idx = widget.Idx + 1
|
|
||||||
if widget.Idx == len(widget.GitRepos) {
|
|
||||||
widget.Idx = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if widget.DisplayFunction != nil {
|
|
||||||
widget.DisplayFunction()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (widget *Widget) Prev() {
|
|
||||||
widget.Idx = widget.Idx - 1
|
|
||||||
if widget.Idx < 0 {
|
|
||||||
widget.Idx = len(widget.GitRepos) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if widget.DisplayFunction != nil {
|
|
||||||
widget.DisplayFunction()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -19,7 +19,7 @@ func (widget *Widget) display() {
|
|||||||
title := fmt.Sprintf("[green]%s[white]", proj.Project.Name)
|
title := fmt.Sprintf("[green]%s[white]", proj.Project.Name)
|
||||||
|
|
||||||
_, _, width, _ := widget.View.GetRect()
|
_, _, width, _ := widget.View.GetRect()
|
||||||
str := widget.settings.common.SigilStr(len(widget.projects), widget.idx, width) + "\n"
|
str := widget.settings.common.SigilStr(len(widget.projects), widget.Idx, width) + "\n"
|
||||||
|
|
||||||
maxLen := proj.LongestLine()
|
maxLen := proj.LongestLine()
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@ func (widget *Widget) initializeKeyboardControls() {
|
|||||||
widget.SetKeyboardChar("/", widget.ShowHelp, "Show/hide this help prompt")
|
widget.SetKeyboardChar("/", widget.ShowHelp, "Show/hide this help prompt")
|
||||||
widget.SetKeyboardChar("c", widget.Close, "Close item")
|
widget.SetKeyboardChar("c", widget.Close, "Close item")
|
||||||
widget.SetKeyboardChar("d", widget.Delete, "Delete item")
|
widget.SetKeyboardChar("d", widget.Delete, "Delete item")
|
||||||
widget.SetKeyboardChar("h", widget.PreviousProject, "Select previous project")
|
widget.SetKeyboardChar("h", widget.Prev, "Select previous project")
|
||||||
widget.SetKeyboardChar("j", widget.Up, "Select previous item")
|
widget.SetKeyboardChar("j", widget.Up, "Select previous item")
|
||||||
widget.SetKeyboardChar("k", widget.Down, "Select next item")
|
widget.SetKeyboardChar("k", widget.Down, "Select next item")
|
||||||
widget.SetKeyboardChar("l", widget.NextProject, "Select next project")
|
widget.SetKeyboardChar("l", widget.Next, "Select next project")
|
||||||
widget.SetKeyboardChar("r", widget.Refresh, "Refresh widget")
|
widget.SetKeyboardChar("r", widget.Refresh, "Refresh widget")
|
||||||
|
|
||||||
widget.SetKeyboardKey(tcell.KeyDown, widget.Down, "Select next item")
|
widget.SetKeyboardKey(tcell.KeyDown, widget.Down, "Select next item")
|
||||||
widget.SetKeyboardKey(tcell.KeyLeft, widget.PreviousProject, "Select previous project")
|
widget.SetKeyboardKey(tcell.KeyLeft, widget.Prev, "Select previous project")
|
||||||
widget.SetKeyboardKey(tcell.KeyRight, widget.NextProject, "Select next project")
|
widget.SetKeyboardKey(tcell.KeyRight, widget.Next, "Select next project")
|
||||||
widget.SetKeyboardKey(tcell.KeyUp, widget.Up, "Select previous item")
|
widget.SetKeyboardKey(tcell.KeyUp, widget.Up, "Select previous item")
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ import (
|
|||||||
type Widget struct {
|
type Widget struct {
|
||||||
wtf.KeyboardWidget
|
wtf.KeyboardWidget
|
||||||
wtf.TextWidget
|
wtf.TextWidget
|
||||||
|
wtf.MultiSourceWidget
|
||||||
|
|
||||||
idx int
|
|
||||||
projects []*Project
|
projects []*Project
|
||||||
settings *Settings
|
settings *Settings
|
||||||
}
|
}
|
||||||
@ -20,8 +20,9 @@ type Widget struct {
|
|||||||
// NewWidget creates a new instance of a widget
|
// NewWidget creates a new instance of a widget
|
||||||
func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget {
|
func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget {
|
||||||
widget := Widget{
|
widget := Widget{
|
||||||
KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common),
|
KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common),
|
||||||
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
TextWidget: wtf.NewTextWidget(app, settings.common, true),
|
||||||
|
MultiSourceWidget: wtf.NewMultiSourceWidget(settings.common, "project", "projects"),
|
||||||
|
|
||||||
settings: settings,
|
settings: settings,
|
||||||
}
|
}
|
||||||
@ -31,6 +32,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
|||||||
|
|
||||||
widget.initializeKeyboardControls()
|
widget.initializeKeyboardControls()
|
||||||
widget.View.SetInputCapture(widget.InputCapture)
|
widget.View.SetInputCapture(widget.InputCapture)
|
||||||
|
widget.SetDisplayFunction(widget.display)
|
||||||
|
|
||||||
widget.KeyboardWidget.SetView(widget.View)
|
widget.KeyboardWidget.SetView(widget.View)
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *
|
|||||||
/* -------------------- Exported Functions -------------------- */
|
/* -------------------- Exported Functions -------------------- */
|
||||||
|
|
||||||
func (widget *Widget) CurrentProject() *Project {
|
func (widget *Widget) CurrentProject() *Project {
|
||||||
return widget.ProjectAt(widget.idx)
|
return widget.ProjectAt(widget.Idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (widget *Widget) ProjectAt(idx int) *Project {
|
func (widget *Widget) ProjectAt(idx int) *Project {
|
||||||
@ -51,24 +53,6 @@ func (widget *Widget) ProjectAt(idx int) *Project {
|
|||||||
return widget.projects[idx]
|
return widget.projects[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Widget) NextProject() {
|
|
||||||
w.idx = w.idx + 1
|
|
||||||
if w.idx == len(w.projects) {
|
|
||||||
w.idx = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
w.display()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Widget) PreviousProject() {
|
|
||||||
w.idx = w.idx - 1
|
|
||||||
if w.idx < 0 {
|
|
||||||
w.idx = len(w.projects) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
w.display()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Widget) Refresh() {
|
func (w *Widget) Refresh() {
|
||||||
if w.Disabled() || w.CurrentProject() == nil {
|
if w.Disabled() || w.CurrentProject() == nil {
|
||||||
return
|
return
|
||||||
|
46
wtf/utils.go
46
wtf/utils.go
@ -6,6 +6,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/wtfutil/wtf/utils"
|
"github.com/wtfutil/wtf/utils"
|
||||||
@ -21,6 +22,14 @@ const TimestampFormat = "2006-01-02T15:04:05-0700"
|
|||||||
|
|
||||||
var OpenFileUtil = "open"
|
var OpenFileUtil = "open"
|
||||||
|
|
||||||
|
// CenterText takes a string and a width and pads the left and right of the string with
|
||||||
|
// empty spaces to ensure that the string is in the middle of the returned value
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// x := CenterText("cat", 11)
|
||||||
|
// > " cat "
|
||||||
|
//
|
||||||
func CenterText(str string, width int) string {
|
func CenterText(str string, width int) string {
|
||||||
if width < 0 {
|
if width < 0 {
|
||||||
width = 0
|
width = 0
|
||||||
@ -29,6 +38,7 @@ func CenterText(str string, width int) string {
|
|||||||
return fmt.Sprintf("%[1]*s", -width, fmt.Sprintf("%[1]*s", (width+len(str))/2, str))
|
return fmt.Sprintf("%[1]*s", -width, fmt.Sprintf("%[1]*s", (width+len(str))/2, str))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecuteCommand executes an external command on the local machine as the current user
|
||||||
func ExecuteCommand(cmd *exec.Cmd) string {
|
func ExecuteCommand(cmd *exec.Cmd) string {
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -52,6 +62,14 @@ func ExecuteCommand(cmd *exec.Cmd) string {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exclude takes a slice of strings and a target string and returns the contents of the original
|
||||||
|
// slice of strings without the target string in it
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// x := Exclude([]string{"cat", "dog", "rat"}, "dog")
|
||||||
|
// > []string{"cat", "rat"}
|
||||||
|
//
|
||||||
func Exclude(strs []string, val string) bool {
|
func Exclude(strs []string, val string) bool {
|
||||||
for _, str := range strs {
|
for _, str := range strs {
|
||||||
if val == str {
|
if val == str {
|
||||||
@ -61,16 +79,33 @@ func Exclude(strs []string, val string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindMatch takes a regex pattern and a string of data and returns back all the matches
|
||||||
|
// in that string
|
||||||
func FindMatch(pattern string, data string) [][]string {
|
func FindMatch(pattern string, data string) [][]string {
|
||||||
r := regexp.MustCompile(pattern)
|
r := regexp.MustCompile(pattern)
|
||||||
return r.FindAllStringSubmatch(data, -1)
|
return r.FindAllStringSubmatch(data, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NameFromEmail takes an email address and returns the part that comes before the @ symbol
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// NameFromEmail("test_user@example.com")
|
||||||
|
// > "Test_user"
|
||||||
|
//
|
||||||
func NameFromEmail(email string) string {
|
func NameFromEmail(email string) string {
|
||||||
parts := strings.Split(email, "@")
|
parts := strings.Split(email, "@")
|
||||||
return strings.Title(strings.Replace(parts[0], ".", " ", -1))
|
return strings.Title(strings.Replace(parts[0], ".", " ", -1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamesFromEmails takes a slice of email addresses and returns a slice of the parts that
|
||||||
|
// come before the @ symbol
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// NamesFromEmail("test_user@example.com", "other_user@example.com")
|
||||||
|
// > []string{"Test_user", "Other_user"}
|
||||||
|
//
|
||||||
func NamesFromEmails(emails []string) []string {
|
func NamesFromEmails(emails []string) []string {
|
||||||
names := []string{}
|
names := []string{}
|
||||||
|
|
||||||
@ -112,6 +147,7 @@ func PadRow(offset int, max int) string {
|
|||||||
return strings.Repeat(" ", padSize)
|
return strings.Repeat(" ", padSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadFileBytes reads the contents of a file and returns those contents as a slice of bytes
|
||||||
func ReadFileBytes(filePath string) ([]byte, error) {
|
func ReadFileBytes(filePath string) ([]byte, error) {
|
||||||
fileData, err := ioutil.ReadFile(filePath)
|
fileData, err := ioutil.ReadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -123,6 +159,7 @@ func ReadFileBytes(filePath string) ([]byte, error) {
|
|||||||
|
|
||||||
/* -------------------- Map Conversion -------------------- */
|
/* -------------------- Map Conversion -------------------- */
|
||||||
|
|
||||||
|
// MapToStrs takes a map of interfaces and returns a map of strings
|
||||||
func MapToStrs(aMap map[string]interface{}) map[string]string {
|
func MapToStrs(aMap map[string]interface{}) map[string]string {
|
||||||
results := make(map[string]string)
|
results := make(map[string]string)
|
||||||
|
|
||||||
@ -135,6 +172,7 @@ func MapToStrs(aMap map[string]interface{}) map[string]string {
|
|||||||
|
|
||||||
/* -------------------- Slice Conversion -------------------- */
|
/* -------------------- Slice Conversion -------------------- */
|
||||||
|
|
||||||
|
// ToInts takes a slice of interfaces and returns a slice of ints
|
||||||
func ToInts(slice []interface{}) []int {
|
func ToInts(slice []interface{}) []int {
|
||||||
results := []int{}
|
results := []int{}
|
||||||
|
|
||||||
@ -145,11 +183,17 @@ func ToInts(slice []interface{}) []int {
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToStrs takes a slice of interfaces and returns a slice of strings
|
||||||
func ToStrs(slice []interface{}) []string {
|
func ToStrs(slice []interface{}) []string {
|
||||||
results := []string{}
|
results := []string{}
|
||||||
|
|
||||||
for _, val := range slice {
|
for _, val := range slice {
|
||||||
results = append(results, val.(string))
|
switch val.(type) {
|
||||||
|
case int:
|
||||||
|
results = append(results, strconv.Itoa(val.(int)))
|
||||||
|
case string:
|
||||||
|
results = append(results, val.(string))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
Loading…
x
Reference in New Issue
Block a user