X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fmessenger.go;h=b55557af290832cbea0a799e47f2d8fd8ada3ce2;hb=71af765b4e4f368c4bbbcb3947f3497e17271b62;hp=bc71b64490c4736a2e3bb13edd4cda87bf503f18;hpb=afedad997797bb25a1b8fd7109ec19a5605ff8e7;p=micro.git diff --git a/cmd/micro/messenger.go b/cmd/micro/messenger.go index bc71b644..b55557af 100644 --- a/cmd/micro/messenger.go +++ b/cmd/micro/messenger.go @@ -10,6 +10,7 @@ import ( "github.com/mattn/go-runewidth" "github.com/zyedidia/clipboard" + "github.com/zyedidia/micro/cmd/micro/shellwords" "github.com/zyedidia/tcell" ) @@ -222,6 +223,7 @@ func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (rune, bool) } } +// Completion represents a type of completion type Completion int const ( @@ -259,6 +261,11 @@ func (m *Messenger) Prompt(prompt, placeholder, historyType string, completionTy event := <-events switch e := event.(type) { + case *tcell.EventResize: + for _, t := range tabs { + t.Resize() + } + RedrawAll() case *tcell.EventKey: switch e.Key() { case tcell.KeyCtrlQ, tcell.KeyCtrlC, tcell.KeyEscape: @@ -272,9 +279,16 @@ func (m *Messenger) Prompt(prompt, placeholder, historyType string, completionTy response, canceled = m.response, false m.history[historyType][len(m.history[historyType])-1] = response case tcell.KeyTab: - args := SplitCommandArgs(m.response) - currentArgNum := len(args) - 1 - currentArg := args[currentArgNum] + args, err := shellwords.Split(m.response) + if err != nil { + break + } + currentArg := "" + currentArgNum := 0 + if len(args) > 0 { + currentArgNum = len(args) - 1 + currentArg = args[currentArgNum] + } var completionType Completion if completionTypes[0] == CommandCompletion && currentArgNum > 0 { @@ -314,8 +328,8 @@ func (m *Messenger) Prompt(prompt, placeholder, historyType string, completionTy chosen = chosen + CommonSubstring(suggestions...) } - if chosen != "" { - m.response = JoinCommandArgs(append(args[:len(args)-1], chosen)...) + if len(suggestions) != 0 && chosen != "" { + m.response = shellwords.Join(append(args[:len(args)-1], chosen)...) m.cursorx = Count(m.response) } } @@ -324,7 +338,7 @@ func (m *Messenger) Prompt(prompt, placeholder, historyType string, completionTy m.HandleEvent(event, m.history[historyType]) m.Clear() - for _, v := range tabs[curTab].views { + for _, v := range tabs[curTab].Views { v.Display() } DisplayTabs() @@ -340,62 +354,160 @@ func (m *Messenger) Prompt(prompt, placeholder, historyType string, completionTy return response, canceled } +// UpHistory fetches the previous item in the history +func (m *Messenger) UpHistory(history []string) { + if m.historyNum > 0 { + m.historyNum-- + m.response = history[m.historyNum] + m.cursorx = Count(m.response) + } +} + +// DownHistory fetches the next item in the history +func (m *Messenger) DownHistory(history []string) { + if m.historyNum < len(history)-1 { + m.historyNum++ + m.response = history[m.historyNum] + m.cursorx = Count(m.response) + } +} + +// CursorLeft moves the cursor one character left +func (m *Messenger) CursorLeft() { + if m.cursorx > 0 { + m.cursorx-- + } +} + +// CursorRight moves the cursor one character right +func (m *Messenger) CursorRight() { + if m.cursorx < Count(m.response) { + m.cursorx++ + } +} + +// Start moves the cursor to the start of the line +func (m *Messenger) Start() { + m.cursorx = 0 +} + +// End moves the cursor to the end of the line +func (m *Messenger) End() { + m.cursorx = Count(m.response) +} + +// Backspace deletes one character +func (m *Messenger) Backspace() { + if m.cursorx > 0 { + m.response = string([]rune(m.response)[:m.cursorx-1]) + string([]rune(m.response)[m.cursorx:]) + m.cursorx-- + } +} + +// Paste pastes the clipboard +func (m *Messenger) Paste() { + clip, _ := clipboard.ReadAll("clipboard") + m.response = Insert(m.response, m.cursorx, clip) + m.cursorx += Count(clip) +} + +// WordLeft moves the cursor one word to the left +func (m *Messenger) WordLeft() { + response := []rune(m.response) + m.CursorLeft() + if m.cursorx <= 0 { + return + } + for IsWhitespace(response[m.cursorx]) { + if m.cursorx <= 0 { + return + } + m.CursorLeft() + } + m.CursorLeft() + for IsWordChar(string(response[m.cursorx])) { + if m.cursorx <= 0 { + return + } + m.CursorLeft() + } + m.CursorRight() +} + +// WordRight moves the cursor one word to the right +func (m *Messenger) WordRight() { + response := []rune(m.response) + if m.cursorx >= len(response) { + return + } + for IsWhitespace(response[m.cursorx]) { + m.CursorRight() + if m.cursorx >= len(response) { + m.CursorRight() + return + } + } + m.CursorRight() + if m.cursorx >= len(response) { + return + } + for IsWordChar(string(response[m.cursorx])) { + m.CursorRight() + if m.cursorx >= len(response) { + return + } + } +} + +// DeleteWordLeft deletes one word to the left +func (m *Messenger) DeleteWordLeft() { + m.WordLeft() + m.response = string([]rune(m.response)[:m.cursorx]) +} + // HandleEvent handles an event for the prompter func (m *Messenger) HandleEvent(event tcell.Event, history []string) { switch e := event.(type) { case *tcell.EventKey: - 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) - } - } - } - } - } - } switch e.Key() { + case tcell.KeyCtrlA: + m.Start() + case tcell.KeyCtrlE: + m.End() + case tcell.KeyUp: + m.UpHistory(history) + case tcell.KeyDown: + m.DownHistory(history) + case tcell.KeyLeft: + if e.Modifiers() == tcell.ModCtrl { + m.Start() + } else if e.Modifiers() == tcell.ModAlt || e.Modifiers() == tcell.ModMeta { + m.WordLeft() + } else { + m.CursorLeft() + } + case tcell.KeyRight: + if e.Modifiers() == tcell.ModCtrl { + m.End() + } else if e.Modifiers() == tcell.ModAlt || e.Modifiers() == tcell.ModMeta { + m.WordRight() + } else { + m.CursorRight() + } + case tcell.KeyBackspace2, tcell.KeyBackspace: + if e.Modifiers() == tcell.ModCtrl || e.Modifiers() == tcell.ModAlt || e.Modifiers() == tcell.ModMeta { + m.DeleteWordLeft() + } else { + m.Backspace() + } + case tcell.KeyCtrlW: + m.DeleteWordLeft() + case tcell.KeyCtrlV: + m.Paste() + case tcell.KeyCtrlF: + m.WordRight() + case tcell.KeyCtrlB: + m.WordLeft() case tcell.KeyRune: m.response = Insert(m.response, m.cursorx, string(e.Rune())) m.cursorx++ @@ -492,21 +604,23 @@ func (m *Messenger) Display() { func (m *Messenger) LoadHistory() { if GetGlobalOption("savehistory").(bool) { file, err := os.Open(configDir + "/buffers/history") + defer file.Close() var decodedMap map[string][]string if err == nil { decoder := gob.NewDecoder(file) err = decoder.Decode(&decodedMap) - file.Close() + + if err != nil { + m.Error("Error loading history:", err) + return + } } - if err != nil { - m.Error("Error loading history:", err) - SetOption("savehistory", "false") + if decodedMap != nil { + m.history = decodedMap + } else { m.history = make(map[string][]string) - return } - - m.history = decodedMap } else { m.history = make(map[string][]string) } @@ -519,11 +633,12 @@ func (m *Messenger) SaveHistory() { // Don't save history past 100 for k, v := range m.history { if len(v) > 100 { - m.history[k] = v[0:100] + m.history[k] = v[len(m.history[k])-100:] } } file, err := os.Create(configDir + "/buffers/history") + defer file.Close() if err == nil { encoder := gob.NewEncoder(file) @@ -532,7 +647,6 @@ func (m *Messenger) SaveHistory() { m.Error("Error saving history:", err) return } - file.Close() } } }