168 lines
3.5 KiB
Go
168 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/chzyer/readline"
|
|
)
|
|
|
|
func usage(w io.Writer) {
|
|
io.WriteString(w, "commands:\n")
|
|
io.WriteString(w, completer.Tree(" "))
|
|
}
|
|
|
|
// Function constructor - constructs new function for listing given directory
|
|
func listFiles(path string) func(string) []string {
|
|
return func(line string) []string {
|
|
names := make([]string, 0)
|
|
files, _ := ioutil.ReadDir(path)
|
|
for _, f := range files {
|
|
names = append(names, f.Name())
|
|
}
|
|
return names
|
|
}
|
|
}
|
|
|
|
var completer = readline.NewPrefixCompleter(
|
|
readline.PcItem("mode",
|
|
readline.PcItem("vi"),
|
|
readline.PcItem("emacs"),
|
|
),
|
|
readline.PcItem("login"),
|
|
readline.PcItem("say",
|
|
readline.PcItemDynamic(listFiles("./"),
|
|
readline.PcItem("with",
|
|
readline.PcItem("following"),
|
|
readline.PcItem("items"),
|
|
),
|
|
),
|
|
readline.PcItem("hello"),
|
|
readline.PcItem("bye"),
|
|
),
|
|
readline.PcItem("setprompt"),
|
|
readline.PcItem("setpassword"),
|
|
readline.PcItem("bye"),
|
|
readline.PcItem("help"),
|
|
readline.PcItem("go",
|
|
readline.PcItem("build", readline.PcItem("-o"), readline.PcItem("-v")),
|
|
readline.PcItem("install",
|
|
readline.PcItem("-v"),
|
|
readline.PcItem("-vv"),
|
|
readline.PcItem("-vvv"),
|
|
),
|
|
readline.PcItem("test"),
|
|
),
|
|
readline.PcItem("sleep"),
|
|
)
|
|
|
|
func filterInput(r rune) (rune, bool) {
|
|
switch r {
|
|
// block CtrlZ feature
|
|
case readline.CharCtrlZ:
|
|
return r, false
|
|
}
|
|
return r, true
|
|
}
|
|
|
|
func main() {
|
|
l, err := readline.NewEx(&readline.Config{
|
|
Prompt: "\033[31m»\033[0m ",
|
|
HistoryFile: "/tmp/readline.tmp",
|
|
AutoComplete: completer,
|
|
InterruptPrompt: "^C",
|
|
EOFPrompt: "exit",
|
|
|
|
HistorySearchFold: true,
|
|
FuncFilterInputRune: filterInput,
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer l.Close()
|
|
|
|
setPasswordCfg := l.GenPasswordConfig()
|
|
setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
|
l.SetPrompt(fmt.Sprintf("Enter password(%v): ", len(line)))
|
|
l.Refresh()
|
|
return nil, 0, false
|
|
})
|
|
|
|
log.SetOutput(l.Stderr())
|
|
for {
|
|
line, err := l.Readline()
|
|
if err == readline.ErrInterrupt {
|
|
if len(line) == 0 {
|
|
break
|
|
} else {
|
|
continue
|
|
}
|
|
} else if err == io.EOF {
|
|
break
|
|
}
|
|
|
|
line = strings.TrimSpace(line)
|
|
switch {
|
|
case strings.HasPrefix(line, "mode "):
|
|
switch line[5:] {
|
|
case "vi":
|
|
l.SetVimMode(true)
|
|
case "emacs":
|
|
l.SetVimMode(false)
|
|
default:
|
|
println("invalid mode:", line[5:])
|
|
}
|
|
case line == "mode":
|
|
if l.IsVimMode() {
|
|
println("current mode: vim")
|
|
} else {
|
|
println("current mode: emacs")
|
|
}
|
|
case line == "login":
|
|
pswd, err := l.ReadPassword("please enter your password: ")
|
|
if err != nil {
|
|
break
|
|
}
|
|
println("you enter:", strconv.Quote(string(pswd)))
|
|
case line == "help":
|
|
usage(l.Stderr())
|
|
case line == "setpassword":
|
|
pswd, err := l.ReadPasswordWithConfig(setPasswordCfg)
|
|
if err == nil {
|
|
println("you set:", strconv.Quote(string(pswd)))
|
|
}
|
|
case strings.HasPrefix(line, "setprompt"):
|
|
if len(line) <= 10 {
|
|
log.Println("setprompt <prompt>")
|
|
break
|
|
}
|
|
l.SetPrompt(line[10:])
|
|
case strings.HasPrefix(line, "say"):
|
|
line := strings.TrimSpace(line[3:])
|
|
if len(line) == 0 {
|
|
log.Println("say what?")
|
|
break
|
|
}
|
|
go func() {
|
|
for range time.Tick(time.Second) {
|
|
log.Println(line)
|
|
}
|
|
}()
|
|
case line == "bye":
|
|
goto exit
|
|
case line == "sleep":
|
|
log.Println("sleep 4 second")
|
|
time.Sleep(4 * time.Second)
|
|
case line == "":
|
|
default:
|
|
log.Println("you said:", strconv.Quote(line))
|
|
}
|
|
}
|
|
exit:
|
|
}
|