"bufio"
"bytes"
"fmt"
- "io/ioutil"
"os"
"strconv"
"strings"
m.Display()
screen.ShowCursor(Count(m.message), h-1)
screen.Show()
- event := screen.PollEvent()
+ event := <-events
switch e := event.(type) {
case *tcell.EventKey:
const (
NoCompletion Completion = iota
FileCompletion
+ CommandCompletion
+ HelpCompletion
+ OptionCompletion
)
// Prompt sends the user a message and waits for a response to be typed in
// This function blocks the main loop while waiting for input
-func (m *Messenger) Prompt(prompt, historyType string, completionType Completion) (string, bool) {
+func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Completion) (string, bool) {
m.hasPrompt = true
m.Message(prompt)
if _, ok := m.history[historyType]; !ok {
response, canceled := "", true
+ RedrawAll()
for m.hasPrompt {
+ var suggestions []string
m.Clear()
- m.Display()
- event := screen.PollEvent()
+ event := <-events
switch e := event.(type) {
case *tcell.EventKey:
response, canceled = m.response, false
m.history[historyType][len(m.history[historyType])-1] = response
case tcell.KeyTab:
- if completionType == FileCompletion {
- dirs := strings.Split(m.response, "/")
- var files []os.FileInfo
- var err error
- if len(dirs) > 1 {
- files, err = ioutil.ReadDir(strings.Join(dirs[:len(dirs)-1], "/"))
- } else {
- files, err = ioutil.ReadDir(".")
- }
- if err != nil {
- continue
- }
- var suggestions []string
- for _, f := range files {
- name := f.Name()
- if f.IsDir() {
- name += "/"
- }
- if strings.HasPrefix(name, dirs[len(dirs)-1]) {
- suggestions = append(suggestions, name)
- }
+ args := strings.Split(m.response, " ")
+ currentArgNum := len(args) - 1
+ currentArg := args[currentArgNum]
+ var completionType Completion
+
+ if completionTypes[0] == CommandCompletion && currentArgNum > 0 {
+ if command, ok := commands[args[0]]; ok {
+ completionTypes = append([]Completion{CommandCompletion}, command.completions...)
}
- if len(suggestions) == 1 {
- m.response = strings.Join(dirs[:len(dirs)-1], "/") + "/" + suggestions[0]
- m.cursorx = Count(m.response)
+ }
+
+ if currentArgNum >= len(completionTypes) {
+ completionType = completionTypes[len(completionTypes)-1]
+ } else {
+ completionType = completionTypes[currentArgNum]
+ }
+
+ var chosen string
+ if completionType == FileCompletion {
+ chosen, suggestions = FileComplete(currentArg)
+ } else if completionType == CommandCompletion {
+ chosen, suggestions = CommandComplete(currentArg)
+ } else if completionType == HelpCompletion {
+ chosen, suggestions = HelpComplete(currentArg)
+ } else if completionType == OptionCompletion {
+ chosen, suggestions = OptionComplete(currentArg)
+ }
+
+ if chosen != "" {
+ if len(args) > 1 {
+ chosen = " " + chosen
}
+ m.response = strings.Join(args[:len(args)-1], " ") + chosen
+ m.cursorx = Count(m.response)
}
}
}
m.HandleEvent(event, m.history[historyType])
- if m.cursorx < 0 {
- // Cancel
- m.hasPrompt = false
+ messenger.Clear()
+ for _, v := range tabs[curTab].views {
+ v.Display()
+ }
+ DisplayTabs()
+ messenger.Display()
+ if len(suggestions) > 1 {
+ m.DisplaySuggestions(suggestions)
}
+ screen.Show()
}
m.Reset()
}
case tcell.KeyBackspace2, tcell.KeyBackspace:
if m.cursorx > 0 {
- m.response = string([]rune(m.response)[:m.cursorx-1]) + string(m.response[m.cursorx:])
+ m.response = string([]rune(m.response)[:m.cursorx-1]) + string([]rune(m.response)[m.cursorx:])
+ m.cursorx--
}
- m.cursorx--
case tcell.KeyRune:
m.response = Insert(m.response, m.cursorx, string(e.Rune()))
m.cursorx++
}
}
+func (m *Messenger) DisplaySuggestions(suggestions []string) {
+ w, screenH := screen.Size()
+
+ y := screenH - 2
+
+ statusLineStyle := defStyle.Reverse(true)
+ if style, ok := colorscheme["statusline"]; ok {
+ statusLineStyle = style
+ }
+
+ for x := 0; x < w; x++ {
+ screen.SetContent(x, y, ' ', nil, statusLineStyle)
+ }
+
+ x := 1
+ for _, suggestion := range suggestions {
+ for _, c := range suggestion {
+ screen.SetContent(x, y, c, nil, statusLineStyle)
+ x++
+ }
+ screen.SetContent(x, y, ' ', nil, statusLineStyle)
+ x++
+ }
+}
+
// Display displays messages or prompts
func (m *Messenger) Display() {
_, h := screen.Size()