commit 9a32ec335a1d9932469be2cbb6d6e114c881d464
parent c9f3e5560d737fc2159de8adac6dd843313b4790
Author: Sean Enck <sean@ttypty.com>
Date: Sat, 16 Jul 2022 11:43:37 -0400
cleaning up clipboard
Diffstat:
3 files changed, 94 insertions(+), 21 deletions(-)
diff --git a/cmd/lb/main.go b/cmd/lb/main.go
@@ -251,15 +251,12 @@ func main() {
if err != nil {
misc.Die("unable to get paste command", err)
}
- var args []string
- if len(clipboard.Paste) > 1 {
- args = clipboard.Paste[1:]
- }
+ pCmd, pArgs := clipboard.Args(false)
val = strings.TrimSpace(val)
- for idx < clip.MaxTime {
+ for idx < clipboard.MaxTime {
idx++
time.Sleep(1 * time.Second)
- out, err := exec.Command(clipboard.Paste[0], args...).Output()
+ out, err := exec.Command(pCmd, pArgs...).Output()
if err != nil {
continue
}
diff --git a/internal/clip/clipboard.go b/internal/clip/clipboard.go
@@ -6,14 +6,14 @@ import (
"os"
"os/exec"
"path/filepath"
+ "strconv"
"strings"
"github.com/enckse/lockbox/internal/misc"
)
const (
- // MaxTime is the max time to let something stay in the clipboard.
- MaxTime = 45
+ maxTime = 45
pbClipMode = "pb"
waylandClipMode = "wayland"
xClipMode = "x11"
@@ -23,8 +23,9 @@ const (
type (
// Commands represent system clipboard operations.
Commands struct {
- Copy []string
- Paste []string
+ copying []string
+ pasting []string
+ MaxTime int
}
)
@@ -58,33 +59,64 @@ func NewCommands() (Commands, error) {
return Commands{}, errors.New("unable to detect clipboard mode")
}
}
+ max := maxTime
+ useMax := os.Getenv("LOCKBOX_CLIPMAX")
+ if useMax != "" {
+ i, err := strconv.Atoi(useMax)
+ if err != nil {
+ return Commands{}, err
+ }
+ if i < 1 {
+ return Commands{}, errors.New("clipboard max time must be greater than 0")
+ }
+ max = i
+ }
+ var copying []string
+ var pasting []string
switch env {
case pbClipMode:
- return Commands{Copy: []string{"pbcopy"}, Paste: []string{"pbpaste"}}, nil
+ copying = []string{"pbcopy"}
+ pasting = []string{"pbpaste"}
case xClipMode:
- return Commands{Copy: []string{"xclip"}, Paste: []string{"xclip", "-o"}}, nil
+ copying = []string{"xclip"}
+ pasting = []string{"xclip", "-o"}
case waylandClipMode:
- return Commands{Copy: []string{"wl-copy"}, Paste: []string{"wl-paste"}}, nil
+ copying = []string{"wl-copy"}
+ pasting = []string{"wl-paste"}
case wslMode:
- return Commands{Copy: []string{"clip.exe"}, Paste: []string{"powershell.exe", "-command", "Get-Clipboard"}}, nil
+ copying = []string{"clip.exe"}
+ pasting = []string{"powershell.exe", "-command", "Get-Clipboard"}
default:
return Commands{}, errors.New("clipboard is unavailable")
}
+ return Commands{copying: copying, pasting: pasting, MaxTime: max}, nil
}
// CopyTo will copy to clipboard, if non-empty will clear later.
func (c Commands) CopyTo(value, executable string) {
- var args []string
- if len(c.Copy) > 1 {
- args = c.Copy[1:]
- }
- pipeTo(c.Copy[0], value, true, args...)
+ cmd, args := c.Args(true)
+ pipeTo(cmd, value, true, args...)
if value != "" {
- fmt.Printf("clipboard will clear in %d seconds\n", MaxTime)
+ fmt.Printf("clipboard will clear in %d seconds\n", c.MaxTime)
pipeTo(filepath.Join(filepath.Dir(executable), "lb"), value, false, "clear")
}
}
+// Args returns clipboard args for execution.
+func (c Commands) Args(copying bool) (string, []string) {
+ var using []string
+ if copying {
+ using = c.copying
+ } else {
+ using = c.pasting
+ }
+ var args []string
+ if len(using) > 1 {
+ args = using[1:]
+ }
+ return using[0], args
+}
+
func pipeTo(command, value string, wait bool, args ...string) {
cmd := exec.Command(command, args...)
stdin, err := cmd.StdinPipe()
diff --git a/internal/clip/clipboard_test.go b/internal/clip/clipboard_test.go
@@ -6,6 +6,7 @@ import (
)
func TestNoClipboard(t *testing.T) {
+ os.Setenv("LOCKBOX_CLIPMAX", "")
os.Setenv("LOCKBOX_CLIPMODE", "off")
_, err := NewCommands()
if err == nil || err.Error() != "clipboard is unavailable" {
@@ -13,15 +14,58 @@ func TestNoClipboard(t *testing.T) {
}
}
+func TestMaxTime(t *testing.T) {
+ os.Setenv("LOCKBOX_CLIPMODE", pbClipMode)
+ os.Setenv("LOCKBOX_CLIPMAX", "")
+ c, err := NewCommands()
+ if err != nil {
+ t.Errorf("invalid clipboard: %v", err)
+ }
+ if c.MaxTime != 45 {
+ t.Error("invalid default")
+ }
+ os.Setenv("LOCKBOX_CLIPMAX", "1")
+ c, err = NewCommands()
+ if err != nil {
+ t.Errorf("invalid clipboard: %v", err)
+ }
+ if c.MaxTime != 1 {
+ t.Error("invalid default")
+ }
+ os.Setenv("LOCKBOX_CLIPMAX", "-1")
+ _, err = NewCommands()
+ if err == nil || err.Error() != "clipboard max time must be greater than 0" {
+ t.Errorf("invalid max time error: %v", err)
+ }
+ os.Setenv("LOCKBOX_CLIPMAX", "$&(+")
+ _, err = NewCommands()
+ if err == nil || err.Error() != "strconv.Atoi: parsing \"$&(+\": invalid syntax" {
+ t.Errorf("invalid max time error: %v", err)
+ }
+}
+
func TestClipboardInstances(t *testing.T) {
+ os.Setenv("LOCKBOX_CLIPMAX", "")
for _, item := range []string{pbClipMode, xClipMode, waylandClipMode, wslMode} {
os.Setenv("LOCKBOX_CLIPMODE", item)
c, err := NewCommands()
if err != nil {
t.Errorf("invalid clipboard: %v", err)
}
- if len(c.Copy) == 0 || len(c.Paste) == 0 {
+ if len(c.copying) == 0 || len(c.pasting) == 0 {
t.Error("invalid command retrieved")
}
}
}
+
+func TestArgs(t *testing.T) {
+ c := Commands{copying: []string{"cp"}, pasting: []string{"paste", "with", "args"}}
+ cmd, args := c.Args(true)
+ if cmd != "cp" || len(args) != 0 {
+ t.Error("invalid parse")
+ }
+ cmd, args = c.Args(false)
+ if cmd != "paste" || len(args) != 2 || args[0] != "with" || args[1] != "args" {
+ t.Error("invalid parse")
+ }
+}