]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/messenger.go
Fix replace cursor relocation
[micro.git] / cmd / micro / messenger.go
index 27f556912adccbaf6300fb0e748772db2303c46c..1542c1c8a6000a3d47c694fb91a439e65e75168f 100644 (file)
@@ -4,8 +4,10 @@ import (
        "bufio"
        "bytes"
        "fmt"
+       "io/ioutil"
        "os"
        "strconv"
+       "strings"
 
        "github.com/zyedidia/tcell"
 )
@@ -57,6 +59,11 @@ type Messenger struct {
        // We have to keep track of the cursor for prompting
        cursorx int
 
+       // This map stores the history for all the different kinds of uses Prompt has
+       // It's a map of history type -> history array
+       history    map[string][]string
+       historyNum int
+
        // Is the current message a message from the gutter
        gutterMessage bool
 }
@@ -93,11 +100,13 @@ func (m *Messenger) Error(msg ...interface{}) {
 func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
        m.Message(prompt)
 
+       _, h := screen.Size()
        for {
                m.Clear()
                m.Display()
+               screen.ShowCursor(Count(m.message), h-1)
                screen.Show()
-               event := screen.PollEvent()
+               event := <-events
 
                switch e := event.(type) {
                case *tcell.EventKey:
@@ -115,11 +124,24 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
        }
 }
 
+type Completion int
+
+const (
+       NoCompletion Completion = iota
+       FileCompletion
+)
+
 // 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 string) (string, bool) {
+func (m *Messenger) Prompt(prompt, historyType string, completionType Completion) (string, bool) {
        m.hasPrompt = true
        m.Message(prompt)
+       if _, ok := m.history[historyType]; !ok {
+               m.history[historyType] = []string{""}
+       } else {
+               m.history[historyType] = append(m.history[historyType], "")
+       }
+       m.historyNum = len(m.history[historyType]) - 1
 
        response, canceled := "", true
 
@@ -127,7 +149,7 @@ func (m *Messenger) Prompt(prompt string) (string, bool) {
                m.Clear()
                m.Display()
 
-               event := screen.PollEvent()
+               event := <-events
 
                switch e := event.(type) {
                case *tcell.EventKey:
@@ -139,10 +161,43 @@ func (m *Messenger) Prompt(prompt string) (string, bool) {
                                // User is done entering their response
                                m.hasPrompt = false
                                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)
+                                               }
+                                       }
+                                       if len(suggestions) == 1 {
+                                               if len(dirs) > 1 {
+                                                       m.response = strings.Join(dirs[:len(dirs)-1], "/") + "/" + suggestions[0]
+                                               } else {
+                                                       m.response = suggestions[0]
+                                               }
+                                               m.cursorx = Count(m.response)
+                                       }
+                               }
                        }
                }
 
-               m.HandleEvent(event)
+               m.HandleEvent(event, m.history[historyType])
 
                if m.cursorx < 0 {
                        // Cancel
@@ -155,10 +210,22 @@ func (m *Messenger) Prompt(prompt string) (string, bool) {
 }
 
 // HandleEvent handles an event for the prompter
-func (m *Messenger) HandleEvent(event tcell.Event) {
+func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
        switch e := event.(type) {
        case *tcell.EventKey:
                switch e.Key() {
+               case tcell.KeyUp:
+                       if m.historyNum > 0 {
+                               m.historyNum--
+                               m.response = history[m.historyNum]
+                               m.cursorx = Count(m.response)
+                       }
+               case tcell.KeyDown:
+                       if m.historyNum < len(history)-1 {
+                               m.historyNum++
+                               m.response = history[m.historyNum]
+                               m.cursorx = Count(m.response)
+                       }
                case tcell.KeyLeft:
                        if m.cursorx > 0 {
                                m.cursorx--
@@ -176,6 +243,7 @@ func (m *Messenger) HandleEvent(event tcell.Event) {
                        m.response = Insert(m.response, m.cursorx, string(e.Rune()))
                        m.cursorx++
                }
+               history[m.historyNum] = m.response
        }
 }