Emacs 中根据扩展名称,自动用对应的应用程序打开

用任何方式带开一个文件的时候,根据文件的扩展名, 调用相应的程序打开。有一点像 MS 的 Explore ,

具体做法 , 在 .emacs 中写

下面的另一种方法更好一些。

(defvar wcy-dired-find-file-cmds-alist
  `(("\\.xls$" "start" file-name)
    ("\\.doc$" "start" file-name)
    ("\\.pdf$" "xpdf"  file-name)
    ("\\.rar$" "start" file-name)
    ("\\.zip$" "start" file-name)
    ("\\.ppt$" "start" file-name))
第一个字符串表示过滤文件的正则表达式。 表示那些文件不用 emacs 打开。而是用外部程序打开。

后面的内容对于 windows 系统没有什么 用,在 windows 系统下会根据注册的文件类型打开文件。

在 Unix 系统下, 后面的元素指明的打开某一个文件的方式。 符号 file-name 表示文件的全名。")

(defun wcy-open-file-via-extension(&optional file-name)
  (interactive "fOpen file:")
  (let ((cmd (cdr (find-if (lambda (x)
                             (string-match (car x) file-name))
                           wcy-dired-find-file-cmds-alist))))

    (if (not cmd)
        nil
      (setq cmd
            (mapcar (lambda (s)
                      (if (eq s 'file-name)
                          file-name
                        s))
                    cmd))
      (cond
       ((eq system-type 'windows-nt)
        (w32-shell-execute 'open file-name))
       (t
        (let* ((process (apply 'start-process-shell-command
                               "no name"
                               (get-buffer-create "*open file*")
                               cmd))
               (status (process-status process)))
          (princ (apply 'concat "start process: " cmd))))))))


(defun wcy-dired-find-file()
  (interactive)
  (let* ((file-name (file-name-sans-versions (dired-get-filename) t)))
    (when (not (and (file-exists-p file-name)
                    (file-regular-p file-name)
                    (wcy-open-file-via-extension file-name)))
      (dired-find-file))))
(defun wcy-dired-mouse-find-file-other-window (event)
  "In dired, visit the file or directory name you click on."
  (interactive "e")
  (let (file)
    (save-excursion
      (set-buffer (window-buffer (posn-window (event-end event))))
      (save-excursion
        (goto-char (posn-point (event-end event)))
        (setq file (dired-get-filename))))
    (when (not (wcy-open-file-via-extension file))
      (select-window (posn-window (event-end event)))
      (find-file-other-window (file-name-sans-versions file t)))))
(defun wcy-dired-mouse-find-file (event)
  "In dired, visit the file or directory name you click on."
  (interactive "e")
  (let (file)
    (save-excursion
      (set-buffer (window-buffer (posn-window (event-end event))))
      (save-excursion
        (goto-char (posn-point (event-end event)))
        (setq file (dired-get-filename))
        (when (not (wcy-open-file-via-extension file))
          (select-window (posn-window (event-end event)))
          (dired-find-file))))))
(add-hook 'dired-mode-hook 'wcy-dired-mode-hook)

(defun wcy-dired-mode-hook  ()
  ;; Set buffer-local variables here.  For example:
  (setq dired-omit-files-p t)
  (define-key dired-mode-map (kbd "[" ) 'backward-page)
  (define-key dired-mode-map (kbd "]" ) 'forward-page)
  (define-key dired-mode-map (kbd "<M-up>" )
    'dired-up-directory)
  (define-key dired-mode-map (kbd "ESC <up>" ) 'dired-up-directory)
  (define-key dired-mode-map (kbd "<down-mouse-1>" ) 'ignore)
  (define-key dired-mode-map (kbd "<double-mouse-1>" ) 'wcy-dired-mouse-find-file)
  (substitute-key-definition 'dired-find-file 'wcy-dired-find-file dired-mode-map)
  (substitute-key-definition 'dired-mouse-find-file-other-window 'wcy-dired-mouse-find-file-other-window dired-mode-map)
  (substitute-key-definition 'dired-next-line 'dired-next-file-line dired-mode-map)
  (substitute-key-definition 'dired-previous-line 'dired-previous-file-line dired-mode-map)
  (setq dired-omit-files "^\\.?#\\|^\\.$\\|^\\.[^.]*$")
  ;; remove .pdf .dvi from the default value.
  (setq dired-omit-extensions '("CVS/" ".o" "~" ".bin" ".lbin"
                                ".fasl" ".ufsl" ".a" ".ln" ".blg"
                                ".bbl" ".elc" ".lof" ".glo" ".idx"
                                ".lot" ".fmt" ".tfm" ".class" ".fas" ".lib" ".x86f"
                                ".sparcf" ".lo" ".la" ".toc" ".log" ".aux" ".cp" ".fn" ".ky" ".pg"
                                ".tp" ".vr" ".cps" ".fns" ".kys" ".pgs" ".tps" ".vrs"
                                ".idx" ".lof" ".lot" ".glo" ".blg" ".bbl" ".cp" ".cps" ".fn" ".fns" ".ky"
                                ".kys" ".pg" ".pgs" ".tp"
                                ".tps" ".vr" ".vrs"))
  (define-key dired-mode-map (kbd "/")  'dired-omit-expunge)

下面是另一种方法。不是特别好。

(defun define-trivial-mode(mode-prefix file-regexp &optional command)
  (or command (setq command mode-prefix))
  (let ((mode-command (intern (concat mode-prefix "-mode"))))
    (fset mode-command
          `(lambda ()
             (interactive)
         (progn
           (start-process-shell-command ,mode-prefix nil
                        ,command (buffer-file-name))
           (kill-buffer (current-buffer)))
    (add-to-list 'auto-mode-alist (cons file-regexp mode-command))))))
(define-trivial-mode "xpdf" "\.pdf$")

可以根据你的需要,在添加一些新的东西,

(define-trivial-mode "ghostview" "\.ps$" "gv")
(define-trivial-mode "xdvi" "\.dvi$" "xdvi")
...

不能说这个东西是我写的,我在 emacs wiki 上溜达的时候,碰到的, 不过我做了一个很小的改动

     (progn
           (start-process-shell-command ,mode-prefix nil
                        ,command (buffer-file-name))
           (kill-buffer (current-buffer)))

部分,原来是

            (start-process ,mode-prefix (current-buffer)
                            ,command (buffer-file-name))))

原来是会用 emacs 打开 ps 或者 pdf 文件,但是那样做没有意义, 我也不想看懂ps 或者 pdf 文件,尽管他们是文本文件,但在我看来 和binary 的没有区别,天书。

于是我就,kill-process ,发现,process 没有了,gv 就会收到 SIGHUP ,自己就关闭了,不爽,于是 把 (current-buffer) 改为 nil , 解决了 !

但是还有一点不爽,在用 dired 的时候,打开文件之后, dired 的 buffer 就跑到最下面去了,结果就是一个不相干的 buffer 出来了, 我还要用 C-x b 找回来刚刚的dired buffer .