emacs dired 和 openwith

标签 emacs elisp dired

我想配置 emacs 以使用外部应用程序
当我从直接模式打开图像文件时。

另一方面,我也想在 emacs 缓冲区中使用内联图像。

要在外部应用程序中打开文件,我使用 openwith.el
包裹http://www.emacswiki.org/emacs/OpenWith

openwith minor 模式的问题在于它是
全局以及当它由 dired-mode-hook 启用时

(add-hook 'dired-mode-hook
          (lambda ()
            (setq truncate-lines t)
            (openwith-mode t)
            ))

它在 emacs 缓冲区中无处不在和所有内联图像
在外部应用程序中打开。

我试图改变
:global t 


:global nil 

openwith.el ,但它以某种方式完全禁用了 openwith 模式。

所以,我的问题是:如何告诉 emacs 仅使用 openwith 次要模式
使用 dired 缓冲区而不是其他任何地方?

谢谢。

最佳答案

openwith-mode 的工作方式有点奇怪:它确实假设您要么全局使用它,要么根本不使用它。然而,您在这里想要的是在本地使用它,即仅在 dired 缓冲区内使用它。

这不是很容易实现,但这里有一个方法。

打开 openwith-mode 的源文件 openwith.el。然后一直向下滚动,直到找到实际次要模式的定义。然后通过在每行的开头放置一个分号来注释该定义:

;;;###autoload
; (define-minor-mode openwith-mode
;   "Automatically open files with external programs."
;   :lighter ""
;   :global t
;   (if openwith-mode
;       (progn
;         ;; register `openwith-file-handler' for all files
;         (put 'openwith-file-handler 'safe-magic t)
;         (put 'openwith-file-handler 'operations '(insert-file-contents))
;         (add-to-list 'file-name-handler-alist '("" . openwith-file-handler)))
;     (setq file-name-handler-alist
;           (delete '("" . openwith-file-handler) file-name-handler-alist))))

然后在此代码下方(但在 (provide 'openwith) 之前),插入以下代码:
(defvar openwith-mode nil)

(mapc (lambda (function) 
        (ad-add-advice function 
                       '(dired-openwith nil t (advice . (lambda () (let ((openwith-mode t)) ad-do-it))))
                       'around 0))
      '(dired-find-alternate-file 
        dired-find-file 
        dired-find-file-other-window
        dired-mouse-find-file-other-window
        dired-view-file))

(put 'openwith-file-handler 'safe-magic t)
(put 'openwith-file-handler 'operations '(insert-file-contents))
(add-to-list 'file-name-handler-alist '("" . openwith-file-handler))

这段代码做了几件事。

首先,它定义了一个名为 openwith-mode 的变量。此变量在 openwith-mode 的其中一个函数中使用,该函数决定是否使用外部应用程序。通常,当您定义次要模式时,Emacs 会自动提供这样的变量——但是由于我们刚刚注释掉了上面实际次要模式的定义,我们在这里明确地重新引入了这个变量。

该变量的目的是作为一种开关,通过它我们可以控制图像文件是否应该内联或传递给外部查看器。

接下来我们有 (mapc ...)表达。我们在这里做的是迭代五个函数的列表:
  • 直接查找替代文件
  • 直接查找文件
  • dired-find-file-other-window
  • dired-mouse-find-file-other-window
  • 定向 View 文件

  • 哪些是 dired 提供的用于打开文件的函数。我们用一种叫做 advising 的技术向这些函数中的每一个添加了少量代码。 : 什么 (ad-add-advice...)确实设置了变量 openwith-modet每当调用这五个函数之一时。在函数调用之外,变量仍然设置为 nil .

    这会导致每当您使用 dired 的函数之一打开文件时,负责调用外部应用程序的 openwith-mode 函数会看到变量设置为 t。如果它知道一个外部应用程序,并立即尝试打开它。
    我们必须跳过这些问题的原因是,每当您使用 C-x C-f 打开图像文件时,也会调用相同的 openwith-mode 函数——这正是 openwith-mode 的实现方式。

    (注意:不幸的是,我们不能只使用当前的主模式作为开关,因为这将是为打开文件而创建的新缓冲区的主模式。它始终是 fundamental-mode 。)

    最后,最后三行只是从我们之前注释掉的次要模式定义中复制和粘贴。他们说我已经提到了很多的函数,它负责调用外部应用程序——称为 open-with-filehandler -- 是所谓的文件处理程序。它对于实际访问文件并没有真正做任何特殊的事情,因此我们设置了 safe-magic对于该功能 t .此外,我们声明操作 insert-file-contents由我们的函数以一种非平凡的方式处理。 (有关这些属性的更多信息,请参阅 here。)

    最后,我们实际安装了文件处理程序。

    重要 :openwith-mode 文档建议您将以下两行放入您的 .emacs 文件中:
    (require 'openwith)
    (openwith-mode t)
    

    现在没有次要模式 openwith-mode再多(在我们注释掉它的定义之后),请确保删除第二行,例如通过评论它太:
    ;; (openwith-mode t)
    

    重启Emacs后,如果用dired打开图片文件,应该是在外部应用程序中打开;如果您通过 C-x C-f 打开它,它将被内联到缓冲区中。

    关于emacs dired 和 openwith,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11218316/

    相关文章:

    emacs - 如何在 Emacs 中 [tar 和] 压缩标记的文件

    xml - 删除emacs中某种类型的所有标签

    python - Emacs Python 劣质 shell 在 matplotlib show() 命令后不显示提示

    emacs - 如何关闭特定主要模式的电子缩进模式?

    emacs - 为什么 Emacs 中应该有行号的地方有空格?

    emacs - Emacs Lisp 中函数名的内部是什么意思?

    emacs - Dired:如何以 super 用户身份执行 chown?

    emacs - 如何防止Emacs Dired将帧拆分为两个以上的窗口?

    python - 如何将 pipenv python 作为 emacs Python shell 运行

    emacs 前进 n 逗号