From bb6061158e770fb52272eabba2b427e08735b9e3 Mon Sep 17 00:00:00 2001 From: Neko Box Coder Date: Sat, 19 Jul 2025 18:19:31 +0100 Subject: [PATCH] Pasting multi cursor clipboard with newlines for non matching cursors --- internal/action/actions.go | 28 ++++++++++++++--------- internal/clipboard/clipboard.go | 39 +++++++++++++++++++++++---------- internal/clipboard/multi.go | 21 ++++++++++++------ 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/internal/action/actions.go b/internal/action/actions.go index 94fe3cf769..3301114491 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -1583,23 +1583,31 @@ 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, err := clipboard.ReadMulti(clipboard.ClipboardReg, h.Cursor.Num, h.Buf.NumCursors()) - if err != nil { - InfoBar.Error(err) - } else { - h.paste(clip) - } - h.Relocate() - return true + return h.pasteReg(clipboard.ClipboardReg) } // PastePrimary pastes from the primary clipboard (only use on linux) func (h *BufPane) PastePrimary() bool { - clip, err := clipboard.ReadMulti(clipboard.PrimaryReg, h.Cursor.Num, h.Buf.NumCursors()) + return h.pasteReg(clipboard.PrimaryReg) +} + +func (h *BufPane) pasteReg(reg clipboard.Register) bool { + clips, err := clipboard.ReadMulti(reg) if err != nil { InfoBar.Error(err) } else { - h.paste(clip) + if h.Buf.NumCursors() != len(clips) { + // If cursor clipboard length doesn't match number of cursors, paste each cursor + // clipboard to a newline + for i, clip := range clips { + h.paste(clip) + if i != len(clips)-1 { + h.InsertNewline() + } + } + } else { + h.paste(clips[h.Cursor.Num]) + } } h.Relocate() return true diff --git a/internal/clipboard/clipboard.go b/internal/clipboard/clipboard.go index 3a57caf431..aeacf44463 100644 --- a/internal/clipboard/clipboard.go +++ b/internal/clipboard/clipboard.go @@ -2,7 +2,6 @@ package clipboard import ( "errors" - "github.com/zyedidia/clipper" ) @@ -78,16 +77,27 @@ func Write(text string, r Register) error { return write(text, r, CurrentMethod) } -// ReadMulti reads text from a clipboard register for a certain multi-cursor -func ReadMulti(r Register, num, ncursors int) (string, error) { +// ReadMulti reads text array from a clipboard register, which can be a multi cursor clipboard +func ReadMulti(r Register) ([]string, error) { clip, err := Read(r) - if err != nil { - return "", err + multivalid := false + if err == nil { + multivalid = ValidMulti(r, &clip) + } else { + multivalid = ValidMulti(r, nil) } - if ValidMulti(r, clip, ncursors) { - return multi.getText(r, num), nil + + if !multivalid { + returnarray := make([]string, 1, 1) + if err == nil { + returnarray[0] = clip + } else { + returnarray[0] = "" + } + return returnarray, err } - return clip, nil + + return multi.getAllText(r), nil } // WriteMulti writes text to a clipboard register for a certain multi-cursor @@ -97,13 +107,20 @@ func WriteMulti(text string, r Register, num int, ncursors int) error { // ValidMulti checks if the internal multi-clipboard is valid and up-to-date // with the system clipboard -func ValidMulti(r Register, clip string, ncursors int) bool { - return multi.isValid(r, clip, ncursors) +func ValidMulti(r Register, clip *string) bool { + return multi.isValid(r, clip) } func writeMulti(text string, r Register, num int, ncursors int, m Method) error { + // Write to multi cursor clipboard multi.writeText(text, r, num, ncursors) - return write(multi.getAllText(r), r, m) + + // Write to normal cliipboard + multitext := multi.getAllTextConcated(r) + if multitext == "" { + return write("", r, m) + } + return write(multitext, r, m) } func read(r Register, m Method) (string, error) { diff --git a/internal/clipboard/multi.go b/internal/clipboard/multi.go index 18836c86f7..8ea33035b9 100644 --- a/internal/clipboard/multi.go +++ b/internal/clipboard/multi.go @@ -9,19 +9,26 @@ type multiClipboard map[Register][]string var multi multiClipboard -func (c multiClipboard) getAllText(r Register) string { - content := c[r] - if content == nil { +func (c multiClipboard) getAllTextConcated(r Register) string { + multitext := c.getAllText(r) + if multitext == nil { return "" } buf := &bytes.Buffer{} - for _, s := range content { + for i, s := range multitext { buf.WriteString(s) + if i != len(multitext)-1 { + buf.WriteString("\n") + } } return buf.String() } +func (c multiClipboard) getAllText(r Register) []string { + return c[r] +} + func (c multiClipboard) getText(r Register, num int) string { content := c[r] if content == nil || len(content) <= num { @@ -35,13 +42,13 @@ func (c multiClipboard) getText(r Register, num int) string { // text stored in the system clipboard (provided as an argument), and therefore // if it is safe to use the multi-clipboard for pasting instead of the system // clipboard. -func (c multiClipboard) isValid(r Register, clipboard string, ncursors int) bool { +func (c multiClipboard) isValid(r Register, clipboard *string) bool { content := c[r] - if content == nil || len(content) != ncursors { + if content == nil { return false } - return clipboard == c.getAllText(r) + return c.getAllTextConcated(r) == *clipboard } func (c multiClipboard) writeText(text string, r Register, num int, ncursors int) {