]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/messenger.go
Fix some issues with unicode handling
[micro.git] / cmd / micro / messenger.go
index 7715ccfd9c06b64fb999b50d95429993e68d5e1e..2391bca86dad92ac58ab54d2a1a2724562f18f39 100644 (file)
@@ -4,7 +4,6 @@ import (
        "bufio"
        "bytes"
        "fmt"
-       "io/ioutil"
        "os"
        "strconv"
        "strings"
@@ -129,11 +128,14 @@ type Completion int
 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 {
@@ -145,9 +147,10 @@ func (m *Messenger) Prompt(prompt, historyType string, completionType Completion
 
        response, canceled := "", true
 
+       RedrawAll()
        for m.hasPrompt {
+               var suggestions []string
                m.Clear()
-               m.Display()
 
                event := <-events
 
@@ -163,52 +166,56 @@ func (m *Messenger) Prompt(prompt, historyType string, completionType Completion
                                response, canceled = m.response, false
                                m.history[historyType][len(m.history[historyType])-1] = response
                        case tcell.KeyTab:
-                               if completionType == FileCompletion {
-                                       args := strings.Split(m.response, " ")
-                                       currentArg := args[len(args)-1]
-                                       dirs := strings.Split(currentArg, "/")
-                                       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 {
-                                               if len(dirs) > 1 {
-                                                       currentArg = strings.Join(dirs[:len(dirs)-1], "/") + "/" + suggestions[0]
-                                               } else {
-                                                       currentArg = suggestions[0]
-                                               }
-                                               if len(args) > 1 {
-                                                       currentArg = " " + currentArg
-                                               }
-                                               m.response = strings.Join(args[:len(args)-1], " ") + currentArg
-                                               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()
@@ -242,9 +249,9 @@ func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
                        }
                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++
@@ -268,6 +275,31 @@ func (m *Messenger) Clear() {
        }
 }
 
+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()