summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-07-09 04:55:19 -0500
committeradamdottv <[email protected]>2025-07-09 04:55:24 -0500
commit3f25e5bf869d70a06afab64ca7812930f06e4ed5 (patch)
tree0a2aaf39ec4bfb945d62ab3becd1918f1f4a9dca
parent67765fa47c54c0d0b8146fb124c0d412e09bf5e8 (diff)
downloadopencode-3f25e5bf869d70a06afab64ca7812930f06e4ed5.tar.gz
opencode-3f25e5bf869d70a06afab64ca7812930f06e4ed5.zip
chore: internal clipboard package
-rw-r--r--packages/tui/clipboard/.github/FUNDING.yml12
-rw-r--r--packages/tui/clipboard/.github/workflows/clipboard.yml71
-rw-r--r--packages/tui/clipboard/.gitignore15
-rw-r--r--packages/tui/clipboard/Dockerfile13
-rw-r--r--packages/tui/clipboard/LICENSE21
-rw-r--r--packages/tui/clipboard/README.md162
-rw-r--r--packages/tui/clipboard/clipboard_android.c80
-rw-r--r--packages/tui/clipboard/clipboard_android.go102
-rw-r--r--packages/tui/clipboard/clipboard_ios.go80
-rw-r--r--packages/tui/clipboard/clipboard_ios.m20
-rw-r--r--packages/tui/clipboard/clipboard_test.go336
-rw-r--r--packages/tui/clipboard/cmd/gclip-gui/AndroidManifest.xml33
-rw-r--r--packages/tui/clipboard/cmd/gclip-gui/README.md31
-rw-r--r--packages/tui/clipboard/cmd/gclip-gui/main.go236
-rw-r--r--packages/tui/clipboard/cmd/gclip/README.md40
-rw-r--r--packages/tui/clipboard/cmd/gclip/main.go131
-rw-r--r--packages/tui/clipboard/example_test.go56
-rw-r--r--packages/tui/clipboard/export_test.go14
-rw-r--r--packages/tui/clipboard/go.mod13
-rw-r--r--packages/tui/clipboard/go.sum8
-rwxr-xr-xpackages/tui/clipboard/test_linux_nocgo.sh109
-rw-r--r--packages/tui/clipboard/tests/Makefile15
-rwxr-xr-xpackages/tui/clipboard/tests/test-docker.sh11
-rw-r--r--packages/tui/clipboard/tests/testdata/android.pngbin109241 -> 0 bytes
-rw-r--r--packages/tui/clipboard/tests/testdata/clipboard.pngbin21310 -> 0 bytes
-rw-r--r--packages/tui/clipboard/tests/testdata/darwin.pngbin118106 -> 0 bytes
-rw-r--r--packages/tui/clipboard/tests/testdata/ios.pngbin47419 -> 0 bytes
-rw-r--r--packages/tui/clipboard/tests/testdata/linux.pngbin28976 -> 0 bytes
-rw-r--r--packages/tui/clipboard/tests/testdata/windows.pngbin20532 -> 0 bytes
-rw-r--r--packages/tui/cmd/opencode/main.go2
-rw-r--r--packages/tui/go.mod10
-rw-r--r--packages/tui/go.sum4
-rw-r--r--packages/tui/internal/app/app.go2
-rw-r--r--packages/tui/internal/clipboard/clipboard.go (renamed from packages/tui/clipboard/clipboard.go)2
-rw-r--r--packages/tui/internal/clipboard/clipboard_darwin.go (renamed from packages/tui/clipboard/clipboard_darwin.go)2
-rw-r--r--packages/tui/internal/clipboard/clipboard_linux.go (renamed from packages/tui/clipboard/clipboard_linux.go)2
-rw-r--r--packages/tui/internal/clipboard/clipboard_nocgo.go (renamed from packages/tui/clipboard/clipboard_nocgo.go)0
-rw-r--r--packages/tui/internal/clipboard/clipboard_windows.go (renamed from packages/tui/clipboard/clipboard_windows.go)0
-rw-r--r--packages/tui/internal/components/chat/editor.go2
-rwxr-xr-xpackages/tui/opencodebin0 -> 24791266 bytes
40 files changed, 8 insertions, 1627 deletions
diff --git a/packages/tui/clipboard/.github/FUNDING.yml b/packages/tui/clipboard/.github/FUNDING.yml
deleted file mode 100644
index 2957eb0ea..000000000
--- a/packages/tui/clipboard/.github/FUNDING.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-# These are supported funding model platforms
-
-github: [changkun] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/packages/tui/clipboard/.github/workflows/clipboard.yml b/packages/tui/clipboard/.github/workflows/clipboard.yml
deleted file mode 100644
index 38441335d..000000000
--- a/packages/tui/clipboard/.github/workflows/clipboard.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright 2021 The golang.design Initiative Authors.
-# All rights reserved. Use of this source code is governed
-# by a MIT license that can be found in the LICENSE file.
-#
-# Written by Changkun Ou <changkun.de>
-
-name: clipboard
-
-on:
- push:
- branches: [ main ]
- pull_request:
- branches: [ main ]
-
-jobs:
- platform_test:
- env:
- DISPLAY: ':0.0'
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix:
- os: [ubuntu-latest, macos-latest, windows-latest]
- go: ['1.24.x']
- steps:
- - name: Install and run dependencies (xvfb libx11-dev)
- if: ${{ runner.os == 'Linux' }}
- run: |
- sudo apt update
- sudo apt install -y xvfb libx11-dev x11-utils libegl1-mesa-dev libgles2-mesa-dev
- Xvfb :0 -screen 0 1024x768x24 > /dev/null 2>&1 &
- # Wait for Xvfb
- MAX_ATTEMPTS=120 # About 60 seconds
- COUNT=0
- echo -n "Waiting for Xvfb to be ready..."
- while ! xdpyinfo -display "${DISPLAY}" >/dev/null 2>&1; do
- echo -n "."
- sleep 0.50s
- COUNT=$(( COUNT + 1 ))
- if [ "${COUNT}" -ge "${MAX_ATTEMPTS}" ]; then
- echo " Gave up waiting for X server on ${DISPLAY}"
- exit 1
- fi
- done
- echo "Done - Xvfb is ready!"
-
- - uses: actions/checkout@v2
- - uses: actions/setup-go@v2
- with:
- stable: 'false'
- go-version: ${{ matrix.go }}
-
- - name: Build (${{ matrix.go }})
- run: |
- go build -o gclip cmd/gclip/main.go
- go build -o gclip-gui cmd/gclip-gui/main.go
-
- - name: Run Tests with CGO_ENABLED=1 (${{ matrix.go }})
- if: ${{ runner.os == 'Linux' || runner.os == 'macOS'}}
- run: |
- CGO_ENABLED=1 go test -v -covermode=atomic .
-
- - name: Run Tests with CGO_ENABLED=0 (${{ matrix.go }})
- if: ${{ runner.os == 'Linux' || runner.os == 'macOS'}}
- run: |
- CGO_ENABLED=0 go test -v -covermode=atomic .
-
- - name: Run Tests on Windows (${{ matrix.go }})
- if: ${{ runner.os == 'Windows'}}
- run: |
- go test -v -covermode=atomic . \ No newline at end of file
diff --git a/packages/tui/clipboard/.gitignore b/packages/tui/clipboard/.gitignore
deleted file mode 100644
index 66fd13c90..000000000
--- a/packages/tui/clipboard/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Test binary, built with `go test -c`
-*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
-
-# Dependency directories (remove the comment below to include it)
-# vendor/
diff --git a/packages/tui/clipboard/Dockerfile b/packages/tui/clipboard/Dockerfile
deleted file mode 100644
index b810346f3..000000000
--- a/packages/tui/clipboard/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2021 The golang.design Initiative Authors.
-# All rights reserved. Use of this source code is governed
-# by a MIT license that can be found in the LICENSE file.
-#
-# Written by Changkun Ou <changkun.de>
-
-FROM golang:1.24
-RUN apt-get update && apt-get install -y \
- xvfb libx11-dev libegl1-mesa-dev libgles2-mesa-dev \
- && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-WORKDIR /app
-COPY . .
-CMD [ "sh", "-c", "./tests/test-docker.sh" ]
diff --git a/packages/tui/clipboard/LICENSE b/packages/tui/clipboard/LICENSE
deleted file mode 100644
index 7f2bbe295..000000000
--- a/packages/tui/clipboard/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2021 Changkun Ou <[email protected]>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE. \ No newline at end of file
diff --git a/packages/tui/clipboard/README.md b/packages/tui/clipboard/README.md
deleted file mode 100644
index d71200703..000000000
--- a/packages/tui/clipboard/README.md
+++ /dev/null
@@ -1,162 +0,0 @@
-# clipboard [![PkgGoDev](https://pkg.go.dev/badge/golang.design/x/clipboard)](https://pkg.go.dev/golang.design/x/clipboard) ![](https://changkun.de/urlstat?mode=github&repo=golang-design/clipboard) ![clipboard](https://github.com/golang-design/clipboard/workflows/clipboard/badge.svg?branch=main)
-
-Cross platform (macOS/Linux/Windows/Android/iOS) clipboard package in Go
-
-```go
-import "golang.design/x/clipboard"
-```
-
-## Features
-
-- Cross platform supports: **macOS, Linux (X11), Windows, iOS, and Android**
-- Copy/paste UTF-8 text
-- Copy/paste PNG encoded images (Desktop-only)
-- Command `gclip` as a demo application
-- Mobile app `gclip-gui` as a demo application
-
-## API Usage
-
-Package clipboard provides cross platform clipboard access and supports
-macOS/Linux/Windows/Android/iOS platform. Before interacting with the
-clipboard, one must call Init to assert if it is possible to use this
-package:
-
-```go
-// Init returns an error if the package is not ready for use.
-err := clipboard.Init()
-if err != nil {
- panic(err)
-}
-```
-
-The most common operations are `Read` and `Write`. To use them:
-
-```go
-// write/read text format data of the clipboard, and
-// the byte buffer regarding the text are UTF8 encoded.
-clipboard.Write(clipboard.FmtText, []byte("text data"))
-clipboard.Read(clipboard.FmtText)
-
-// write/read image format data of the clipboard, and
-// the byte buffer regarding the image are PNG encoded.
-clipboard.Write(clipboard.FmtImage, []byte("image data"))
-clipboard.Read(clipboard.FmtImage)
-```
-
-Note that read/write regarding image format assumes that the bytes are
-PNG encoded since it serves the alpha blending purpose that might be
-used in other graphical software.
-
-In addition, `clipboard.Write` returns a channel that can receive an
-empty struct as a signal, which indicates the corresponding write call
-to the clipboard is outdated, meaning the clipboard has been overwritten
-by others and the previously written data is lost. For instance:
-
-```go
-changed := clipboard.Write(clipboard.FmtText, []byte("text data"))
-
-select {
-case <-changed:
- println(`"text data" is no longer available from clipboard.`)
-}
-```
-
-You can ignore the returning channel if you don't need this type of
-notification. Furthermore, when you need more than just knowing whether
-clipboard data is changed, use the watcher API:
-
-```go
-ch := clipboard.Watch(context.TODO(), clipboard.FmtText)
-for data := range ch {
- // print out clipboard data whenever it is changed
- println(string(data))
-}
-```
-
-## Demos
-
-- A command line tool `gclip` for command line clipboard accesses, see document [here](./cmd/gclip/README.md).
-- A GUI application `gclip-gui` for functionality verifications on mobile systems, see a document [here](./cmd/gclip-gui/README.md).
-
-
-## Command Usage
-
-`gclip` command offers the ability to interact with the system clipboard
-from the shell. To install:
-
-```bash
-$ go install golang.design/x/clipboard/cmd/gclip@latest
-```
-
-```bash
-$ gclip
-gclip is a command that provides clipboard interaction.
-
-usage: gclip [-copy|-paste] [-f <file>]
-
-options:
- -copy
- copy data to clipboard
- -f string
- source or destination to a given file path
- -paste
- paste data from clipboard
-
-examples:
-gclip -paste paste from clipboard and prints the content
-gclip -paste -f x.txt paste from clipboard and save as text to x.txt
-gclip -paste -f x.png paste from clipboard and save as image to x.png
-
-cat x.txt | gclip -copy copy content from x.txt to clipboard
-gclip -copy -f x.txt copy content from x.txt to clipboard
-gclip -copy -f x.png copy x.png as image data to clipboard
-```
-
-If `-copy` is used, the command will exit when the data is no longer
-available from the clipboard. You can always send the command to the
-background using a shell `&` operator, for example:
-
-```bash
-$ cat x.txt | gclip -copy &
-```
-
-## Platform Specific Details
-
-This package spent efforts to provide cross platform abstraction regarding
-accessing system clipboards, but here are a few details you might need to know.
-
-### Dependency
-
-- macOS: require Cgo, no dependency
- - Linux: require X11 dev package. For instance, install `libx11-dev` or `xorg-dev` or `libX11-devel` to access X window system.
- Wayland sessions are currently unsupported; running under Wayland
- typically requires an XWayland bridge and `DISPLAY` to be set.
-- Windows: no Cgo, no dependency
-- iOS/Android: collaborate with [`gomobile`](https://golang.org/x/mobile)
-
-### Screenshot
-
-In general, when you need test your implementation regarding images,
-There are system level shortcuts to put screenshot image into your system clipboard:
-
-- On macOS, use `Ctrl+Shift+Cmd+4`
-- On Linux/Ubuntu, use `Ctrl+Shift+PrintScreen`
-- On Windows, use `Shift+Win+s`
-
-As described in the API documentation, the package supports read/write
-UTF8 encoded plain text or PNG encoded image data. Thus,
-the other types of data are not supported yet, i.e. undefined behavior.
-
-## Who is using this package?
-
-The main purpose of building this package is to support the
-[midgard](https://changkun.de/s/midgard) project, which offers
-clipboard-based features like universal clipboard service that syncs
-clipboard content across multiple systems, allocating public accessible
-for clipboard content, etc.
-
-To know more projects, check our [wiki](https://github.com/golang-design/clipboard/wiki) page.
-
-## License
-
-MIT | &copy; 2021 The golang.design Initiative Authors, written by [Changkun Ou](https://changkun.de). \ No newline at end of file
diff --git a/packages/tui/clipboard/clipboard_android.c b/packages/tui/clipboard/clipboard_android.c
deleted file mode 100644
index 9dc34f6d6..000000000
--- a/packages/tui/clipboard/clipboard_android.c
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-//go:build android
-
-#include <android/log.h>
-#include <jni.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, \
- "GOLANG.DESIGN/X/CLIPBOARD", __VA_ARGS__)
-
-static jmethodID find_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
- jmethodID m = (*env)->GetMethodID(env, clazz, name, sig);
- if (m == 0) {
- (*env)->ExceptionClear(env);
- LOG_FATAL("cannot find method %s %s", name, sig);
- return 0;
- }
- return m;
-}
-
-jobject get_clipboard(uintptr_t jni_env, uintptr_t ctx) {
- JNIEnv *env = (JNIEnv*)jni_env;
- jclass ctxClass = (*env)->GetObjectClass(env, (jobject)ctx);
- jmethodID getSystemService = find_method(env, ctxClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
-
- jstring service = (*env)->NewStringUTF(env, "clipboard");
- jobject ret = (jobject)(*env)->CallObjectMethod(env, (jobject)ctx, getSystemService, service);
- jthrowable err = (*env)->ExceptionOccurred(env);
-
- if (err != NULL) {
- LOG_FATAL("cannot find clipboard");
- (*env)->ExceptionClear(env);
- return NULL;
- }
- return ret;
-}
-
-char *clipboard_read_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx) {
- JNIEnv *env = (JNIEnv*)jni_env;
- jobject mgr = get_clipboard(jni_env, ctx);
- if (mgr == NULL) {
- return NULL;
- }
-
- jclass mgrClass = (*env)->GetObjectClass(env, mgr);
- jmethodID getText = find_method(env, mgrClass, "getText", "()Ljava/lang/CharSequence;");
-
- jobject content = (jstring)(*env)->CallObjectMethod(env, mgr, getText);
- if (content == NULL) {
- return NULL;
- }
-
- jclass clzCharSequence = (*env)->GetObjectClass(env, content);
- jmethodID toString = (*env)->GetMethodID(env, clzCharSequence, "toString", "()Ljava/lang/String;");
- jobject s = (*env)->CallObjectMethod(env, content, toString);
-
- const char *chars = (*env)->GetStringUTFChars(env, s, NULL);
- char *copy = strdup(chars);
- (*env)->ReleaseStringUTFChars(env, s, chars);
- return copy;
-}
-
-void clipboard_write_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx, char *str) {
- JNIEnv *env = (JNIEnv*)jni_env;
- jobject mgr = get_clipboard(jni_env, ctx);
- if (mgr == NULL) {
- return;
- }
-
- jclass mgrClass = (*env)->GetObjectClass(env, mgr);
- jmethodID setText = find_method(env, mgrClass, "setText", "(Ljava/lang/CharSequence;)V");
-
- (*env)->CallVoidMethod(env, mgr, setText, (*env)->NewStringUTF(env, str));
-}
diff --git a/packages/tui/clipboard/clipboard_android.go b/packages/tui/clipboard/clipboard_android.go
deleted file mode 100644
index c9ce78fcb..000000000
--- a/packages/tui/clipboard/clipboard_android.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-//go:build android
-
-package clipboard
-
-/*
-#cgo LDFLAGS: -landroid -llog
-
-#include <stdlib.h>
-char *clipboard_read_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx);
-void clipboard_write_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx, char *str);
-
-*/
-import "C"
-import (
- "bytes"
- "context"
- "time"
- "unsafe"
-
- "golang.org/x/mobile/app"
-)
-
-func initialize() error { return nil }
-
-func read(t Format) (buf []byte, err error) {
- switch t {
- case FmtText:
- s := ""
- if err := app.RunOnJVM(func(vm, env, ctx uintptr) error {
- cs := C.clipboard_read_string(C.uintptr_t(vm), C.uintptr_t(env), C.uintptr_t(ctx))
- if cs == nil {
- return nil
- }
-
- s = C.GoString(cs)
- C.free(unsafe.Pointer(cs))
- return nil
- }); err != nil {
- return nil, err
- }
- return []byte(s), nil
- case FmtImage:
- return nil, errUnsupported
- default:
- return nil, errUnsupported
- }
-}
-
-// write writes the given data to clipboard and
-// returns true if success or false if failed.
-func write(t Format, buf []byte) (<-chan struct{}, error) {
- done := make(chan struct{}, 1)
- switch t {
- case FmtText:
- cs := C.CString(string(buf))
- defer C.free(unsafe.Pointer(cs))
-
- if err := app.RunOnJVM(func(vm, env, ctx uintptr) error {
- C.clipboard_write_string(C.uintptr_t(vm), C.uintptr_t(env), C.uintptr_t(ctx), cs)
- done <- struct{}{}
- return nil
- }); err != nil {
- return nil, err
- }
- return done, nil
- case FmtImage:
- return nil, errUnsupported
- default:
- return nil, errUnsupported
- }
-}
-
-func watch(ctx context.Context, t Format) <-chan []byte {
- recv := make(chan []byte, 1)
- ti := time.NewTicker(time.Second)
- last := Read(t)
- go func() {
- for {
- select {
- case <-ctx.Done():
- close(recv)
- return
- case <-ti.C:
- b := Read(t)
- if b == nil {
- continue
- }
- if bytes.Compare(last, b) != 0 {
- recv <- b
- last = b
- }
- }
- }
- }()
- return recv
-}
diff --git a/packages/tui/clipboard/clipboard_ios.go b/packages/tui/clipboard/clipboard_ios.go
deleted file mode 100644
index e027b8c2b..000000000
--- a/packages/tui/clipboard/clipboard_ios.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-//go:build ios
-
-package clipboard
-
-/*
-#cgo CFLAGS: -x objective-c
-#cgo LDFLAGS: -framework Foundation -framework UIKit -framework MobileCoreServices
-
-#import <stdlib.h>
-void clipboard_write_string(char *s);
-char *clipboard_read_string();
-*/
-import "C"
-import (
- "bytes"
- "context"
- "time"
- "unsafe"
-)
-
-func initialize() error { return nil }
-
-func read(t Format) (buf []byte, err error) {
- switch t {
- case FmtText:
- return []byte(C.GoString(C.clipboard_read_string())), nil
- case FmtImage:
- return nil, errUnsupported
- default:
- return nil, errUnsupported
- }
-}
-
-// SetContent sets the clipboard content for iOS
-func write(t Format, buf []byte) (<-chan struct{}, error) {
- done := make(chan struct{}, 1)
- switch t {
- case FmtText:
- cs := C.CString(string(buf))
- defer C.free(unsafe.Pointer(cs))
-
- C.clipboard_write_string(cs)
- return done, nil
- case FmtImage:
- return nil, errUnsupported
- default:
- return nil, errUnsupported
- }
-}
-
-func watch(ctx context.Context, t Format) <-chan []byte {
- recv := make(chan []byte, 1)
- ti := time.NewTicker(time.Second)
- last := Read(t)
- go func() {
- for {
- select {
- case <-ctx.Done():
- close(recv)
- return
- case <-ti.C:
- b := Read(t)
- if b == nil {
- continue
- }
- if bytes.Compare(last, b) != 0 {
- recv <- b
- last = b
- }
- }
- }
- }()
- return recv
-}
diff --git a/packages/tui/clipboard/clipboard_ios.m b/packages/tui/clipboard/clipboard_ios.m
deleted file mode 100644
index 15eb122bc..000000000
--- a/packages/tui/clipboard/clipboard_ios.m
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-//go:build ios
-
-#import <UIKit/UIKit.h>
-#import <MobileCoreServices/MobileCoreServices.h>
-
-void clipboard_write_string(char *s) {
- NSString *value = [NSString stringWithUTF8String:s];
- [[UIPasteboard generalPasteboard] setString:value];
-}
-
-char *clipboard_read_string() {
- NSString *str = [[UIPasteboard generalPasteboard] string];
- return (char *)[str UTF8String];
-}
diff --git a/packages/tui/clipboard/clipboard_test.go b/packages/tui/clipboard/clipboard_test.go
deleted file mode 100644
index 9dce284bd..000000000
--- a/packages/tui/clipboard/clipboard_test.go
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-package clipboard_test
-
-import (
- "bytes"
- "context"
- "errors"
- "image/color"
- "image/png"
- "os"
- "reflect"
- "runtime"
- "testing"
- "time"
-
- "golang.design/x/clipboard"
-)
-
-func init() {
- clipboard.Debug = true
-}
-
-func TestClipboardInit(t *testing.T) {
- t.Run("no-cgo", func(t *testing.T) {
- if val, ok := os.LookupEnv("CGO_ENABLED"); !ok || val != "0" {
- t.Skip("CGO_ENABLED is set to 1")
- }
- if runtime.GOOS == "windows" {
- t.Skip("Windows does not need to check for cgo")
- }
-
- if err := clipboard.Init(); !errors.Is(err, clipboard.ErrCgoDisabled) {
- t.Fatalf("expect ErrCgoDisabled, got: %v", err)
- }
- })
- t.Run("with-cgo", func(t *testing.T) {
- if val, ok := os.LookupEnv("CGO_ENABLED"); ok && val == "0" {
- t.Skip("CGO_ENABLED is set to 0")
- }
- if runtime.GOOS != "linux" {
- t.Skip("Only Linux may return error at the moment.")
- }
-
- if err := clipboard.Init(); err != nil && !errors.Is(err, clipboard.ErrUnavailable) {
- t.Fatalf("expect ErrUnavailable, but got: %v", err)
- }
- })
-}
-
-func TestClipboard(t *testing.T) {
- if runtime.GOOS != "windows" {
- if val, ok := os.LookupEnv("CGO_ENABLED"); ok && val == "0" {
- t.Skip("CGO_ENABLED is set to 0")
- }
- }
-
- t.Run("image", func(t *testing.T) {
- data, err := os.ReadFile("tests/testdata/clipboard.png")
- if err != nil {
- t.Fatalf("failed to read gold file: %v", err)
- }
- clipboard.Write(clipboard.FmtImage, data)
-
- b := clipboard.Read(clipboard.FmtText)
- if b != nil {
- t.Fatalf("read clipboard that stores image data as text should fail, but got len: %d", len(b))
- }
-
- b = clipboard.Read(clipboard.FmtImage)
- if b == nil {
- t.Fatalf("read clipboard that stores image data as image should success, but got: nil")
- }
-
- img1, err := png.Decode(bytes.NewReader(data))
- if err != nil {
- t.Fatalf("write image is not png encoded: %v", err)
- }
- img2, err := png.Decode(bytes.NewReader(b))
- if err != nil {
- t.Fatalf("read image is not png encoded: %v", err)
- }
-
- w := img2.Bounds().Dx()
- h := img2.Bounds().Dy()
-
- incorrect := 0
- for i := 0; i < w; i++ {
- for j := 0; j < h; j++ {
- wr, wg, wb, wa := img1.At(i, j).RGBA()
- gr, gg, gb, ga := img2.At(i, j).RGBA()
- want := color.RGBA{
- R: uint8(wr),
- G: uint8(wg),
- B: uint8(wb),
- A: uint8(wa),
- }
- got := color.RGBA{
- R: uint8(gr),
- G: uint8(gg),
- B: uint8(gb),
- A: uint8(ga),
- }
-
- if !reflect.DeepEqual(want, got) {
- t.Logf("read data from clipbaord is inconsistent with previous written data, pix: (%d,%d), got: %+v, want: %+v", i, j, got, want)
- incorrect++
- }
- }
- }
-
- if incorrect > 0 {
- t.Fatalf("read data from clipboard contains too much inconsistent pixels to the previous written data, number of incorrect pixels: %v", incorrect)
- }
- })
-
- t.Run("text", func(t *testing.T) {
- data := []byte("golang.design/x/clipboard")
- clipboard.Write(clipboard.FmtText, data)
-
- b := clipboard.Read(clipboard.FmtImage)
- if b != nil {
- t.Fatalf("read clipboard that stores text data as image should fail, but got len: %d", len(b))
- }
- b = clipboard.Read(clipboard.FmtText)
- if b == nil {
- t.Fatal("read clipboard taht stores text data as text should success, but got: nil")
- }
-
- if !reflect.DeepEqual(data, b) {
- t.Fatalf("read data from clipbaord is inconsistent with previous written data, got: %d, want: %d", len(b), len(data))
- }
- })
-}
-
-func TestClipboardMultipleWrites(t *testing.T) {
- if runtime.GOOS != "windows" {
- if val, ok := os.LookupEnv("CGO_ENABLED"); ok && val == "0" {
- t.Skip("CGO_ENABLED is set to 0")
- }
- }
-
- data, err := os.ReadFile("tests/testdata/clipboard.png")
- if err != nil {
- t.Fatalf("failed to read gold file: %v", err)
- }
- chg := clipboard.Write(clipboard.FmtImage, data)
-
- data = []byte("golang.design/x/clipboard")
- clipboard.Write(clipboard.FmtText, data)
-
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
- defer cancel()
-
- select {
- case <-ctx.Done():
- t.Fatalf("failed to receive clipboard change notification")
- case _, ok := <-chg:
- if !ok {
- t.Fatalf("change channel is closed before receiving the changed clipboard data")
- }
- }
- _, ok := <-chg
- if ok {
- t.Fatalf("changed channel should be closed after receiving the notification")
- }
-
- b := clipboard.Read(clipboard.FmtImage)
- if b != nil {
- t.Fatalf("read clipboard that should store text data as image should fail, but got: %d", len(b))
- }
-
- b = clipboard.Read(clipboard.FmtText)
- if b == nil {
- t.Fatalf("read clipboard that should store text data as text should success, got: nil")
- }
-
- if !reflect.DeepEqual(data, b) {
- t.Fatalf("read data from clipbaord is inconsistent with previous write, want %s, got: %s", string(data), string(b))
- }
-}
-
-func TestClipboardConcurrentRead(t *testing.T) {
- if runtime.GOOS != "windows" {
- if val, ok := os.LookupEnv("CGO_ENABLED"); ok && val == "0" {
- t.Skip("CGO_ENABLED is set to 0")
- }
- }
-
- // This test check that concurrent read/write to the clipboard does
- // not cause crashes on some specific platform, such as macOS.
- done := make(chan bool, 2)
- go func() {
- defer func() {
- done <- true
- }()
- clipboard.Read(clipboard.FmtText)
- }()
- go func() {
- defer func() {
- done <- true
- }()
- clipboard.Read(clipboard.FmtImage)
- }()
- <-done
- <-done
-}
-
-func TestClipboardWriteEmpty(t *testing.T) {
- if runtime.GOOS != "windows" {
- if val, ok := os.LookupEnv("CGO_ENABLED"); ok && val == "0" {
- t.Skip("CGO_ENABLED is set to 0")
- }
- }
-
- chg1 := clipboard.Write(clipboard.FmtText, nil)
- if got := clipboard.Read(clipboard.FmtText); got != nil {
- t.Fatalf("write nil to clipboard should read nil, got: %v", string(got))
- }
- clipboard.Write(clipboard.FmtText, []byte(""))
- <-chg1
-
- if got := clipboard.Read(clipboard.FmtText); string(got) != "" {
- t.Fatalf("write empty string to clipboard should read empty string, got: `%v`", string(got))
- }
-}
-
-func TestClipboardWatch(t *testing.T) {
- if runtime.GOOS != "windows" {
- if val, ok := os.LookupEnv("CGO_ENABLED"); ok && val == "0" {
- t.Skip("CGO_ENABLED is set to 0")
- }
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
- defer cancel()
-
- // clear clipboard
- clipboard.Write(clipboard.FmtText, []byte(""))
- lastRead := clipboard.Read(clipboard.FmtText)
-
- changed := clipboard.Watch(ctx, clipboard.FmtText)
-
- want := []byte("golang.design/x/clipboard")
- go func(ctx context.Context) {
- t := time.NewTicker(time.Millisecond * 500)
- for {
- select {
- case <-ctx.Done():
- return
- case <-t.C:
- clipboard.Write(clipboard.FmtText, want)
- }
- }
- }(ctx)
- for {
- select {
- case <-ctx.Done():
- if string(lastRead) == "" {
- t.Fatalf("clipboard watch never receives a notification")
- }
- t.Log(string(lastRead))
- return
- case data, ok := <-changed:
- if !ok {
- if string(lastRead) == "" {
- t.Fatalf("clipboard watch never receives a notification")
- }
- return
- }
- if !bytes.Equal(data, want) {
- t.Fatalf("received data from watch mismatch, want: %v, got %v", string(want), string(data))
- }
- lastRead = data
- }
- }
-}
-
-func BenchmarkClipboard(b *testing.B) {
- b.Run("text", func(b *testing.B) {
- data := []byte("golang.design/x/clipboard")
-
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- clipboard.Write(clipboard.FmtText, data)
- _ = clipboard.Read(clipboard.FmtText)
- }
- })
-}
-
-func TestClipboardNoCgo(t *testing.T) {
- if val, ok := os.LookupEnv("CGO_ENABLED"); !ok || val != "0" {
- t.Skip("CGO_ENABLED is set to 1")
- }
- if runtime.GOOS == "windows" {
- t.Skip("Windows should always be tested")
- }
-
- t.Run("Read", func(t *testing.T) {
- defer func() {
- if r := recover(); r != nil {
- return
- }
- t.Fatalf("expect to fail when CGO_ENABLED=0")
- }()
-
- clipboard.Read(clipboard.FmtText)
- })
-
- t.Run("Write", func(t *testing.T) {
- defer func() {
- if r := recover(); r != nil {
- return
- }
- t.Fatalf("expect to fail when CGO_ENABLED=0")
- }()
-
- clipboard.Write(clipboard.FmtText, []byte("dummy"))
- })
-
- t.Run("Watch", func(t *testing.T) {
- defer func() {
- if r := recover(); r != nil {
- return
- }
- t.Fatalf("expect to fail when CGO_ENABLED=0")
- }()
-
- clipboard.Watch(context.TODO(), clipboard.FmtText)
- })
-}
diff --git a/packages/tui/clipboard/cmd/gclip-gui/AndroidManifest.xml b/packages/tui/clipboard/cmd/gclip-gui/AndroidManifest.xml
deleted file mode 100644
index 63b0cba57..000000000
--- a/packages/tui/clipboard/cmd/gclip-gui/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright 2021 The golang.design Initiative Authors.
-All rights reserved. Use of this source code is governed
-by a MIT license that can be found in the LICENSE file.
-
-Written by Changkun Ou <changkun.de>
--->
-<manifest
- xmlns:android="http://schemas.android.com/apk/res/android"
- package="design.golang.clipboard.gclip"
- android:versionCode="1"
- android:versionName="1.0">
-
-
- <!-- In order to access the clipboard, the application manifest must
- specify the permission requirement. See the following page for
- details.
- http://developer.android.com/guide/topics/manifest/manifest-intro.html#perms -->
- <uses-permission android:name="android.permission.CLIPBOARD" />
-
- <application android:label="gclip" android:debuggable="true">
- <activity android:name="org.golang.app.GoNativeActivity"
- android:label="Gclip"
- android:configChanges="orientation|keyboardHidden">
- <meta-data android:name="android.app.lib_name" android:value="Gclip" />
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-</manifest>
diff --git a/packages/tui/clipboard/cmd/gclip-gui/README.md b/packages/tui/clipboard/cmd/gclip-gui/README.md
deleted file mode 100644
index 571604e7f..000000000
--- a/packages/tui/clipboard/cmd/gclip-gui/README.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# gclip-gui
-
-This is a very basic example for verification purpose that demonstrates
-how the [golang.design/x/clipboard](https://golang.design/x/clipboard)
-can interact with macOS/Linux/Windows/Android/iOS system clipboard.
-
-The gclip GUI application writes a string to the system clipboard
-periodically then reads it back and renders it if possible.
-
-Because of the system limitation, on mobile devices, only string data is
-supported at the moment. Hence, one must use clipboard.FmtText. Other supplied
-formats result in a panic.
-
-This example is intentded as cross platform application. To build it, one
-must use [gomobile](https://golang.org/x/mobile). You may follow the instructions
-provided in the [GoMobile wiki](https://github.com/golang/go/wiki/Mobile) page.
-
-
-- For desktop: `go build -o gclip-gui`
-- For Android: `gomobile build -v -target=android -o gclip-gui.apk`
-- For iOS: `gomobile build -v -target=ios -bundleid design.golang.gclip-gui.app`
-
-## Screenshots
-
-| macOS | iOS | Windows | Android | Linux |
-|:-----:|:---:|:-------:|:-------:|:-----:|
-|![](../../tests/testdata/darwin.png)|![](../../tests/testdata/ios.png)|![](../../tests/testdata/windows.png)|![](../../tests/testdata/android.png)|![](../../tests/testdata/linux.png)|
-
-## License
-
-MIT | &copy; 2021 The golang.design Initiative Authors, written by [Changkun Ou](https://changkun.de). \ No newline at end of file
diff --git a/packages/tui/clipboard/cmd/gclip-gui/main.go b/packages/tui/clipboard/cmd/gclip-gui/main.go
deleted file mode 100644
index 1bf46270c..000000000
--- a/packages/tui/clipboard/cmd/gclip-gui/main.go
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-//go:build android || ios || linux || darwin || windows
-
-// This is a very basic example for verification purpose that
-// demonstrates how the golang.design/x/clipboard can interact
-// with macOS/Linux/Windows/Android/iOS system clipboard.
-//
-// The gclip GUI application writes a string to the system clipboard
-// periodically then reads it back and renders it if possible.
-//
-// Because of the system limitation, on mobile devices, only string
-// data is supported at the moment. Hence, one must use clipboard.FmtText.
-// Other supplied formats result in a panic.
-//
-// This example is intentded as cross platform application.
-// To build it, one must use gomobile (https://golang.org/x/mobile).
-// You may follow the instructions provided in the GoMobile's wiki page:
-// https://github.com/golang/go/wiki/Mobile.
-//
-// - For desktop:
-//
-// go build -o gclip-gui
-//
-// - For Android:
-//
-// gomobile build -v -target=android -o gclip-gui.apk
-//
-// - For iOS:
-//
-// gomobile build -v -target=ios -bundleid design.golang.gclip-gui.app
-//
-package main
-
-import (
- "fmt"
- "image"
- "image/color"
- "log"
- "os"
- "sync"
- "time"
-
- "golang.design/x/clipboard"
-
- "golang.org/x/image/font"
- "golang.org/x/image/font/basicfont"
- "golang.org/x/image/math/fixed"
- "golang.org/x/mobile/app"
- "golang.org/x/mobile/event/lifecycle"
- "golang.org/x/mobile/event/paint"
- "golang.org/x/mobile/event/size"
- "golang.org/x/mobile/exp/gl/glutil"
- "golang.org/x/mobile/geom"
- "golang.org/x/mobile/gl"
-)
-
-type Label struct {
- sz size.Event
- images *glutil.Images
- m *glutil.Image
- drawer *font.Drawer
-
- mu sync.Mutex
- data string
-}
-
-func NewLabel(images *glutil.Images) *Label {
- return &Label{
- images: images,
- data: "Hello! Gclip.",
- drawer: nil,
- }
-}
-
-func (l *Label) SetLabel(s string) {
- l.mu.Lock()
- defer l.mu.Unlock()
-
- l.data = s
-}
-
-const (
- lineWidth = 100
- lineHeight = 120
-)
-
-func (l *Label) Draw(sz size.Event) {
- l.mu.Lock()
- s := l.data
- l.mu.Unlock()
- imgW, imgH := lineWidth*basicfont.Face7x13.Width, lineHeight*basicfont.Face7x13.Height
- if sz.WidthPx == 0 && sz.HeightPx == 0 {
- return
- }
- if imgW > sz.WidthPx {
- imgW = sz.WidthPx
- }
-
- if l.sz != sz {
- l.sz = sz
- if l.m != nil {
- l.m.Release()
- }
- l.m = l.images.NewImage(imgW, imgH)
- }
- // Clear the drawing image.
- for i := 0; i < len(l.m.RGBA.Pix); i++ {
- l.m.RGBA.Pix[i] = 0
- }
-
- l.drawer = &font.Drawer{
- Dst: l.m.RGBA,
- Src: image.NewUniform(color.RGBA{0, 100, 125, 255}),
- Face: basicfont.Face7x13,
- Dot: fixed.P(5, 10),
- }
- l.drawer.DrawString(s)
- l.m.Upload()
- l.m.Draw(
- sz,
- geom.Point{X: 0, Y: 50},
- geom.Point{X: geom.Pt(imgW), Y: 50},
- geom.Point{X: 0, Y: geom.Pt(imgH)},
- l.m.RGBA.Bounds(),
- )
-}
-
-func (l *Label) Release() {
- if l.m != nil {
- l.m.Release()
- l.m = nil
- l.images = nil
- }
-}
-
-// GclipApp is the application instance.
-type GclipApp struct {
- app app.App
-
- ctx gl.Context
- siz size.Event
-
- images *glutil.Images
- l *Label
-
- counter int
-}
-
-// WatchClipboard watches the system clipboard every seconds.
-func (g *GclipApp) WatchClipboard() {
- go func() {
- tk := time.NewTicker(time.Second)
- for range tk.C {
- // Write something to the clipboard
- w := fmt.Sprintf("(gclip: %d)", g.counter)
- clipboard.Write(clipboard.FmtText, []byte(w))
- g.counter++
- log.Println(w)
-
- // Read it back and render it, if possible.
- data := clipboard.Read(clipboard.FmtText)
- if len(data) == 0 {
- continue
- }
-
- // Set the current clipboard data as label content and render on the screen.
- r := fmt.Sprintf("clipboard: %s", string(data))
- g.l.SetLabel(r)
- g.app.Send(paint.Event{})
- }
- }()
-}
-
-func (g *GclipApp) OnStart(e lifecycle.Event) {
- g.ctx, _ = e.DrawContext.(gl.Context)
- g.images = glutil.NewImages(g.ctx)
- g.l = NewLabel(g.images)
- g.app.Send(paint.Event{})
-}
-
-func (g *GclipApp) OnStop() {
- g.l.Release()
- g.images.Release()
- g.ctx = nil
-}
-
-func (g *GclipApp) OnSize(size size.Event) {
- g.siz = size
-}
-
-func (g *GclipApp) OnDraw() {
- if g.ctx == nil {
- return
- }
- defer g.app.Send(paint.Event{})
- defer g.app.Publish()
- g.ctx.ClearColor(0, 0, 0, 1)
- g.ctx.Clear(gl.COLOR_BUFFER_BIT)
- g.l.Draw(g.siz)
-}
-
-func init() {
- err := clipboard.Init()
- if err != nil {
- panic(err)
- }
-}
-
-func main() {
- app.Main(func(a app.App) {
- gclip := GclipApp{app: a}
- gclip.app.Send(size.Event{WidthPx: 800, HeightPx: 500})
- gclip.WatchClipboard()
- for e := range gclip.app.Events() {
- switch e := gclip.app.Filter(e).(type) {
- case lifecycle.Event:
- switch e.Crosses(lifecycle.StageVisible) {
- case lifecycle.CrossOn:
- gclip.OnStart(e)
- case lifecycle.CrossOff:
- gclip.OnStop()
- os.Exit(0)
- }
- case size.Event:
- gclip.OnSize(e)
- case paint.Event:
- gclip.OnDraw()
- }
- }
- })
-}
diff --git a/packages/tui/clipboard/cmd/gclip/README.md b/packages/tui/clipboard/cmd/gclip/README.md
deleted file mode 100644
index d4ea0a6c0..000000000
--- a/packages/tui/clipboard/cmd/gclip/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# gclip
-
-`gclip` command offers the ability to interact with the system clipboard
-from the shell. To install:
-
-```bash
-$ go install golang.design/x/clipboard/cmd/gclip@latest
-```
-
-```bash
-$ gclip
-gclip is a command that provides clipboard interaction.
-usage: gclip [-copy|-paste] [-f <file>]
-options:
- -copy
- copy data to clipboard
- -f string
- source or destination to a given file path
- -paste
- paste data from clipboard
-examples:
-gclip -paste paste from clipboard and prints the content
-gclip -paste -f x.txt paste from clipboard and save as text to x.txt
-gclip -paste -f x.png paste from clipboard and save as image to x.png
-cat x.txt | gclip -copy copy content from x.txt to clipboard
-gclip -copy -f x.txt copy content from x.txt to clipboard
-gclip -copy -f x.png copy x.png as image data to clipboard
-```
-
-If `-copy` is used, the command will exit when the data is no longer
-available from the clipboard. You can always send the command to the
-background using a shell `&` operator, for example:
-
-```bash
-$ cat x.txt | gclip -copy &
-```
-
-## License
-
-MIT | &copy; 2021 The golang.design Initiative Authors, written by [Changkun Ou](https://changkun.de). \ No newline at end of file
diff --git a/packages/tui/clipboard/cmd/gclip/main.go b/packages/tui/clipboard/cmd/gclip/main.go
deleted file mode 100644
index 30d5714b3..000000000
--- a/packages/tui/clipboard/cmd/gclip/main.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-package main // go install golang.design/x/clipboard/cmd/gclip@latest
-
-import (
- "flag"
- "fmt"
- "io"
- "os"
- "path/filepath"
-
- "golang.design/x/clipboard"
-)
-
-func usage() {
- fmt.Fprintf(os.Stderr, `gclip is a command that provides clipboard interaction.
-
-usage: gclip [-copy|-paste] [-f <file>]
-
-options:
-`)
- flag.PrintDefaults()
- fmt.Fprintf(os.Stderr, `
-examples:
-gclip -paste paste from clipboard and prints the content
-gclip -paste -f x.txt paste from clipboard and save as text to x.txt
-gclip -paste -f x.png paste from clipboard and save as image to x.png
-
-cat x.txt | gclip -copy copy content from x.txt to clipboard
-gclip -copy -f x.txt copy content from x.txt to clipboard
-gclip -copy -f x.png copy x.png as image data to clipboard
-`)
- os.Exit(2)
-}
-
-var (
- in = flag.Bool("copy", false, "copy data to clipboard")
- out = flag.Bool("paste", false, "paste data from clipboard")
- file = flag.String("f", "", "source or destination to a given file path")
-)
-
-func init() {
- err := clipboard.Init()
- if err != nil {
- panic(err)
- }
-}
-
-func main() {
- flag.Usage = usage
- flag.Parse()
- if *out {
- if err := pst(); err != nil {
- usage()
- }
- return
- }
- if *in {
- if err := cpy(); err != nil {
- usage()
- }
- return
- }
- usage()
-}
-
-func cpy() error {
- t := clipboard.FmtText
- ext := filepath.Ext(*file)
-
- switch ext {
- case ".png":
- t = clipboard.FmtImage
- case ".txt":
- fallthrough
- default:
- t = clipboard.FmtText
- }
-
- var (
- b []byte
- err error
- )
- if *file != "" {
- b, err = os.ReadFile(*file)
- if err != nil {
- fmt.Fprintf(os.Stderr, "failed to read given file: %v", err)
- return err
- }
- } else {
- b, err = io.ReadAll(os.Stdin)
- if err != nil {
- fmt.Fprintf(os.Stderr, "failed to read from stdin: %v", err)
- return err
- }
- }
-
- // Wait until clipboard content has been changed.
- <-clipboard.Write(t, b)
- return nil
-}
-
-func pst() (err error) {
- var b []byte
-
- b = clipboard.Read(clipboard.FmtText)
- if b == nil {
- b = clipboard.Read(clipboard.FmtImage)
- }
-
- if *file != "" && b != nil {
- err = os.WriteFile(*file, b, os.ModePerm)
- if err != nil {
- fmt.Fprintf(os.Stderr, "failed to write data to file %s: %v", *file, err)
- }
- return err
- }
-
- for len(b) > 0 {
- n, err := os.Stdout.Write(b)
- if err != nil {
- return err
- }
- b = b[n:]
- }
- return nil
-}
diff --git a/packages/tui/clipboard/example_test.go b/packages/tui/clipboard/example_test.go
deleted file mode 100644
index 72d613a80..000000000
--- a/packages/tui/clipboard/example_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-//go:build cgo
-
-package clipboard_test
-
-import (
- "context"
- "fmt"
- "time"
-
- "golang.design/x/clipboard"
-)
-
-func ExampleWrite() {
- err := clipboard.Init()
- if err != nil {
- panic(err)
- }
-
- clipboard.Write(clipboard.FmtText, []byte("Hello, 世界"))
- // Output:
-}
-
-func ExampleRead() {
- err := clipboard.Init()
- if err != nil {
- panic(err)
- }
-
- fmt.Println(string(clipboard.Read(clipboard.FmtText)))
- // Output:
- // Hello, 世界
-}
-
-func ExampleWatch() {
- err := clipboard.Init()
- if err != nil {
- panic(err)
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
- defer cancel()
-
- changed := clipboard.Watch(context.Background(), clipboard.FmtText)
- go func(ctx context.Context) {
- clipboard.Write(clipboard.FmtText, []byte("你好,world"))
- }(ctx)
- fmt.Println(string(<-changed))
- // Output:
- // 你好,world
-}
diff --git a/packages/tui/clipboard/export_test.go b/packages/tui/clipboard/export_test.go
deleted file mode 100644
index 69af20ace..000000000
--- a/packages/tui/clipboard/export_test.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2021 The golang.design Initiative Authors.
-// All rights reserved. Use of this source code is governed
-// by a MIT license that can be found in the LICENSE file.
-//
-// Written by Changkun Ou <changkun.de>
-
-package clipboard
-
-// for debugging errors
-var (
- Debug = debug
- ErrUnavailable = errUnavailable
- ErrCgoDisabled = errNoCgo
-)
diff --git a/packages/tui/clipboard/go.mod b/packages/tui/clipboard/go.mod
deleted file mode 100644
index ba0dd55b2..000000000
--- a/packages/tui/clipboard/go.mod
+++ /dev/null
@@ -1,13 +0,0 @@
-module golang.design/x/clipboard
-
-go 1.24
-
-require (
- golang.org/x/image v0.28.0
- golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f
-)
-
-require (
- golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 // indirect
- golang.org/x/sys v0.33.0 // indirect
-)
diff --git a/packages/tui/clipboard/go.sum b/packages/tui/clipboard/go.sum
deleted file mode 100644
index a68e266bd..000000000
--- a/packages/tui/clipboard/go.sum
+++ /dev/null
@@ -1,8 +0,0 @@
-golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 h1:Wdx0vgH5Wgsw+lF//LJKmWOJBLWX6nprsMqnf99rYDE=
-golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:ygj7T6vSGhhm/9yTpOQQNvuAUFziTH7RUiH74EoE2C8=
-golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE=
-golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY=
-golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f h1:/n+PL2HlfqeSiDCuhdBbRNlGS/g2fM4OHufalHaTVG8=
-golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f/go.mod h1:ESkJ836Z6LpG6mTVAhA48LpfW/8fNR0ifStlH2axyfg=
-golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
-golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
diff --git a/packages/tui/clipboard/test_linux_nocgo.sh b/packages/tui/clipboard/test_linux_nocgo.sh
deleted file mode 100755
index 877da2112..000000000
--- a/packages/tui/clipboard/test_linux_nocgo.sh
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/bin/bash
-# Test script for Linux CGO-free clipboard implementation
-
-echo "Testing Linux clipboard implementation without CGO..."
-
-# Check for required tools
-echo "Checking for clipboard tools..."
-for tool in xclip xsel wl-copy; do
- if command -v $tool &> /dev/null; then
- echo "✓ $tool is installed"
- else
- echo "✗ $tool is not installed"
- fi
-done
-
-# Create test program
-cat > test_linux_clipboard.go << 'EOF'
-package main
-
-import (
- "fmt"
- "log"
- "os"
- "golang.design/x/clipboard"
-)
-
-func main() {
- err := clipboard.Init()
- if err != nil {
- log.Fatal("Failed to initialize clipboard:", err)
- }
-
- // Test text
- fmt.Println("\n=== Testing Text Clipboard ===")
- testText := []byte("Hello from CGO-free Linux clipboard!")
- clipboard.Write(clipboard.FmtText, testText)
- fmt.Println("Wrote text:", string(testText))
-
- readText := clipboard.Read(clipboard.FmtText)
- fmt.Println("Read text:", string(readText))
-
- if string(testText) == string(readText) {
- fmt.Println("✓ Text clipboard test passed")
- } else {
- fmt.Println("✗ Text clipboard test failed")
- }
-
- // Test empty write
- fmt.Println("\n=== Testing Empty Write ===")
- clipboard.Write(clipboard.FmtText, []byte{})
- emptyRead := clipboard.Read(clipboard.FmtText)
- if emptyRead == nil || len(emptyRead) == 0 {
- fmt.Println("✓ Empty write test passed")
- } else {
- fmt.Println("✗ Empty write test failed, got:", string(emptyRead))
- }
-
- // Test image if requested
- if len(os.Args) > 1 && os.Args[1] == "image" {
- fmt.Println("\n=== Testing Image Clipboard ===")
-
- // Try to read test image
- imageData, err := os.ReadFile("tests/testdata/clipboard.png")
- if err != nil {
- fmt.Println("Could not read test image:", err)
- return
- }
-
- clipboard.Write(clipboard.FmtImage, imageData)
- fmt.Println("Wrote image data, length:", len(imageData))
-
- readImage := clipboard.Read(clipboard.FmtImage)
- if readImage != nil {
- fmt.Println("Read image data, length:", len(readImage))
- if len(imageData) == len(readImage) {
- fmt.Println("✓ Image clipboard test passed")
- } else {
- fmt.Println("✗ Image lengths don't match")
- }
- } else {
- fmt.Println("✗ Failed to read image from clipboard")
- }
-
- // Test that reading text from image clipboard returns nil
- textFromImage := clipboard.Read(clipboard.FmtText)
- if textFromImage == nil {
- fmt.Println("✓ Reading text from image clipboard correctly returned nil")
- } else {
- fmt.Println("✗ Reading text from image clipboard should return nil, got:", string(textFromImage))
- }
- }
-}
-EOF
-
-# Run tests with CGO disabled
-echo -e "\n=== Running with CGO_ENABLED=0 ==="
-CGO_ENABLED=0 go run test_linux_clipboard.go
-
-echo -e "\n=== Running with CGO_ENABLED=0 and image test ==="
-CGO_ENABLED=0 go run test_linux_clipboard.go image
-
-# Run actual tests
-echo -e "\n=== Running go test with CGO_ENABLED=0 ==="
-CGO_ENABLED=0 go test -v -run TestClipboard
-
-# Clean up
-rm -f test_linux_clipboard.go
-
-echo -e "\nTest script completed!" \ No newline at end of file
diff --git a/packages/tui/clipboard/tests/Makefile b/packages/tui/clipboard/tests/Makefile
deleted file mode 100644
index 809e2eaf5..000000000
--- a/packages/tui/clipboard/tests/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2021 The golang.design Initiative Authors.
-# All rights reserved. Use of this source code is governed
-# by a MIT license that can be found in the LICENSE file.
-#
-# Written by Changkun Ou <changkun.de>
-
-all: test
-
-test:
- go test -v -count=1 -covermode=atomic ..
-
-test-docker:
- docker build -t golang-design/x/clipboard ..
- docker run --rm --name cb golang-design/x/clipboard
- docker rmi golang-design/x/clipboard \ No newline at end of file
diff --git a/packages/tui/clipboard/tests/test-docker.sh b/packages/tui/clipboard/tests/test-docker.sh
deleted file mode 100755
index a17a6af75..000000000
--- a/packages/tui/clipboard/tests/test-docker.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2021 The golang.design Initiative Authors.
-# All rights reserved. Use of this source code is governed
-# by a MIT license that can be found in the LICENSE file.
-#
-# Written by Changkun Ou <changkun.de>
-
-# require apt-get install xvfb
-Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
-export DISPLAY=:99.0
-
-go test -v -covermode=atomic ./... \ No newline at end of file
diff --git a/packages/tui/clipboard/tests/testdata/android.png b/packages/tui/clipboard/tests/testdata/android.png
deleted file mode 100644
index b309ce409..000000000
--- a/packages/tui/clipboard/tests/testdata/android.png
+++ /dev/null
Binary files differ
diff --git a/packages/tui/clipboard/tests/testdata/clipboard.png b/packages/tui/clipboard/tests/testdata/clipboard.png
deleted file mode 100644
index cd3af8c10..000000000
--- a/packages/tui/clipboard/tests/testdata/clipboard.png
+++ /dev/null
Binary files differ
diff --git a/packages/tui/clipboard/tests/testdata/darwin.png b/packages/tui/clipboard/tests/testdata/darwin.png
deleted file mode 100644
index b9ed2bff9..000000000
--- a/packages/tui/clipboard/tests/testdata/darwin.png
+++ /dev/null
Binary files differ
diff --git a/packages/tui/clipboard/tests/testdata/ios.png b/packages/tui/clipboard/tests/testdata/ios.png
deleted file mode 100644
index ddc7a9d43..000000000
--- a/packages/tui/clipboard/tests/testdata/ios.png
+++ /dev/null
Binary files differ
diff --git a/packages/tui/clipboard/tests/testdata/linux.png b/packages/tui/clipboard/tests/testdata/linux.png
deleted file mode 100644
index e15627351..000000000
--- a/packages/tui/clipboard/tests/testdata/linux.png
+++ /dev/null
Binary files differ
diff --git a/packages/tui/clipboard/tests/testdata/windows.png b/packages/tui/clipboard/tests/testdata/windows.png
deleted file mode 100644
index dd25f31dc..000000000
--- a/packages/tui/clipboard/tests/testdata/windows.png
+++ /dev/null
Binary files differ
diff --git a/packages/tui/cmd/opencode/main.go b/packages/tui/cmd/opencode/main.go
index ada1880d1..0c8f70c8b 100644
--- a/packages/tui/cmd/opencode/main.go
+++ b/packages/tui/cmd/opencode/main.go
@@ -13,8 +13,8 @@ import (
"github.com/sst/opencode-sdk-go"
"github.com/sst/opencode-sdk-go/option"
"github.com/sst/opencode/internal/app"
+ "github.com/sst/opencode/internal/clipboard"
"github.com/sst/opencode/internal/tui"
- "golang.design/x/clipboard"
)
var Version = "dev"
diff --git a/packages/tui/go.mod b/packages/tui/go.mod
index 08bc1c589..12dd3f88e 100644
--- a/packages/tui/go.mod
+++ b/packages/tui/go.mod
@@ -17,14 +17,11 @@ require (
github.com/muesli/termenv v0.16.0
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
github.com/sst/opencode-sdk-go v0.1.0-alpha.8
- golang.design/x/clipboard v0.7.1
+ golang.org/x/image v0.28.0
rsc.io/qr v0.2.0
)
-replace (
- github.com/sst/opencode-sdk-go => ./sdk
- golang.design/x/clipboard => ./clipboard
-)
+replace github.com/sst/opencode-sdk-go => ./sdk
require golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
@@ -58,8 +55,6 @@ require (
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
- golang.org/x/exp/shiny v0.0.0-20250620022241-b7579e27df2b // indirect
- golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/tools v0.34.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
@@ -87,7 +82,6 @@ require (
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yuin/goldmark v1.7.8 // indirect
github.com/yuin/goldmark-emoji v1.0.5 // indirect
- golang.org/x/image v0.28.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
diff --git a/packages/tui/go.sum b/packages/tui/go.sum
index 969cf1beb..9eab3f577 100644
--- a/packages/tui/go.sum
+++ b/packages/tui/go.sum
@@ -216,12 +216,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
-golang.org/x/exp/shiny v0.0.0-20250620022241-b7579e27df2b h1:zELBzk+7ERc6m8BxhzU2VYjp03wlEvi+cIgYQR5H3CI=
-golang.org/x/exp/shiny v0.0.0-20250620022241-b7579e27df2b/go.mod h1:ygj7T6vSGhhm/9yTpOQQNvuAUFziTH7RUiH74EoE2C8=
golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE=
golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY=
-golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f h1:/n+PL2HlfqeSiDCuhdBbRNlGS/g2fM4OHufalHaTVG8=
-golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f/go.mod h1:ESkJ836Z6LpG6mTVAhA48LpfW/8fNR0ifStlH2axyfg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go
index 83934343e..a70b3ca64 100644
--- a/packages/tui/internal/app/app.go
+++ b/packages/tui/internal/app/app.go
@@ -12,13 +12,13 @@ import (
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode/internal/clipboard"
"github.com/sst/opencode/internal/commands"
"github.com/sst/opencode/internal/components/toast"
"github.com/sst/opencode/internal/config"
"github.com/sst/opencode/internal/styles"
"github.com/sst/opencode/internal/theme"
"github.com/sst/opencode/internal/util"
- "golang.design/x/clipboard"
)
type App struct {
diff --git a/packages/tui/clipboard/clipboard.go b/packages/tui/internal/clipboard/clipboard.go
index bd7c69843..70e05bd29 100644
--- a/packages/tui/clipboard/clipboard.go
+++ b/packages/tui/internal/clipboard/clipboard.go
@@ -53,7 +53,7 @@ clipboard data is changed, use the watcher API:
println(string(data))
}
*/
-package clipboard // import "golang.design/x/clipboard"
+package clipboard
import (
"context"
diff --git a/packages/tui/clipboard/clipboard_darwin.go b/packages/tui/internal/clipboard/clipboard_darwin.go
index 0b902403a..ead6811f1 100644
--- a/packages/tui/clipboard/clipboard_darwin.go
+++ b/packages/tui/internal/clipboard/clipboard_darwin.go
@@ -4,7 +4,7 @@
//
// Written by Changkun Ou <changkun.de>
-//go:build darwin && !ios
+//go:build darwin
package clipboard
diff --git a/packages/tui/clipboard/clipboard_linux.go b/packages/tui/internal/clipboard/clipboard_linux.go
index ca4a8db75..ca8a3bc6a 100644
--- a/packages/tui/clipboard/clipboard_linux.go
+++ b/packages/tui/internal/clipboard/clipboard_linux.go
@@ -4,7 +4,7 @@
//
// Written by Changkun Ou <changkun.de>
-//go:build linux && !android
+//go:build linux
package clipboard
diff --git a/packages/tui/clipboard/clipboard_nocgo.go b/packages/tui/internal/clipboard/clipboard_nocgo.go
index 7b3e05f6c..7b3e05f6c 100644
--- a/packages/tui/clipboard/clipboard_nocgo.go
+++ b/packages/tui/internal/clipboard/clipboard_nocgo.go
diff --git a/packages/tui/clipboard/clipboard_windows.go b/packages/tui/internal/clipboard/clipboard_windows.go
index bd042cda8..bd042cda8 100644
--- a/packages/tui/clipboard/clipboard_windows.go
+++ b/packages/tui/internal/clipboard/clipboard_windows.go
diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go
index 071f22d0e..6053c9c01 100644
--- a/packages/tui/internal/components/chat/editor.go
+++ b/packages/tui/internal/components/chat/editor.go
@@ -15,13 +15,13 @@ import (
"github.com/google/uuid"
"github.com/sst/opencode-sdk-go"
"github.com/sst/opencode/internal/app"
+ "github.com/sst/opencode/internal/clipboard"
"github.com/sst/opencode/internal/commands"
"github.com/sst/opencode/internal/components/dialog"
"github.com/sst/opencode/internal/components/textarea"
"github.com/sst/opencode/internal/styles"
"github.com/sst/opencode/internal/theme"
"github.com/sst/opencode/internal/util"
- "golang.design/x/clipboard"
)
type EditorComponent interface {
diff --git a/packages/tui/opencode b/packages/tui/opencode
new file mode 100755
index 000000000..cdaf172d2
--- /dev/null
+++ b/packages/tui/opencode
Binary files differ