| 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: |
| } |