-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathfzz.go
119 lines (105 loc) · 2.3 KB
/
fzz.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
118
119
package main
import (
"bytes"
"io"
"log"
"os"
"unicode"
"unicode/utf8"
)
const (
keyBackspace = 8
keyDelete = 127
keyEndOfTransmission = 4
keyLineFeed = 10
keyCarriageReturn = 13
keyEndOfTransmissionBlock = 23
keyEscape = 27
)
type Fzz struct {
tty *TTY
printer *Printer
stdinbuf *bytes.Buffer
currentRunner *Runner
input []byte
placeholder string
args []string
printInput bool
}
func (fzz *Fzz) Loop() {
fzz.reset()
ttych := readCharacter(fzz.tty)
for {
if len(fzz.input) > 0 {
if err := fzz.startNewRunner(); err != nil {
log.Fatal(err)
}
}
b := <-ttych
switch b[0] {
case keyBackspace, keyDelete:
fzz.input = removeLastCharacter(fzz.input)
case keyEndOfTransmission, keyLineFeed, keyCarriageReturn:
if fzz.currentRunner != nil {
fzz.currentRunner.Wait()
fzz.tty.resetScreen()
if len(fzz.input) > 0 {
if fzz.currentRunner.stdoutbuf.Len() == 0 && fzz.printInput {
fzz.printInputStdout()
} else {
io.Copy(os.Stdout, fzz.currentRunner.stdoutbuf)
}
}
} else {
fzz.tty.resetScreen()
}
return
case keyEscape:
fzz.tty.resetScreen()
return
case keyEndOfTransmissionBlock:
fzz.input = removeLastWord(fzz.input)
default:
if r, _ := utf8.DecodeRune(b); unicode.IsPrint(r) {
fzz.input = append(fzz.input, b...)
} else {
continue
}
}
fzz.killCurrentRunner()
fzz.reset()
}
}
func (fzz *Fzz) startNewRunner() error {
fzz.currentRunner = NewRunner(fzz.args, fzz.placeholder, string(fzz.input), fzz.stdinbuf)
ch, err := fzz.currentRunner.Run()
if err != nil {
return err
}
go fzz.printRunnerOutput(ch, utf8.RuneCount(fzz.input))
return nil
}
func (fzz *Fzz) killCurrentRunner() {
if fzz.currentRunner != nil {
go func(runner *Runner) {
runner.KillWait()
}(fzz.currentRunner)
}
}
func (fzz *Fzz) reset() {
fzz.tty.resetScreen()
fzz.tty.printPrompt(fzz.input[:len(fzz.input)])
fzz.printer.Reset()
}
func (fzz *Fzz) printRunnerOutput(out <-chan string, inputlen int) {
for line := range out {
fzz.printer.Print(line)
}
fzz.tty.cursorAfterPrompt(inputlen)
}
func (fzz *Fzz) printInputStdout() {
_, err := os.Stdout.Write(fzz.input)
if err != nil {
log.Fatal(err)
}
}