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}