Integrating GNU Screen copy/scrollback mode with the local system clipboard

GNU Screen is a great UNIX tool, allowing a single terminal session to multiplex and manage multiple virtual terminal windows. As a long time user of screen, over 10 years, one of the features I frequently use is the copy/scrollback mode. Oftentimes, I wish this mode had better integration with the system clipboard.

Copy/Scrollback mode (CTRL-A ESC) in screen allows you navigate the buffer of screen's virtual terminals using vi-like keybindings (hjkl, etc). An additional feature of this mode is the ability to mark portions of text in the buffer to be copied into screen's internal clipboard. This internal clipboard is only usable for writing to a preconfigured filename (CTRL-A >) or using a screen command to paste (CTRL-A ]) into a virtual terminal.

I recently came across a blog article touting the benefits of using screen on Mac OSX. One of the sections described "Copying to the Mac Clipboard" using OSX's built-in pbcopy command to integrate screen's copy buffer with the Mac's own system clipboard. This inspired me to come up with a similar solution for use on Windows.

My solution is more complex than simply using a command line program as I often will start screen sessions on remote systems and would still like to maintain the integration with the local system clipboard. pbcopy can't do this. X11 users have it easy with the xclip program, using forwarded X11 sessions with ssh, it is trivial to integrate remote screen copy-buffer with the local clipboard. Windows doesn't have any answer to this problem at all.

First, I wrote a small Java program to listen on a TCP port (4573) and forwards all data received into the local system clipboard; the program is called Clipboard Listener and source is available under the GPL. The program can be minimized to the system tray or notification area to be as unobtrusive as possible. It displays a notification bubble whenever new data is received on port 4573.

Next, there is a small shell script (copy-to-clipboard) which invokes netcat (nc), commonly available on Linux systems and easily installed if not found. Replace CLIPBOARDLISTENERHOSTNAME with localhost (in ssh) or the host upon which the clipboard listener is running on.

#!/bin/sh

if [ -z "$1" ]; then
    echo "Usage: copy-to-clipboard <file>"
    exit 1
fi
nc CLIPBOARDLISTENERHOSTNAME 4573 < "$1"

Third, we setup screen to invoke the copytoclipboard script upon our screen selection. Add or edit the following lines into $HOME/.screenrc; replace /PATH/TO/ with the appropriate locations.

# Buffer file is where the screen copy buffer will be saved to.
bufferfile /PATH/TO/screen-copy-buffer
bind y eval "writebuf" "exec /PATH/TO/copy-to-clipboard /PATH/TO/screen-copy-buffer"

Alternatively, instead of using the copy-to-clipboard wrapper, nc can be invoked directly using the following bind. I use the former rather than the latter because I may attach to a certain screen session from more than a single host; I will edit copy-to-clipboard to point to the appropriate host, rather than change the screen keybinding.

bind y eval "writebuf" "exec sh -c 'nc CLIPBOARDLISTENERHOSTNAME 4573 < /PATH/TO/screen-copy-buffer'"

Basically with those steps done, we have completed our integration of screen and the system clipboard. Additional steps have to be taken when integrating remote sessions via ssh (adding the flag -R 4573:localhost:4573). With the integration complete, we can now use the y (named after vi's yank) binding to forward screen's copy buffer into the local system clipboard (CTRL-A y). You can now use your system's paste functionality (such as CTRL-V) into any application which supports it. The clipboard listener application is portable across platforms, you should be able to use this technique on OSX as well if you have a desire to integrate remote screen sessions.

Note: If you use an escape key other than CTRL-A for screen (I use CTRL-O), substitute CTRL-A with your choice of escape key.

Comments: 8

#8 Kadu wrote on Fri Mar 11 05:57:30 PST 2011

Hi,

I would like to use your clipboard listener but am unable to run it on my linux box:

#javaws clipboard.jnlp 
netx: Unexpected net.sourceforge.jnlp.ParseException: \
Invalid value for heap size (6m) at net.sourceforge.jnlp.JREDesc.checkHeapSize(JREDesc.java:160)

Any thoughts on how I can get around this?

Many thanks Kadu

#7 Kaie wrote on Mon Sep 21 10:07:29 PDT 2009

Great sharing!! I also implement this trick into my vim (putty)! Now I can use Ctrl+C to copy selected text in vim to system-Clipboard... Just Cool~~

#6 resudda wrote on Sat Aug 15 22:28:03 PDT 2009

tmux will make your copy/paste challenges much easier storage and easy access to multiple copy/paste buffers and i find it more much more stable than screen

#5 guyzmo wrote on Wed Oct 15 07:14:22 PDT 2008

thanks for that neat hint, and yes, '+' *IS* a valid email character.

#4 Authenticated User Perry wrote on Wed Apr 23 00:51:54 PDT 2008

Hi Dave,

Glad to hear it's working out well for you, especially on OSX. I had forgotten that I compiled the program with Java 1.5 compatibility, the jnlp file is now updated to be compatible with 1.5+ as well.

#3 drdavo wrote on Tue Apr 22 16:13:55 PDT 2008

Perry - you are a legend - thanks for this post. Can confirm it works fine on mac osx 10.5 - I just had to edit your clipboard java webstart script to set the required java runtime version to 1.4+ (instead of 1.6 in yours) and it worked like a charm.

Namaste, Dave

#2 Authenticated User Perry wrote on Mon Mar 10 11:50:22 PDT 2008

Hi Adam,

Thanks for the feedback and link to your screenrc, mine isn't fancy, but I'll include it below as well. A lot of the cruft comes from the default screenrc.

I'll check out why I don't allow the + as well, although I don't recall it being a valid email character.

vbell on
vbell_msg "     *** DING *** ---- *** DING ***     "
bufferfile /home/pfnguyen/.scr_buf
autodetach on
startup_message off
defscrollback 4096
deflogin off
shelltitle Shell

# emulate .logout message
pow_detach_msg "Screen session of \$LOGNAME \$:cr:\$:nl:ended."

# Enable color for all terminal types
termcap  * 'AF=\E[3%dm:AB=\E[4%dm'
terminfo * 'AF=\E[3%p1%dm:AB=\E[4%p1%dm'

#xterm understands both im/ic and doesn't have a status line.
#Note: Do not specify im and ic in the real termcap/info file as
#some programs (e.g. vi) will not work anymore.
termcap  xterm hs@:cs=\E[%i%d;%dr:im=\E[4h:ei=\E[4l
terminfo xterm hs@:cs=\E[%i%p1%d;%p2%dr:im=\E[4h:ei=\E[4l

#80/132 column switching must be enabled for ^AW to work
#change init sequence to not switch width
termcapinfo  xterm Z0=\E[?3h:Z1=\E[?3l:is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l

# Make the output buffer large for (fast) xterms.
termcapinfo xterm* OL=10000

# tell screen that xterm can switch to dark background and has function
# keys.
termcapinfo xterm 'VR=\E[?5h:VN=\E[?5l'
termcapinfo xterm 'k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~'
termcapinfo xterm 'kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[H:kN=\E[6~'

# special xterm hardstatus: use the window title.
termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]0;screen\007'

# our xterm has colors! (rxvt, too)
termcap  xterm 'AF=\E[3%dm:AB=\E[4%dm'
terminfo xterm 'AF=\E[3%p1%dm:AB=\E[4%p1%dm'

#terminfo xterm 'vb=\E[?5h$<200/>\E[?5l'
termcapinfo xterm 'vi=\E[?25l:ve=\E[34h\E[?25h:vs=\E[34l'
defhstatus "^Et"
hardstatus string "[Ares %n%?: %t%?] %h"

################
#
# keybindings
#

# Change the escape character to ^O instead of ^A
# This is so much easier to type, IMO.
escape ^Oo

# to use nc directly instead of the wrapper script, use the following command
#bind y eval "writebuf" "exec sh -c 'nc localhost 4573 < $HOME/.scr_buf'"
# system clipboard integration
bind y eval "writebuf" "exec copy_to_clipboard $HOME/.scr_buf"

#remove some stupid / dangerous key bindings
bind j focus down
bind k focus up # originally was kill window
bind ^k
bind .
bind ^\
bind \\
bind ^h
bind h
#make them better
#bind '\\' quit
bind 'K' kill
bind 'I' login on
bind 'O' login off
bind '}' history

bind ^] paste [.]

# I often have more than 10 windows, use these keystrokes to intuitively get
# to the next 10 windows.
bind ) select 10
bind ! select 11
bind @ select 12
bind \043 select 13
bind $ select 14
bind % select 15
bind \136 select 16
bind & select 17
bind * select 18
bind ( select 19

#1 Adam Monsen wrote on Sun Mar 09 21:28:21 PDT 2008

That's pretty impressive. Never heard of xclip, but I'm already using it. Thanks!

In case you're curious about more strange and interesting things that can be done with GNU Screen, check out: http://adammonsen.com/post/256

I'm also a fan of a fancy status line with Screen. Here's my .screenrc: http://dotfiles.org/~meonkeys/.screenrc

Please let me know if you decide to share your .screenrc on dotfiles (or elsewhere).

By the way, I wasn't able to include a plus sign ("+") in my email address in the "Identify yourself" form I filled out after entering this comment.

Cheers! -Adam

Comment

No HTML is allowed. Numeric entity refs (&#nnnn;) are supported. Use {{{ and }}} to delimited preformatted sections. Items noted by * are mandatory.

Identify yourself

All new comments are moderated for spam protection. Email addresses are visible only to the entry owner and administrators.

  • Use AccessKey-P to Preview and AccessKey-S to Post