zyedidia / micro

A modern and intuitive terminal-based text editor

Home Page:https://micro-editor.github.io

Repository from Github https://github.comzyedidia/microRepository from Github https://github.comzyedidia/micro

Copying with Ctrl-C Shows "Copied selection" but Does Not Copy to Clipboard When Using Tabby

Drarox opened this issue · comments

I'm using Micro (version 2.0.14) with the Tabby terminal on a SSH session. When I try to copy text using Ctrl-C, the editor displays "Copied selection," but nothing is actually copied to my system clipboard. My clipboard still contains the last thing I copied outside of Micro.

I have clipboard set to "terminal" in my ~/.config/micro/settings.json:

{
  "clipboard": "terminal"
}

Tabby supports OSC 52 (as needed by micro), and I verified that copying via the terminal works correctly using:

printf "\033]52;;$(printf "%s" "foo001" | base64)\a"

This correctly copies "foo001" to my clipboard, so the issue seems to be specific to Micro.

Steps to Reproduce:

  1. Open Micro in Tabby.
  2. Select text and press Ctrl-C.
  3. Try pasting in micro or elsewhere (Ctrl-V in another application).

Expected Behavior:

  • The selected text should be copied to the clipboard.

Actual Behavior:

  • The message "Copied selection" appears, but the clipboard does not update.

Additional Info:

  • Micro version: 2.0.14
  • Tabby version: 1.0.221

Any guidance or fixes would be greatly appreciated! Let me know if I can provide further debugging information.

This seems to be a bug with Tabby: Eugeny/tabby#9845

Someone else may know a better workaround, but probably the easiest one in Micro is creating a script in $PATH named micro-clip (currently undocumented: #3629 (comment)) then setting clipboard to "external".

I tried writing an example script, but I cannot run Tabby probably because I am using Debian 11 (old).
There may be small changes needed.

#!/bin/sh

[ "$2" = clipboard ] || exit 0

case $1 in
-i)
    # copy text
    printf '\033]52;c;%s\033\\' "`base64 -w0`" >/dev/tty;;
-o)
    # paste text

    # probably not supported in tabby?
    exit 0

    exec </dev/tty
    old=`stty -g`
    # wrong settings?
    stty raw -echo min 0 time 6 >/dev/tty

    printf '\033]52;c;?\033\\' >/dev/tty
    IFS=$(printf '\033\\;')
    read -r _ _ _ e _

    stty $old >/dev/tty
    printf %s "$e" | base64 -d;;
esac

Thank you for the information!

I updated the script, and now running:

echo "Test123" | micro-clip -i clipboard

successfully copies "Test123" to my clipboard.

I placed the micro-clip script in my $PATH and changed Micro's clipboard setting to "external". However, Micro doesn’t seem to call micro-clip at all, nothing changes when I try to copy inside Micro.

Is there a way to debug if Micro is actually invoking micro-clip? Or could there be something else preventing it from using the external clipboard handler?

Thanks again for your help!

I placed the micro-clip script in my $PATH and changed Micro's clipboard setting to "external". However, Micro doesn’t seem to call micro-clip at all, nothing changes when I try to copy inside Micro.

I honestly wasn't able to determine the cause, but have you restarted Micro or run > reload?

Is there a way to debug if Micro is actually invoking micro-clip? Or could there be something else preventing it from using the external clipboard handler?

There isn't really a way to debug, but a line like { printf '%s\n' "`date`: $*"; } >> clip-test.log could be inserted in the script before the case statement.

Thanks for the help! It turns out the script was being executed correctly—I just forgot to redirect the output to > /dev/tty, which was why the OSC 52 sequence wasn’t updating the clipboard. Once I added that, copying inside Micro started working as expected.

While testing, I noticed that when Micro starts, it automatically runs:

  1. micro-clip -o clipboard (which fails since pasting isn’t supported via OSC 52).
  2. micro-clip -i clipboard (but with no actual input, which overwrites the clipboard with an empty value).

This meant my clipboard was being cleared every time I opened Micro. I'm not sure why it's doing this but I fixed it by modifying the script to ignore empty inputs when copying. Here’s the final working version:

#!/bin/sh

[ "$2" = clipboard ] || exit 0

case $1 in
  -i)
    # Prevent copying if no input is provided (fix for Micro startup issue)
    data=$(cat)
    if [ -z "$data" ]; then
      exit 0
    fi

    # Encode in Base64 and send via OSC 52
    printf "\033]52;;%s\a" "$(echo -n "$data" | base64)" > /dev/tty
    ;;
  -o)
    # Pasting is not supported via OSC 52
    exit 1
    ;;
esac

Now, copying in Micro correctly updates the clipboard without any issues, and opening Micro no longer clears it.

If anyone else needs this fix, all you need to do is create a script named micro-clip with the above code and place it in your $PATH. Then, set Micro’s clipboard settings to "external" (which is the default), and it should work!

Thanks again for pointing me in the right direction! 🚀

You're welcome, it's at least good that the workaround works.

It may be better to change these parts:

  • data=$(cat)data=$(cat && echo .); data=${data%.} - does not add or remove \n in copied data
  • "$(echo -n "$data" | base64)""$(printf %s "$data" | base64 -w0)" - avoids platform portability issues with echo and wrapping the Base64 string at 80 columns

While testing, I noticed that when Micro starts, it automatically runs:

...
2. micro-clip -i clipboard (but with no actual input, which overwrites the clipboard with an empty value).

This meant my clipboard was being cleared every time I opened Micro.

I think it is weird that the clipboard is cleared, even when reading the comment in the code of the library used. If anyone is interested: https://github.com/zyedidia/clipper/blob/v0.1.1/clipboard.go#L31

Thanks again for the help! Those improvements definitely make the script better, handling newlines properly and ensuring Base64 encoding is more portable are great refinements. I’ve updated my script accordingly.

Here’s the final improved script with the changes:

#!/bin/sh

[ "$2" = clipboard ] || exit 0

case $1 in
  -i)
    # Prevent copying if no input is provided (fix for Micro startup issue)
    data=$(cat && echo .); data=${data%.}
    if [ -z "$data" ]; then
      exit 0
    fi

    # Encode in Base64 and send via OSC 52
    printf "\033]52;;%s\a" "$(printf %s "$data" | base64 -w0)" > /dev/tty
    ;;
  -o)
    # Pasting is not supported via OSC 52
    exit 1
    ;;
esac