You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
3.5 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "io/ioutil"
  6. "log"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/chzyer/readline"
  11. )
  12. func usage(w io.Writer) {
  13. io.WriteString(w, "commands:\n")
  14. io.WriteString(w, completer.Tree(" "))
  15. }
  16. // Function constructor - constructs new function for listing given directory
  17. func listFiles(path string) func(string) []string {
  18. return func(line string) []string {
  19. names := make([]string, 0)
  20. files, _ := ioutil.ReadDir(path)
  21. for _, f := range files {
  22. names = append(names, f.Name())
  23. }
  24. return names
  25. }
  26. }
  27. var completer = readline.NewPrefixCompleter(
  28. readline.PcItem("mode",
  29. readline.PcItem("vi"),
  30. readline.PcItem("emacs"),
  31. ),
  32. readline.PcItem("login"),
  33. readline.PcItem("say",
  34. readline.PcItemDynamic(listFiles("./"),
  35. readline.PcItem("with",
  36. readline.PcItem("following"),
  37. readline.PcItem("items"),
  38. ),
  39. ),
  40. readline.PcItem("hello"),
  41. readline.PcItem("bye"),
  42. ),
  43. readline.PcItem("setprompt"),
  44. readline.PcItem("setpassword"),
  45. readline.PcItem("bye"),
  46. readline.PcItem("help"),
  47. readline.PcItem("go",
  48. readline.PcItem("build", readline.PcItem("-o"), readline.PcItem("-v")),
  49. readline.PcItem("install",
  50. readline.PcItem("-v"),
  51. readline.PcItem("-vv"),
  52. readline.PcItem("-vvv"),
  53. ),
  54. readline.PcItem("test"),
  55. ),
  56. readline.PcItem("sleep"),
  57. )
  58. func filterInput(r rune) (rune, bool) {
  59. switch r {
  60. // block CtrlZ feature
  61. case readline.CharCtrlZ:
  62. return r, false
  63. }
  64. return r, true
  65. }
  66. func main() {
  67. l, err := readline.NewEx(&readline.Config{
  68. Prompt: "\033[31m»\033[0m ",
  69. HistoryFile: "/tmp/readline.tmp",
  70. AutoComplete: completer,
  71. InterruptPrompt: "^C",
  72. EOFPrompt: "exit",
  73. HistorySearchFold: true,
  74. FuncFilterInputRune: filterInput,
  75. })
  76. if err != nil {
  77. panic(err)
  78. }
  79. defer l.Close()
  80. setPasswordCfg := l.GenPasswordConfig()
  81. setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
  82. l.SetPrompt(fmt.Sprintf("Enter password(%v): ", len(line)))
  83. l.Refresh()
  84. return nil, 0, false
  85. })
  86. log.SetOutput(l.Stderr())
  87. for {
  88. line, err := l.Readline()
  89. if err == readline.ErrInterrupt {
  90. if len(line) == 0 {
  91. break
  92. } else {
  93. continue
  94. }
  95. } else if err == io.EOF {
  96. break
  97. }
  98. line = strings.TrimSpace(line)
  99. switch {
  100. case strings.HasPrefix(line, "mode "):
  101. switch line[5:] {
  102. case "vi":
  103. l.SetVimMode(true)
  104. case "emacs":
  105. l.SetVimMode(false)
  106. default:
  107. println("invalid mode:", line[5:])
  108. }
  109. case line == "mode":
  110. if l.IsVimMode() {
  111. println("current mode: vim")
  112. } else {
  113. println("current mode: emacs")
  114. }
  115. case line == "login":
  116. pswd, err := l.ReadPassword("please enter your password: ")
  117. if err != nil {
  118. break
  119. }
  120. println("you enter:", strconv.Quote(string(pswd)))
  121. case line == "help":
  122. usage(l.Stderr())
  123. case line == "setpassword":
  124. pswd, err := l.ReadPasswordWithConfig(setPasswordCfg)
  125. if err == nil {
  126. println("you set:", strconv.Quote(string(pswd)))
  127. }
  128. case strings.HasPrefix(line, "setprompt"):
  129. if len(line) <= 10 {
  130. log.Println("setprompt <prompt>")
  131. break
  132. }
  133. l.SetPrompt(line[10:])
  134. case strings.HasPrefix(line, "say"):
  135. line := strings.TrimSpace(line[3:])
  136. if len(line) == 0 {
  137. log.Println("say what?")
  138. break
  139. }
  140. go func() {
  141. for range time.Tick(time.Second) {
  142. log.Println(line)
  143. }
  144. }()
  145. case line == "bye":
  146. goto exit
  147. case line == "sleep":
  148. log.Println("sleep 4 second")
  149. time.Sleep(4 * time.Second)
  150. case line == "":
  151. default:
  152. log.Println("you said:", strconv.Quote(line))
  153. }
  154. }
  155. exit:
  156. }