├── .github └── dependabot.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── cmd ├── osc-copy │ └── main.go └── osc-paste │ └── main.go ├── flake.lock ├── flake.nix ├── go.mod └── go.sum /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gomod" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "monthly" 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /osc-copy 2 | /osc-paste 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [0.5.0] - XXXX-XX-XX 9 | ### Changed 10 | 11 | - Rewrite in Go and use a OSC52 library as a backend. 12 | - Real clipboard clear for system and primary clipboard is supported. 13 | - `-n`/`--trim-newline` became `-t`/`--trim`. 14 | - Multiplexer bypass is disabled by default and can be enabled with `--bypass`. `--no-bypass` is gone. 15 | In `tmux` there is the option `set-clipboard` if accessing the clipboard is desired. 16 | 17 | ### Fixed 18 | 19 | - The Go rewrite addresses some cross-plattform problems, see #46. 20 | 21 | 22 | ## [0.4.1] - 2022-09-12 23 | ### Changed 24 | 25 | - Changed the default of bypassing to `--no-bypass`, since tmux has disabled this option by default. It can be enabled with `allow-passthrough`. 26 | 27 | ## [0.4.0] - 2022-05-08 28 | ### Added 29 | 30 | - Automatic linter checks via Github Actions 31 | - Automatic deployment to PyPi via Github Actions 32 | 33 | ### Fixed 34 | 35 | - Correctly detect the end of OSC52 response and increase buffersize. 36 | 37 | ## [0.3.0] - 2022-01-14 38 | #### Added 39 | 40 | - support for GNU screen 41 | 42 | ### Changed 43 | 44 | - poetry as a build system 45 | 46 | ### Fixed 47 | 48 | - small bugfixes according to ctrl+c 49 | 50 | ## [0.2.1] - 2021-10-25 51 | ### Fixed 52 | 53 | - Remove debugging invocation of the paste entry point 54 | - Print the decoded data instead 55 | 56 | ## [0.2.0] - 2021-10-25 57 | ### Added 58 | 59 | - Add --direct flag to bypass tmux 60 | 61 | ### Fixed 62 | 63 | - Implement OSC52 correcly for non tmux scenarios 64 | 65 | ## [0.1.0] - 2021-10-24 66 | 67 | Initial Release 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Stefan Tatschner 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Stefan Tatschner 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | GO ?= go 6 | 7 | .PHONY: build 8 | build: osc-copy osc-paste 9 | 10 | .PHONY: osc-copy 11 | osc-copy: 12 | $(GO) build $(GOFLAGS) -o $@ ./cmd/$@ 13 | 14 | .PHONY: osc-paste 15 | osc-paste: 16 | $(GO) build $(GOFLAGS) -o $@ ./cmd/$@ 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # oscclip 2 | 3 | **There is a better maintained alternative available; just use this instead: https://github.com/theimpostor/osc** 4 | 5 | [![Packaging status](https://repology.org/badge/vertical-allrepos/oscclip.svg)](https://repology.org/project/oscclip/versions) 6 | 7 | `oscclip` is a utility which utilizes the system clipboard via OSC52 escape sequences. 8 | Using these sequences, the system clipboard is accessible via SSH as well. 9 | Terminal multiplexers, such as `tmux` and `screen` are supported. 10 | 11 | ## Build 12 | 13 | ``` 14 | $ make 15 | ``` 16 | 17 | ## Examples 18 | 19 | **Setting the clipboard** 20 | 21 | ``` 22 | $ echo "Foo" | osc-copy 23 | ``` 24 | 25 | **Setting the clipboard and bypass terminal multiplexers** 26 | 27 | ``` 28 | $ echo "Foo" | osc-copy --bypass 29 | ``` 30 | 31 | **Reading the clipboard** 32 | 33 | ``` 34 | $ osc-paste 35 | Foo 36 | ``` 37 | 38 | ## Tested Terminals 39 | 40 | * [alacritty](https://github.com/alacritty/alacritty) 41 | * [foot](https://codeberg.org/dnkl/foot) 42 | 43 | For a list of terminals that support OSC52, see [this table](https://github.com/ojroques/vim-oscyank#vim-oscyank). 44 | 45 | ## Caveats 46 | 47 | ### tmux 48 | 49 | There is a [bug](https://github.com/tmux/tmux/pull/2942) in `tmux` 50 | Due to this `osc-paste` does not work with `tmux < 3.3` running in `foot`. 51 | 52 | In order to make `--bypass` work, `allow-passthrough` must be enabled. 53 | Check the manpage of `tmux`. 54 | `osc-copy` issues a warning to `stderr` when this option is not set and `--bypass` is present. 55 | 56 | In order to let `tmux` set the system clipboard, the option `set-clipboard` must be enabled. 57 | 58 | ## Installation 59 | 60 | **Arch Linux** 61 | 62 | ``` 63 | $ paru -S oscclip 64 | ``` 65 | 66 | **NixOS** 67 | 68 | ``` 69 | $ nix-shell -p oscclip 70 | ``` 71 | -------------------------------------------------------------------------------- /cmd/osc-copy/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "runtime/debug" 8 | "strings" 9 | 10 | "github.com/alecthomas/kong" 11 | "github.com/aymanbagabas/go-osc52/v2" 12 | ) 13 | 14 | func die(msg string, code int) { 15 | fmt.Fprintln(os.Stderr, msg) 16 | os.Exit(1) 17 | } 18 | 19 | type cli struct { 20 | Text string `kong:"arg,default='-',help='Text to copy, - means stdin (default)'"` 21 | Bypass bool `kong:"help='Bypass terminal multiplexers if present'"` 22 | Clear bool `kong:"short='c',help='Clear clipboard and exit'"` 23 | Trim bool `kong:"short='t',help='Trim whitespace of input'"` 24 | Primary bool `kong:"short='p',help='Use the primary X11 clipboard'"` 25 | Version bool `kong:"help='Print version information and exit'"` 26 | } 27 | 28 | func main() { 29 | var args cli 30 | kong.Parse(&args) 31 | 32 | if args.Clear { 33 | seq := osc52.Clear() 34 | if args.Primary { 35 | seq = seq.Primary() 36 | } 37 | 38 | _, err := seq.WriteTo(os.Stderr) 39 | if err != nil { 40 | die(err.Error(), 1) 41 | } 42 | os.Exit(0) 43 | } 44 | 45 | if args.Version { 46 | buildInfo, ok := debug.ReadBuildInfo() 47 | if ok { 48 | fmt.Println(strings.TrimSpace(buildInfo.String())) 49 | } else { 50 | fmt.Println("unknown") 51 | } 52 | 53 | os.Exit(0) 54 | } 55 | 56 | var ( 57 | seq osc52.Sequence 58 | text = args.Text 59 | ) 60 | 61 | if text == "-" { 62 | t, err := io.ReadAll(os.Stdin) 63 | if err != nil { 64 | die(err.Error(), 1) 65 | } 66 | 67 | text = string(t) 68 | } 69 | 70 | if args.Trim { 71 | text = strings.TrimSpace(text) 72 | } 73 | 74 | seq = osc52.New(text) 75 | if args.Primary { 76 | seq = seq.Primary() 77 | } 78 | 79 | if args.Bypass { 80 | if _, ok := os.LookupEnv("TMUX"); ok { 81 | seq = osc52.New(text).Tmux() 82 | } else if _, ok := os.LookupEnv("STY"); ok { 83 | seq = osc52.New(text).Screen() 84 | } 85 | } 86 | 87 | _, err := seq.WriteTo(os.Stderr) 88 | if err != nil { 89 | die(err.Error(), 1) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /cmd/osc-paste/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "encoding/base64" 7 | "fmt" 8 | "io" 9 | "os" 10 | "runtime/debug" 11 | "strings" 12 | 13 | "github.com/alecthomas/kong" 14 | "github.com/aymanbagabas/go-osc52/v2" 15 | "github.com/gdamore/tcell/v2" 16 | ) 17 | 18 | type cli struct { 19 | Trim bool `kong:"short='t',help='Trim whitespace of input'"` 20 | Primary bool `kong:"short='p',help='Use the primary X11 clipboard'"` 21 | Version bool `kong:"help='Print version information and exit'"` 22 | } 23 | 24 | type OSC52Response struct { 25 | Source string 26 | Data []byte 27 | } 28 | 29 | func ParseOSC52Resp(raw []byte) (*OSC52Response, error) { 30 | var ( 31 | prefixLen = 4 32 | source string 33 | ) 34 | 35 | // Check OSC52 header. 36 | if !bytes.Equal(raw[:prefixLen], []byte("\x1b]52")) { 37 | return nil, fmt.Errorf("invalid OSC52 header: %q", raw[:prefixLen]) 38 | } 39 | 40 | // Check OSC52 terminator. 41 | if raw[len(raw)-1] != '\a' { 42 | return nil, fmt.Errorf("invalid OSC52 data; invalid terminator: %q", raw) 43 | } 44 | 45 | // Strip header. 46 | raw = raw[prefixLen:] 47 | 48 | if raw[0] == ';' && raw[2] == ';' { 49 | // Variant 1: source is set. 50 | source = string(raw[1]) 51 | prefixLen = 3 52 | } else if raw[0] == ';' && raw[1] == ';' && raw[2] != ';' { 53 | // Variant 2: source is unset. 54 | source = "c" 55 | prefixLen = 2 56 | } else { 57 | // Variant 3: Data is invalid. 58 | return nil, fmt.Errorf("invalid OSC52 arguments: %q", raw) 59 | } 60 | 61 | // Strip arguments and terminator. 62 | raw = raw[prefixLen : len(raw)-1] 63 | 64 | bufSize := base64.StdEncoding.DecodedLen(len(raw)) 65 | data := make([]byte, bufSize) 66 | n, err := base64.StdEncoding.Decode(data, raw) 67 | if err != nil { 68 | return nil, fmt.Errorf("%s: %q", err, raw) 69 | } 70 | 71 | return &OSC52Response{Source: source, Data: data[:n]}, nil 72 | } 73 | 74 | func die(msg string, code int) { 75 | fmt.Fprintln(os.Stderr, msg) 76 | os.Exit(1) 77 | } 78 | 79 | func main() { 80 | var args cli 81 | kong.Parse(&args) 82 | 83 | if args.Version { 84 | buildInfo, ok := debug.ReadBuildInfo() 85 | if ok { 86 | fmt.Println(strings.TrimSpace(buildInfo.String())) 87 | } else { 88 | fmt.Println("unknown") 89 | } 90 | 91 | os.Exit(0) 92 | } 93 | 94 | seq := osc52.Query() 95 | 96 | if args.Primary { 97 | seq = seq.Primary() 98 | } 99 | 100 | tty, err := tcell.NewDevTty() 101 | if err != nil { 102 | die(err.Error(), 1) 103 | } 104 | 105 | tty.Start() 106 | _, err = seq.WriteTo(tty) 107 | if err != nil { 108 | die(err.Error(), 1) 109 | } 110 | 111 | reader := bufio.NewReader(tty) 112 | slice, err := reader.ReadSlice('\a') 113 | if err != nil { 114 | die(err.Error(), 1) 115 | } 116 | tty.Stop() 117 | tty.Close() 118 | 119 | resp, err := ParseOSC52Resp(slice) 120 | if err != nil { 121 | die(err.Error(), 1) 122 | } 123 | 124 | data := resp.Data 125 | 126 | if args.Trim { 127 | data = bytes.TrimSpace(data) 128 | } 129 | 130 | if !bytes.HasSuffix(data, []byte("\n")) { 131 | data = append(data, '\n') 132 | } 133 | 134 | if _, err := io.Copy(os.Stderr, bytes.NewReader(data)); err != nil { 135 | die(err.Error(), 1) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1704161960, 6 | "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "63143ac2c9186be6d9da6035fa22620018c85932", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "id": "nixpkgs", 14 | "type": "indirect" 15 | } 16 | }, 17 | "root": { 18 | "inputs": { 19 | "nixpkgs": "nixpkgs" 20 | } 21 | } 22 | }, 23 | "root": "root", 24 | "version": 7 25 | } 26 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Stefan Tatschner 2 | # 3 | # SPDX-License-Identifier: CC0-1.0 4 | 5 | { 6 | inputs = { 7 | nixpkgs.url = "nixpkgs"; 8 | }; 9 | 10 | outputs = { self, nixpkgs }: 11 | with import nixpkgs { system = "x86_64-linux"; }; 12 | let pkgs = nixpkgs.legacyPackages.x86_64-linux; 13 | in { 14 | devShell.x86_64-linux = pkgs.mkShell { 15 | buildInputs = with pkgs; [ 16 | go 17 | gnumake 18 | gopls 19 | gotools 20 | ]; 21 | }; 22 | formatter.x86_64-linux = pkgs.nixpkgs-fmt; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/rumpelsepp/oscclip 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/alecthomas/kong v0.9.0 7 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 8 | github.com/gdamore/tcell/v2 v2.7.4 9 | ) 10 | 11 | require ( 12 | github.com/gdamore/encoding v1.0.1 // indirect 13 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 14 | github.com/mattn/go-runewidth v0.0.16 // indirect 15 | github.com/rivo/uniseg v0.4.7 // indirect 16 | golang.org/x/sys v0.24.0 // indirect 17 | golang.org/x/term v0.23.0 // indirect 18 | golang.org/x/text v0.17.0 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU= 2 | github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= 3 | github.com/alecthomas/kong v0.9.0 h1:G5diXxc85KvoV2f0ZRVuMsi45IrBgx9zDNGNj165aPA= 4 | github.com/alecthomas/kong v0.9.0/go.mod h1:Y47y5gKfHp1hDc7CH7OeXgLIpp+Q2m1Ni0L5s3bI8Os= 5 | github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= 6 | github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= 7 | github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= 8 | github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= 9 | github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= 10 | github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw= 11 | github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo= 12 | github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= 13 | github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= 14 | github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= 15 | github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= 16 | github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 17 | github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 18 | github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 19 | github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= 20 | github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 21 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 22 | github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 23 | github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 24 | github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 25 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 26 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 27 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 28 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 29 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 30 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 31 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 32 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 33 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 34 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 35 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 36 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 37 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 38 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 39 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 40 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 41 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 42 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 43 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 44 | golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= 45 | golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 46 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 47 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 48 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 49 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 50 | golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= 51 | golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= 52 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 53 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 54 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 55 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 56 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 57 | golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= 58 | golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 59 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 60 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 61 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 62 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 63 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 64 | --------------------------------------------------------------------------------