]> git.lizzy.rs Git - micro.git/blobdiff - internal/action/actions.go
Add support for copy-paste via OSC 52
[micro.git] / internal / action / actions.go
index c42b6c8a6d2f16522e2ace4d9c2d1544f39c9761..5d7b31e0238b9f0dd70ab9ca2a4515791a2eefea 100644 (file)
@@ -5,11 +5,10 @@ import (
        "runtime"
        "strings"
        "time"
-       "unicode/utf8"
 
        shellquote "github.com/kballard/go-shellquote"
-       "github.com/zyedidia/clipboard"
        "github.com/zyedidia/micro/v2/internal/buffer"
+       "github.com/zyedidia/micro/v2/internal/clipboard"
        "github.com/zyedidia/micro/v2/internal/config"
        "github.com/zyedidia/micro/v2/internal/screen"
        "github.com/zyedidia/micro/v2/internal/shell"
@@ -60,7 +59,7 @@ func (h *BufPane) MousePress(e *tcell.EventMouse) bool {
                                h.doubleClick = false
 
                                h.Cursor.SelectLine()
-                               h.Cursor.CopySelection("primary")
+                               h.Cursor.CopySelection(clipboard.PrimaryReg)
                        } else {
                                // Double click
                                h.lastClickTime = time.Now()
@@ -69,7 +68,7 @@ func (h *BufPane) MousePress(e *tcell.EventMouse) bool {
                                h.tripleClick = false
 
                                h.Cursor.SelectWord()
-                               h.Cursor.CopySelection("primary")
+                               h.Cursor.CopySelection(clipboard.PrimaryReg)
                        }
                } else {
                        h.doubleClick = false
@@ -175,7 +174,7 @@ func (h *BufPane) CursorRight() bool {
                if tabstospaces && tabmovement {
                        tabsize := int(h.Buf.Settings["tabsize"].(float64))
                        line := h.Buf.LineBytes(h.Cursor.Y)
-                       if h.Cursor.X+tabsize < utf8.RuneCount(line) && util.IsSpaces(line[h.Cursor.X:h.Cursor.X+tabsize]) && util.IsBytesWhitespace(line[0:h.Cursor.X]) {
+                       if h.Cursor.X+tabsize < util.CharacterCount(line) && util.IsSpaces(line[h.Cursor.X:h.Cursor.X+tabsize]) && util.IsBytesWhitespace(line[0:h.Cursor.X]) {
                                for i := 0; i < tabsize; i++ {
                                        h.Cursor.Right()
                                }
@@ -486,7 +485,7 @@ func (h *BufPane) InsertNewline() bool {
                // Remove the whitespaces if keepautoindent setting is off
                if util.IsSpacesOrTabs(h.Buf.LineBytes(h.Cursor.Y-1)) && !h.Buf.Settings["keepautoindent"].(bool) {
                        line := h.Buf.LineBytes(h.Cursor.Y - 1)
-                       h.Buf.Remove(buffer.Loc{X: 0, Y: h.Cursor.Y - 1}, buffer.Loc{X: utf8.RuneCount(line), Y: h.Cursor.Y - 1})
+                       h.Buf.Remove(buffer.Loc{X: 0, Y: h.Cursor.Y - 1}, buffer.Loc{X: util.CharacterCount(line), Y: h.Cursor.Y - 1})
                }
        }
        h.Cursor.LastVisualX = h.Cursor.GetVisualX()
@@ -511,7 +510,7 @@ func (h *BufPane) Backspace() bool {
                // tab (tabSize number of spaces)
                lineStart := util.SliceStart(h.Buf.LineBytes(h.Cursor.Y), h.Cursor.X)
                tabSize := int(h.Buf.Settings["tabsize"].(float64))
-               if h.Buf.Settings["tabstospaces"].(bool) && util.IsSpaces(lineStart) && len(lineStart) != 0 && utf8.RuneCount(lineStart)%tabSize == 0 {
+               if h.Buf.Settings["tabstospaces"].(bool) && util.IsSpaces(lineStart) && len(lineStart) != 0 && util.CharacterCount(lineStart)%tabSize == 0 {
                        loc := h.Cursor.Loc
                        h.Buf.Remove(loc.Move(-tabSize, h.Buf), loc)
                } else {
@@ -664,7 +663,12 @@ func (h *BufPane) Autocomplete() bool {
                return false
        }
 
-       if !util.IsNonAlphaNumeric(h.Cursor.RuneUnder(h.Cursor.X)) {
+       if h.Cursor.X == 0 {
+               return false
+       }
+       r := h.Cursor.RuneUnder(h.Cursor.X)
+       prev := h.Cursor.RuneUnder(h.Cursor.X - 1)
+       if !util.IsAutocomplete(prev) || !util.IsNonAlphaNumeric(r) {
                // don't autocomplete if cursor is on alpha numeric character (middle of a word)
                return false
        }
@@ -728,6 +732,7 @@ func (h *BufPane) Save() bool {
 }
 
 // SaveAsCB performs a save as and does a callback at the very end (after all prompts have been resolved)
+// The callback is only called if the save was successful
 func (h *BufPane) SaveAsCB(action string, callback func()) bool {
        InfoBar.Prompt("Filename: ", "", "Save", nil, func(resp string, canceled bool) {
                if !canceled {
@@ -758,6 +763,7 @@ func (h *BufPane) SaveAs() bool {
 
 // This function saves the buffer to `filename` and changes the buffer's path and name
 // to `filename` if the save is successful
+// The callback is only called if the save was successful
 func (h *BufPane) saveBufToFile(filename string, action string, callback func()) bool {
        err := h.Buf.SaveAs(filename)
        if err != nil {
@@ -770,6 +776,9 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
                                        h.Buf.Path = filename
                                        h.Buf.SetName(filename)
                                        InfoBar.Message("Saved " + filename)
+                                       if callback != nil {
+                                               callback()
+                                       }
                                }
                        }
                        if h.Buf.Settings["autosu"].(bool) {
@@ -780,9 +789,6 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
                                                saveWithSudo()
                                                h.completeAction(action)
                                        }
-                                       if callback != nil {
-                                               callback()
-                                       }
                                })
                                return false
                        }
@@ -793,9 +799,9 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
                h.Buf.Path = filename
                h.Buf.SetName(filename)
                InfoBar.Message("Saved " + filename)
-       }
-       if callback != nil {
-               callback()
+               if callback != nil {
+                       callback()
+               }
        }
        return true
 }
@@ -810,6 +816,30 @@ func (h *BufPane) FindLiteral() bool {
        return h.find(false)
 }
 
+// Search searches for a given string/regex in the buffer and selects the next
+// match if a match is found
+// This function affects lastSearch and lastSearchRegex (saved searches) for
+// use with FindNext and FindPrevious
+func (h *BufPane) Search(str string, useRegex bool, searchDown bool) error {
+       match, found, err := h.Buf.FindNext(str, h.Buf.Start(), h.Buf.End(), h.Cursor.Loc, searchDown, useRegex)
+       if err != nil {
+               return err
+       }
+       if found {
+               h.Cursor.SetSelectionStart(match[0])
+               h.Cursor.SetSelectionEnd(match[1])
+               h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
+               h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
+               h.Cursor.GotoLoc(h.Cursor.CurSelection[1])
+               h.lastSearch = str
+               h.lastSearchRegex = useRegex
+               h.Relocate()
+       } else {
+               h.Cursor.ResetSelection()
+       }
+       return nil
+}
+
 func (h *BufPane) find(useRegex bool) bool {
        h.searchOrig = h.Cursor.Loc
        prompt := "Find: "
@@ -931,13 +961,9 @@ func (h *BufPane) Redo() bool {
 // Copy the selection to the system clipboard
 func (h *BufPane) Copy() bool {
        if h.Cursor.HasSelection() {
-               h.Cursor.CopySelection("clipboard")
+               h.Cursor.CopySelection(clipboard.ClipboardReg)
                h.freshClip = true
-               if clipboard.Unsupported {
-                       InfoBar.Message("Copied selection (install xclip for external clipboard)")
-               } else {
-                       InfoBar.Message("Copied selection")
-               }
+               InfoBar.Message("Copied selection")
        }
        h.Relocate()
        return true
@@ -949,13 +975,9 @@ func (h *BufPane) CopyLine() bool {
                return false
        } else {
                h.Cursor.SelectLine()
-               h.Cursor.CopySelection("clipboard")
+               h.Cursor.CopySelection(clipboard.ClipboardReg)
                h.freshClip = true
-               if clipboard.Unsupported {
-                       InfoBar.Message("Copied line (install xclip for external clipboard)")
-               } else {
-                       InfoBar.Message("Copied line")
-               }
+               InfoBar.Message("Copied line")
        }
        h.Cursor.Deselect(true)
        h.Relocate()
@@ -970,10 +992,10 @@ func (h *BufPane) CutLine() bool {
        }
        if h.freshClip == true {
                if h.Cursor.HasSelection() {
-                       if clip, err := clipboard.ReadAll("clipboard"); err != nil {
-                               // messenger.Error(err)
+                       if clip, err := clipboard.Read(clipboard.ClipboardReg); err != nil {
+                               InfoBar.Error(err)
                        } else {
-                               clipboard.WriteAll(clip+string(h.Cursor.GetSelection()), "clipboard")
+                               clipboard.Write(clip+string(h.Cursor.GetSelection()), clipboard.ClipboardReg)
                        }
                }
        } else if time.Since(h.lastCutTime)/time.Second > 10*time.Second || h.freshClip == false {
@@ -991,7 +1013,7 @@ func (h *BufPane) CutLine() bool {
 // Cut the selection to the system clipboard
 func (h *BufPane) Cut() bool {
        if h.Cursor.HasSelection() {
-               h.Cursor.CopySelection("clipboard")
+               h.Cursor.CopySelection(clipboard.ClipboardReg)
                h.Cursor.DeleteSelection()
                h.Cursor.ResetSelection()
                h.freshClip = true
@@ -1117,7 +1139,10 @@ func (h *BufPane) MoveLinesDown() bool {
 // Paste whatever is in the system clipboard into the buffer
 // Delete and paste if the user has a selection
 func (h *BufPane) Paste() bool {
-       clip, _ := clipboard.ReadAll("clipboard")
+       clip, err := clipboard.Read(clipboard.ClipboardReg)
+       if err != nil {
+               InfoBar.Error(err)
+       }
        h.paste(clip)
        h.Relocate()
        return true
@@ -1125,7 +1150,10 @@ func (h *BufPane) Paste() bool {
 
 // PastePrimary pastes from the primary clipboard (only use on linux)
 func (h *BufPane) PastePrimary() bool {
-       clip, _ := clipboard.ReadAll("primary")
+       clip, err := clipboard.Read(clipboard.PrimaryReg)
+       if err != nil {
+               InfoBar.Error(err)
+       }
        h.paste(clip)
        h.Relocate()
        return true
@@ -1147,11 +1175,7 @@ func (h *BufPane) paste(clip string) {
        h.Buf.Insert(h.Cursor.Loc, clip)
        // h.Cursor.Loc = h.Cursor.Loc.Move(Count(clip), h.Buf)
        h.freshClip = false
-       if clipboard.Unsupported {
-               InfoBar.Message("Pasted clipboard (install xclip for external clipboard)")
-       } else {
-               InfoBar.Message("Pasted clipboard")
-       }
+       InfoBar.Message("Pasted clipboard")
 }
 
 // JumpToMatchingBrace moves the cursor to the matching brace if it is
@@ -1413,6 +1437,18 @@ func (h *BufPane) Escape() bool {
        return true
 }
 
+// Deselect deselects on the current cursor
+func (h *BufPane) Deselect() bool {
+       h.Cursor.Deselect(true)
+       return true
+}
+
+// ClearInfo clears the infobar
+func (h *BufPane) ClearInfo() bool {
+       InfoBar.Message("")
+       return true
+}
+
 // Quit this will close the current tab or view that is open
 func (h *BufPane) Quit() bool {
        quit := func() {