summaryrefslogtreecommitdiff
path: root/openwith.el
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2017-01-28 20:34:56 -0700
committerSean Whitton <spwhitton@spwhitton.name>2017-01-28 20:34:56 -0700
commit22194540508d25e545df5c35a971f27eb7ed56ea (patch)
treeba50920880a4c7e38b5d388c5febd1bbc5a6e8e3 /openwith.el
import upstream version 0.8g
Diffstat (limited to 'openwith.el')
-rw-r--r--openwith.el120
1 files changed, 120 insertions, 0 deletions
diff --git a/openwith.el b/openwith.el
new file mode 100644
index 0000000..e3cf3d0
--- /dev/null
+++ b/openwith.el
@@ -0,0 +1,120 @@
+;;; openwith.el --- Open files with external programs
+
+;; Copyright (C) 2007, 2013 Markus Triska
+
+;; Author: Markus Triska <markus.triska@gmx.at>
+;; Keywords: files, processes
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This lets you associate external applications with files so that
+;; you can open them via C-x C-f, with RET in dired, etc.
+
+;; Copy openwith.el to your load-path and add to your .emacs:
+
+;; (require 'openwith)
+;; (openwith-mode t)
+
+;; To customize associations etc., use:
+;;
+;; M-x customize-group RET openwith RET
+;;
+;; To prevent openwith-mode from interfering with attachments when
+;; writing a message in Gnus, add the following to your .emacs:
+;;
+;; (require 'mm-util)
+;; (add-to-list 'mm-inhibit-file-name-handlers 'openwith-file-handler)
+
+;;; Code:
+
+(defconst openwith-version "0.8g")
+
+(defgroup openwith nil
+ "Associate external applications with file name patterns."
+ :group 'files
+ :group 'processes)
+
+(defcustom openwith-associations
+ '(("\\.pdf\\'" "acroread" (file))
+ ("\\.mp3\\'" "xmms" (file))
+ ("\\.\\(?:mpe?g\\|avi\\|wmv\\)\\'" "mplayer" ("-idx" file))
+ ("\\.\\(?:jp?g\\|png\\)\\'" "display" (file)))
+ "Associations of file patterns to external programs.
+File pattern is a regular expression describing the files to
+associate with a program. The program arguments are a list of
+strings and symbols and are passed to the program on invocation,
+where the symbol 'file' is replaced by the file to be opened."
+ :group 'openwith
+ :type '(repeat (list (regexp :tag "Files")
+ (string :tag "Program")
+ (sexp :tag "Parameters"))))
+
+(defcustom openwith-confirm-invocation nil
+ "Ask for confirmation before invoking external programs."
+ :group 'openwith
+ :type 'boolean)
+
+(defun openwith-file-handler (operation &rest args)
+ "Open file with external program, if an association is configured."
+ (when (and openwith-mode (not (buffer-modified-p)) (zerop (buffer-size)))
+ (let ((assocs openwith-associations)
+ (file (car args))
+ oa)
+ ;; do not use `dolist' here, since some packages (like cl)
+ ;; temporarily unbind it
+ (while assocs
+ (setq oa (car assocs)
+ assocs (cdr assocs))
+ (when (save-match-data (string-match (car oa) file))
+ (let ((params (mapcar (lambda (x) (if (eq x 'file) file x))
+ (nth 2 oa))))
+ (when (or (not openwith-confirm-invocation)
+ (y-or-n-p (format "%s %s? " (cadr oa)
+ (mapconcat #'identity params " "))))
+ (apply #'start-process "openwith-process" nil (cadr oa) params)
+ (kill-buffer nil)
+ ;; inhibit actions that would follow the regular
+ ;; insertion of file contents
+ (let (debug-on-error)
+ (error "Opened %s in external program"
+ (file-name-nondirectory file)))))))))
+ ;; when no association was found, relay the operation to other handlers
+ (let ((inhibit-file-name-handlers
+ (cons 'openwith-file-handler
+ (and (eq inhibit-file-name-operation operation)
+ inhibit-file-name-handlers)))
+ (inhibit-file-name-operation operation))
+ (apply operation args)))
+
+;;;###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)
+
+;;; openwith.el ends here