将 Emacs 作为 X 剪切板管理器

发布于 2024-07-12 14:22:04 字数 4515 浏览 25 评论 0

一直以来,我都是使用 clipit(parcellite 的克隆版本) 作为 X 环境下的剪切板管理器(X clipboard manager)。 但是我发现当有一个剪切板管理器运行时,Emacs 会出现一个 bug , 这逼着我去寻找 clipit 的替代品。

我如愿以偿地找到了一个名为 clipmon 的 package, 它工作的相对还不错,但是美中不足的是,它也有一个 bug

而且,看起来在 Emacs 中监测 X 剪切板的唯一方式似乎只能由 Emacs 主动去检查 X 剪切板中的内容。 我不是很喜欢这种每隔一两秒就由 Emacs 检查一次 X 剪切板的方案。 我的替代方案是将检查剪切板的动作移出 Emacs,由 shell 脚本来完成。

  #!/bin/sh

  occ=$(xclip -sel clip -o | sed 's/[\"]/\\&/g')

  while sleep 2; do
      ncc=$(xclip -sel clip -o | sed 's/[\"]/\\&/g')
      if [ "${occ}" != "${ncc}" ]; then
          emacsclient -e "(kill-new \"${ncc}\")"
          occ=${ncc}
      fi
  done

这是一个简单而有效的解决方案,但是它依然要不断的探测剪切板的内容。 若能有一个事件驱动的解决方案就好了。 我的 Emacs 经历让我有股冲动去为 X 试着写一个 on-clipboard-change hook, 但这个工作量就太大了。

一般来讲, 除了 Emacs 之外,我只用另外两个应用(一个 web 浏览器,一个终端模拟器),而且这两款应用都是可定制的。

这使得每次我从这些应用中拷贝东西到 X 剪切板时都可以同时再将剪切板中的内容拷贝到 Emacs 的 kill ring 中去。我用的浏览器是 Conkeror,我将下面这段配置添加到它的初始化文件中去了。

  function ekr (cc) {
      if (typeof cc `=` 'undefined') { cc = read_from_clipboard(); }
      cc = cc.replace(/([^\\]*)\\([^\\]*)/g, "$1\\\\$2");
      cc = cc.replace('"', '\\"', "g");
      cc = cc.replace("'", "'\\''", "g");
      var ecc = "emacsclient -e '(kill-new \"" + cc + "\")' > /dev/null";
      shell_command_blind(ecc);
  }

  interactive(
      "ekr_cmd_copy",
      "Copy the selection to the clipboard and the Emacs kill ring",
      function (I) {
          call_builtin_command(I.window, "cmd_copy", true);
          ekr();
      }
  );

  undefine_key(caret_keymap,"M-w");
  define_key(caret_keymap,"M-w", "ekr_cmd_copy");
  undefine_key(content_buffer_normal_keymap,"M-w");
  define_key(content_buffer_normal_keymap,"M-w", "ekr_cmd_copy");
  undefine_key(special_buffer_keymap,"M-w");
  define_key(special_buffer_keymap,"M-w", "ekr_cmd_copy");
  undefine_key(text_keymap,"M-w");
  define_key(text_keymap,"M-w", "ekr_cmd_copy");

我还在 modules/commands.js 中的 kill-regionkill-ring-save 的命令以及 modules/content-buffer-input.js 中的 cut-to-end-of-line 命令后添加了对 ekr() 的调用。在 modules/elements.js 中的 copy_text 函数最后添加了对 ekr(text) 的调用.

第二个常用的非 Emacs 应用是 urxvt/tmux。 为了完成跟上面一样的效果,我将下面这行配置加入到 ~/.tmux.conf 中。

  bind-key -temacs-copy M-w copy-pipe 'c2e -r'

下面是 c2e 脚本的源代码。

  #!/bin/sh

  # c2e: Copy text to the Emacs kill ring.
  #
  # With no arguments, send the contents of the X clipboard to the Emacs kill ring.
  # With -r, first set the clipboard to the contents read from standard input.
  # With -s, instead send X primary selection to the Emacs kill ring.

  if [ "${1}" = '-r' ]; then
      exec xclip -sel clip -i -f | \
          emacsclient -e "(kill-new \"$(sed 's/[\"]/\\&/g')\")"
  elif [ "${1}" = '-s' ]; then
      exec xclip -o | \
          emacsclient -e "(kill-new \"$(sed 's/[\"]/\\&/g')\")"
  else
      exec xclip -sel clip -o | \
          emacsclient -e "(kill-new \"$(sed 's/[\"]/\\&/g')\")"
  fi

为了使这个新剪切板管理器(即 Emacs 的 kill ring) 更容易使用,我为 StumpWM 添加了一个新的命令和相应的快捷键。

  (defcommand eaacm () ()
    "Emacs as a clipboard manager."
    (run-or-raise "emacsclient -nc" '(:class "Emacs"))
    (run-shell-command "emacsclient -n -e '(let ((helm-full-frame t)) \
        (save-window-excursion (delete-other-windows) (helm-show-kill-ring)))'"))

  (define-key *root-map* (kbd "c") "eaacm")

现在不管我正在使用哪个应用,只需要按下 C-t c 就会有一个 helm 界面让我选择 kill ring 中的内容。 在 Helm 中甚至有一项功能可以将当前 entry 移动到 kill ring 的顶端同时将该 entry 的内容拷贝到 X 剪切板中。 该功能的默认快捷键是 C-c C-k

偶尔我也会需要在其他应用中拷贝内容到剪切板中,因此我还创建了两个简单的 StumpWM 命令来调用 c2e 脚本,并分别分配了快捷键。

  (defcommand c2e () ()
    "Copy the X clipboard contents to the Emacs kill ring."
    (run-shell-command "c2e"))

  (defcommand s2e () ()
    "Copy the X selection contents to the Emacs kill ring."
    (run-shell-command "c2e -s"))

  (define-key *root-map* (kbd "C")        "c2e")
  (define-key *root-map* (kbd "s")        "s2e")

仅仅过了几天而已,Emacs 就变成了一个很不错的 X 剪切板管理器了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

德意的啸

暂无简介

0 文章
0 评论
608 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文