6

当我从 dired 模式打开图像文件时,我想将 emacs 配置为使用外部应用程序。

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

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

openwith 次要模式的问题在于它是全局的,并且当它由 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 只在 dired 缓冲区而不是其他任何地方使用 openwith 次要模式?

谢谢。

4

3 回答 3

4

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-alternate 文件
  • 目录查找文件
  • dired-查找文件-其他窗口
  • dired-mouse-find-file-other-window
  • 目录视图文件

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

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

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

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

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


重要提示:openwith-mode 文档建议您将以下两行放入 .emacs 文件中:

(require 'openwith)
(openwith-mode t)

现在不再存在次要模式openwith-mode(在我们注释掉它的定义之后),请确保删除第二行,例如也将其注释掉:

;; (openwith-mode t)

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

于 2012-06-27T09:56:03.187 回答
3

我不使用openwith. 我使用定义的函数

http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html

于 2012-06-27T12:49:59.440 回答
0

一种方法是在 openwith.el 中将 emacsclient 设置为您喜欢的文件类型的首选程序,openwith-associations然后开始使用 emacsclient。

您可以每次都启动新的 emacs 会话,但这听起来比以前的建议更难看。

于 2012-06-27T02:17:20.060 回答