blob: 8b223e4dddcad87311bd86a1c8e13dd435458139 [file] [log] [blame]
package ishell
import (
"bytes"
"fmt"
"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)
// 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
// 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)
// 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) 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) 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 showPaged(s.Shell, text)
}
func (s *shellActionsImpl) Stop() {
s.stop()
}
func (s *shellActionsImpl) HelpText() string {
return s.rootCmd.HelpText()
}
func showPaged(s *Shell, text string) error {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("more")
} else {
cmd = exec.Command("less")
}
cmd.Stdout = s.writer
cmd.Stderr = s.writer
cmd.Stdin = bytes.NewBufferString(text)
return cmd.Run()
}