forked from manishrjain/into-ledger
-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
utils.go
117 lines (107 loc) · 2.83 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
import (
"bytes"
"flag"
"fmt"
"io"
"log"
"os"
"os/exec"
"strings"
"github.com/fatih/color"
"github.com/pkg/errors"
)
func checkf(err error, format string, args ...interface{}) {
if err != nil {
log.Printf(format, args...)
log.Println()
log.Fatalf("%+v", errors.WithStack(err))
}
}
func assertf(ok bool, format string, args ...interface{}) {
if !ok {
log.Printf(format, args...)
log.Println()
log.Fatalf("%+v", errors.Errorf("Should be true, but is false"))
}
}
var errc = color.New(color.BgRed, color.FgWhite).PrintfFunc()
func oerr(msg string) {
errc("\tERROR: " + msg + " ")
fmt.Println()
fmt.Println("Flags available:")
flag.PrintDefaults()
fmt.Println()
}
// runCommandRaw excute the given cmd and return stdout as a string
func runCommandRaw(name string, arg ...string) string {
cmd := exec.Command(name, arg...)
out, err := cmd.Output()
checkf(err, "Error running `%v`: `%v`", name, arg)
return string(out)
}
// runCommand excute the given cmd and return the list of lines outputted on
// stdout
func runCommand(name string, arg ...string) []string {
out := runCommandRaw(name, arg...)
return strings.Split(out, "\n")
}
// Fzf holds parameters for github.com/junegunn/fzf
type Fzf struct {
// Items to be selected by user
Items []string
// If prompt is set "", a default prompt is used.
Prompt string
// Used to fill the search field
Query string
// Returns what the user searched for
ReturnQuery bool
// More arguments to the fzf command
MoreArgs []string
}
// FuzzySelect prompts the user to select one or more items in a fuzzy menu.
func fuzzySelect(f Fzf) (selected []string) {
// TODO Find a more idiomatic way
args := []string{}
if f.Prompt != "" {
args = append(args, "--prompt", f.Prompt+" >")
}
if f.ReturnQuery {
// Print what the user entered first-line
args = append(args, "--print-query")
}
args = append(args, "--query", f.Query)
// Default options, TODO Make this configurable
args = append(args, "--height", "80%", "--layout=reverse")
// Other options
args = append(args, f.MoreArgs...)
// Inspired from https://stackoverflow.com/a/23167416/ by mraron (Apache
// 2.0 licence)
subProcess := exec.Command("fzf", args...)
stdin, err := subProcess.StdinPipe()
if err != nil {
log.Fatal(err)
}
stdout, err := subProcess.StdoutPipe()
if err != nil {
log.Fatal(err)
}
subProcess.Stderr = os.Stderr
err = subProcess.Start()
checkf(err, "Error running fzf. Is https://github.com/junegunn/fzf installed?")
io.WriteString(stdin, strings.Join(f.Items, "\n"))
buf := new(bytes.Buffer)
buf.ReadFrom(stdout)
s := buf.String()
subProcess.Wait()
for i, s := range strings.Split(s, "\n") {
switch {
// Always keep user query even if it is empty
case f.ReturnQuery && i == 0:
selected = append(selected, s)
case s != "":
selected = append(selected, s)
}
}
return
}