summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortheimpostor <sahirhoda@gmail.com>2023-08-03 08:28:41 -0500
committertheimpostor <sahirhoda@gmail.com>2023-08-03 08:28:41 -0500
commit2d684e8e11525641c3db594b317b10faa2daa437 (patch)
tree88cfb83e1fa34062ec315b96ba0626915950275d
parenta51cea32f79859f6cf33bd6a45737a6019aa4ef9 (diff)
Rename module to osc, and use subcommands via spf13/cobra
-rw-r--r--.gitignore2
-rw-r--r--go.mod14
-rw-r--r--go.sum43
-rw-r--r--main.go297
4 files changed, 172 insertions, 184 deletions
diff --git a/.gitignore b/.gitignore
index 4e4c367..1258998 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,4 @@
# Dependency directories (remove the comment below to include it)
# vendor/
-osc52
+osc
diff --git a/go.mod b/go.mod
index 17ba0a7..a939270 100644
--- a/go.mod
+++ b/go.mod
@@ -1,20 +1,22 @@
-module github.com/theimpostor/osc52
+module github.com/theimpostor/osc
-go 1.17
+go 1.20
require (
github.com/gdamore/tcell/v2 v2.6.0
- golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
- golang.org/x/sys v0.10.0 // indirect
+ github.com/jba/slog v0.0.0-20230720141417-43400bf08a38
+ github.com/spf13/cobra v1.7.0
+ golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b
)
-require github.com/jba/slog v0.0.0-20230720141417-43400bf08a38
-
require (
github.com/gdamore/encoding v1.0.0 // indirect
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
+ golang.org/x/sys v0.10.0 // indirect
golang.org/x/term v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
)
diff --git a/go.sum b/go.sum
index d0b31cb..89d519d 100644
--- a/go.sum
+++ b/go.sum
@@ -1,16 +1,10 @@
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg=
github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y=
-github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
-github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
-github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jba/slog v0.0.0-20230720141417-43400bf08a38 h1:Pc2El2u3jtQE4+SDrDRAwkrKW2YtNeYk071bWAUvGuI=
github.com/jba/slog v0.0.0-20230720141417-43400bf08a38/go.mod h1:R9u+1Qbl7LcDnJaFNIPer+AJa3yK9eZ8SQUE4waKFiw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
@@ -18,65 +12,48 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
+github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI=
-go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
+golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI=
+golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/main.go b/main.go
index f7161a5..85ae9d0 100644
--- a/main.go
+++ b/main.go
@@ -3,7 +3,6 @@ package main
import (
"bufio"
"encoding/base64"
- "flag"
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/jba/slog/handlers/loghandler"
@@ -13,12 +12,16 @@ import (
"os"
"strings"
"time"
+
+ "github.com/spf13/cobra"
)
var (
- oscOpen string = "\x1b]52;c;"
- oscClose string = "\a"
- isScreen bool
+ oscOpen string = "\x1b]52;c;"
+ oscClose string = "\a"
+ isScreen bool
+ verboseFlag bool
+ logfileFlag string
)
func encode(fname string, encoder io.WriteCloser) {
@@ -54,44 +57,8 @@ func closetty(tty tcell.Tty) {
tty.Close()
}
-func _main() int {
- var fnames []string
+func initLogging() {
var err error
- var exitCode int
-
- flag.Usage = func() {
- template := `Reads or writes the system clipboard using the ANSI OSC52 escape sequence.
-
-Usage:
-
-COPY mode (default):
-
- %s [file1 [...fileN]]
-
-With no arguments, will read from stdin.
-
-PASTE mode:
-
- %s --paste
-
-Outputs clipboard contents to stdout.
-
-Options:
-`
- fmt.Fprintf(flag.CommandLine.Output(), template, os.Args[0], os.Args[0])
- flag.PrintDefaults()
- }
-
- var pasteFlag bool
- var verboseFlag bool
- var logfileFlag string
- flag.BoolVar(&pasteFlag, "paste", pasteFlag, "paste operation")
- flag.BoolVar(&verboseFlag, "verbose", verboseFlag, "verbose logging")
- flag.BoolVar(&verboseFlag, "v", verboseFlag, "verbose logging")
- flag.StringVar(&logfileFlag, "logFile", logfileFlag, "redirect logs to file")
-
- flag.Parse()
-
logLevel := &slog.LevelVar{} // INFO
logOutput := os.Stdout
@@ -113,7 +80,9 @@ Options:
slog.SetDefault(logger)
slog.Debug("logging started")
+}
+func identifyTerm() {
if ti, err := tcell.LookupTerminfo(os.Getenv("TERM")); err != nil {
slog.Error(fmt.Sprintf("Failed to lookup terminfo: %v", err))
} else {
@@ -128,129 +97,169 @@ Options:
oscOpen = "\x1bP" + oscOpen
oscClose = oscClose + "\x1b\\"
}
+}
+
+func copy(fnames []string) error {
+ // copy
+ if len(fnames) == 0 {
+ fnames = []string{"-"}
+ }
- if !pasteFlag {
- // copy
- if len(flag.Args()) > 0 {
- fnames = flag.Args()
- } else {
- fnames = []string{"-"}
+ slog.Debug("Beginning osc52 copy operation")
+ err := func() error {
+ tty, err := opentty()
+ if err != nil {
+ slog.Error(fmt.Sprintf("opentty: %v", err))
+ return err
}
+ defer closetty(tty)
- slog.Debug("Beginning osc52 copy operation")
- func() {
- tty, err := opentty()
- if err != nil {
- slog.Error(fmt.Sprintf("opentty: %v", err))
- exitCode = 1
- return
- }
- defer closetty(tty)
+ // Open buffered output, using default max OSC52 length as buffer size
+ // TODO limit size
+ out := bufio.NewWriterSize(tty, 1000000)
- // Open buffered output, using default max OSC52 length as buffer size
- // TODO limit size
- out := bufio.NewWriterSize(tty, 1000000)
+ // Start OSC52
+ fmt.Fprint(out, oscOpen)
- // Start OSC52
- fmt.Fprint(out, oscOpen)
+ b64 := base64.NewEncoder(base64.StdEncoding, out)
+ for _, fname := range fnames {
+ encode(fname, b64)
+ }
+ b64.Close()
- b64 := base64.NewEncoder(base64.StdEncoding, out)
- for _, fname := range fnames {
- encode(fname, b64)
- }
- b64.Close()
+ // End OSC52
+ fmt.Fprint(out, oscClose)
- // End OSC52
- fmt.Fprint(out, oscClose)
+ out.Flush()
+ return nil
+ }()
+ slog.Debug("Ended osc52")
+ return err
+}
- out.Flush()
- }()
- slog.Debug("Ended osc52")
- } else {
- // paste
-
- slog.Debug("Beginning osc52 paste operation")
- data := func() []byte {
- tty, err := opentty()
- if err != nil {
- slog.Error(fmt.Sprintf("opentty: %v", err))
- exitCode = 1
- return nil
+func paste() error {
+ slog.Debug("Beginning osc52 paste operation")
+ if data, err := func() ([]byte, error) {
+ tty, err := opentty()
+ if err != nil {
+ slog.Error(fmt.Sprintf("opentty: %v", err))
+ return nil, err
+ }
+ defer closetty(tty)
+
+ // Start OSC52
+ fmt.Fprint(tty, oscOpen+"?"+oscClose)
+
+ ttyReader := bufio.NewReader(tty)
+ buf := make([]byte, 0, 1024)
+
+ // time out intial read in 100 milliseconds
+ readChan := make(chan byte, 1)
+ defer close(readChan)
+ go func() {
+ if b, e := ttyReader.ReadByte(); e != nil {
+ slog.Debug(fmt.Sprintf("Initial ReadByte error: %v", e))
+ } else {
+ readChan <- b
}
- defer closetty(tty)
-
- // Start OSC52
- fmt.Fprint(tty, oscOpen+"?"+oscClose)
-
- ttyReader := bufio.NewReader(tty)
- buf := make([]byte, 0, 1024)
-
- // time out intial read in 100 milliseconds
- readChan := make(chan byte, 1)
- defer close(readChan)
- go func() {
- if b, e := ttyReader.ReadByte(); e != nil {
- slog.Debug(fmt.Sprintf("Initial ReadByte error: %v", e))
- } else {
- readChan <- b
+ }()
+ select {
+ case b := <-readChan:
+ buf = append(buf, b)
+ case <-time.After(100 * time.Millisecond):
+ slog.Debug("tty read timeout")
+ return nil, fmt.Errorf("tty read timeout")
+ }
+
+ for {
+ if b, e := ttyReader.ReadByte(); e != nil {
+ slog.Error(fmt.Sprintf("ReadByte: %v", e))
+ return nil, e
+ } else {
+ slog.Debug(fmt.Sprintf("Read: %x '%s'", b, string(b)))
+ // Terminator might be BEL (\a) or ESC-backslash (\x1b\\)
+ if b == '\a' {
+ break
}
- }()
- select {
- case b := <-readChan:
buf = append(buf, b)
- case <-time.After(100 * time.Millisecond):
- slog.Debug("tty read timeout")
- exitCode = 1
- return nil
- }
-
- for {
- if b, e := ttyReader.ReadByte(); e != nil {
- slog.Error(fmt.Sprintf("ReadByte: %v", e))
- exitCode = 1
- return nil
- } else {
- slog.Debug(fmt.Sprintf("Read: %x '%s'", b, string(b)))
- // Terminator might be BEL (\a) or ESC-backslash (\x1b\\)
- if b == '\a' {
- break
- }
- buf = append(buf, b)
- // Skip initial 7 bytes of response
- if len(buf) > 9 && buf[len(buf)-2] == '\x1b' && buf[len(buf)-1] == '\\' {
- buf = buf[:len(buf)-2]
- break
- }
+ // Skip initial 7 bytes of response
+ if len(buf) > 9 && buf[len(buf)-2] == '\x1b' && buf[len(buf)-1] == '\\' {
+ buf = buf[:len(buf)-2]
+ break
}
}
+ }
- slog.Debug(fmt.Sprintf("buf[:7]: %q", buf[:7]))
- buf = buf[7:]
-
- decodedBuf := make([]byte, base64.StdEncoding.DecodedLen(len(buf)))
- n, err := base64.StdEncoding.Decode(decodedBuf, []byte(buf))
- if err != nil {
- slog.Error(fmt.Sprintf("decode error: %v", err))
- exitCode = 1
- return nil
- }
- decodedBuf = decodedBuf[:n]
+ slog.Debug(fmt.Sprintf("buf[:7]: %q", buf[:7]))
+ buf = buf[7:]
- return decodedBuf
- }()
+ decodedBuf := make([]byte, base64.StdEncoding.DecodedLen(len(buf)))
+ n, err := base64.StdEncoding.Decode(decodedBuf, []byte(buf))
+ if err != nil {
+ slog.Error(fmt.Sprintf("decode error: %v", err))
+ return nil, err
+ }
+ decodedBuf = decodedBuf[:n]
- if data != nil {
- if _, err := os.Stdout.Write(data); err != nil {
- slog.Error(fmt.Sprintf("Error writing to stdout: %v", err))
- exitCode = 1
- }
+ return decodedBuf, nil
+ }(); err != nil {
+ return err
+ } else {
+ if _, err = os.Stdout.Write(data); err != nil {
+ slog.Error(fmt.Sprintf("Error writing to stdout: %v", err))
+ return err
}
- slog.Debug("Ended osc52")
}
+ slog.Debug("Ended osc52")
- return exitCode
+ return nil
+}
+
+var copyCmd = &cobra.Command{
+ Use: "copy",
+ Short: "Copies input to the system clipboard",
+ Long: `Copies input to the system clipboard. Usage:
+
+osc copy [file1 [...fileN]]
+
+With no arguments, will read from stdin.`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ initLogging()
+ identifyTerm()
+ return copy(args)
+ },
+}
+
+var pasteCmd = &cobra.Command{
+ Use: "paste",
+ Short: "Outputs system clipboard contents to stdout",
+ Long: `Outputs system clipboard contents to stdout. Usage:
+
+osc paste`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ initLogging()
+ identifyTerm()
+ return paste()
+ },
+}
+
+var rootCmd = &cobra.Command{
+ Use: "osc",
+ Short: "Reads or writes the system clipboard using the ANSI OSC52 escape sequence",
+ Long: `Reads or writes the system clipboard using the ANSI OSC52 escape sequence.`,
+}
+
+func init() {
+ rootCmd.PersistentFlags().BoolVarP(&verboseFlag, "verbose", "v", false, "verbose logging")
+ rootCmd.PersistentFlags().StringVarP(&logfileFlag, "log", "l", "", "write logs to file")
+
+ rootCmd.AddCommand(copyCmd)
+ rootCmd.AddCommand(pasteCmd)
}
func main() {
- os.Exit(_main())
+ err := rootCmd.Execute()
+ if err != nil {
+ os.Exit(1)
+ }
}