charmbracelet / bubbletea

A powerful little TUI framework 🏗
MIT License
27.48k stars 794 forks source link

Async Clipboard #982

Closed meowgorithm closed 1 month ago

meowgorithm commented 6 months ago

I've been seeing reports that clipboard operations can take a long time in WSL. While moving copy/paste to Cmds won't solve this issue, it's probably worth doing it regardless, both because clipboard stuff is I/O, and to provide a unified copy/paste API to all Bubble Tea applications.

Note that we also discussed this in @aymanbagabas's upcoming Kitty Keyboard work.

ajayd-san commented 3 months ago

Hey can I take this up ?

meowgorithm commented 3 months ago

Sounds good to me. @aymanbagabas, whatcha think?

aymanbagabas commented 3 months ago

I think that would be wonderful to add to Bubble Tea!

Looking at implementation details, there are a couple of golang clipboard libraries such as https://github.com/atotto/clipboard and https://github.com/golang-design/clipboard, but each has its own shortcomings. The former always assumes programs running locally (no remote sessions support) and the latter uses CGO.

Given this, I'm proposing porting atotto/clipboard to bubbletea with a few changes to recognize the program environment variables and use OSC52 when working with remote sessions like SSH. Something along the lines of this API

type ClipboardWriteMsg bool

func ClipboardWrite(text string) tea.Cmd {
  return func() tea.Msg {
    err := copyClipboard()
    return ClipboardWriteMsg(err == nil)
  }
}

type ClipboardReadMsg string

func ClipboardRead() tea.Cmd {
  return func() tea.Msg {
    text := readClipboard()
    return ClipboardReadMsg(text)
  }
}
ajayd-san commented 3 months ago

Hey, So tell me if I'm going in the right direction.

I'm thinking of adding ClipboardRead and ClipboardWrite functions in commands.go and I'll be using atotto/clipboard for normal sessions and x/clipboard for ssh session.

How do i know if I'm in a ssh session? Check if SSH_CLIENT or SSH_TTY is set in p.environ.

Does this look good?

aymanbagabas commented 3 months ago

I'll be using atotto/clipboard for normal sessions

That wouldn't work because atotto/clipboard uses os.Getenv() instead of p.environ to determine environment variables. We need to port atotto/clipboard to bubbletea and make it use the program's environment variables.

How do i know if I'm in a ssh session? Check if SSH_CLIENT or SSH_TTY is set in p.environ.

Correct, check for SSH_TTY to determine if the remote session is a terminal and use ansi.SetClipboard to use OSC52.

ajayd-san commented 3 months ago

Aight I'll fork atotto/clipboard make the required changes, and get back to you when I'm done.

ajayd-san commented 3 months ago

So, I've ported atotto/clipboard to use user defined env vars (p.environ) instead of os.GetEnv() : https://github.com/ajayd-san/clipboard/commit/b53899f6654a2fe1d1a0aa887ea4f2c9138a609c

Have a look and let me know if it looks good.

ajayd-san commented 3 months ago

Hey, Can anyone tell me if I'm going in the right direction? Any input would be appreciated. Thanks