From 6c9d06a2a0477c3a9ad1672f021dc485cf5030df Mon Sep 17 00:00:00 2001 From: Takumi Sue <23391543+mikutas@users.noreply.github.com> Date: Thu, 22 Sep 2022 04:27:42 +0900 Subject: [PATCH] Replace clipboard package (#868) (#1721) * Replace clipboard package Fixes #868 * Raise error when clipboard.Write fails * Call clipboard.Write when Init successes * Flash error rather than panic * Refactor copying into clipboard * Refactor cpCmd to remove wrappers * Use clipboardWrite instead of cpCmd --- go.mod | 5 ++++- go.sum | 10 ++++++++-- internal/view/details.go | 12 +----------- internal/view/helpers.go | 23 +++++++++++++++++++++++ internal/view/live_view.go | 12 +----------- internal/view/log.go | 11 +---------- internal/view/logger.go | 12 +----------- internal/view/table.go | 9 ++++----- 8 files changed, 43 insertions(+), 51 deletions(-) diff --git a/go.mod b/go.mod index 76fd06128d..6406f12ce4 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ replace github.com/gdamore/tcell/v2 => github.com/derailed/tcell/v2 v2.3.1-rc.2 require ( github.com/adrg/xdg v0.4.0 - github.com/atotto/clipboard v0.1.4 github.com/cenkalti/backoff v2.2.1+incompatible github.com/cenkalti/backoff/v4 v4.1.3 github.com/derailed/popeye v0.10.1 @@ -24,6 +23,7 @@ require ( github.com/sahilm/fuzzy v0.1.0 github.com/spf13/cobra v1.5.0 github.com/stretchr/testify v1.8.0 + golang.design/x/clipboard v0.6.2 golang.org/x/text v0.3.7 gopkg.in/yaml.v2 v2.4.0 helm.sh/helm/v3 v3.9.2 @@ -146,6 +146,9 @@ require ( github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect + golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect + golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554 // indirect golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect diff --git a/go.sum b/go.sum index d391ed86ad..a4b8872774 100644 --- a/go.sum +++ b/go.sum @@ -109,8 +109,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= -github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aws/aws-sdk-go v1.38.49 h1:E31vxjCe6a5I+mJLmUGaZobiWmg9KdWaud9IfceYeYQ= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= @@ -792,6 +790,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.design/x/clipboard v0.6.2 h1:a3Np4qfKnLWwfFJQhUWU3IDeRfmVuqWl+QPtP4CSYGw= +golang.design/x/clipboard v0.6.2/go.mod h1:kqBSweBP0/im4SZGGjLrppH0D400Hnfo5WbFKSNK8N4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -812,15 +812,19 @@ golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -835,6 +839,8 @@ golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554 h1:3In5TnfvnuXTF/uflgpYxSCEGP2NdYT37KsPh3VjZYU= +golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554/go.mod h1:jFTmtFYCV0MFtXBU+J5V/+5AUeVS0ON/0WkE/KSrl6E= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= diff --git a/internal/view/details.go b/internal/view/details.go index 95724c930b..fec1cc8271 100644 --- a/internal/view/details.go +++ b/internal/view/details.go @@ -5,7 +5,6 @@ import ( "fmt" "strings" - "github.com/atotto/clipboard" "github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/ui" @@ -125,7 +124,7 @@ func (d *Details) bindKeys() { tcell.KeyEnter: ui.NewSharedKeyAction("Filter", d.filterCmd, false), tcell.KeyEscape: ui.NewKeyAction("Back", d.resetCmd, false), tcell.KeyCtrlS: ui.NewKeyAction("Save", d.saveCmd, false), - ui.KeyC: ui.NewKeyAction("Copy", d.cpCmd, true), + ui.KeyC: ui.NewKeyAction("Copy", cpCmd(d.app.Flash(), d.text), true), ui.KeyF: ui.NewKeyAction("Toggle FullScreen", d.toggleFullScreenCmd, true), ui.KeyN: ui.NewKeyAction("Next Match", d.nextCmd, true), ui.KeyShiftN: ui.NewKeyAction("Prev Match", d.prevCmd, true), @@ -292,15 +291,6 @@ func (d *Details) saveCmd(evt *tcell.EventKey) *tcell.EventKey { return nil } -func (d *Details) cpCmd(evt *tcell.EventKey) *tcell.EventKey { - d.app.Flash().Info("Content copied to clipboard...") - if err := clipboard.WriteAll(d.text.GetText(true)); err != nil { - d.app.Flash().Err(err) - } - - return nil -} - func (d *Details) updateTitle() { if d.title == "" { return diff --git a/internal/view/helpers.go b/internal/view/helpers.go index 544b4d98ce..6bcf4bad62 100644 --- a/internal/view/helpers.go +++ b/internal/view/helpers.go @@ -13,8 +13,10 @@ import ( "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/render" "github.com/derailed/k9s/internal/ui" + "github.com/derailed/tview" "github.com/gdamore/tcell/v2" "github.com/rs/zerolog/log" + "golang.design/x/clipboard" ) func parsePFAnn(s string) (string, string, bool) { @@ -214,3 +216,24 @@ func decorateCpuMemHeaderRows(app *App, data *render.TableData) *render.TableDat return data } + +func clipboardWrite(text string) error { + if err := clipboard.Init(); err != nil { + return err + } + if clipboard.Write(clipboard.FmtText, []byte(text)) == nil { + return errors.New("unable to write to clipboard") + } + return nil +} + +func cpCmd(flash *model.Flash, v *tview.TextView) func(*tcell.EventKey) *tcell.EventKey { + return func(evt *tcell.EventKey) *tcell.EventKey { + if err := clipboardWrite(v.GetText(true)); err != nil { + flash.Err(err) + return evt + } + flash.Info("Content copied to clipboard...") + return nil + } +} diff --git a/internal/view/live_view.go b/internal/view/live_view.go index 967be431c7..ac81e39c50 100644 --- a/internal/view/live_view.go +++ b/internal/view/live_view.go @@ -6,7 +6,6 @@ import ( "strconv" "strings" - "github.com/atotto/clipboard" "github.com/derailed/k9s/internal" "github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/model" @@ -136,7 +135,7 @@ func (v *LiveView) bindKeys() { tcell.KeyEnter: ui.NewSharedKeyAction("Filter", v.filterCmd, false), tcell.KeyEscape: ui.NewKeyAction("Back", v.resetCmd, false), tcell.KeyCtrlS: ui.NewKeyAction("Save", v.saveCmd, false), - ui.KeyC: ui.NewKeyAction("Copy", v.cpCmd, true), + ui.KeyC: ui.NewKeyAction("Copy", cpCmd(v.app.Flash(), v.text), true), ui.KeyF: ui.NewKeyAction("Toggle FullScreen", v.toggleFullScreenCmd, true), ui.KeyR: ui.NewKeyAction("Toggle Auto-Refresh", v.toggleRefreshCmd, true), ui.KeyN: ui.NewKeyAction("Next Match", v.nextCmd, true), @@ -341,15 +340,6 @@ func (v *LiveView) saveCmd(evt *tcell.EventKey) *tcell.EventKey { return nil } -func (v *LiveView) cpCmd(evt *tcell.EventKey) *tcell.EventKey { - v.app.Flash().Info("Content copied to clipboard...") - if err := clipboard.WriteAll(v.text.GetText(true)); err != nil { - v.app.Flash().Err(err) - } - - return nil -} - func (v *LiveView) updateTitle() { if v.title == "" { return diff --git a/internal/view/log.go b/internal/view/log.go index b030220297..5406232732 100644 --- a/internal/view/log.go +++ b/internal/view/log.go @@ -10,7 +10,6 @@ import ( "sync" "time" - "github.com/atotto/clipboard" "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/color" "github.com/derailed/k9s/internal/config" @@ -252,7 +251,7 @@ func (l *Log) bindKeys() { ui.KeyT: ui.NewKeyAction("Toggle Timestamp", l.toggleTimestampCmd, true), ui.KeyW: ui.NewKeyAction("Toggle Wrap", l.toggleTextWrapCmd, true), tcell.KeyCtrlS: ui.NewKeyAction("Save", l.SaveCmd, true), - ui.KeyC: ui.NewKeyAction("Copy", l.cpCmd, true), + ui.KeyC: ui.NewKeyAction("Copy", cpCmd(l.app.Flash(), l.logs.TextView), true), }) if l.model.HasDefaultContainer() { l.logs.Actions().Set(ui.KeyActions{ @@ -406,14 +405,6 @@ func (l *Log) SaveCmd(*tcell.EventKey) *tcell.EventKey { return nil } -func (l *Log) cpCmd(*tcell.EventKey) *tcell.EventKey { - l.app.Flash().Info("Content copied to clipboard...") - if err := clipboard.WriteAll(l.logs.GetText(true)); err != nil { - l.app.Flash().Err(err) - } - return nil -} - func ensureDir(dir string) error { return os.MkdirAll(dir, 0744) } diff --git a/internal/view/logger.go b/internal/view/logger.go index 4f977bb201..4d1dea4fc7 100644 --- a/internal/view/logger.go +++ b/internal/view/logger.go @@ -3,7 +3,6 @@ package view import ( "context" - "github.com/atotto/clipboard" "github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/ui" @@ -70,7 +69,7 @@ func (l *Logger) bindKeys() { l.actions.Set(ui.KeyActions{ tcell.KeyEscape: ui.NewKeyAction("Back", l.resetCmd, false), tcell.KeyCtrlS: ui.NewKeyAction("Save", l.saveCmd, false), - ui.KeyC: ui.NewKeyAction("Copy", l.cpCmd, true), + ui.KeyC: ui.NewKeyAction("Copy", cpCmd(l.app.Flash(), l.TextView), true), ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", l.activateCmd, false), tcell.KeyDelete: ui.NewSharedKeyAction("Erase", l.eraseCmd, false), }) @@ -160,12 +159,3 @@ func (l *Logger) saveCmd(evt *tcell.EventKey) *tcell.EventKey { return nil } - -func (l *Logger) cpCmd(evt *tcell.EventKey) *tcell.EventKey { - l.app.Flash().Info("Content copied to clipboard...") - if err := clipboard.WriteAll(l.GetText(true)); err != nil { - l.app.Flash().Err(err) - } - - return nil -} diff --git a/internal/view/table.go b/internal/view/table.go index 6a415a0b63..b3ef4b255e 100644 --- a/internal/view/table.go +++ b/internal/view/table.go @@ -5,7 +5,6 @@ import ( "strings" "time" - "github.com/atotto/clipboard" "github.com/derailed/k9s/internal" "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/model" @@ -207,12 +206,12 @@ func (t *Table) cpCmd(evt *tcell.EventKey) *tcell.EventKey { if path == "" { return evt } - _, n := client.Namespaced(path) - log.Debug().Msgf("Copied selection to clipboard %q", n) - t.app.Flash().Info("Current selection copied to clipboard...") - if err := clipboard.WriteAll(n); err != nil { + err := clipboardWrite(n) + if err != nil { t.app.Flash().Err(err) + } else { + t.app.Flash().Info("Current selection copied to clipboard...") } return nil