parent
67355337b3
commit
f143418267
16 changed files with 403 additions and 61 deletions
|
@ -16,6 +16,7 @@ import (
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
"github.com/zyedidia/micro/v2/internal/action"
|
"github.com/zyedidia/micro/v2/internal/action"
|
||||||
"github.com/zyedidia/micro/v2/internal/buffer"
|
"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/config"
|
||||||
ulua "github.com/zyedidia/micro/v2/internal/lua"
|
ulua "github.com/zyedidia/micro/v2/internal/lua"
|
||||||
"github.com/zyedidia/micro/v2/internal/screen"
|
"github.com/zyedidia/micro/v2/internal/screen"
|
||||||
|
@ -269,6 +270,9 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m := clipboard.SetMethod(config.GetGlobalOption("clipboard").(string))
|
||||||
|
clipErr := clipboard.Initialize(m)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
screen.Screen.Fini()
|
screen.Screen.Fini()
|
||||||
|
@ -313,6 +317,10 @@ func main() {
|
||||||
screen.TermMessage(err)
|
screen.TermMessage(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if clipErr != nil {
|
||||||
|
action.InfoBar.Error(clipErr, " or change 'clipboard' option")
|
||||||
|
}
|
||||||
|
|
||||||
events = make(chan tcell.Event)
|
events = make(chan tcell.Event)
|
||||||
|
|
||||||
// Here is the event loop which runs in a separate thread
|
// Here is the event loop which runs in a separate thread
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -12,12 +12,12 @@ require (
|
||||||
github.com/sergi/go-diff v1.1.0
|
github.com/sergi/go-diff v1.1.0
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb
|
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb
|
||||||
github.com/zyedidia/clipboard v1.0.1
|
github.com/zyedidia/clipboard v1.0.3
|
||||||
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3
|
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3
|
||||||
github.com/zyedidia/highlight v0.0.0-20170330143449-201131ce5cf5
|
github.com/zyedidia/highlight v0.0.0-20170330143449-201131ce5cf5
|
||||||
github.com/zyedidia/json5 v0.0.0-20200102012142-2da050b1a98d
|
github.com/zyedidia/json5 v0.0.0-20200102012142-2da050b1a98d
|
||||||
github.com/zyedidia/pty v2.0.0+incompatible // indirect
|
github.com/zyedidia/pty v2.0.0+incompatible // indirect
|
||||||
github.com/zyedidia/tcell v1.4.8
|
github.com/zyedidia/tcell v1.4.9
|
||||||
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415
|
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415
|
||||||
golang.org/x/text v0.3.2
|
golang.org/x/text v0.3.2
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -40,6 +40,10 @@ github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox
|
||||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||||
github.com/zyedidia/clipboard v1.0.1 h1:DNsDMRXdptfdp4f6gSnSNJpWadAgI8UCm26elADCYak=
|
github.com/zyedidia/clipboard v1.0.1 h1:DNsDMRXdptfdp4f6gSnSNJpWadAgI8UCm26elADCYak=
|
||||||
github.com/zyedidia/clipboard v1.0.1/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
github.com/zyedidia/clipboard v1.0.1/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
||||||
|
github.com/zyedidia/clipboard v1.0.2 h1:Mh5t+hjEf9I5pcveVxVAFJsuOhd2ByavDgIkflK3Qps=
|
||||||
|
github.com/zyedidia/clipboard v1.0.2/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
||||||
|
github.com/zyedidia/clipboard v1.0.3 h1:F/nCDVYMdbDWTmY8s8cJl0tnwX32q96IF09JHM14bUI=
|
||||||
|
github.com/zyedidia/clipboard v1.0.3/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
||||||
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3 h1:oMHjjTLfGXVuyOQBYj5/td9WC0mw4g1xDBPovIqmHew=
|
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3 h1:oMHjjTLfGXVuyOQBYj5/td9WC0mw4g1xDBPovIqmHew=
|
||||||
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3/go.mod h1:YKbIYP//Eln8eDgAJGI3IDvR3s4Tv9Z9TGIOumiyQ5c=
|
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3/go.mod h1:YKbIYP//Eln8eDgAJGI3IDvR3s4Tv9Z9TGIOumiyQ5c=
|
||||||
github.com/zyedidia/go-shellquote v0.0.0-20200613203517-eccd813c0655 h1:Z3RhH6hvcSx7eX6Q/pP6YVsgea/1eMDG99vtWwi3nK4=
|
github.com/zyedidia/go-shellquote v0.0.0-20200613203517-eccd813c0655 h1:Z3RhH6hvcSx7eX6Q/pP6YVsgea/1eMDG99vtWwi3nK4=
|
||||||
|
@ -54,6 +58,8 @@ github.com/zyedidia/pty v2.0.0+incompatible h1:Ou5vXL6tvjst+RV8sUFISbuKDnUJPhnpy
|
||||||
github.com/zyedidia/pty v2.0.0+incompatible/go.mod h1:4y9l9yJZNxRa7GB/fB+mmDmGkG3CqmzLf4vUxGGotEA=
|
github.com/zyedidia/pty v2.0.0+incompatible/go.mod h1:4y9l9yJZNxRa7GB/fB+mmDmGkG3CqmzLf4vUxGGotEA=
|
||||||
github.com/zyedidia/tcell v1.4.8 h1:s4zYGOyCNDK4cdrgNVME0SxGizuT/oKY3OyB4Ls2Qpg=
|
github.com/zyedidia/tcell v1.4.8 h1:s4zYGOyCNDK4cdrgNVME0SxGizuT/oKY3OyB4Ls2Qpg=
|
||||||
github.com/zyedidia/tcell v1.4.8/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
|
github.com/zyedidia/tcell v1.4.8/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
|
||||||
|
github.com/zyedidia/tcell v1.4.9 h1:DYUrd8gCmSxUlbFd280sT6tzEqhxfyWMbZNNnup6iQ0=
|
||||||
|
github.com/zyedidia/tcell v1.4.9/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
|
||||||
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415 h1:752dTQ5OatJ9M5ULK2+9lor+nzyZz+LYDo3WGngg3Rc=
|
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415 h1:752dTQ5OatJ9M5ULK2+9lor+nzyZz+LYDo3WGngg3Rc=
|
||||||
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415/go.mod h1:8leT8G0Cm8NoJHdrrKHyR9MirWoF4YW7pZh06B6H+1E=
|
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415/go.mod h1:8leT8G0Cm8NoJHdrrKHyR9MirWoF4YW7pZh06B6H+1E=
|
||||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
shellquote "github.com/kballard/go-shellquote"
|
shellquote "github.com/kballard/go-shellquote"
|
||||||
"github.com/zyedidia/clipboard"
|
|
||||||
"github.com/zyedidia/micro/v2/internal/buffer"
|
"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/config"
|
||||||
"github.com/zyedidia/micro/v2/internal/screen"
|
"github.com/zyedidia/micro/v2/internal/screen"
|
||||||
"github.com/zyedidia/micro/v2/internal/shell"
|
"github.com/zyedidia/micro/v2/internal/shell"
|
||||||
|
@ -59,7 +59,7 @@ func (h *BufPane) MousePress(e *tcell.EventMouse) bool {
|
||||||
h.doubleClick = false
|
h.doubleClick = false
|
||||||
|
|
||||||
h.Cursor.SelectLine()
|
h.Cursor.SelectLine()
|
||||||
h.Cursor.CopySelection("primary")
|
h.Cursor.CopySelection(clipboard.PrimaryReg)
|
||||||
} else {
|
} else {
|
||||||
// Double click
|
// Double click
|
||||||
h.lastClickTime = time.Now()
|
h.lastClickTime = time.Now()
|
||||||
|
@ -68,7 +68,7 @@ func (h *BufPane) MousePress(e *tcell.EventMouse) bool {
|
||||||
h.tripleClick = false
|
h.tripleClick = false
|
||||||
|
|
||||||
h.Cursor.SelectWord()
|
h.Cursor.SelectWord()
|
||||||
h.Cursor.CopySelection("primary")
|
h.Cursor.CopySelection(clipboard.PrimaryReg)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
h.doubleClick = false
|
h.doubleClick = false
|
||||||
|
@ -961,14 +961,10 @@ func (h *BufPane) Redo() bool {
|
||||||
// Copy the selection to the system clipboard
|
// Copy the selection to the system clipboard
|
||||||
func (h *BufPane) Copy() bool {
|
func (h *BufPane) Copy() bool {
|
||||||
if h.Cursor.HasSelection() {
|
if h.Cursor.HasSelection() {
|
||||||
h.Cursor.CopySelection("clipboard")
|
h.Cursor.CopySelection(clipboard.ClipboardReg)
|
||||||
h.freshClip = true
|
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()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -979,14 +975,10 @@ func (h *BufPane) CopyLine() bool {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
h.Cursor.SelectLine()
|
h.Cursor.SelectLine()
|
||||||
h.Cursor.CopySelection("clipboard")
|
h.Cursor.CopySelection(clipboard.ClipboardReg)
|
||||||
h.freshClip = true
|
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.Cursor.Deselect(true)
|
||||||
h.Relocate()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
|
@ -1000,10 +992,10 @@ func (h *BufPane) CutLine() bool {
|
||||||
}
|
}
|
||||||
if h.freshClip == true {
|
if h.freshClip == true {
|
||||||
if h.Cursor.HasSelection() {
|
if h.Cursor.HasSelection() {
|
||||||
if clip, err := clipboard.ReadAll("clipboard"); err != nil {
|
if clip, err := clipboard.Read(clipboard.ClipboardReg); err != nil {
|
||||||
// messenger.Error(err)
|
InfoBar.Error(err)
|
||||||
} else {
|
} 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 {
|
} else if time.Since(h.lastCutTime)/time.Second > 10*time.Second || h.freshClip == false {
|
||||||
|
@ -1021,7 +1013,7 @@ func (h *BufPane) CutLine() bool {
|
||||||
// Cut the selection to the system clipboard
|
// Cut the selection to the system clipboard
|
||||||
func (h *BufPane) Cut() bool {
|
func (h *BufPane) Cut() bool {
|
||||||
if h.Cursor.HasSelection() {
|
if h.Cursor.HasSelection() {
|
||||||
h.Cursor.CopySelection("clipboard")
|
h.Cursor.CopySelection(clipboard.ClipboardReg)
|
||||||
h.Cursor.DeleteSelection()
|
h.Cursor.DeleteSelection()
|
||||||
h.Cursor.ResetSelection()
|
h.Cursor.ResetSelection()
|
||||||
h.freshClip = true
|
h.freshClip = true
|
||||||
|
@ -1147,7 +1139,10 @@ func (h *BufPane) MoveLinesDown() bool {
|
||||||
// Paste whatever is in the system clipboard into the buffer
|
// Paste whatever is in the system clipboard into the buffer
|
||||||
// Delete and paste if the user has a selection
|
// Delete and paste if the user has a selection
|
||||||
func (h *BufPane) Paste() bool {
|
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.paste(clip)
|
||||||
h.Relocate()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
|
@ -1155,7 +1150,10 @@ func (h *BufPane) Paste() bool {
|
||||||
|
|
||||||
// PastePrimary pastes from the primary clipboard (only use on linux)
|
// PastePrimary pastes from the primary clipboard (only use on linux)
|
||||||
func (h *BufPane) PastePrimary() bool {
|
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.paste(clip)
|
||||||
h.Relocate()
|
h.Relocate()
|
||||||
return true
|
return true
|
||||||
|
@ -1177,11 +1175,7 @@ func (h *BufPane) paste(clip string) {
|
||||||
h.Buf.Insert(h.Cursor.Loc, clip)
|
h.Buf.Insert(h.Cursor.Loc, clip)
|
||||||
// h.Cursor.Loc = h.Cursor.Loc.Move(Count(clip), h.Buf)
|
// h.Cursor.Loc = h.Cursor.Loc.Move(Count(clip), h.Buf)
|
||||||
h.freshClip = false
|
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
|
// JumpToMatchingBrace moves the cursor to the matching brace if it is
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
"github.com/zyedidia/micro/v2/internal/buffer"
|
"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/config"
|
||||||
"github.com/zyedidia/micro/v2/internal/display"
|
"github.com/zyedidia/micro/v2/internal/display"
|
||||||
ulua "github.com/zyedidia/micro/v2/internal/lua"
|
ulua "github.com/zyedidia/micro/v2/internal/lua"
|
||||||
|
@ -360,7 +361,7 @@ func (h *BufPane) HandleEvent(event tcell.Event) {
|
||||||
// h.Cursor.SetSelectionEnd(h.Cursor.Loc)
|
// h.Cursor.SetSelectionEnd(h.Cursor.Loc)
|
||||||
// }
|
// }
|
||||||
if h.Cursor.HasSelection() {
|
if h.Cursor.HasSelection() {
|
||||||
h.Cursor.CopySelection("primary")
|
h.Cursor.CopySelection(clipboard.PrimaryReg)
|
||||||
}
|
}
|
||||||
h.mouseReleased = true
|
h.mouseReleased = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
shellquote "github.com/kballard/go-shellquote"
|
shellquote "github.com/kballard/go-shellquote"
|
||||||
"github.com/zyedidia/micro/v2/internal/buffer"
|
"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/config"
|
||||||
"github.com/zyedidia/micro/v2/internal/screen"
|
"github.com/zyedidia/micro/v2/internal/screen"
|
||||||
"github.com/zyedidia/micro/v2/internal/shell"
|
"github.com/zyedidia/micro/v2/internal/shell"
|
||||||
|
@ -505,6 +506,12 @@ func SetGlobalOptionNative(option string, nativeValue interface{}) error {
|
||||||
}
|
}
|
||||||
} else if option == "paste" {
|
} else if option == "paste" {
|
||||||
screen.Screen.SetPaste(nativeValue.(bool))
|
screen.Screen.SetPaste(nativeValue.(bool))
|
||||||
|
} else if option == "clipboard" {
|
||||||
|
m := clipboard.SetMethod(nativeValue.(string))
|
||||||
|
err := clipboard.Initialize(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, pl := range config.Plugins {
|
for _, pl := range config.Plugins {
|
||||||
if option == pl.Name {
|
if option == pl.Name {
|
||||||
|
|
|
@ -186,6 +186,16 @@ func OptionValueComplete(b *buffer.Buffer) ([]string, []string) {
|
||||||
if strings.HasPrefix("doas", input) {
|
if strings.HasPrefix("doas", input) {
|
||||||
suggestions = append(suggestions, "doas")
|
suggestions = append(suggestions, "doas")
|
||||||
}
|
}
|
||||||
|
case "clipboard":
|
||||||
|
if strings.HasPrefix("external", input) {
|
||||||
|
suggestions = append(suggestions, "external")
|
||||||
|
}
|
||||||
|
if strings.HasPrefix("internal", input) {
|
||||||
|
suggestions = append(suggestions, "internal")
|
||||||
|
}
|
||||||
|
if strings.HasPrefix("terminal", input) {
|
||||||
|
suggestions = append(suggestions, "terminal")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Strings(suggestions)
|
sort.Strings(suggestions)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/zyedidia/clipboard"
|
"github.com/zyedidia/micro/v2/internal/clipboard"
|
||||||
"github.com/zyedidia/micro/v2/internal/display"
|
"github.com/zyedidia/micro/v2/internal/display"
|
||||||
"github.com/zyedidia/micro/v2/internal/screen"
|
"github.com/zyedidia/micro/v2/internal/screen"
|
||||||
"github.com/zyedidia/micro/v2/internal/shell"
|
"github.com/zyedidia/micro/v2/internal/shell"
|
||||||
|
@ -90,7 +90,7 @@ func (t *TermPane) HandleEvent(event tcell.Event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if e.Key() == tcell.KeyCtrlC && t.HasSelection() {
|
if e.Key() == tcell.KeyCtrlC && t.HasSelection() {
|
||||||
clipboard.WriteAll(t.GetSelection(t.GetView().Width), "clipboard")
|
clipboard.Write(t.GetSelection(t.GetView().Width), clipboard.ClipboardReg)
|
||||||
InfoBar.Message("Copied selection to clipboard")
|
InfoBar.Message("Copied selection to clipboard")
|
||||||
} else if t.Status != shell.TTDone {
|
} else if t.Status != shell.TTDone {
|
||||||
t.WriteString(event.EscSeq())
|
t.WriteString(event.EscSeq())
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package buffer
|
package buffer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/zyedidia/clipboard"
|
"github.com/zyedidia/micro/v2/internal/clipboard"
|
||||||
"github.com/zyedidia/micro/v2/internal/util"
|
"github.com/zyedidia/micro/v2/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -125,10 +125,10 @@ func (c *Cursor) End() {
|
||||||
|
|
||||||
// CopySelection copies the user's selection to either "primary"
|
// CopySelection copies the user's selection to either "primary"
|
||||||
// or "clipboard"
|
// or "clipboard"
|
||||||
func (c *Cursor) CopySelection(target string) {
|
func (c *Cursor) CopySelection(target clipboard.Register) {
|
||||||
if c.HasSelection() {
|
if c.HasSelection() {
|
||||||
if target != "primary" || c.buf.Settings["useprimary"].(bool) {
|
if target != clipboard.PrimaryReg || c.buf.Settings["useprimary"].(bool) {
|
||||||
clipboard.WriteAll(string(c.GetSelection()), target)
|
clipboard.Write(string(c.GetSelection()), target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
151
internal/clipboard/clipboard.go
Normal file
151
internal/clipboard/clipboard.go
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
package clipboard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/zyedidia/clipboard"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Method int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// External relies on external tools for accessing the clipboard
|
||||||
|
// These include xclip, xsel, wl-clipboard for linux, pbcopy/pbpaste on Mac,
|
||||||
|
// and Syscalls on Windows.
|
||||||
|
External Method = iota
|
||||||
|
// Terminal uses the terminal to manage the clipboard via OSC 52. Many
|
||||||
|
// terminals do not support OSC 52, in which case this method won't work.
|
||||||
|
Terminal
|
||||||
|
// Internal just manages the clipboard with an internal buffer and doesn't
|
||||||
|
// attempt to interface with the system clipboard
|
||||||
|
Internal
|
||||||
|
)
|
||||||
|
|
||||||
|
// CurrentMethod is the method used to store clipboard information
|
||||||
|
var CurrentMethod Method = Internal
|
||||||
|
|
||||||
|
// A Register is a buffer used to store text. The system clipboard has the 'clipboard'
|
||||||
|
// and 'primary' (linux-only) registers, but other registers may be used internal to micro.
|
||||||
|
type Register int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ClipboardReg is the main system clipboard
|
||||||
|
ClipboardReg Register = -1
|
||||||
|
// PrimaryReg is the system primary clipboard (linux only)
|
||||||
|
PrimaryReg = -2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Initialize attempts to initialize the clipboard using the given method
|
||||||
|
func Initialize(m Method) error {
|
||||||
|
var err error
|
||||||
|
switch m {
|
||||||
|
case External:
|
||||||
|
err = clipboard.Initialize()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMethod changes the clipboard access method
|
||||||
|
func SetMethod(m string) Method {
|
||||||
|
switch m {
|
||||||
|
case "internal":
|
||||||
|
CurrentMethod = Internal
|
||||||
|
case "external":
|
||||||
|
CurrentMethod = External
|
||||||
|
case "terminal":
|
||||||
|
CurrentMethod = Terminal
|
||||||
|
}
|
||||||
|
return CurrentMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads from a clipboard register
|
||||||
|
func Read(r Register) (string, error) {
|
||||||
|
return read(r, CurrentMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes text to a clipboard register
|
||||||
|
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 int) (string, error) {
|
||||||
|
s := multi.getText(r, num)
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteMulti writes text to a clipboard register for a certain multi-cursor
|
||||||
|
func WriteMulti(text string, r Register, num int) error {
|
||||||
|
return writeMulti(text, r, num, CurrentMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidMulti checks if the internal multi-clipboard is valid and up-to-date
|
||||||
|
// with the system clipboard
|
||||||
|
func ValidMulti(r Register, ncursors int) bool {
|
||||||
|
clip, err := Read(r)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return multi.isValid(r, ncursors, clip)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeMulti(text string, r Register, num int, m Method) error {
|
||||||
|
multi.writeText(text, r, num)
|
||||||
|
return write(multi.getAllText(r), r, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func read(r Register, m Method) (string, error) {
|
||||||
|
switch m {
|
||||||
|
case External:
|
||||||
|
switch r {
|
||||||
|
case ClipboardReg:
|
||||||
|
return clipboard.ReadAll("clipboard")
|
||||||
|
case PrimaryReg:
|
||||||
|
return clipboard.ReadAll("primary")
|
||||||
|
default:
|
||||||
|
return internal.read(r), nil
|
||||||
|
}
|
||||||
|
case Internal:
|
||||||
|
return internal.read(r), nil
|
||||||
|
case Terminal:
|
||||||
|
switch r {
|
||||||
|
case ClipboardReg:
|
||||||
|
// terminal paste works by sending an esc sequence to the
|
||||||
|
// terminal to trigger a paste event
|
||||||
|
err := terminal.read("clipboard")
|
||||||
|
return "", err
|
||||||
|
case PrimaryReg:
|
||||||
|
err := terminal.read("primary")
|
||||||
|
return "", err
|
||||||
|
default:
|
||||||
|
return internal.read(r), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", errors.New("Invalid clipboard method")
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(text string, r Register, m Method) error {
|
||||||
|
switch m {
|
||||||
|
case External:
|
||||||
|
switch r {
|
||||||
|
case ClipboardReg:
|
||||||
|
return clipboard.WriteAll(text, "clipboard")
|
||||||
|
case PrimaryReg:
|
||||||
|
return clipboard.WriteAll(text, "primary")
|
||||||
|
default:
|
||||||
|
internal.write(text, r)
|
||||||
|
}
|
||||||
|
case Internal:
|
||||||
|
internal.write(text, r)
|
||||||
|
case Terminal:
|
||||||
|
switch r {
|
||||||
|
case ClipboardReg:
|
||||||
|
return terminal.write(text, "c")
|
||||||
|
case PrimaryReg:
|
||||||
|
return terminal.write(text, "p")
|
||||||
|
default:
|
||||||
|
internal.write(text, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
17
internal/clipboard/internal.go
Normal file
17
internal/clipboard/internal.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package clipboard
|
||||||
|
|
||||||
|
type internalClipboard map[Register]string
|
||||||
|
|
||||||
|
var internal internalClipboard
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
internal = make(internalClipboard)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c internalClipboard) read(r Register) string {
|
||||||
|
return c[r]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c internalClipboard) write(text string, r Register) {
|
||||||
|
c[r] = text
|
||||||
|
}
|
66
internal/clipboard/multi.go
Normal file
66
internal/clipboard/multi.go
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
package clipboard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"hash/fnv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// For storing multi cursor clipboard contents
|
||||||
|
type multiClipboard map[Register][]string
|
||||||
|
|
||||||
|
var multi multiClipboard
|
||||||
|
|
||||||
|
func (c multiClipboard) getAllText(r Register) string {
|
||||||
|
content := c[r]
|
||||||
|
if content == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
for _, s := range content {
|
||||||
|
buf.WriteString(s)
|
||||||
|
buf.WriteByte('\n')
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c multiClipboard) getText(r Register, num int) string {
|
||||||
|
content := c[r]
|
||||||
|
if content == nil || len(content) <= num {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return content[num]
|
||||||
|
}
|
||||||
|
|
||||||
|
func hash(s string) uint32 {
|
||||||
|
h := fnv.New32a()
|
||||||
|
h.Write([]byte(s))
|
||||||
|
return h.Sum32()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValid checks if the text stored in this multi-clipboard is the same as the
|
||||||
|
// 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, ncursors int, clipboard string) bool {
|
||||||
|
content := c[r]
|
||||||
|
if content == nil || len(content) != ncursors {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash(clipboard) == hash(c.getAllText(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c multiClipboard) writeText(text string, r Register, num int) {
|
||||||
|
content := c[r]
|
||||||
|
if content == nil || num >= cap(content) {
|
||||||
|
content = make([]string, num+1, num+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
content[num] = text
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
multi = make(multiClipboard)
|
||||||
|
}
|
15
internal/clipboard/terminal.go
Normal file
15
internal/clipboard/terminal.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package clipboard
|
||||||
|
|
||||||
|
import "github.com/zyedidia/micro/v2/internal/screen"
|
||||||
|
|
||||||
|
type terminalClipboard struct{}
|
||||||
|
|
||||||
|
var terminal terminalClipboard
|
||||||
|
|
||||||
|
func (t terminalClipboard) read(reg string) error {
|
||||||
|
return screen.Screen.GetClipboard(reg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t terminalClipboard) write(text, reg string) error {
|
||||||
|
return screen.Screen.SetClipboard(text, reg)
|
||||||
|
}
|
|
@ -43,6 +43,7 @@ func init() {
|
||||||
// Options with validators
|
// Options with validators
|
||||||
var optionValidators = map[string]optionValidator{
|
var optionValidators = map[string]optionValidator{
|
||||||
"autosave": validateNonNegativeValue,
|
"autosave": validateNonNegativeValue,
|
||||||
|
"clipboard": validateClipboard,
|
||||||
"tabsize": validatePositiveValue,
|
"tabsize": validatePositiveValue,
|
||||||
"scrollmargin": validateNonNegativeValue,
|
"scrollmargin": validateNonNegativeValue,
|
||||||
"scrollspeed": validateNonNegativeValue,
|
"scrollspeed": validateNonNegativeValue,
|
||||||
|
@ -322,6 +323,7 @@ func DefaultCommonSettings() map[string]interface{} {
|
||||||
// default values
|
// default values
|
||||||
var DefaultGlobalOnlySettings = map[string]interface{}{
|
var DefaultGlobalOnlySettings = map[string]interface{}{
|
||||||
"autosave": float64(0),
|
"autosave": float64(0),
|
||||||
|
"clipboard": "external",
|
||||||
"colorscheme": "default",
|
"colorscheme": "default",
|
||||||
"divchars": "|-",
|
"divchars": "|-",
|
||||||
"divreverse": true,
|
"divreverse": true,
|
||||||
|
@ -450,6 +452,22 @@ func validateColorscheme(option string, value interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateClipboard(option string, value interface{}) error {
|
||||||
|
val, ok := value.(string)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return errors.New("Expected string type for clipboard")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val {
|
||||||
|
case "internal", "external", "terminal":
|
||||||
|
default:
|
||||||
|
return errors.New(option + " must be 'internal', 'external', or 'terminal'")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func validateLineEnding(option string, value interface{}) error {
|
func validateLineEnding(option string, value interface{}) error {
|
||||||
endingType, ok := value.(string)
|
endingType, ok := value.(string)
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,51 @@ because there are multiple methods. This help document will explain
|
||||||
the various methods for copying and pasting, how they work,
|
the various methods for copying and pasting, how they work,
|
||||||
and the best methods for doing so over SSH.
|
and the best methods for doing so over SSH.
|
||||||
|
|
||||||
|
# OSC 52 (terminal clipboard)
|
||||||
|
|
||||||
|
If possible, setting the `clipboard` option to `terminal` will give
|
||||||
|
best results because it will work over SSH and locally. However, there
|
||||||
|
is limited support among terminal emulators for the terminal clipboard
|
||||||
|
(which uses the OSC 52 protocol to communicate clipboard contents).
|
||||||
|
Here is a list of terminal emulators and their status:
|
||||||
|
|
||||||
|
* Kitty: supported, but only writing is enabled by default. To enable
|
||||||
|
reading, add `read-primary` and `read-clipboard` to the
|
||||||
|
`clipboard_control` option.
|
||||||
|
|
||||||
|
* iTerm2: supported, but must be enabled in
|
||||||
|
`Preferences->General-> Selection->Applications in terminal may access clipboard`.
|
||||||
|
|
||||||
|
* `st`: supported.
|
||||||
|
|
||||||
|
* `rxvt-unicode`: not natively supported, but there is a Perl extension
|
||||||
|
[here](http://anti.teamidiot.de/static/nei/*/Code/urxvt/).
|
||||||
|
|
||||||
|
* `xterm`: supported, but disabled by default. It can be enabled by putting
|
||||||
|
the following in `.Xresources` or `.Xdefaults`:
|
||||||
|
`XTerm*disallowedWindowOps: 20,21,SetXprop`.
|
||||||
|
|
||||||
|
* `gnome-terminal`: does not support OSC 52.
|
||||||
|
|
||||||
|
**Summary:** If you want copy and paste to work over SSH, then you
|
||||||
|
should set `clipboard` to `terminal`, and make sure your terminal
|
||||||
|
supports OSC 52.
|
||||||
|
|
||||||
# Pasting
|
# Pasting
|
||||||
|
|
||||||
|
## Recommendations (TL;DR)
|
||||||
|
|
||||||
|
The recommended method of pasting is the following:
|
||||||
|
|
||||||
|
* If you are not working over SSH, use the micro keybinding (Ctrl-v
|
||||||
|
by default) to perform pastes. If on Linux, install `xclip` or
|
||||||
|
`xsel` beforehand.
|
||||||
|
|
||||||
|
* If you are working over SSH, use the terminal keybinding
|
||||||
|
(Ctrl-Shift-v or Command-v) to perform pastes. If your terminal
|
||||||
|
does not support bracketed paste, when performing a paste first
|
||||||
|
enable the `paste` option, and when finished disable the option.
|
||||||
|
|
||||||
## Micro paste events
|
## Micro paste events
|
||||||
|
|
||||||
Micro is an application that runs within the terminal. This means
|
Micro is an application that runs within the terminal. This means
|
||||||
|
@ -56,20 +99,23 @@ machine's clipboard. On the other hand, the terminal keybinding
|
||||||
for paste will access your local clipboard and send the text over
|
for paste will access your local clipboard and send the text over
|
||||||
the network as a paste event, which is what you want.
|
the network as a paste event, which is what you want.
|
||||||
|
|
||||||
## Recommendations
|
# Copying
|
||||||
|
|
||||||
The recommended method of pasting is the following:
|
# Recommendations (TL;DR)
|
||||||
|
|
||||||
* If you are not working over SSH, use the micro keybinding (Ctrl-v
|
The recommended method of copying is the following:
|
||||||
by default) to perform pastes. If on Linux, install `xclip` or
|
|
||||||
`xsel` beforehand.
|
* If you are not working over SSH, use the micro keybinding (Ctrl-c by
|
||||||
|
default) to perform copies. If on Linux, install `xclip` or `xsel`
|
||||||
|
beforehand.
|
||||||
|
|
||||||
* If you are working over SSH, use the terminal keybinding
|
* If you are working over SSH, use the terminal keybinding
|
||||||
(Ctrl-Shift-v or Command-v) to perform pastes. If your terminal
|
(Ctrl-Shift-c or Command-c) to perform copies. You must first disable
|
||||||
does not support bracketed paste, when performing a paste first
|
the `mouse` option to perform a terminal selection, and you may wish
|
||||||
enable the `paste` option, and when finished disable the option.
|
to disable line numbers and diff indicators (`ruler` and `diffgutter`
|
||||||
|
options) and close other splits. This method will only be able to copy
|
||||||
# Copying
|
characters that are displayed on the screen (you will not be able to
|
||||||
|
copy more than one page's worth of characters).
|
||||||
|
|
||||||
Copying follows a similar discussion to the one above about pasting.
|
Copying follows a similar discussion to the one above about pasting.
|
||||||
The primary difference is before performing a copy, the application
|
The primary difference is before performing a copy, the application
|
||||||
|
@ -92,19 +138,3 @@ means that for copying multiple lines using the terminal selection, you
|
||||||
should first disable line numbers and diff indicators (turn off the `ruler`
|
should first disable line numbers and diff indicators (turn off the `ruler`
|
||||||
and `diffgutter` options), otherwise they might be part of your selection
|
and `diffgutter` options), otherwise they might be part of your selection
|
||||||
and copied.
|
and copied.
|
||||||
|
|
||||||
## Recommendations
|
|
||||||
|
|
||||||
The recommended method of copying is the following:
|
|
||||||
|
|
||||||
* If you are not working over SSH, use the micro keybinding (Ctrl-c by
|
|
||||||
default) to perform copies. If on Linux, install `xclip` or `xsel`
|
|
||||||
beforehand.
|
|
||||||
|
|
||||||
* If you are working over SSH, use the terminal keybinding
|
|
||||||
(Ctrl-Shift-c or Command-c) to perform copies. You must first disable
|
|
||||||
the `mouse` option to perform a terminal selection, and you may wish
|
|
||||||
to disable line numbers and diff indicators (`ruler` and `diffgutter`
|
|
||||||
options) and close other splits. This method will only be able to copy
|
|
||||||
characters that are displayed on the screen (you will not be able to
|
|
||||||
copy more than one page's worth of characters).
|
|
||||||
|
|
|
@ -54,6 +54,25 @@ Here are the available options:
|
||||||
|
|
||||||
default value: `false`
|
default value: `false`
|
||||||
|
|
||||||
|
* `clipboard`: specifies how micro should access the system clipboard.
|
||||||
|
Possible values are:
|
||||||
|
* `external`: accesses clipboard via an external tool, such as xclip/xsel
|
||||||
|
or wl-clipboard on Linux, pbcopy/pbpaste on MacOS, and system calls on
|
||||||
|
Windows. On Linux, if you do not have one of the tools installed, or if
|
||||||
|
they are not working, micro will throw an error and use an internal
|
||||||
|
clipboard.
|
||||||
|
* `terminal`: accesses the clipboard via your terminal emulator. Note that
|
||||||
|
there is limited support among terminal emulators for this feature
|
||||||
|
(called OSC 52). Terminals that are known to work are Kitty (enable
|
||||||
|
reading with `clipboard_control` setting), iTerm2 (enable in prefs),
|
||||||
|
st, rxvt-unicode and xterm if enabled (see `> help copypaste` for
|
||||||
|
details). Note that Gnome-terminal does not support this feature. With
|
||||||
|
this setting, copy-paste **will** work over ssh. See `> help copypaste`
|
||||||
|
for details.
|
||||||
|
* `internal`: micro will use an internal clipboard.
|
||||||
|
|
||||||
|
default value: `external`
|
||||||
|
|
||||||
* `colorcolumn`: if this is not set to 0, it will display a column at the
|
* `colorcolumn`: if this is not set to 0, it will display a column at the
|
||||||
specified column. This is useful if you want column 80 to be highlighted
|
specified column. This is useful if you want column 80 to be highlighted
|
||||||
special for example.
|
special for example.
|
||||||
|
|
Loading…
Reference in a new issue