集成readline的kill-ring和X11剪贴板

问题描述 投票:0回答:5

在我的

.zshrc
中,我使用以下代码片段来集成 shell 的剪贴板和我的主 X11 剪贴板。由于这种集成,我可以在 emacs、firefox 和终端之间剪切和粘贴文本,而无需使用鼠标。

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

注意:我也在 mac os x 上使用这个技巧(使用 pbcopy/pbpaste 而不是 xclip),并且感谢 Synergy 我的两台计算机共享一个剪贴板。整洁的。但它不适用于 readline。我发现自己经常使用 readline,例如在 (i)python、gdb、ncftp 中...

所以我的问题来了:有没有办法将 readline 的剪贴板与世界其他地方集成?

当然,我正在考虑一些

.inputrc
魔法,但欢迎任何见解/想法。

unix zsh clipboard zsh-zle
5个回答
17
投票

Bash 4.0 引入了一些新功能:

新闻

分配给带有“

bind -x
”的按键序列的命令现在设置两个新的 执行命令的环境中的变量:
READLINE_LINE_BUFFER
READLINE_POINT
。 该命令可以改变当前readline行 和光标位置通过修改
READLINE_LINE_BUFFER
READLINE_POINT
, 分别。

NEWS
文件似乎不准确;
READLINE_LINE
(不是
_BUFFER
)是其他地方记录的并且实际上有效的。

以下内容将模拟 Bash 现有 Ctrl+(U|K|Y) 的行为,但会影响 X 选择,尽管我使用 Meta/Esc 因为我不喜欢覆盖现有功能。

_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'

我仍然更喜欢

screen
,但这更好地回答了你的问题——只要你关心的唯一 readline 应用程序是 Bash。


5
投票

就我个人而言,我在GNU 屏幕内运行所有内容。 这为我提供了跨所有基于终端的程序的大量功能,而不仅仅是基于读取行的程序。 它有自己的粘贴缓冲区,在当前会话中的所有屏幕之间共享,并且可以读取/写入交换文件(可使用

bufferfile
配置)。

  • 使用 Ctrl+A[、<移动>、空格、<移动>;
  • 进行屏幕选择
  • 使用 Enter复制到粘贴缓冲区;
  • 使用 Ctrl+A, ];
  • 粘贴
  • Ctrl+A<;
  • 替换为交换文件的内容
  • 并使用 Ctrl+A>写入交换文件。

那么您所需要的只是同步

/tmp/screen-exchange
和 X 选择的小帮手。 像这样简单的事情就可以了。

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

当然,一些更好的绑定和宏会让生活更轻松(这需要

C-a { C-a < C-a ]
将X选择粘贴到终端),但这完全取决于你。


5
投票

我想根据ephemient的答案提出以下

_xyank()
功能:

_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))
}

这样做的作用是将光标移动到拉出文本的末尾,使其与其他内置命令更加一致。


0
投票

正如我在here所写的那样,我发现使用单独的键绑定来填充X剪贴板会更好,这是因为我经常在Readline中使用“kill”进行文本操作,并且我不希望这会消除每次都剪贴板。

当 Readline 能够通过按键绑定来触发与 X 的交互时,我建议绑定 ^Xw 和 ^Xy 来复制和粘贴。

我知道这并不能解决你的问题,但我没有足够的代表在评论中说出来。

至于扩展 Readline 使其能够将按键绑定到命令,我在 Readline 邮件列表中提出了它,我们将看看 Chet 怎么说:

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


0
投票

除了上述答案之外,bash 5.0 还添加了一个新的

READLINE_MARK
变量,它也可以让我们实现“_xkill_ring_save”命令。

_xkill_ring_save() {
    if [[ -z "${READLINE_MARK}" ]]; then
        CLIP="${READLINE_LINE}"
    elif [[ "${READLINE_MARK}" -gt "${READLINE_POINT}" ]]; then
        LEN=$((READLINE_MARK - READLINE_POINT))
        CLIP="${READLINE_LINE:$READLINE_POINT:$LEN}"
    else
        LEN=$((READLINE_POINT - READLINE_MARK))
        CLIP="${READLINE_LINE:$READLINE_MARK:$LEN}"
    fi
    echo -n "${CLIP}" | xclip
}
bind -m emacs-meta -x '"w": _xkill_ring_save'
© www.soinside.com 2019 - 2024. All rights reserved.