【问题标题】:on Emacs for OSX, how to keep kill ring and clipboard separate?在 OSX 的 Emacs 上,如何将杀戮环和剪贴板分开?
【发布时间】:2014-05-15 23:15:41
【问题描述】:

在 OSX 的 GNU Emacs 中,我怎样才能将 kill ring 和 OSX 剪贴板分开? (这样我基本上就有了两个独立的杀戮环。)

对于所需的行为,这将起作用:
1. C 将文本从网络复制到 OSX 剪贴板。
2. controlk在Emacs中杀死一行。
3. controly 将已终止文本从 Emacs 终止环拉到当前 Emacs 缓冲区。
4. v 将原始 Web 文本从 OSX 剪贴板粘贴到当前 Emacs 缓冲区。

这在 Aquamacs 中开箱即用。如何在 GNU Emacs 中工作?

这里讨论了这个问题,因为它与 Windows 相关: Emacs: How to separate the kill ring from the system clipboard?

这里: http://lists.gnu.org/archive/html/help-emacs-windows/2010-02/msg00001.HTML

...但是此解决方案在 OSX 中不起作用。我想要 Mac OSX 的解决方案。

【问题讨论】:

    标签: emacs clipboard aquamacs kill-ring


    【解决方案1】:

    simpleclip 可能会有所帮助 -

    在 Emacs 中简化了对系统剪贴板的访问。

    simpleclip-mode 从根本上简化了剪贴板处理:系统 剪贴板和 Emacs kill ring 是完全独立的,并且 永远不要互相影响。

    super 键绑定对 OS X 很友好:super 通常是映射的 到“命令”键,即⌘。

    在 OS X、X11 和 MS Windows 上测试

    https://github.com/rolandwalker/simpleclip

    【讨论】:

      【解决方案2】:

      注意:此解决方案草案不是旨在将剪贴板分开的 Emacs 系统范围的修改 -- 相反,这是一个自定义解决方案旨在在专门使用这些自定义功能时interactive 基础上保持剪贴板分离。内的其他功能 使用 kill-ring 的 Emacs 可以使用类似的方法进行修改——变量 interprogram-cut-functioninterprogram-paste-function 可以在特定函数的持续时间内将 let-bound 设置为 nil 值(通过 advice ,或修改源本身,或创建新功能和/或使用defalias)。但是,后者超出了这个有限示例的范围。


      历史

      初稿(2014 年 12 月 23 日):这是初稿,其理念是只有在调用副本或调用之前使用 C-u 时才能访问 OSX 剪贴板粘贴功能。如果首先调用C-u,则使用OSX 剪贴板。随着我每天更多地使用这些功能,我可能会对这段代码进行额外的修改,我会不时更新:

      编辑(2014 年 12 月 24 日):从交互式命令语句中删除了与 lawlist-copy-selected-region 相关的 * - 这是粘贴而不是复制所需的 read-only 检查。添加了有关此示例一般性质的声明。

      编辑(2014 年 12 月 28 日):修改代码以更好地处理用户在调用 lawlist-copy-selected-region 之前忘记选择区域的情况。小修改,让代码更简洁。


      (defun lawlist-copy-selected-region (&optional arg)
      (interactive "P")
        (let* (
            (interprogram-cut-function
              (when (equal arg '(4)) interprogram-cut-function))
            (interprogram-paste-function
              (when (equal arg '(4)) interprogram-paste-function))
            (region-active-p (region-active-p))
            (beg (when region-active-p (region-beginning)))
            (end (when region-active-p (region-end)))
            (copied-string
              (when region-active-p (buffer-substring-no-properties beg end))) )
          (unless region-active-p
            (let ((debug-on-quit nil))
              (signal 'quit `("No region has been selected!"))))
          (copy-region-as-kill beg end)
          (when (not (active-minibuffer-window))
            (message "%s"
              (concat
                (if (and interprogram-cut-function interprogram-paste-function)
                  "OSX+Emacs:  "
                  "Emacs:  ")
                (truncate-string-to-width copied-string 40)
                (when (> (length copied-string) 40)
                  " . . .")))) ))
      
      (defun lawlist-yank (&optional arg)
        (interactive "*P")
        (unless arg (setq arg 1))
        (setq yank-window-start (window-start))
        (setq this-command t)
        (push-mark (point))
        (insert-for-yank
          (lawlist-current-kill
            (cond
              ((listp arg)
                arg)
              ((eq arg '-)
                -2)
              (t
                (1- arg) ))))
        (if (consp arg)
            (goto-char (prog1 (mark t)
             (set-marker (mark-marker) (point) (current-buffer)))))
        (if (eq this-command t)
            (setq this-command 'yank))
        (when (region-active-p)
          (setq mark-active nil))
        nil)
      
      (defun lawlist-current-kill (n &optional do-not-move)
        (let ((interprogram-paste
                (and
                  (equal n '(4))
                  interprogram-paste-function
                  (funcall interprogram-paste-function))))
          (cond
            (interprogram-paste
              (let ((interprogram-cut-function nil))
                (if (listp interprogram-paste)
                  (mapc 'kill-new (nreverse interprogram-paste))
                  (kill-new interprogram-paste)))
              (car kill-ring))
            ((and (equal n '(4)) (not interprogram-paste))
              (car kill-ring))
            (t
              (or kill-ring 
                (let ((debug-on-quit nil))
                  (signal 'quit `("The kill-ring is empty."))))
              (let (
                  (ARGth-kill-element
                    (nthcdr
                      (mod (- n (length kill-ring-yank-pointer)) (length kill-ring))
                      kill-ring)))
                (unless do-not-move
                  (setq kill-ring-yank-pointer ARGth-kill-element)
                  (when
                      (and
                        yank-pop-change-selection
                        (> n 0)
                        interprogram-cut-function)
                    (funcall interprogram-cut-function (car ARGth-kill-element))))
              (car ARGth-kill-element))))))
      

      【讨论】:

        【解决方案3】:
        (global-set-key (kbd "C-x M-y")
                      (lambda ()
                        (interactive)
                        (insert-string (ns-get-pasteboard))))
        
        (global-set-key (kbd "C-x M-w")
                      (lambda ()
                        (interactive)
                        (when (region-active-p)
                          (ns-set-pasteboard
                           (buffer-substring (region-beginning)
                                             (region-end))))))
        

        【讨论】:

          【解决方案4】:

          Emacs: How to separate the kill ring from the system clipboard? 中的解决方案确实有效,但并不完整。您可以自己致电pbcopy 以正确粘贴剪贴板。例如,在您的 .emacs 中尝试以下操作。请注意,s-v 用于 OS X 窗口系统中的Cmd+Vs-c 也是如此。

          ;;; Tested on:
          ;;; 1.  GNU Emacs 24.3.1 (x86_64-apple-darwin13.0.0)
          ;;;     of 2013-12-22 on tennine-slave.macports.org
          ;;;     (MacPorts emacs@24.3_1)
          ;;;
          ;;; 2.  GNU Emacs 24.3.1 (x86_64-apple-darwin, NS apple-appkit-1038.36)
          ;;;     of 2013-03-12 on bob.porkrind.org
          ;;;     (Emacs For Mac OS X)
          
          (defun isolate-kill-ring()
            "Isolate Emacs kill ring from OS X system pasteboard.
          This function is only necessary in window system."
            (interactive)
            (setq interprogram-cut-function nil)
            (setq interprogram-paste-function nil))
          
          (defun pasteboard-copy()
            "Copy region to OS X system pasteboard."
            (interactive)
            (shell-command-on-region
             (region-beginning) (region-end) "pbcopy"))
          
          (defun pasteboard-paste()
            "Paste from OS X system pasteboard via `pbpaste' to point."
            (interactive)
            (shell-command-on-region
             (point) (if mark-active (mark) (point)) "pbpaste" nil t))
          
          (defun pasteboard-cut()
            "Cut region and put on OS X system pasteboard."
            (interactive)
            (pasteboard-copy)
            (delete-region (region-beginning) (region-end)))
          
          (if window-system
              (progn
                (isolate-kill-ring)
                ;; bind CMD+C to pasteboard-copy
                (global-set-key (kbd "s-c") 'pasteboard-copy)
                ;; bind CMD+V to pasteboard-paste
                (global-set-key (kbd "s-v") 'pasteboard-paste)
                ;; bind CMD+X to pasteboard-cut
                (global-set-key (kbd "s-x") 'pasteboard-cut))
          
            ;; you might also want to assign some keybindings for non-window
            ;; system usage (i.e., in your text terminal, where the
            ;; command->super does not work)
            )
          

          如果您遇到 UTF-8 问题,请考虑以下可能的解决方案:

          ;; handle emacs utf-8 input
          (set-terminal-coding-system 'utf-8)
          (set-keyboard-coding-system 'utf-8)
          (prefer-coding-system 'utf-8)
          (setenv "LANG" "en_US.UTF-8")
          

          【讨论】:

          • @PeterSalazar 好点(尽管我怀疑我是否会需要它)。更新。还分解了函数,以便您也可以从 tty 调用它们(或为 tty 设置键绑定)。对于这样简单的事情,一个包显然是一种过度杀伤力。那我就发布一个要点。
          • @PeterSalazar 是的,minibuffer 有自己的一组本地地图。
          • @PeterSalazar 很高兴它有帮助。关于^M,肯定有一个非常简单的解决方案。 ^M 是 CR(回车,ASCII \x0d)。虽然类 Unix 系统(包括 OS X)使用 LF(换行)作为换行符,但 MS DOS 和 Windows 使用 CR+LF,而经典的 Mac OS 仅使用 CR。这些是您看到的^M 的来源(例如,许多网页源代码使用CR+LF 作为换行符——事实上,甚至一些服务器响应标头;而Apple 自己的脚本编辑器使用CR)。
          • @PeterSalazar 如果您确定您永远不想看到^M(我不想),只需将原始代码中的"pbpaste" 替换为"pbpaste | perl -p -e 's/\r$//' | tr '\r' '\n'"。应该单独处理 CRLF 和 CR。我在这里使用 perl 是因为 OS X 附带的 BSD sed 非常有限,它甚至无法识别 \r 转义。 (也许我对 BSD sed 不够好;无论如何,当 GNU sed 更好时,我没有动力去擅长这个废话。)请告诉我这是否有效。
          • @incandescentman 您可能需要创建一个带有终止环内容的临时缓冲区,然后是 shell-command-on-region
          【解决方案5】:

          经过一番折腾,我很确定让这项工作的唯一方法是覆盖 x-select-text 方法。在此处查看我的答案以了解所有详细信息:https://stackoverflow.com/a/23254771/71522

          【讨论】:

          • 它仍然未能通过我的主要测试:org-kill-line 后跟 clipboard-yank 应该相互独立。
          • 我 (1) 评估了此代码:(defun x-select-text (text)) (setq x-select-enable-clipboard nil) (setq x-select-enable-primary nil) (setq mouse-drag-copy-region nil) (setq interprogram-cut-function 'ns-set-pasteboard) (setq interprogram-paste-function 'ns-get-pasteboard); (2) 做了org-kill-line (3) 做了clipboard-yank。 Clipboard yank 仍然插入被终止的文本,而不是 OSX 剪贴板的内容......或者那个或被终止的行正在进入 OSX 剪贴板。
          • 嗯,烦人。这条线是否放在 OS X 剪贴板上?否则,也许检查org-kill-line 看看它在做什么? (M-x find-function org-kill-line)
          • 我用M-x kill-line 试过了。被杀死的文本仍然直接进入 OSX 剪贴板。
          【解决方案6】:

          这有帮助吗:

          (setq x-select-enable-clipboard nil)
          

          这只会将两个剪贴板分开,并且要使 Cmd+cCmd+v 像提到的那样工作,您必须将它们重新绑定到 clipboard-kill-ring-save 和 @ 987654324@.

          我正在使用这个 Emacs:https://github.com/railwaycat/emacs-mac-port

          【讨论】:

          • 我试过了,不,它不起作用。要使解决方案正常工作,它应该能够通过上述步骤 #1 到 #4 中的测试。
          • 还是不行。当我 (1) 将文本从 Chrome 复制到 OSX 剪贴板,然后 (2) 在 Emacs 中执行 kill-line,然后 (3) 执行 clipboard-yank 时,它仍然会粘贴 Emacs 中的终止行而不是所需的 OSX 剪贴板文本.
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多