X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fmessenger.go;h=d031ba83a5d7b7e3f7e160acad1c2f34c54db8da;hb=3ecdd96931ac75039105b5a4ac2fdd3b5526dbf6;hp=b57d7ff1238e74dcd13e6fc3ff4dd5575139ec62;hpb=fc2d9bb461050d90b238d1e7986b1398fd734227;p=micro.git diff --git a/cmd/micro/messenger.go b/cmd/micro/messenger.go index b57d7ff1..d031ba83 100644 --- a/cmd/micro/messenger.go +++ b/cmd/micro/messenger.go @@ -6,7 +6,6 @@ import ( "fmt" "os" "strconv" - "strings" "github.com/zyedidia/clipboard" "github.com/zyedidia/tcell" @@ -22,6 +21,7 @@ func TermMessage(msg ...interface{}) { screenWasNil := screen == nil if !screenWasNil { screen.Fini() + screen = nil } fmt.Println(msg...) @@ -44,6 +44,7 @@ func TermError(filename string, lineNum int, err string) { // Messenger is an object that makes it easy to send messages to the user // and get input from the user type Messenger struct { + log *Buffer // Are we currently prompting the user? hasPrompt bool // Is there a message to print @@ -68,16 +69,30 @@ type Messenger struct { gutterMessage bool } +func (m *Messenger) AddLog(msg string) { + buffer := m.getBuffer() + buffer.insert(buffer.End(), []byte(msg+"\n")) + buffer.Cursor.Loc = buffer.End() + buffer.Cursor.Relocate() +} + +func (m *Messenger) getBuffer() *Buffer { + if m.log == nil { + m.log = NewBuffer([]byte{}, "") + m.log.Name = "Log" + } + return m.log +} + // Message sends a message to the user func (m *Messenger) Message(msg ...interface{}) { - buf := new(bytes.Buffer) - fmt.Fprint(buf, msg...) - m.message = buf.String() + m.message = fmt.Sprint(msg...) m.style = defStyle if _, ok := colorscheme["message"]; ok { m.style = colorscheme["message"] } + m.AddLog(m.message) m.hasMessage = true } @@ -93,11 +108,13 @@ func (m *Messenger) Error(msg ...interface{}) { if _, ok := colorscheme["error-message"]; ok { m.style = colorscheme["error-message"] } + m.AddLog(m.message) m.hasMessage = true } // YesNoPrompt asks the user a yes or no question (waits for y or n) and returns the result func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) { + m.hasPrompt = true m.Message(prompt) _, h := screen.Size() @@ -113,11 +130,17 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) { switch e.Key() { case tcell.KeyRune: if e.Rune() == 'y' { + m.AddLog("\t--> y") + m.hasPrompt = false return true, false } else if e.Rune() == 'n' { + m.AddLog("\t--> n") + m.hasPrompt = false return false, false } case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape: + m.AddLog("\t--> (cancel)") + m.hasPrompt = false return false, true } } @@ -126,6 +149,7 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) { // LetterPrompt gives the user a prompt and waits for a one letter response func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (rune, bool) { + m.hasPrompt = true m.Message(prompt) _, h := screen.Size() @@ -142,11 +166,18 @@ func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (rune, bool) case tcell.KeyRune: for _, r := range responses { if e.Rune() == r { + m.AddLog("\t--> " + string(r)) + m.Clear() m.Reset() + m.hasPrompt = false return r, false } } case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape: + m.AddLog("\t--> (cancel)") + m.Clear() + m.Reset() + m.hasPrompt = false return ' ', true } } @@ -161,6 +192,8 @@ const ( CommandCompletion HelpCompletion OptionCompletion + PluginCmdCompletion + PluginNameCompletion ) // Prompt sends the user a message and waits for a response to be typed in @@ -189,14 +222,16 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple switch e.Key() { case tcell.KeyCtrlQ, tcell.KeyCtrlC, tcell.KeyEscape: // Cancel + m.AddLog("\t--> (cancel)") m.hasPrompt = false case tcell.KeyEnter: // User is done entering their response + m.AddLog("\t--> " + m.response) m.hasPrompt = false response, canceled = m.response, false m.history[historyType][len(m.history[historyType])-1] = response case tcell.KeyTab: - args := strings.Split(m.response, " ") + args := SplitCommandArgs(m.response) currentArgNum := len(args) - 1 currentArg := args[currentArgNum] var completionType Completion @@ -222,6 +257,12 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple chosen, suggestions = HelpComplete(currentArg) } else if completionType == OptionCompletion { chosen, suggestions = OptionComplete(currentArg) + } else if completionType == PluginCmdCompletion { + chosen, suggestions = PluginCmdComplete(currentArg) + } else if completionType == PluginNameCompletion { + chosen, suggestions = PluginNameComplete(currentArg) + } else if completionType < NoCompletion { + chosen, suggestions = PluginComplete(completionType, currentArg) } if len(suggestions) > 1 { @@ -229,10 +270,7 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple } if chosen != "" { - if len(args) > 1 { - chosen = " " + chosen - } - m.response = strings.Join(args[:len(args)-1], " ") + chosen + m.response = JoinCommandArgs(append(args[:len(args)-1], chosen)...) m.cursorx = Count(m.response) } } @@ -240,18 +278,19 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple m.HandleEvent(event, m.history[historyType]) - messenger.Clear() + m.Clear() for _, v := range tabs[curTab].views { v.Display() } DisplayTabs() - messenger.Display() + m.Display() if len(suggestions) > 1 { m.DisplaySuggestions(suggestions) } screen.Show() } + m.Clear() m.Reset() return response, canceled } @@ -260,36 +299,58 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple 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-- - } - case tcell.KeyRight: - if m.cursorx < Count(m.response) { - m.cursorx++ - } - case tcell.KeyBackspace2, tcell.KeyBackspace: - if m.cursorx > 0 { - m.response = string([]rune(m.response)[:m.cursorx-1]) + string([]rune(m.response)[m.cursorx:]) - m.cursorx-- + if e.Key() != tcell.KeyRune || e.Modifiers() != 0 { + for key, actions := range bindings { + if e.Key() == key.keyCode { + if e.Key() == tcell.KeyRune { + if e.Rune() != key.r { + continue + } + } + if e.Modifiers() == key.modifiers { + for _, action := range actions { + funcName := FuncName(action) + switch funcName { + case "main.(*View).CursorUp": + if m.historyNum > 0 { + m.historyNum-- + m.response = history[m.historyNum] + m.cursorx = Count(m.response) + } + case "main.(*View).CursorDown": + if m.historyNum < len(history)-1 { + m.historyNum++ + m.response = history[m.historyNum] + m.cursorx = Count(m.response) + } + case "main.(*View).CursorLeft": + if m.cursorx > 0 { + m.cursorx-- + } + case "main.(*View).CursorRight": + if m.cursorx < Count(m.response) { + m.cursorx++ + } + case "main.(*View).CursorStart", "main.(*View).StartOfLine": + m.cursorx = 0 + case "main.(*View).CursorEnd", "main.(*View).EndOfLine": + m.cursorx = Count(m.response) + case "main.(*View).Backspace": + if m.cursorx > 0 { + m.response = string([]rune(m.response)[:m.cursorx-1]) + string([]rune(m.response)[m.cursorx:]) + m.cursorx-- + } + case "main.(*View).Paste": + clip, _ := clipboard.ReadAll("clipboard") + m.response = Insert(m.response, m.cursorx, clip) + m.cursorx += Count(clip) + } + } + } + } } - case tcell.KeyCtrlV: - clip, _ := clipboard.ReadAll() - m.response = Insert(m.response, m.cursorx, clip) - m.cursorx += Count(clip) + } + switch e.Key() { case tcell.KeyRune: m.response = Insert(m.response, m.cursorx, string(e.Rune())) m.cursorx++ @@ -300,6 +361,23 @@ func (m *Messenger) HandleEvent(event tcell.Event, history []string) { clip := e.Text() m.response = Insert(m.response, m.cursorx, clip) m.cursorx += Count(clip) + case *tcell.EventMouse: + x, y := e.Position() + x -= Count(m.message) + button := e.Buttons() + _, screenH := screen.Size() + + if y == screenH-1 { + switch button { + case tcell.Button1: + m.cursorx = x + if m.cursorx < 0 { + m.cursorx = 0 + } else if m.cursorx > Count(m.response) { + m.cursorx = Count(m.response) + } + } + } } } @@ -347,14 +425,14 @@ func (m *Messenger) DisplaySuggestions(suggestions []string) { func (m *Messenger) Display() { _, h := screen.Size() if m.hasMessage { - if !m.hasPrompt && !globalSettings["infobar"].(bool) { - return - } - runes := []rune(m.message + m.response) - for x := 0; x < len(runes); x++ { - screen.SetContent(x, h-1, runes[x], nil, m.style) + if m.hasPrompt || globalSettings["infobar"].(bool) { + runes := []rune(m.message + m.response) + for x := 0; x < len(runes); x++ { + screen.SetContent(x, h-1, runes[x], nil, m.style) + } } } + if m.hasPrompt { screen.ShowCursor(Count(m.message)+m.cursorx, h-1) screen.Show()