【问题标题】:emacs terminal mode: how to copy and paste efficientlyemacs终端模式:如何高效复制粘贴
【发布时间】:2015-01-04 09:11:46
【问题描述】:

我很难让这个 emacs -nw 在终端模式 (emacs -nw) 下有效工作。 一些设置信息: 工作服务器通过 SSH 连接,并且 emacs 正在服务器上运行。通常我使用 SSH 和“emacs -nw”连接来处理我的文件。

emacs 配置取自:https://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/

;; make mouse selection to be emacs region marking
(require 'mouse)
(xterm-mouse-mode t)
(defun track-mouse (e)) 
(setq mouse-sel-mode t)

;; enable clipboard in emacs
(setq x-select-enable-clipboard t)

;; enable copy/paste between emacs and other apps (terminal version of emacs)
(unless window-system
 (when (getenv "DISPLAY")
  ;; Callback for when user cuts
  (defun xsel-cut-function (text &optional push)
    ;; Insert text to temp-buffer, and "send" content to xsel stdin
    (with-temp-buffer
      (insert text)
      ;; I prefer using the "clipboard" selection (the one the
      ;; typically is used by c-c/c-v) before the primary selection
      ;; (that uses mouse-select/middle-button-click)
      (call-process-region (point-min) (point-max) "xsel" nil 0 nil "--clipboard" "--input")))
  ;; Call back for when user pastes
  (defun xsel-paste-function()
    ;; Find out what is current selection by xsel. If it is different
    ;; from the top of the kill-ring (car kill-ring), then return
    ;; it. Else, nil is returned, so whatever is in the top of the
    ;; kill-ring will be used.
    (let ((xsel-output (shell-command-to-string "xsel --clipboard --output")))
      (unless (string= (car kill-ring) xsel-output)
        xsel-output )))
  ;; Attach callbacks to hooks
  (setq interprogram-cut-function 'xsel-cut-function)
  (setq interprogram-paste-function 'xsel-paste-function)
  ;; Idea from
  ;; http://shreevatsa.wordpress.com/2006/10/22/emacs-copypaste-and-x/
  ;; http://www.mail-archive.com/help-gnu-emacs@gnu.org/msg03577.html
 ))

拥有的理由:

 (require 'mouse)
 (xterm-mouse-mode t)
 (defun track-mouse (e)) 
 (setq mouse-sel-mode t)

是启用鼠标选择文本,以便文本区域突出显示,就像“C-x SPC”标记该区域一样。然后我可以使用 "M-x w" 复制和 "C-x y" 在 emacs 内以及 emacs 和其他应用程序之间粘贴文本。

除了任何与 X 相关的操作都非常慢之外,所有看起来都很完美!我与远程服务器的连接很顺畅——延迟通常低于 100 毫秒。但是要使用“C-x k”删除一行文本,大约需要 5 秒!要粘贴它,还需要 5 秒钟!

当复制/粘贴有时很频繁时,这真的很烦人。我认为这与 X 服务器消息传递有关,但不确定是否有解决此问题的好方法。

有什么想法吗? 谢谢!

【问题讨论】:

  • 你试过在本地运行emacs并使用tramp模式吗?
  • 这是我的第一次尝试——每次我保存任何编辑时,它都会与远程服务器上的文件同步,这并不顺畅。另外,我不喜欢经常启动 emacs(本地机器是笔记本)。
  • 出于好奇,您是否遇到过 (setq interprogram-paste...) 行没有运行的问题?我必须手动运行它们。

标签: emacs copy-paste


【解决方案1】:

这本身并不是一个理想的解决方案,但我想出了一个比前一个感觉更好的方法。

我们的想法是消除导致严重延迟问题的 X,即只保留以下内容:

;; enable clipboard in emacs
(setq x-select-enable-clipboard t)

结果是:

  1. 在 Emacs 中复制/粘贴非常简单快捷。

  2. 从其他应用复制到 Emacs:Ctrl+Shift+v

  3. 从 Emacs 复制到其他应用程序:鼠标选择现在位于 X 选择上,因此右键单击并复制应将文本复制到选择中。请注意,“M-w”现在不会将任何内容复制到选择或系统剪贴板中。

这又是一种妥协,而不是解决方案,但考虑到我复制/粘贴比跨应用程序操作更频繁的事实,目前这是可以接受的。

仍然期待一个好的解决方案!

【讨论】:

    【解决方案2】:

    您可以使用终端转义码来完成此操作! 有一种独特的终端转义码类别,称为“操作系统控件”(OSC),其中一个序列 (\033]52) 用于与系统剪贴板交互。最棒的是您的终端并不关心代码的来源,因此它也可以在远程会话中工作。

    大多数终端仿真器都支持它(iTerm2、OS X 终端,我认为除了 GNOME 之外的所有 Linux 终端)。你可以通过简单的运行来测试你的终端是否支持这个序列:

    $ printf "\033]52;c;$(printf "Hello, world" | base64)\a"
    

    然后从您的系统剪贴板粘贴。如果它粘贴“Hello, world”,那么你的终端支持它!

    我的init.el 中有这个函数,所以当我调用yank-to-clipboard 时,Emacs 会将值从我的 kill ring 拉到系统剪贴板中:

    (defun yank-to-clipboard ()
    "Use ANSI OSC 52 escape sequence to attempt clipboard copy"
      (interactive)
      (send-string-to-terminal
        (format "\033]52;c;%s\a"
          (base64-encode-string 
            (encode-coding-string 
              (substring-no-properties 
                (nth 0 kill-ring)) 'utf-8) t))))
    

    当我输入这个时,我偶然发现了一个几乎相同的脚本,它受到 Chromium 社区的支持:https://chromium.googlesource.com/apps/libapps/+/master/hterm/etc/osc52.el

    对于那些在内部运行 Emacs 的人 Tmux: Tmux 使用序列,因此您需要将序列通过管道传输到 Tmux 活动 tty 才能使其工作。我的博文中有一个解决方案:https://justinchips.medium.com/have-vim-emacs-tmux-use-system-clipboard-4c9d901eef40

    【讨论】:

      【解决方案3】:

      为了扩展@justinokamoto 的答案以在 tmux 中使用,它工作得很好,真的很棒。我没有用例如调试它tramp 或其他花哨的 emacs 设置,但要让它工作

      1. 按照https://sunaku.github.io/tmux-yank-osc52.html 伟大的指示,修改你的tmux.conf~/bin/yank
      2. 确保在您的终端上启用了对剪贴板的终端访问权限

      然后,您可以使用以下函数来拉入 emacs:

      (请注意,我对 elisp 很陌生。这会写入 /tmp/yank 中的临时文件)

      (defun custom-terminal-yank (&rest args)
        (message "-> CLIP")
      
        ;; FOR EVIL MODE: UNCOMMENT SO FIRST YANKS TO KILL RING
        ;; need to yank first, with all those args
        ;; ;; https://emacs.stackexchange.com/questions/19215/how-to-write-a-transparent-pass-through-function-wrapper
        ;; (interactive (advice-eval-interactive-spec
        ;;               (cadr (interactive-form #'evil-yank))))
        ;; (apply #'evil-yank args)
        
        ;; https://stackoverflow.com/questions/27764059/emacs-terminal-mode-how-to-copy-and-paste-efficiently
        ;; https://sunaku.github.io/tmux-yank-osc52.html
        (f-write-text (nth 0 kill-ring) 'utf-8 "/tmp/yank")
        (send-string-to-terminal (shell-command-to-string "~/bin/yank /tmp/yank"))
        )
      

      如果其他人也使用邪恶模式(只是为了让事情变得复杂),您可以取消注释这些行并使用类似 (define-key evil-visual-state-map "Y" 'jonah-terminal-yank) 因此,正常的“y”用于视觉模式下的正常拉动,而“Y”用于跨剪贴板拉动

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-14
        • 2011-10-30
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-09
        相关资源
        最近更新 更多