diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | go.mod | 14 | ||||
| -rw-r--r-- | go.sum | 43 | ||||
| -rw-r--r-- | main.go | 297 |
4 files changed, 172 insertions, 184 deletions
@@ -14,4 +14,4 @@ # Dependency directories (remove the comment below to include it) # vendor/ -osc52 +osc @@ -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 ) @@ -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= @@ -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) + } } |
