1// Copyright 2013 @atotto. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// +build freebsd linux netbsd openbsd solaris dragonfly 6 7package clipboard 8 9import ( 10 "errors" 11 "os" 12 "os/exec" 13) 14 15const ( 16 xsel = "xsel" 17 xclip = "xclip" 18 powershellExe = "powershell.exe" 19 clipExe = "clip.exe" 20 wlcopy = "wl-copy" 21 wlpaste = "wl-paste" 22 termuxClipboardGet = "termux-clipboard-get" 23 termuxClipboardSet = "termux-clipboard-set" 24) 25 26var ( 27 Primary bool 28 trimDos bool 29 30 pasteCmdArgs []string 31 copyCmdArgs []string 32 33 xselPasteArgs = []string{xsel, "--output", "--clipboard"} 34 xselCopyArgs = []string{xsel, "--input", "--clipboard"} 35 36 xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"} 37 xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"} 38 39 powershellExePasteArgs = []string{powershellExe, "Get-Clipboard"} 40 clipExeCopyArgs = []string{clipExe} 41 42 wlpasteArgs = []string{wlpaste, "--no-newline"} 43 wlcopyArgs = []string{wlcopy} 44 45 termuxPasteArgs = []string{termuxClipboardGet} 46 termuxCopyArgs = []string{termuxClipboardSet} 47 48 missingCommands = errors.New("No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.") 49) 50 51func init() { 52 if os.Getenv("WAYLAND_DISPLAY") != "" { 53 pasteCmdArgs = wlpasteArgs 54 copyCmdArgs = wlcopyArgs 55 56 if _, err := exec.LookPath(wlcopy); err == nil { 57 if _, err := exec.LookPath(wlpaste); err == nil { 58 return 59 } 60 } 61 } 62 63 pasteCmdArgs = xclipPasteArgs 64 copyCmdArgs = xclipCopyArgs 65 66 if _, err := exec.LookPath(xclip); err == nil { 67 return 68 } 69 70 pasteCmdArgs = xselPasteArgs 71 copyCmdArgs = xselCopyArgs 72 73 if _, err := exec.LookPath(xsel); err == nil { 74 return 75 } 76 77 pasteCmdArgs = termuxPasteArgs 78 copyCmdArgs = termuxCopyArgs 79 80 if _, err := exec.LookPath(termuxClipboardSet); err == nil { 81 if _, err := exec.LookPath(termuxClipboardGet); err == nil { 82 return 83 } 84 } 85 86 pasteCmdArgs = powershellExePasteArgs 87 copyCmdArgs = clipExeCopyArgs 88 trimDos = true 89 90 if _, err := exec.LookPath(clipExe); err == nil { 91 if _, err := exec.LookPath(powershellExe); err == nil { 92 return 93 } 94 } 95 96 Unsupported = true 97} 98 99func getPasteCommand() *exec.Cmd { 100 if Primary { 101 pasteCmdArgs = pasteCmdArgs[:1] 102 } 103 return exec.Command(pasteCmdArgs[0], pasteCmdArgs[1:]...) 104} 105 106func getCopyCommand() *exec.Cmd { 107 if Primary { 108 copyCmdArgs = copyCmdArgs[:1] 109 } 110 return exec.Command(copyCmdArgs[0], copyCmdArgs[1:]...) 111} 112 113func readAll() (string, error) { 114 if Unsupported { 115 return "", missingCommands 116 } 117 pasteCmd := getPasteCommand() 118 out, err := pasteCmd.Output() 119 if err != nil { 120 return "", err 121 } 122 result := string(out) 123 if trimDos && len(result) > 1 { 124 result = result[:len(result)-2] 125 } 126 return result, nil 127} 128 129func writeAll(text string) error { 130 if Unsupported { 131 return missingCommands 132 } 133 copyCmd := getCopyCommand() 134 in, err := copyCmd.StdinPipe() 135 if err != nil { 136 return err 137 } 138 139 if err := copyCmd.Start(); err != nil { 140 return err 141 } 142 if _, err := in.Write([]byte(text)); err != nil { 143 return err 144 } 145 if err := in.Close(); err != nil { 146 return err 147 } 148 return copyCmd.Wait() 149} 150