diff options
| author | Tassilo Horn | 2016-04-10 09:39:51 +0200 |
|---|---|---|
| committer | Tassilo Horn | 2016-04-10 18:15:45 +0200 |
| commit | b4b83fa2ba52cd5398e3b9d085b4afea679d1515 (patch) | |
| tree | ab4cf32e906b9924792461331a4f35b5b896416c | |
| parent | 7172ba7f7f5b1a91357ea727ab188db3ccc99a77 (diff) | |
| download | emacs-b4b83fa2ba52cd5398e3b9d085b4afea679d1515.tar.gz emacs-b4b83fa2ba52cd5398e3b9d085b4afea679d1515.zip | |
New custom option for overriding mailcap choices
* lisp/net/mailcap.el (mailcap--get-user-mime-data): New function.
(mailcap--set-user-mime-data): New function.
(mailcap-user-mime-data): New customization option.
(mailcap-select-preferred-viewer): New function.
(mailcap-mime-info): Use it.
* doc/misc/emacs-mime.texi (mailcap): Document `mailcap-user-mime-data'.
| -rw-r--r-- | doc/misc/emacs-mime.texi | 5 | ||||
| -rw-r--r-- | lisp/net/mailcap.el | 131 |
2 files changed, 107 insertions, 29 deletions
diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi index c9c4b7c2a2f..2b3bba39ad9 100644 --- a/doc/misc/emacs-mime.texi +++ b/doc/misc/emacs-mime.texi | |||
| @@ -1826,6 +1826,11 @@ matching types. | |||
| 1826 | @vindex mailcap-mime-data | 1826 | @vindex mailcap-mime-data |
| 1827 | This variable is an alist of alists containing backup viewing rules. | 1827 | This variable is an alist of alists containing backup viewing rules. |
| 1828 | 1828 | ||
| 1829 | @item mailcap-user-mime-data | ||
| 1830 | @vindex mailcap-user-mime-data | ||
| 1831 | A customizable list of viewers that take preference over | ||
| 1832 | @code{mailcap-mime-data}. | ||
| 1833 | |||
| 1829 | @end table | 1834 | @end table |
| 1830 | 1835 | ||
| 1831 | Interface functions: | 1836 | Interface functions: |
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el index 609a8f4d64b..ae49972f5bf 100644 --- a/lisp/net/mailcap.el +++ b/lisp/net/mailcap.el | |||
| @@ -58,6 +58,59 @@ | |||
| 58 | " ") | 58 | " ") |
| 59 | "Shell command (including switches) used to print PostScript files.") | 59 | "Shell command (including switches) used to print PostScript files.") |
| 60 | 60 | ||
| 61 | (defun mailcap--get-user-mime-data (sym) | ||
| 62 | (let ((val (default-value sym)) | ||
| 63 | res) | ||
| 64 | (dolist (entry val) | ||
| 65 | (setq res (cons (list (cdr (assq 'viewer entry)) | ||
| 66 | (cdr (assq 'type entry)) | ||
| 67 | (cdr (assq 'test entry))) | ||
| 68 | res))) | ||
| 69 | (nreverse res))) | ||
| 70 | |||
| 71 | (defun mailcap--set-user-mime-data (sym val) | ||
| 72 | (let (res) | ||
| 73 | (dolist (entry val) | ||
| 74 | (setq res (cons `((viewer . ,(car entry)) | ||
| 75 | (type . ,(cadr entry)) | ||
| 76 | ,@(when (caddr entry) | ||
| 77 | `((test . ,(caddr entry))))) | ||
| 78 | res))) | ||
| 79 | (set-default sym (nreverse res)))) | ||
| 80 | |||
| 81 | (defcustom mailcap-user-mime-data nil | ||
| 82 | "A list of viewers preferred for different MIME types. | ||
| 83 | The elements of the list are alists of the following structure | ||
| 84 | |||
| 85 | ((viewer . VIEWER) | ||
| 86 | (type . MIME-TYPE) | ||
| 87 | (test . TEST)) | ||
| 88 | |||
| 89 | where VIEWER is either a lisp command, e.g., a major-mode, or a | ||
| 90 | string containing a shell command for viewing files of the | ||
| 91 | defined MIME-TYPE. In case of a shell command, %s will be | ||
| 92 | replaced with the file. | ||
| 93 | |||
| 94 | MIME-TYPE is a regular expression being matched against the | ||
| 95 | actual MIME type. It is implicitly surrounded with ^ and $. | ||
| 96 | |||
| 97 | TEST is an lisp form which is evaluated in order to test if the | ||
| 98 | entry should be chosen. The `test' entry is optional. | ||
| 99 | |||
| 100 | When selecting a viewer for a given MIME type, the first viewer | ||
| 101 | in this list with a matching MIME-TYPE and successful TEST is | ||
| 102 | selected. Only if none matches, the standard `mailcap-mime-data' | ||
| 103 | is consulted." | ||
| 104 | :type '(repeat | ||
| 105 | (list | ||
| 106 | (choice (function :tag "Function or mode") | ||
| 107 | (string :tag "Shell command")) | ||
| 108 | (regexp :tag "MIME Type") | ||
| 109 | (sexp :tag "Test (optional)"))) | ||
| 110 | :get #'mailcap--get-user-mime-data | ||
| 111 | :set #'mailcap--set-user-mime-data | ||
| 112 | :group 'mailcap) | ||
| 113 | |||
| 61 | ;; Postpone using defcustom for this as it's so big and we essentially | 114 | ;; Postpone using defcustom for this as it's so big and we essentially |
| 62 | ;; have to have two copies of the data around then. Perhaps just | 115 | ;; have to have two copies of the data around then. Perhaps just |
| 63 | ;; customize the Lisp viewers and rely on the normal configuration | 116 | ;; customize the Lisp viewers and rely on the normal configuration |
| @@ -700,6 +753,20 @@ If TEST is not given, it defaults to t." | |||
| 700 | t) | 753 | t) |
| 701 | (t nil)))) | 754 | (t nil)))) |
| 702 | 755 | ||
| 756 | (defun mailcap-select-preferred-viewer (type-info) | ||
| 757 | "Return an applicable viewer entry from `mailcap-user-mime-data'." | ||
| 758 | (let ((info (mapcar (lambda (a) (cons (symbol-name (car a)) | ||
| 759 | (cdr a))) | ||
| 760 | (cdr type-info))) | ||
| 761 | viewer) | ||
| 762 | (dolist (entry mailcap-user-mime-data) | ||
| 763 | (when (and (null viewer) | ||
| 764 | (string-match (concat "^" (cdr (assq 'type entry)) "$") | ||
| 765 | (car type-info)) | ||
| 766 | (mailcap-viewer-passes-test entry info)) | ||
| 767 | (setq viewer entry))) | ||
| 768 | viewer)) | ||
| 769 | |||
| 703 | (defun mailcap-mime-info (string &optional request no-decode) | 770 | (defun mailcap-mime-info (string &optional request no-decode) |
| 704 | "Get the MIME viewer command for STRING, return nil if none found. | 771 | "Get the MIME viewer command for STRING, return nil if none found. |
| 705 | Expects a complete content-type header line as its argument. | 772 | Expects a complete content-type header line as its argument. |
| @@ -732,41 +799,47 @@ If NO-DECODE is non-nil, don't decode STRING." | |||
| 732 | (if no-decode | 799 | (if no-decode |
| 733 | (list (or string "text/plain")) | 800 | (list (or string "text/plain")) |
| 734 | (mail-header-parse-content-type (or string "text/plain")))) | 801 | (mail-header-parse-content-type (or string "text/plain")))) |
| 735 | (setq major (split-string (car ctl) "/")) | 802 | ;; Check if there's a user-defined viewer from `mailcap-user-mime-data'. |
| 736 | (setq minor (cadr major) | 803 | (setq viewer (mailcap-select-preferred-viewer ctl)) |
| 737 | major (car major)) | 804 | (if viewer |
| 738 | (when (setq major-info (cdr (assoc major mailcap-mime-data))) | 805 | (setq passed (list viewer)) |
| 739 | (when (setq viewers (mailcap-possible-viewers major-info minor)) | 806 | ;; None found, so heuristically select some applicable viewer |
| 740 | (setq info (mapcar (lambda (a) (cons (symbol-name (car a)) | 807 | ;; from `mailcap-mime-data'. |
| 741 | (cdr a))) | 808 | (setq major (split-string (car ctl) "/")) |
| 742 | (cdr ctl))) | 809 | (setq minor (cadr major) |
| 743 | (while viewers | 810 | major (car major)) |
| 744 | (if (mailcap-viewer-passes-test (car viewers) info) | 811 | (when (setq major-info (cdr (assoc major mailcap-mime-data))) |
| 745 | (setq passed (cons (car viewers) passed))) | 812 | (when (setq viewers (mailcap-possible-viewers major-info minor)) |
| 746 | (setq viewers (cdr viewers))) | 813 | (setq info (mapcar (lambda (a) (cons (symbol-name (car a)) |
| 747 | (setq passed (sort passed 'mailcap-viewer-lessp)) | 814 | (cdr a))) |
| 748 | (setq viewer (car passed)))) | 815 | (cdr ctl))) |
| 749 | (when (and (stringp (cdr (assq 'viewer viewer))) | 816 | (while viewers |
| 750 | passed) | 817 | (if (mailcap-viewer-passes-test (car viewers) info) |
| 751 | (setq viewer (car passed))) | 818 | (setq passed (cons (car viewers) passed))) |
| 819 | (setq viewers (cdr viewers))) | ||
| 820 | (setq passed (sort passed 'mailcap-viewer-lessp)) | ||
| 821 | (setq viewer (car passed)))) | ||
| 822 | (when (and (stringp (cdr (assq 'viewer viewer))) | ||
| 823 | passed) | ||
| 824 | (setq viewer (car passed)))) | ||
| 752 | (cond | 825 | (cond |
| 753 | ((and (null viewer) (not (equal major "default")) request) | 826 | ((and (null viewer) (not (equal major "default")) request) |
| 754 | (mailcap-mime-info "default" request no-decode)) | 827 | (mailcap-mime-info "default" request no-decode)) |
| 755 | ((or (null request) (equal request "")) | 828 | ((or (null request) (equal request "")) |
| 756 | (mailcap-unescape-mime-test (cdr (assq 'viewer viewer)) info)) | 829 | (mailcap-unescape-mime-test (cdr (assq 'viewer viewer)) info)) |
| 757 | ((stringp request) | 830 | ((stringp request) |
| 758 | (mailcap-unescape-mime-test | 831 | (mailcap-unescape-mime-test |
| 759 | (cdr-safe (assoc request viewer)) info)) | 832 | (cdr-safe (assoc request viewer)) info)) |
| 760 | ((eq request 'all) | 833 | ((eq request 'all) |
| 761 | passed) | 834 | passed) |
| 762 | (t | 835 | (t |
| 763 | ;; MUST make a copy *sigh*, else we modify mailcap-mime-data | 836 | ;; MUST make a copy *sigh*, else we modify mailcap-mime-data |
| 764 | (setq viewer (copy-sequence viewer)) | 837 | (setq viewer (copy-sequence viewer)) |
| 765 | (let ((view (assq 'viewer viewer)) | 838 | (let ((view (assq 'viewer viewer)) |
| 766 | (test (assq 'test viewer))) | 839 | (test (assq 'test viewer))) |
| 767 | (if view (setcdr view (mailcap-unescape-mime-test (cdr view) info))) | 840 | (if view (setcdr view (mailcap-unescape-mime-test (cdr view) info))) |
| 768 | (if test (setcdr test (mailcap-unescape-mime-test (cdr test) info)))) | 841 | (if test (setcdr test (mailcap-unescape-mime-test (cdr test) info)))) |
| 769 | viewer))))) | 842 | viewer))))) |
| 770 | 843 | ||
| 771 | ;;; | 844 | ;;; |
| 772 | ;;; Experimental MIME-types parsing | 845 | ;;; Experimental MIME-types parsing |