forked from abiosoft/ishell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
actions.go
210 lines (184 loc) · 6.48 KB
/
actions.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package ishell
import (
"fmt"
"io"
"os/exec"
"runtime"
"strings"
)
// Actions are actions that can be performed by a shell.
type Actions interface {
// ReadLine reads a line from standard input.
ReadLine() string
// ReadLineErr is ReadLine but returns error as well
ReadLineErr() (string, error)
// ReadLineWithDefault reads a line from standard input with default value.
ReadLineWithDefault(string) string
// ReadPassword reads password from standard input without echoing the characters.
// Note that this only works as expected when the standard input is a terminal.
ReadPassword() string
// ReadPasswordErr is ReadPassword but returns error as well
ReadPasswordErr() (string, error)
// ReadMultiLinesFunc reads multiple lines from standard input. It passes each read line to
// f and stops reading when f returns false.
ReadMultiLinesFunc(f func(string) bool) string
// ReadMultiLines reads multiple lines from standard input. It stops reading when terminator
// is encountered at the end of the line. It returns the lines read including terminator.
// For more control, use ReadMultiLinesFunc.
ReadMultiLines(terminator string) string
// Println prints to output and ends with newline character.
Println(val ...interface{})
// Print prints to output.
Print(val ...interface{})
// Printf prints to output using string format.
Printf(format string, val ...interface{})
// ShowPaged shows a paged text that is scrollable.
// This leverages on "less" for unix and "more" for windows.
ShowPaged(text string) error
// ShowPagedReader shows a paged text that is scrollable, from a reader source.
// This leverages on "less" for unix and "more" for windows.
ShowPagedReader(r io.Reader) error
// MultiChoice presents options to the user.
// returns the index of the selection or -1 if nothing is
// selected.
// text is displayed before the options.
MultiChoice(options []string, text string) int
// Checklist is similar to MultiChoice but user can choose multiple variants using Space.
// init is initially selected options.
Checklist(options []string, text string, init []int) []int
// SetPrompt sets the prompt string. The string to be displayed before the cursor.
SetPrompt(prompt string)
// SetMultiPrompt sets the prompt string used for multiple lines. The string to be displayed before
// the cursor; starting from the second line of input.
SetMultiPrompt(prompt string)
// SetMultiChoicePrompt sets the prompt strings used for MultiChoice().
SetMultiChoicePrompt(prompt, spacer string)
// SetChecklistOptions sets the strings representing the options of Checklist().
// The generated string depends on SetMultiChoicePrompt() also.
SetChecklistOptions(open, selected string)
// ShowPrompt sets whether prompt should show when requesting input for ReadLine and ReadPassword.
// Defaults to true.
ShowPrompt(show bool)
// Cmds returns all the commands added to the shell.
Cmds() []*Cmd
// HelpText returns the computed help of top level commands.
HelpText() string
// ClearScreen clears the screen. Same behaviour as running 'clear' in unix terminal or 'cls' in windows cmd.
ClearScreen() error
// Stop stops the shell. This will stop the shell from auto reading inputs and calling
// registered functions. A stopped shell is only inactive but totally functional.
// Its functions can still be called and can be restarted.
Stop()
}
type shellActionsImpl struct {
*Shell
}
// ReadLine reads a line from standard input.
func (s *shellActionsImpl) ReadLine() string {
line, _ := s.readLine()
return line
}
func (s *shellActionsImpl) ReadLineErr() (string, error) {
return s.readLine()
}
func (s *shellActionsImpl) ReadLineWithDefault(defaultValue string) string {
s.reader.defaultInput = defaultValue
line, _ := s.readLine()
s.reader.defaultInput = ""
return line
}
func (s *shellActionsImpl) ReadPassword() string {
return s.reader.readPassword()
}
func (s *shellActionsImpl) ReadPasswordErr() (string, error) {
return s.reader.readPasswordErr()
}
func (s *shellActionsImpl) ReadMultiLinesFunc(f func(string) bool) string {
lines, _ := s.readMultiLinesFunc(f)
return lines
}
func (s *shellActionsImpl) ReadMultiLines(terminator string) string {
return s.ReadMultiLinesFunc(func(line string) bool {
if strings.HasSuffix(strings.TrimSpace(line), terminator) {
return false
}
return true
})
}
func (s *shellActionsImpl) Println(val ...interface{}) {
s.reader.buf.Truncate(0)
fmt.Fprintln(s.writer, val...)
}
func (s *shellActionsImpl) Print(val ...interface{}) {
s.reader.buf.Truncate(0)
fmt.Fprint(s.reader.buf, val...)
fmt.Fprint(s.writer, val...)
}
func (s *shellActionsImpl) Printf(format string, val ...interface{}) {
s.reader.buf.Truncate(0)
fmt.Fprintf(s.reader.buf, format, val...)
fmt.Fprintf(s.writer, format, val...)
}
func (s *shellActionsImpl) MultiChoice(options []string, text string) int {
choice := s.multiChoice(options, text, nil, false)
return choice[0]
}
func (s *shellActionsImpl) Checklist(options []string, text string, init []int) []int {
return s.multiChoice(options, text, init, true)
}
func (s *shellActionsImpl) SetPrompt(prompt string) {
s.reader.prompt = prompt
s.reader.scanner.SetPrompt(s.reader.rlPrompt())
}
func (s *shellActionsImpl) SetMultiPrompt(prompt string) {
s.reader.multiPrompt = prompt
}
func (s *shellActionsImpl) SetMultiChoicePrompt(prompt, spacer string) {
strMultiChoice = prompt
strMultiChoiceSpacer = spacer
}
func (s *shellActionsImpl) SetChecklistOptions(open, selected string) {
strMultiChoiceOpen = open
strMultiChoiceSelect = selected
}
func (s *shellActionsImpl) ShowPrompt(show bool) {
s.reader.showPrompt = show
s.reader.scanner.SetPrompt(s.reader.rlPrompt())
}
func (s *shellActionsImpl) Cmds() []*Cmd {
var cmds []*Cmd
for _, cmd := range s.rootCmd.children {
cmds = append(cmds, cmd)
}
return cmds
}
func (s *shellActionsImpl) ClearScreen() error {
return clearScreen(s.Shell)
}
func (s *shellActionsImpl) ShowPaged(text string) error {
return showPagedReader(s.Shell, strings.NewReader(text))
}
func (s *shellActionsImpl) ShowPagedReader(r io.Reader) error {
return showPagedReader(s.Shell, r)
}
func (s *shellActionsImpl) Stop() {
s.stop()
}
func (s *shellActionsImpl) HelpText() string {
return s.rootCmd.HelpText()
}
func showPagedReader(s *Shell, r io.Reader) error {
var cmd *exec.Cmd
if s.pager == "" {
if runtime.GOOS == "windows" {
s.pager = "more"
} else {
s.pager = "less"
}
}
cmd = exec.Command(s.pager, s.pagerArgs...)
cmd.Stdout = s.writer
cmd.Stderr = s.writer
cmd.Stdin = r
return cmd.Run()
}