15

In my .zshrc, I use the following snippet to integrate the shell's clipboard and my primary X11 clipboard. Thanks to this integration, I can cut-and-paste text to and from emacs, firefox, and the terminal without having to use the mouse.

kill-line() { zle .kill-line ; echo -n $CUTBUFFER | xclip -i }
zle -N kill-line # bound on C-k

yank() { LBUFFER=$LBUFFER$(xclip -o) }
zle -N yank # bound on C-y

Note: I use this trick on mac os x as well (with pbcopy/pbpaste instead of xclip) and thanks to Synergy my two computers share a single clipboard. Neat. But it doesn't work with readline. And I find myself using readline quite often, for example in (i)python, in gdb, in ncftp...

So here comes my question: is there a way to integrate readline's clipboard with the-rest-of-the-world ?

Of course, I'm thinkging about some .inputrc wizardry here, but any insight/ideas would be welcome.

ocodo
  • 29,401
  • 18
  • 105
  • 117
Gyom
  • 3,773
  • 5
  • 29
  • 38
  • I'm not sure what you really want here but I found another tool like xclip XSEL - http://www.vergenet.net/~conrad/software/xsel/ which seems more powerful – jitter Jun 15 '09 at 06:16
  • Thanks for sharing. Actually, what I'm after is a way to call a program like XSEL automatically from readline programs (e.g. bash) when I press Ctrl-K / Ctrl-Y. I guess this comes down to binding shell command to readline key combinations... – Gyom Jun 15 '09 at 07:15
  • I'd suggest you change your `echo -n` to `print -rn --` (or `printf %s`) above – Stephane Chazelas Feb 07 '14 at 14:28

4 Answers4

15

Bash 4.0 introduces some new functionality:

NEWS

The command assigned to a key sequence with `bind -x' now sets two new variables in the environment of the executed command: READLINE_LINE_BUFFER and READLINE_POINT. The command can change the current readline line and cursor position by modifying READLINE_LINE_BUFFER and READLINE_POINT, respectively.

The NEWS file seems to be inaccurate; READLINE_LINE (no _BUFFER) is what's documented elsewhere and actually works.

The following will simulate the behavior of Bash's existing Ctrl+(U|K|Y) but affecting the X selection, though I use Meta/Esc because I don't like overwriting existing functionality.

_xdiscard() {
    echo -n "${READLINE_LINE:0:$READLINE_POINT}" | xclip
    READLINE_LINE="${READLINE_LINE:$READLINE_POINT}"
    READLINE_POINT=0
}
_xkill() {
    echo -n "${READLINE_LINE:$READLINE_POINT}" | xclip
    READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}"
}
_xyank() {
    READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$(xclip -o)${READLINE_LINE:$READLINE_POINT}"
}
bind -m emacs -x '"\eu": _xdiscard'
bind -m emacs -x '"\ek": _xkill'
bind -m emacs -x '"\ey": _xyank'

I still like screen more, but this better answers your question — as long as the only readline application you care about is Bash.

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • thanks ; this is indeed the kind of stuff I wanted. Unfortunately, I'm using zsh as a shell, so when I use readline it is often with _other_ programs than bash :-) I guess I'll have to get used to screen. – Gyom Jul 07 '09 at 22:43
  • 1
    this is not working for me under bash 4.2.37. Those variables actually do not contain any value. – Forethinker Mar 20 '13 at 00:28
  • I up-voted this answer and user @Wei_Hu's modification below. See there. – user1404316 Mar 21 '18 at 13:50
5

Personally, I run everything inside GNU screen. This gives me tons of functionality across all terminal-based programs, not just readline-based ones. It has its own paste buffer(s), which are shared between all screens in your current session, and can read/write an exchange file (configurable with bufferfile).

  • A screen selection is made with Ctrl+A, [, <movement>, Space, <movement>;
  • copied to the paste buffer with Enter;
  • pasted with Ctrl+A, ];
  • replaced by the contents of the exchange file with Ctrl+A, <;
  • and written out to the exchange file with Ctrl+A, >.

Then all you need are little helpers to synchronize /tmp/screen-exchange and the X selection. Something as simple as this would work.

# ~/.screenrc (or entered at C-a : command prompt)
bind '{' exec sh -c 'xclip -o>~/.screen_exchange'
bind '}' exec sh -c 'xclip -i ~/.screen_exchange'

Of course some nicer bindings and macros would make life easier (this requires C-a { C-a < C-a ] to paste X selection to the terminal), but it's completely up to you.

ephemient
  • 198,619
  • 38
  • 280
  • 391
5

I'd like to propose the following _xyank() function based on ephemient's answer:

_xyank() {
    CLIP=$(xclip -o)
    COUNT=$(echo -n "$CLIP" | wc -c)
    READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}${CLIP}${READLINE_LINE:$READLINE_POINT}"
    READLINE_POINT=$(($READLINE_POINT + $COUNT))
}

What this does is to move the cursor to the end of yanked text, making it more consistent with other built-in commands.

Wei Hu
  • 2,888
  • 2
  • 27
  • 28
  • 1
    thanks as well, but again, my question was for non-bash readline applications :-) – Gyom Feb 03 '10 at 13:34
0

As I wrote here, I found it can be nicer to have separate keybindings to populate the X clipboard, this is because I often use "kill" for text manipulation in Readline, and I don't want this to wipe out the clipboard each time.

When Readline ever gets the ability to have keybindings which trigger interactions with X, I'd recommend binding ^Xw and ^Xy to copy and paste.

I know this doesn't provide a solution to your question, but I don't have enough rep to say it in a comment.

As for extending Readline with the ability to bind keys to commands, I brought it up on the Readline mailing list, we'll see what Chet says:

https://lists.gnu.org/archive/html/bug-readline/2016-05/msg00002.html

Community
  • 1
  • 1
Metamorphic
  • 732
  • 6
  • 16