在emacs中使用默认的Windows应用程序打开文件

12

我正在尝试调整emacs中Windows XP的dired-find-file函数,以便在从dired打开(例如)pdf文件时,启动Acrobat Reader并用其打开该文件,而不是在emacs内部打开。 但我无法确定要使用哪个shell-command/call-process变体。以下是我目前拥有的:

(defadvice dired-find-file (around dired-find-file-external (filename &optional wildcards))
  "Open non-text files with an appropriate external program."
  (if (string= ".pdf" (substring filename (- (length filename) 4))) ; obviously I'll replace this with something more general/robust
    (shell-command filename) ;; what should go here?
    (ad-do-it)))

(ad-activate 'dired-find-file)

我知道我可以通过指定Acrobat Reader的.exe文件位置来硬编码启动它。但我更倾向于使用一些需要我进行更少搜索并且不会在默认应用程序移动/更改时中断的东西。我应该使用什么?

9个回答

9

关于“org-open-file”提案的扩展:

(defun my-dired-find-file (&optional prefix)
    (interactive "P")
    (if prefix
        (org-open-file (dired-get-file-for-visit) 'system)
      (dired-find-file)))

(define-key dired-mode-map "\r" 'my-dired-find-file)

这将允许你使用`C-u RET'外部打开一个文件。

http://lists.gnu.org/archive/html/bug-gnu-emacs/2012-11/msg01069.html找到此信息。


8
  1. 评估以下elisp代码
  2. 运行dired (M-x dired)
  3. 浏览到目录和文件
  4. 将光标放在文件上,按F3将根据Windows扩展名打开该文件。

    (defun w32-browser (doc) (w32-shell-execute 1 doc))

    (eval-after-load "dired" '(define-key dired-mode-map [f3] (lambda () (interactive) (w32-browser (dired-replace-in-string "/" "\\" (dired-get-filename))))))


不太喜欢eval-after-load,但w32-shell-execute值得肯定——这显然是正确的做法。 - Tom Smith
当我按下F3键时,为什么会出现定义kbd宏...的提示? - ZhaoGang

4

使用Dired+w32-browser.el来完成此操作。

  • C-RET使用Windows文件关联应用程序打开当前行的文件。

  • M-RET打开Windows资源管理器到文件或文件夹。

  • ^在根目录(例如C:\)中,向上移动到类似Dired的所有Windows驱动器(本地和远程)的列表。

前两个命令可以在w32-browser.el中找到。(Dired+将它们绑定到这些键上。)第三个命令来自Dired+。


但是迷你缓冲区显示“未定义M-Ret”。 - ZhaoGang
@ZhaoGang:谢谢。已更正。忘记了前两个命令是在w32-browser.el中定义的。 - Drew

3

我通过谷歌找到了这个很棒的网页,它向我介绍了使用RunDll技术的方法。如果其他人也感兴趣的话,我在这里分享一下。

这是代码的关键部分,它使用适当的应用程序打开filename

(shell-command (concat "rundll32 shell32,ShellExec_RunDLL " (shell-quote-argument filename)))

以下是我的完整解决方案。(请注意, dired-find-file 只是对 find-file 的包装器,它不知道文件名,因此您必须建议 find-file 而不是像问题中那样建议 dired-find-file 。如果您不想要 find-file 的行为,您可能需要重写 dired-find-file 或编写更复杂的建议。)
(defun open-externally (filename)
  (shell-command (concat "rundll32 shell32,ShellExec_RunDLL " (shell-quote-argument filename))))

(defun is-file-type? (filename type)
  (string= type (substring filename (- (length filename) (length type)))))

(defun should-open-externally? (filename)
  (let ((file-types '(".pdf" ".doc" ".xls")))
    (member t (mapcar #'(lambda (type) (is-file-type? filename type)) file-types))))

(defadvice find-file (around find-file-external-file-advice (filename &optional wildcards))
  "Open non-emacs files with an appropriate external program"
  (if (should-open-externally? filename)
      (open-externally filename)
    ad-do-it))

(ad-activate 'find-file)

2

我在我的.emacs文件中写了以下内容:

(setq dired-guess-shell-alist-user
  (list
    (list "\\.*$" "cmd /k")
  ))

这将使用cmd.exe打开文件,该文件将使用与文件扩展名相关联的任何程序。 在Windows 8和GNU Emacs 24.2.1上测试可用。


我目前正在测试 (setq dired-guess-shell-alist-user '((".*" (concat "start " "\"" file "\""))))。(我遇到了带有空格的文件名。) - Brady Trainor

1

我会使用(w32-shell-execute "open" file-name)

事实上,在我的初始化文件中,我有:

(defun open-externally (file-name)
  (interactive "fOpen externally: ")
  (let ((process-connection-type nil))
     (start-process "open-externally" nil
                    "xdg-open" file-name)))

(when (eq window-system 'w32)
  (defun open-externally (file-name)
    (interactive "fOpen externally: ")
    (w32-shell-execute "open" file-name)))

这定义了一个命令,可以交互地使用,并根据 xdg-open 打开文件到默认应用程序,如果我实际上在 Windows 上,则相应地重新定义该命令。


1

Tom Smith的回答很好,但你也可以直接运行程序"start"并将文件名作为参数。

(shell-command (concat "start " (shell-quote-argument filename)))

1
你确定吗?当我尝试过这个时它并没有工作 - 我只会得到一个空的命令提示符窗口。 - Tom Smith
1
@Tom:这很有道理,因为 start 的第一个引用参数被用作窗口标题。 - jamessan

0

在扩展@tom-smith的答案之后,这里是我验证过并且在Windows上正常工作的代码(灵感来自@Tom-smith和xahlee博客文章)。

将此片段添加到您的~/.emacs.d/init.el中:

;;; Open file types with default Windows apps
;;; -------------------------------------------------------------------
(defun open-externally (filename)
  (shell-command (format "%s" (shell-quote-argument filename))))

(defun is-file-type? (filename type)
  (string= type (substring filename (- (length filename) (length type)))))

;; => change this to include more file types <=
(defun should-open-externally? (filename)
  (let ((file-types '(".pdf" ".doc" ".xls" ".html")))
    (member t (mapcar #'(lambda (type) (is-file-type? filename type)) file-types))))

(defadvice find-file (around find-file-external-file-advice (filename &optional wildcards))
  "Open non-emacs files with an appropriate external program"
   (if (should-open-externally? filename)
      (open-externally filename)
     ad-do-it))

(ad-activate 'find-file)
;;; -------------------------------------------------------------------

0

org-open-file 是一个系统无关的外部打开器。请参阅 org-file-apps 以进一步自定义它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接