mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Move a bunch of code out of utils.go and into dedicated files
This commit is contained in:
parent
4e46fff145
commit
ecd95ba2d2
47
utils/conversions.go
Normal file
47
utils/conversions.go
Normal file
@ -0,0 +1,47 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
/* -------------------- Map Conversion -------------------- */
|
||||
|
||||
// MapToStrs takes a map of interfaces and returns a map of strings
|
||||
func MapToStrs(aMap map[string]interface{}) map[string]string {
|
||||
results := make(map[string]string)
|
||||
|
||||
for key, val := range aMap {
|
||||
results[key] = val.(string)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
/* -------------------- Slice Conversion -------------------- */
|
||||
|
||||
// ToInts takes a slice of interfaces and returns a slice of ints
|
||||
func ToInts(slice []interface{}) []int {
|
||||
results := []int{}
|
||||
|
||||
for _, val := range slice {
|
||||
results = append(results, val.(int))
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// ToStrs takes a slice of interfaces and returns a slice of strings
|
||||
func ToStrs(slice []interface{}) []string {
|
||||
results := []string{}
|
||||
|
||||
for _, val := range slice {
|
||||
switch val.(type) {
|
||||
case int:
|
||||
results = append(results, strconv.Itoa(val.(int)))
|
||||
case string:
|
||||
results = append(results, val.(string))
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
44
utils/conversions_test.go
Normal file
44
utils/conversions_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_MapToStrs(t *testing.T) {
|
||||
expected := map[string]string{
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
}
|
||||
|
||||
source := make(map[string]interface{})
|
||||
for _, val := range expected {
|
||||
source[val] = val
|
||||
}
|
||||
|
||||
Equal(t, expected, MapToStrs(source))
|
||||
}
|
||||
|
||||
func Test_ToInts(t *testing.T) {
|
||||
expected := []int{1, 2, 3}
|
||||
|
||||
source := make([]interface{}, len(expected))
|
||||
for idx, val := range expected {
|
||||
source[idx] = val
|
||||
}
|
||||
|
||||
Equal(t, expected, ToInts(source))
|
||||
}
|
||||
|
||||
func Test_ToStrs(t *testing.T) {
|
||||
expected := []string{"cat", "dog", "rat"}
|
||||
|
||||
source := make([]interface{}, len(expected))
|
||||
for idx, val := range expected {
|
||||
source[idx] = val
|
||||
}
|
||||
|
||||
Equal(t, expected, ToStrs(source))
|
||||
}
|
35
utils/email_addresses.go
Normal file
35
utils/email_addresses.go
Normal file
@ -0,0 +1,35 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
parts := strings.Split(email, "@")
|
||||
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 {
|
||||
names := []string{}
|
||||
|
||||
for _, email := range emails {
|
||||
names = append(names, NameFromEmail(email))
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
22
utils/email_addresses_test.go
Normal file
22
utils/email_addresses_test.go
Normal file
@ -0,0 +1,22 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_NameFromEmail(t *testing.T) {
|
||||
Equal(t, "", NameFromEmail(""))
|
||||
Equal(t, "Chris Cummer", NameFromEmail("chris.cummer@me.com"))
|
||||
}
|
||||
|
||||
func Test_NamesFromEmails(t *testing.T) {
|
||||
var result []string
|
||||
|
||||
result = NamesFromEmails([]string{})
|
||||
Equal(t, []string{}, result)
|
||||
|
||||
result = NamesFromEmails([]string{"chris.cummer@me.com", "chriscummer@me.com"})
|
||||
Equal(t, []string{"Chris Cummer", "Chriscummer"}, result)
|
||||
}
|
@ -10,47 +10,7 @@ import (
|
||||
"github.com/wtfutil/wtf/cfg"
|
||||
)
|
||||
|
||||
func lowercaseTitle(title string) string {
|
||||
if title == "" {
|
||||
return ""
|
||||
}
|
||||
r, n := utf8.DecodeRuneInString(title)
|
||||
return string(unicode.ToLower(r)) + title[n:]
|
||||
}
|
||||
|
||||
var (
|
||||
openColorRegex = regexp.MustCompile(`\[.*?\]`)
|
||||
)
|
||||
|
||||
func StripColorTags(input string) string {
|
||||
return openColorRegex.ReplaceAllString(input, "")
|
||||
}
|
||||
|
||||
func helpFromValue(field reflect.StructField) string {
|
||||
result := ""
|
||||
|
||||
optional, err := strconv.ParseBool(field.Tag.Get("optional"))
|
||||
if err != nil {
|
||||
optional = false
|
||||
}
|
||||
|
||||
help := field.Tag.Get("help")
|
||||
if optional {
|
||||
help = "Optional " + help
|
||||
}
|
||||
|
||||
values := field.Tag.Get("values")
|
||||
if help != "" {
|
||||
result += "\n\n " + lowercaseTitle(field.Name)
|
||||
result += "\n " + help
|
||||
|
||||
if values != "" {
|
||||
result += "\n Values: " + values
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
func HelpFromInterface(item interface{}) string {
|
||||
result := ""
|
||||
@ -78,3 +38,45 @@ func HelpFromInterface(item interface{}) string {
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// StripColorTags removes tcell color tags from a given string
|
||||
func StripColorTags(input string) string {
|
||||
openColorRegex := regexp.MustCompile(`\[.*?\]`)
|
||||
return openColorRegex.ReplaceAllString(input, "")
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func helpFromValue(field reflect.StructField) string {
|
||||
result := ""
|
||||
|
||||
optional, err := strconv.ParseBool(field.Tag.Get("optional"))
|
||||
if err != nil {
|
||||
optional = false
|
||||
}
|
||||
|
||||
help := field.Tag.Get("help")
|
||||
if optional {
|
||||
help = "Optional " + help
|
||||
}
|
||||
|
||||
values := field.Tag.Get("values")
|
||||
if help != "" {
|
||||
result += "\n\n " + lowercaseTitle(field.Name)
|
||||
result += "\n " + help
|
||||
|
||||
if values != "" {
|
||||
result += "\n Values: " + values
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func lowercaseTitle(title string) string {
|
||||
if title == "" {
|
||||
return ""
|
||||
}
|
||||
r, n := utf8.DecodeRuneInString(title)
|
||||
return string(unicode.ToLower(r)) + title[n:]
|
||||
}
|
||||
|
@ -10,21 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Dir returns the home directory for the executing user.
|
||||
// An error is returned if a home directory cannot be detected.
|
||||
func Home() (string, error) {
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if currentUser.HomeDir == "" {
|
||||
return "", errors.New("cannot find user-specific home dir")
|
||||
}
|
||||
|
||||
return currentUser.HomeDir, nil
|
||||
}
|
||||
|
||||
// Expand expands the path to include the home directory if the path
|
||||
// ExpandHomeDir expands the path to include the home directory if the path
|
||||
// is prefixed with `~`. If it isn't prefixed with `~`, the path is
|
||||
// returned as-is.
|
||||
func ExpandHomeDir(path string) (string, error) {
|
||||
@ -47,3 +33,18 @@ func ExpandHomeDir(path string) (string, error) {
|
||||
|
||||
return filepath.Join(dir, path[1:]), nil
|
||||
}
|
||||
|
||||
// Home returns the home directory for the executing user.
|
||||
// An error is returned if a home directory cannot be detected.
|
||||
func Home() (string, error) {
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if currentUser.HomeDir == "" {
|
||||
return "", errors.New("cannot find user-specific home dir")
|
||||
}
|
||||
|
||||
return currentUser.HomeDir, nil
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package utils
|
||||
|
||||
// OpenFileUtil defines the system utility to use to open files
|
||||
var OpenFileUtil = "open"
|
||||
|
||||
// Init initializes global settings in the wtf package
|
||||
|
12
utils/init_test.go
Normal file
12
utils/init_test.go
Normal file
@ -0,0 +1,12 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_Init(t *testing.T) {
|
||||
Init("cats")
|
||||
Equal(t, OpenFileUtil, "cats")
|
||||
}
|
48
utils/text.go
Normal file
48
utils/text.go
Normal file
@ -0,0 +1,48 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
if width < 0 {
|
||||
width = 0
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%[1]*s", -width, fmt.Sprintf("%[1]*s", (width+len(str))/2, str))
|
||||
}
|
||||
|
||||
// HighlightableHelper pads the given text with blank spaces to the width of the view
|
||||
// containing it. This is helpful for extending row highlighting across the entire width
|
||||
// of the view
|
||||
func HighlightableHelper(view *tview.TextView, input string, idx, offset int) string {
|
||||
fmtStr := fmt.Sprintf(`["%d"][""]`, idx)
|
||||
_, _, w, _ := view.GetInnerRect()
|
||||
fmtStr += input
|
||||
fmtStr += PadRow(offset, w+1)
|
||||
fmtStr += `[""]` + "\n"
|
||||
return fmtStr
|
||||
}
|
||||
|
||||
// PadRow returns a padding for a row to make it the full width of the containing widget.
|
||||
// Useful for ensurig row highlighting spans the full width (I suspect tcell has a better
|
||||
// way to do this, but I haven't yet found it)
|
||||
func PadRow(offset int, max int) string {
|
||||
padSize := max - offset
|
||||
if padSize < 0 {
|
||||
padSize = 0
|
||||
}
|
||||
|
||||
return strings.Repeat(" ", padSize)
|
||||
}
|
19
utils/text_test.go
Normal file
19
utils/text_test.go
Normal file
@ -0,0 +1,19 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_CenterText(t *testing.T) {
|
||||
Equal(t, "cat", CenterText("cat", -9))
|
||||
Equal(t, "cat", CenterText("cat", 0))
|
||||
Equal(t, " cat ", CenterText("cat", 9))
|
||||
}
|
||||
|
||||
func Test_PadRow(t *testing.T) {
|
||||
Equal(t, "", PadRow(0, 0))
|
||||
Equal(t, "", PadRow(5, 2))
|
||||
Equal(t, " ", PadRow(1, 2))
|
||||
}
|
112
utils/utils.go
112
utils/utils.go
@ -6,10 +6,7 @@ import (
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -24,22 +21,6 @@ const (
|
||||
TimestampFormat = "2006-01-02T15:04:05-0700"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
if width < 0 {
|
||||
width = 0
|
||||
}
|
||||
|
||||
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 {
|
||||
if cmd == nil {
|
||||
@ -92,36 +73,6 @@ func FindMatch(pattern string, data string) [][]string {
|
||||
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 {
|
||||
parts := strings.Split(email, "@")
|
||||
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 {
|
||||
names := []string{}
|
||||
|
||||
for _, email := range emails {
|
||||
names = append(names, NameFromEmail(email))
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
// OpenFile opens the file defined in `path` via the operating system
|
||||
func OpenFile(path string) {
|
||||
if (strings.HasPrefix(path, "http://")) || (strings.HasPrefix(path, "https://")) {
|
||||
@ -141,18 +92,6 @@ func OpenFile(path string) {
|
||||
}
|
||||
}
|
||||
|
||||
// PadRow returns a padding for a row to make it the full width of the containing widget.
|
||||
// Useful for ensurig row highlighting spans the full width (I suspect tcell has a better
|
||||
// way to do this, but I haven't yet found it)
|
||||
func PadRow(offset int, max int) string {
|
||||
padSize := max - offset
|
||||
if padSize < 0 {
|
||||
padSize = 0
|
||||
}
|
||||
|
||||
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) {
|
||||
fileData, err := ioutil.ReadFile(filePath)
|
||||
@ -162,54 +101,3 @@ func ReadFileBytes(filePath string) ([]byte, error) {
|
||||
|
||||
return fileData, nil
|
||||
}
|
||||
|
||||
/* -------------------- Map Conversion -------------------- */
|
||||
|
||||
// MapToStrs takes a map of interfaces and returns a map of strings
|
||||
func MapToStrs(aMap map[string]interface{}) map[string]string {
|
||||
results := make(map[string]string)
|
||||
|
||||
for key, val := range aMap {
|
||||
results[key] = val.(string)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
/* -------------------- Slice Conversion -------------------- */
|
||||
|
||||
// ToInts takes a slice of interfaces and returns a slice of ints
|
||||
func ToInts(slice []interface{}) []int {
|
||||
results := []int{}
|
||||
|
||||
for _, val := range slice {
|
||||
results = append(results, val.(int))
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// ToStrs takes a slice of interfaces and returns a slice of strings
|
||||
func ToStrs(slice []interface{}) []string {
|
||||
results := []string{}
|
||||
|
||||
for _, val := range slice {
|
||||
switch val.(type) {
|
||||
case int:
|
||||
results = append(results, strconv.Itoa(val.(int)))
|
||||
case string:
|
||||
results = append(results, val.(string))
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
func HighlightableHelper(view *tview.TextView, input string, idx, offset int) string {
|
||||
fmtStr := fmt.Sprintf(`["%d"][""]`, idx)
|
||||
_, _, w, _ := view.GetInnerRect()
|
||||
fmtStr += input
|
||||
fmtStr += PadRow(offset, w+1)
|
||||
fmtStr += `[""]` + "\n"
|
||||
return fmtStr
|
||||
}
|
||||
|
@ -7,17 +7,6 @@ import (
|
||||
. "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_Init(t *testing.T) {
|
||||
Init("cats")
|
||||
Equal(t, OpenFileUtil, "cats")
|
||||
}
|
||||
|
||||
func Test_CenterText(t *testing.T) {
|
||||
Equal(t, "cat", CenterText("cat", -9))
|
||||
Equal(t, "cat", CenterText("cat", 0))
|
||||
Equal(t, " cat ", CenterText("cat", 9))
|
||||
}
|
||||
|
||||
func Test_ExecuteCommand(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -59,61 +48,3 @@ func Test_ExcludeWhenTrue(t *testing.T) {
|
||||
Equal(t, true, Exclude([]string{"cat", "dog", "rat"}, "bat"))
|
||||
Equal(t, false, Exclude([]string{"cat", "dog", "rat"}, "dog"))
|
||||
}
|
||||
|
||||
func Test_NameFromEmail(t *testing.T) {
|
||||
Equal(t, "", NameFromEmail(""))
|
||||
Equal(t, "Chris Cummer", NameFromEmail("chris.cummer@me.com"))
|
||||
}
|
||||
|
||||
func Test_NamesFromEmails(t *testing.T) {
|
||||
var result []string
|
||||
|
||||
result = NamesFromEmails([]string{})
|
||||
Equal(t, []string{}, result)
|
||||
|
||||
result = NamesFromEmails([]string{"chris.cummer@me.com", "chriscummer@me.com"})
|
||||
Equal(t, []string{"Chris Cummer", "Chriscummer"}, result)
|
||||
}
|
||||
|
||||
func Test_PadRow(t *testing.T) {
|
||||
Equal(t, "", PadRow(0, 0))
|
||||
Equal(t, "", PadRow(5, 2))
|
||||
Equal(t, " ", PadRow(1, 2))
|
||||
}
|
||||
|
||||
func Test_MapToStrs(t *testing.T) {
|
||||
expected := map[string]string{
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
}
|
||||
|
||||
source := make(map[string]interface{})
|
||||
for _, val := range expected {
|
||||
source[val] = val
|
||||
}
|
||||
|
||||
Equal(t, expected, MapToStrs(source))
|
||||
}
|
||||
|
||||
func Test_ToInts(t *testing.T) {
|
||||
expected := []int{1, 2, 3}
|
||||
|
||||
source := make([]interface{}, len(expected))
|
||||
for idx, val := range expected {
|
||||
source[idx] = val
|
||||
}
|
||||
|
||||
Equal(t, expected, ToInts(source))
|
||||
}
|
||||
|
||||
func Test_ToStrs(t *testing.T) {
|
||||
expected := []string{"cat", "dog", "rat"}
|
||||
|
||||
source := make([]interface{}, len(expected))
|
||||
for idx, val := range expected {
|
||||
source[idx] = val
|
||||
}
|
||||
|
||||
Equal(t, expected, ToStrs(source))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user