-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathfilter.go
90 lines (84 loc) · 1.71 KB
/
filter.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
package ecsta
import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"os"
"os/exec"
"strings"
"github.com/Songmu/prompter"
)
func (app *Ecsta) runFilter(ctx context.Context, src io.Reader, title string) (string, error) {
command := app.Config.FilterCommand
if command == "" {
return runInternalFilter(ctx, src, title)
}
var f *exec.Cmd
if strings.Contains(command, " ") {
f = exec.CommandContext(ctx, "sh", "-c", command)
} else {
f = exec.CommandContext(ctx, command)
}
f.Stderr = os.Stderr
p, _ := f.StdinPipe()
go func() {
io.Copy(p, src)
p.Close()
}()
b, err := f.Output()
if err != nil {
return "", fmt.Errorf("failed to execute filter command: %w", err)
}
return string(bytes.TrimRight(b, "\r\n")), nil
}
func runInternalFilter(ctx context.Context, src io.Reader, title string) (string, error) {
var items []string
s := bufio.NewScanner(src)
for s.Scan() {
fmt.Println(s.Text())
items = append(items, strings.Fields(s.Text())[0])
}
result := make(chan string)
go func() {
var input string
for {
input = prompter.Prompt("Enter "+title, "")
if input == "" {
select {
case <-ctx.Done():
return
default:
}
continue
}
var found []string
for _, item := range items {
item := item
if item == input {
found = []string{item}
break
} else if strings.HasPrefix(item, input) {
found = append(found, item)
}
}
switch len(found) {
case 0:
fmt.Printf("no such item %s\n", input)
case 1:
fmt.Printf("%s=%s\n", title, found[0])
result <- found[0]
return
default:
fmt.Printf("%s is ambiguous\n", input)
}
}
}()
select {
case <-ctx.Done():
return "", ErrAborted
case r := <-result:
return r, nil
}
}