diff options
| author | Vincent Belaïche | 2016-01-20 08:30:51 +0100 |
|---|---|---|
| committer | Vincent Belaïche | 2016-01-20 08:30:51 +0100 |
| commit | b895c72059521fec064ff27b4cfcfa4104081c4e (patch) | |
| tree | c1697f0e4d95d8c3556798f6c4c53c98a4714bd0 /lisp | |
| parent | badcd38aa86ed7973f2be2743c405710973a0bdd (diff) | |
| parent | 1b76d9168336ede8976b980aeaed64ae2908501a (diff) | |
| download | emacs-b895c72059521fec064ff27b4cfcfa4104081c4e.tar.gz emacs-b895c72059521fec064ff27b4cfcfa4104081c4e.zip | |
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'lisp')
78 files changed, 1325 insertions, 2291 deletions
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el index 30320b00946..ce367485c16 100644 --- a/lisp/cedet/mode-local.el +++ b/lisp/cedet/mode-local.el | |||
| @@ -670,7 +670,7 @@ SYMBOL is a function that can be overridden." | |||
| 670 | 670 | ||
| 671 | (add-hook 'help-fns-describe-function-functions 'describe-mode-local-overload) | 671 | (add-hook 'help-fns-describe-function-functions 'describe-mode-local-overload) |
| 672 | 672 | ||
| 673 | (declare-function xref-item-location "xref" (xref)) | 673 | (declare-function xref-item-location "xref" (xref) t) |
| 674 | 674 | ||
| 675 | (defun xref-mode-local--override-present (sym xrefs) | 675 | (defun xref-mode-local--override-present (sym xrefs) |
| 676 | "Return non-nil if SYM is in XREFS." | 676 | "Return non-nil if SYM is in XREFS." |
diff --git a/lisp/descr-text.el b/lisp/descr-text.el index dcc697e1b9a..a352ed0849c 100644 --- a/lisp/descr-text.el +++ b/lisp/descr-text.el | |||
| @@ -322,7 +322,7 @@ This function is semi-obsolete. Use `get-char-code-property'." | |||
| 322 | (nth 13 fields) 16))))))))))) | 322 | (nth 13 fields) 16))))))))))) |
| 323 | 323 | ||
| 324 | ;; Not defined on builds without X, but behind display-graphic-p. | 324 | ;; Not defined on builds without X, but behind display-graphic-p. |
| 325 | (declare-function internal-char-font "fontset.c" (position &optional ch)) | 325 | (declare-function internal-char-font "font.c" (position &optional ch)) |
| 326 | 326 | ||
| 327 | ;; Return information about how CHAR is displayed at the buffer | 327 | ;; Return information about how CHAR is displayed at the buffer |
| 328 | ;; position POS. If the selected frame is on a graphic display, | 328 | ;; position POS. If the selected frame is on a graphic display, |
diff --git a/lisp/desktop.el b/lisp/desktop.el index cb973c48f8d..e795d9c2300 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el | |||
| @@ -140,8 +140,15 @@ | |||
| 140 | 140 | ||
| 141 | (defvar desktop-file-version "208" | 141 | (defvar desktop-file-version "208" |
| 142 | "Version number of desktop file format. | 142 | "Version number of desktop file format. |
| 143 | Written into the desktop file and used at desktop read to provide | 143 | Used at desktop read to provide backward compatibility.") |
| 144 | backward compatibility.") | 144 | |
| 145 | (defconst desktop-native-file-version 208 | ||
| 146 | "Format version of the current desktop package, an integer.") | ||
| 147 | (defvar desktop-io-file-version nil | ||
| 148 | "The format version of the current desktop file (an integer) or nil.") | ||
| 149 | ;; Note: Historically, the version number is embedded in the entry for | ||
| 150 | ;; each buffer. It is highly inadvisable for different buffer entries | ||
| 151 | ;; to have different format versions. | ||
| 145 | 152 | ||
| 146 | ;; ---------------------------------------------------------------------------- | 153 | ;; ---------------------------------------------------------------------------- |
| 147 | ;; USER OPTIONS -- settings you might want to play with. | 154 | ;; USER OPTIONS -- settings you might want to play with. |
| @@ -693,6 +700,7 @@ deletes all frames except the selected one (and its minibuffer frame, | |||
| 693 | if different)." | 700 | if different)." |
| 694 | (interactive) | 701 | (interactive) |
| 695 | (desktop-lazy-abort) | 702 | (desktop-lazy-abort) |
| 703 | (setq desktop-io-file-version nil) | ||
| 696 | (dolist (var desktop-globals-to-clear) | 704 | (dolist (var desktop-globals-to-clear) |
| 697 | (if (symbolp var) | 705 | (if (symbolp var) |
| 698 | (eval `(setq-default ,var nil)) | 706 | (eval `(setq-default ,var nil)) |
| @@ -781,44 +789,46 @@ buffer, which is (in order): | |||
| 781 | local variables; | 789 | local variables; |
| 782 | auxiliary information given by `desktop-var-serdes-funs'." | 790 | auxiliary information given by `desktop-var-serdes-funs'." |
| 783 | (set-buffer buffer) | 791 | (set-buffer buffer) |
| 784 | (list | 792 | `( |
| 785 | ;; base name of the buffer; replaces the buffer name if managed by uniquify | 793 | ;; base name of the buffer; replaces the buffer name if managed by uniquify |
| 786 | (and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name)) | 794 | ,(and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name)) |
| 787 | ;; basic information | 795 | ;; basic information |
| 788 | (desktop-file-name (buffer-file-name) desktop-dirname) | 796 | ,(desktop-file-name (buffer-file-name) desktop-dirname) |
| 789 | (buffer-name) | 797 | ,(buffer-name) |
| 790 | major-mode | 798 | ,major-mode |
| 791 | ;; minor modes | 799 | ;; minor modes |
| 792 | (let (ret) | 800 | ,(let (ret) |
| 793 | (dolist (minor-mode (mapcar #'car minor-mode-alist) ret) | 801 | (dolist (minor-mode (mapcar #'car minor-mode-alist) ret) |
| 794 | (and (boundp minor-mode) | 802 | (and (boundp minor-mode) |
| 795 | (symbol-value minor-mode) | 803 | (symbol-value minor-mode) |
| 796 | (let* ((special (assq minor-mode desktop-minor-mode-table)) | 804 | (let* ((special (assq minor-mode desktop-minor-mode-table)) |
| 797 | (value (cond (special (cadr special)) | 805 | (value (cond (special (cadr special)) |
| 798 | ((functionp minor-mode) minor-mode)))) | 806 | ((functionp minor-mode) minor-mode)))) |
| 799 | (when value (cl-pushnew value ret)))))) | 807 | (when value (cl-pushnew value ret)))))) |
| 800 | ;; point and mark, and read-only status | 808 | ;; point and mark, and read-only status |
| 801 | (point) | 809 | ,(point) |
| 802 | (list (mark t) mark-active) | 810 | ,(list (mark t) mark-active) |
| 803 | buffer-read-only | 811 | ,buffer-read-only |
| 804 | ;; auxiliary information | 812 | ;; auxiliary information |
| 805 | (when (functionp desktop-save-buffer) | 813 | ,(when (functionp desktop-save-buffer) |
| 806 | (funcall desktop-save-buffer desktop-dirname)) | 814 | (funcall desktop-save-buffer desktop-dirname)) |
| 807 | ;; local variables | 815 | ;; local variables |
| 808 | (let ((loclist (buffer-local-variables)) | 816 | ,(let ((loclist (buffer-local-variables)) |
| 809 | (ll nil)) | 817 | (ll nil)) |
| 810 | (dolist (local desktop-locals-to-save) | 818 | (dolist (local desktop-locals-to-save) |
| 811 | (let ((here (assq local loclist))) | 819 | (let ((here (assq local loclist))) |
| 812 | (cond (here | 820 | (cond (here |
| 813 | (push here ll)) | 821 | (push here ll)) |
| 814 | ((member local loclist) | 822 | ((member local loclist) |
| 815 | (push local ll))))) | 823 | (push local ll))))) |
| 816 | ll) | 824 | ll) |
| 817 | (mapcar (lambda (record) | 825 | ,@(when (>= desktop-io-file-version 208) |
| 818 | (let ((var (car record))) | 826 | (list |
| 819 | (list var | 827 | (mapcar (lambda (record) |
| 820 | (funcall (cadr record) (symbol-value var))))) | 828 | (let ((var (car record))) |
| 821 | desktop-var-serdes-funs))) | 829 | (list var |
| 830 | (funcall (cadr record) (symbol-value var))))) | ||
| 831 | desktop-var-serdes-funs))))) | ||
| 822 | 832 | ||
| 823 | ;; ---------------------------------------------------------------------------- | 833 | ;; ---------------------------------------------------------------------------- |
| 824 | (defun desktop--v2s (value) | 834 | (defun desktop--v2s (value) |
| @@ -983,20 +993,41 @@ Frames with a non-nil `desktop-dont-save' parameter are not saved." | |||
| 983 | :predicate #'desktop--check-dont-save)))) | 993 | :predicate #'desktop--check-dont-save)))) |
| 984 | 994 | ||
| 985 | ;;;###autoload | 995 | ;;;###autoload |
| 986 | (defun desktop-save (dirname &optional release only-if-changed) | 996 | (defun desktop-save (dirname &optional release only-if-changed version) |
| 987 | "Save the desktop in a desktop file. | 997 | "Save the desktop in a desktop file. |
| 988 | Parameter DIRNAME specifies where to save the desktop file. | 998 | Parameter DIRNAME specifies where to save the desktop file. |
| 989 | Optional parameter RELEASE says whether we're done with this desktop. | 999 | Optional parameter RELEASE says whether we're done with this |
| 990 | If ONLY-IF-CHANGED is non-nil, compare the current desktop information | 1000 | desktop. If ONLY-IF-CHANGED is non-nil, compare the current |
| 991 | to that in the desktop file, and if the desktop information has not | 1001 | desktop information to that in the desktop file, and if the |
| 992 | changed since it was last saved then do not rewrite the file." | 1002 | desktop information has not changed since it was last saved then |
| 1003 | do not rewrite the file. | ||
| 1004 | |||
| 1005 | This function can save the desktop in either format version | ||
| 1006 | 208 (which only Emacs 25.1 and later can read) or version | ||
| 1007 | 206 (which is readable by any Emacs from version 22.1 onwards). | ||
| 1008 | By default, it will use the same format the desktop file had when | ||
| 1009 | it was last saved, or version 208 when writing a fresh desktop | ||
| 1010 | file. | ||
| 1011 | |||
| 1012 | To upgrade a version 206 file to version 208, call this command | ||
| 1013 | explicitly with a bare prefix argument: C-u M-x desktop-save. | ||
| 1014 | You are recommended to do this once you have firmly upgraded to | ||
| 1015 | Emacs 25.1 (or later). To downgrade a version 208 file to version | ||
| 1016 | 206, use a double command prefix: C-u C-u M-x desktop-save. | ||
| 1017 | Confirmation will be requested in either case. In a non-interactive | ||
| 1018 | call, VERSION can be given as an integer, either 206 or 208, which | ||
| 1019 | will be accepted as the format version in which to save the file | ||
| 1020 | without further confirmation." | ||
| 993 | (interactive (list | 1021 | (interactive (list |
| 994 | ;; Or should we just use (car desktop-path)? | 1022 | ;; Or should we just use (car desktop-path)? |
| 995 | (let ((default (if (member "." desktop-path) | 1023 | (let ((default (if (member "." desktop-path) |
| 996 | default-directory | 1024 | default-directory |
| 997 | user-emacs-directory))) | 1025 | user-emacs-directory))) |
| 998 | (read-directory-name "Directory to save desktop file in: " | 1026 | (read-directory-name "Directory to save desktop file in: " |
| 999 | default default t)))) | 1027 | default default t)) |
| 1028 | nil | ||
| 1029 | nil | ||
| 1030 | current-prefix-arg)) | ||
| 1000 | (setq desktop-dirname (file-name-as-directory (expand-file-name dirname))) | 1031 | (setq desktop-dirname (file-name-as-directory (expand-file-name dirname))) |
| 1001 | (save-excursion | 1032 | (save-excursion |
| 1002 | (let ((eager desktop-restore-eager) | 1033 | (let ((eager desktop-restore-eager) |
| @@ -1017,12 +1048,34 @@ changed since it was last saved then do not rewrite the file." | |||
| 1017 | (desktop-release-lock) | 1048 | (desktop-release-lock) |
| 1018 | (unless (and new-modtime (desktop-owner)) (desktop-claim-lock))) | 1049 | (unless (and new-modtime (desktop-owner)) (desktop-claim-lock))) |
| 1019 | 1050 | ||
| 1051 | ;; What format are we going to write the file in? | ||
| 1052 | (setq desktop-io-file-version | ||
| 1053 | (cond | ||
| 1054 | ((equal version '(4)) | ||
| 1055 | (if (or (eq desktop-io-file-version 208) | ||
| 1056 | (yes-or-no-p "Save desktop file in format 208 \ | ||
| 1057 | \(Readable by Emacs 25.1 and later only)? ")) | ||
| 1058 | 208 | ||
| 1059 | (or desktop-io-file-version desktop-native-file-version))) | ||
| 1060 | ((equal version '(16)) | ||
| 1061 | (if (or (eq desktop-io-file-version 206) | ||
| 1062 | (yes-or-no-p "Save desktop file in format 206 \ | ||
| 1063 | \(Readable by all Emacs versions since 22.1)? ")) | ||
| 1064 | 206 | ||
| 1065 | (or desktop-io-file-version desktop-native-file-version))) | ||
| 1066 | ((memq version '(206 208)) | ||
| 1067 | version) | ||
| 1068 | ((null desktop-io-file-version) ; As yet, no desktop file exists. | ||
| 1069 | desktop-native-file-version) | ||
| 1070 | (t | ||
| 1071 | desktop-io-file-version))) | ||
| 1072 | |||
| 1020 | (with-temp-buffer | 1073 | (with-temp-buffer |
| 1021 | (insert | 1074 | (insert |
| 1022 | ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n" | 1075 | ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n" |
| 1023 | desktop-header | 1076 | desktop-header |
| 1024 | ";; Created " (current-time-string) "\n" | 1077 | ";; Created " (current-time-string) "\n" |
| 1025 | ";; Desktop file format version " desktop-file-version "\n" | 1078 | ";; Desktop file format version " (format "%d" desktop-io-file-version) "\n" |
| 1026 | ";; Emacs version " emacs-version "\n") | 1079 | ";; Emacs version " emacs-version "\n") |
| 1027 | (save-excursion (run-hooks 'desktop-save-hook)) | 1080 | (save-excursion (run-hooks 'desktop-save-hook)) |
| 1028 | (goto-char (point-max)) | 1081 | (goto-char (point-max)) |
| @@ -1052,7 +1105,7 @@ changed since it was last saved then do not rewrite the file." | |||
| 1052 | "desktop-create-buffer" | 1105 | "desktop-create-buffer" |
| 1053 | "desktop-append-buffer-args") | 1106 | "desktop-append-buffer-args") |
| 1054 | " " | 1107 | " " |
| 1055 | desktop-file-version) | 1108 | (format "%d" desktop-io-file-version)) |
| 1056 | ;; If there's a non-empty base name, we save it instead of the buffer name | 1109 | ;; If there's a non-empty base name, we save it instead of the buffer name |
| 1057 | (when (and base (not (string= base ""))) | 1110 | (when (and base (not (string= base ""))) |
| 1058 | (setcar (nthcdr 1 l) base)) | 1111 | (setcar (nthcdr 1 l) base)) |
| @@ -1390,6 +1443,8 @@ and try to load that." | |||
| 1390 | compacted-vars | 1443 | compacted-vars |
| 1391 | &rest _unsupported) | 1444 | &rest _unsupported) |
| 1392 | 1445 | ||
| 1446 | (setq desktop-io-file-version file-version) | ||
| 1447 | |||
| 1393 | (let ((desktop-file-version file-version) | 1448 | (let ((desktop-file-version file-version) |
| 1394 | (desktop-buffer-file-name buffer-filename) | 1449 | (desktop-buffer-file-name buffer-filename) |
| 1395 | (desktop-buffer-name buffer-name) | 1450 | (desktop-buffer-name buffer-name) |
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index a678fca3ea3..ab10edeedbf 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el | |||
| @@ -2713,6 +2713,41 @@ with the command \\[tags-loop-continue]." | |||
| 2713 | (tags-query-replace from to delimited | 2713 | (tags-query-replace from to delimited |
| 2714 | '(dired-get-marked-files nil nil 'dired-nondirectory-p))) | 2714 | '(dired-get-marked-files nil nil 'dired-nondirectory-p))) |
| 2715 | 2715 | ||
| 2716 | (declare-function xref--show-xrefs "xref") | ||
| 2717 | (declare-function xref-query-replace "xref") | ||
| 2718 | |||
| 2719 | ;;;###autoload | ||
| 2720 | (defun dired-do-find-regexp (regexp) | ||
| 2721 | "Find all matches for REGEXP in all marked files, recursively." | ||
| 2722 | (interactive "sSearch marked files (regexp): ") | ||
| 2723 | (require 'grep) | ||
| 2724 | (defvar grep-find-ignored-files) | ||
| 2725 | (let* ((files (dired-get-marked-files)) | ||
| 2726 | (ignores (nconc (mapcar | ||
| 2727 | (lambda (s) (concat s "/")) | ||
| 2728 | vc-directory-exclusion-list) | ||
| 2729 | grep-find-ignored-files)) | ||
| 2730 | (xrefs (cl-mapcan | ||
| 2731 | (lambda (file) | ||
| 2732 | (xref-collect-matches regexp "*" file | ||
| 2733 | (and (file-directory-p file) | ||
| 2734 | ignores))) | ||
| 2735 | files))) | ||
| 2736 | (unless xrefs | ||
| 2737 | (user-error "No matches for: %s" regexp)) | ||
| 2738 | (xref--show-xrefs xrefs nil t))) | ||
| 2739 | |||
| 2740 | ;;;###autoload | ||
| 2741 | (defun dired-do-find-regexp-and-replace (from to) | ||
| 2742 | "Replace matches of FROM with TO, in all marked files, recursively." | ||
| 2743 | (interactive | ||
| 2744 | (let ((common | ||
| 2745 | (query-replace-read-args | ||
| 2746 | "Query replace regexp in marked files" t t))) | ||
| 2747 | (list (nth 0 common) (nth 1 common)))) | ||
| 2748 | (with-current-buffer (dired-do-find-regexp from) | ||
| 2749 | (xref-query-replace from to))) | ||
| 2750 | |||
| 2716 | (defun dired-nondirectory-p (file) | 2751 | (defun dired-nondirectory-p (file) |
| 2717 | (not (file-directory-p file))) | 2752 | (not (file-directory-p file))) |
| 2718 | 2753 | ||
diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 053b3cb9738..e8cea85d988 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el | |||
| @@ -816,16 +816,14 @@ If in a Dired buffer, reverts it." | |||
| 816 | (interactive) | 816 | (interactive) |
| 817 | (if (file-exists-p dired-local-variables-file) | 817 | (if (file-exists-p dired-local-variables-file) |
| 818 | (error "Old-style dired-local-variables-file `./%s' found; | 818 | (error "Old-style dired-local-variables-file `./%s' found; |
| 819 | replace it with a dir-locals-file `./%s'" | 819 | replace it with a dir-locals-file `./%s.el'" |
| 820 | dired-local-variables-file | 820 | dired-local-variables-file |
| 821 | dir-locals-file)) | 821 | dir-locals-file)) |
| 822 | (if (file-exists-p dir-locals-file) | 822 | (if (dir-locals--all-files default-directory) |
| 823 | (message "File `./%s' already exists." dir-locals-file) | 823 | (message "File `./%s' already exists." |
| 824 | (with-temp-buffer | 824 | (car (dir-locals--all-files default-directory))) |
| 825 | (insert "\ | 825 | (add-dir-local-variable 'dired-mode 'subdirs nil) |
| 826 | \((dired-mode . ((subdirs . nil) | 826 | (add-dir-local-variable 'dired-mode 'dired-omit-mode t) |
| 827 | (dired-omit-mode . t))))\n") | ||
| 828 | (write-file dir-locals-file)) | ||
| 829 | ;; Run extra-hooks and revert directory. | 827 | ;; Run extra-hooks and revert directory. |
| 830 | (when (derived-mode-p 'dired-mode) | 828 | (when (derived-mode-p 'dired-mode) |
| 831 | (hack-dir-local-variables-non-file-buffer) | 829 | (hack-dir-local-variables-non-file-buffer) |
diff --git a/lisp/dired.el b/lisp/dired.el index 63124fce5e5..6c7445c3486 100644 --- a/lisp/dired.el +++ b/lisp/dired.el | |||
| @@ -1453,7 +1453,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." | |||
| 1453 | (define-key map "." 'dired-clean-directory) | 1453 | (define-key map "." 'dired-clean-directory) |
| 1454 | (define-key map "~" 'dired-flag-backup-files) | 1454 | (define-key map "~" 'dired-flag-backup-files) |
| 1455 | ;; Upper case keys (except !) for operating on the marked files | 1455 | ;; Upper case keys (except !) for operating on the marked files |
| 1456 | (define-key map "A" 'dired-do-search) | 1456 | (define-key map "A" 'dired-do-find-regexp) |
| 1457 | (define-key map "C" 'dired-do-copy) | 1457 | (define-key map "C" 'dired-do-copy) |
| 1458 | (define-key map "B" 'dired-do-byte-compile) | 1458 | (define-key map "B" 'dired-do-byte-compile) |
| 1459 | (define-key map "D" 'dired-do-delete) | 1459 | (define-key map "D" 'dired-do-delete) |
| @@ -1463,7 +1463,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." | |||
| 1463 | (define-key map "M" 'dired-do-chmod) | 1463 | (define-key map "M" 'dired-do-chmod) |
| 1464 | (define-key map "O" 'dired-do-chown) | 1464 | (define-key map "O" 'dired-do-chown) |
| 1465 | (define-key map "P" 'dired-do-print) | 1465 | (define-key map "P" 'dired-do-print) |
| 1466 | (define-key map "Q" 'dired-do-query-replace-regexp) | 1466 | (define-key map "Q" 'dired-do-find-regexp-and-replace) |
| 1467 | (define-key map "R" 'dired-do-rename) | 1467 | (define-key map "R" 'dired-do-rename) |
| 1468 | (define-key map "S" 'dired-do-symlink) | 1468 | (define-key map "S" 'dired-do-symlink) |
| 1469 | (define-key map "T" 'dired-do-touch) | 1469 | (define-key map "T" 'dired-do-touch) |
diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el index 7defb388b74..0ce2b23527d 100644 --- a/lisp/dos-fns.el +++ b/lisp/dos-fns.el | |||
| @@ -201,8 +201,8 @@ that are used in Emacs Lisp sources; any other file name will be | |||
| 201 | returned unaltered." | 201 | returned unaltered." |
| 202 | (cond | 202 | (cond |
| 203 | ;; See files.el:dir-locals-file. | 203 | ;; See files.el:dir-locals-file. |
| 204 | ((string= file-name ".dir-locals.el") | 204 | ((string= file-name ".dir-locals") |
| 205 | "_dir-locals.el") | 205 | "_dir-locals") |
| 206 | (t | 206 | (t |
| 207 | file-name))) | 207 | file-name))) |
| 208 | 208 | ||
diff --git a/lisp/electric.el b/lisp/electric.el index abddd986ef8..ab79943c9dd 100644 --- a/lisp/electric.el +++ b/lisp/electric.el | |||
| @@ -417,14 +417,17 @@ The variable `electric-layout-rules' says when and how to insert newlines." | |||
| 417 | 417 | ||
| 418 | (defcustom electric-quote-comment t | 418 | (defcustom electric-quote-comment t |
| 419 | "Non-nil means to use electric quoting in program comments." | 419 | "Non-nil means to use electric quoting in program comments." |
| 420 | :version "25.1" | ||
| 420 | :type 'boolean :safe 'booleanp :group 'electricity) | 421 | :type 'boolean :safe 'booleanp :group 'electricity) |
| 421 | 422 | ||
| 422 | (defcustom electric-quote-string nil | 423 | (defcustom electric-quote-string nil |
| 423 | "Non-nil means to use electric quoting in program strings." | 424 | "Non-nil means to use electric quoting in program strings." |
| 425 | :version "25.1" | ||
| 424 | :type 'boolean :safe 'booleanp :group 'electricity) | 426 | :type 'boolean :safe 'booleanp :group 'electricity) |
| 425 | 427 | ||
| 426 | (defcustom electric-quote-paragraph t | 428 | (defcustom electric-quote-paragraph t |
| 427 | "Non-nil means to use electric quoting in text paragraphs." | 429 | "Non-nil means to use electric quoting in text paragraphs." |
| 430 | :version "25.1" | ||
| 428 | :type 'boolean :safe 'booleanp :group 'electricity) | 431 | :type 'boolean :safe 'booleanp :group 'electricity) |
| 429 | 432 | ||
| 430 | (defun electric--insertable-p (string) | 433 | (defun electric--insertable-p (string) |
diff --git a/lisp/emacs-lisp/check-declare.el b/lisp/emacs-lisp/check-declare.el index 513aa319798..b6fa0546088 100644 --- a/lisp/emacs-lisp/check-declare.el +++ b/lisp/emacs-lisp/check-declare.el | |||
| @@ -131,6 +131,7 @@ With optional argument FULL, sums the number of elements in each element." | |||
| 131 | 131 | ||
| 132 | (defcustom check-declare-ext-errors nil | 132 | (defcustom check-declare-ext-errors nil |
| 133 | "When non-nil, warn about functions not found in :ext." | 133 | "When non-nil, warn about functions not found in :ext." |
| 134 | :version "25.1" | ||
| 134 | :type 'boolean) | 135 | :type 'boolean) |
| 135 | 136 | ||
| 136 | (defun check-declare-verify (fnfile fnlist) | 137 | (defun check-declare-verify (fnfile fnlist) |
diff --git a/lisp/emacs-lisp/cursor-sensor.el b/lisp/emacs-lisp/cursor-sensor.el index 70c4458d300..ac063d4896a 100644 --- a/lisp/emacs-lisp/cursor-sensor.el +++ b/lisp/emacs-lisp/cursor-sensor.el | |||
| @@ -167,8 +167,8 @@ | |||
| 167 | This property should hold a list of functions which react to the motion | 167 | This property should hold a list of functions which react to the motion |
| 168 | of the cursor. They're called with three arguments (WINDOW OLDPOS DIR) | 168 | of the cursor. They're called with three arguments (WINDOW OLDPOS DIR) |
| 169 | where WINDOW is the affected window, OLDPOS is the last known position of | 169 | where WINDOW is the affected window, OLDPOS is the last known position of |
| 170 | the cursor and DIR can be `left' or `entered' depending on whether the cursor is | 170 | the cursor and DIR can be `entered' or `left' depending on whether the cursor |
| 171 | entering the area covered by the text-property property or leaving it." | 171 | is entering the area covered by the text-property property or leaving it." |
| 172 | nil nil nil | 172 | nil nil nil |
| 173 | (if cursor-sensor-mode | 173 | (if cursor-sensor-mode |
| 174 | (add-hook 'pre-redisplay-functions #'cursor-sensor--detect | 174 | (add-hook 'pre-redisplay-functions #'cursor-sensor--detect |
diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el index 56780fbb05a..058c56c3b49 100644 --- a/lisp/emacs-lisp/inline.el +++ b/lisp/emacs-lisp/inline.el | |||
| @@ -102,7 +102,7 @@ VARS should be a list of elements of the form (VAR EXP) or just VAR, in case | |||
| 102 | EXP is equal to VAR. The result is to evaluate EXP and bind the result to VAR. | 102 | EXP is equal to VAR. The result is to evaluate EXP and bind the result to VAR. |
| 103 | 103 | ||
| 104 | The tail of VARS can be either nil or a symbol VAR which should hold a list | 104 | The tail of VARS can be either nil or a symbol VAR which should hold a list |
| 105 | of arguments,in which case each argument is evaluated and the resulting | 105 | of arguments, in which case each argument is evaluated and the resulting |
| 106 | new list is re-bound to VAR. | 106 | new list is re-bound to VAR. |
| 107 | 107 | ||
| 108 | After VARS is handled, BODY is evaluated in the new environment." | 108 | After VARS is handled, BODY is evaluated in the new environment." |
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 057d01488cc..08f64147d44 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -329,6 +329,7 @@ by running `package-install-selected-packages'. | |||
| 329 | To check if a package is contained in this list here, use | 329 | To check if a package is contained in this list here, use |
| 330 | `package--user-selected-p', as it may populate the variable with | 330 | `package--user-selected-p', as it may populate the variable with |
| 331 | a sane initial value." | 331 | a sane initial value." |
| 332 | :version "25.1" | ||
| 332 | :type '(repeat symbol)) | 333 | :type '(repeat symbol)) |
| 333 | 334 | ||
| 334 | (defcustom package-menu-async t | 335 | (defcustom package-menu-async t |
| @@ -2654,6 +2655,7 @@ omitted from the package menu. To toggle this, type \\[package-menu-toggle-hidi | |||
| 2654 | 2655 | ||
| 2655 | Values can be interactively added to this list by typing | 2656 | Values can be interactively added to this list by typing |
| 2656 | \\[package-menu-hide-package] on a package" | 2657 | \\[package-menu-hide-package] on a package" |
| 2658 | :version "25.1" | ||
| 2657 | :type '(repeat (regexp :tag "Hide packages with name matching"))) | 2659 | :type '(repeat (regexp :tag "Hide packages with name matching"))) |
| 2658 | 2660 | ||
| 2659 | (defun package-menu--refresh (&optional packages keywords) | 2661 | (defun package-menu--refresh (&optional packages keywords) |
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el index e20a210de71..c221a017f51 100644 --- a/lisp/emacs-lisp/syntax.el +++ b/lisp/emacs-lisp/syntax.el | |||
| @@ -416,6 +416,9 @@ point (where the PPSS is equivalent to nil).") | |||
| 416 | (error nil))) | 416 | (error nil))) |
| 417 | syntax-ppss-stats)) | 417 | syntax-ppss-stats)) |
| 418 | 418 | ||
| 419 | (defvar-local syntax-ppss-table nil | ||
| 420 | "Syntax-table to use during `syntax-ppss', if any.") | ||
| 421 | |||
| 419 | (defun syntax-ppss (&optional pos) | 422 | (defun syntax-ppss (&optional pos) |
| 420 | "Parse-Partial-Sexp State at POS, defaulting to point. | 423 | "Parse-Partial-Sexp State at POS, defaulting to point. |
| 421 | The returned value is the same as that of `parse-partial-sexp' | 424 | The returned value is the same as that of `parse-partial-sexp' |
| @@ -431,6 +434,7 @@ running the hook." | |||
| 431 | (unless pos (setq pos (point))) | 434 | (unless pos (setq pos (point))) |
| 432 | (syntax-propertize pos) | 435 | (syntax-propertize pos) |
| 433 | ;; | 436 | ;; |
| 437 | (with-syntax-table (or syntax-ppss-table (syntax-table)) | ||
| 434 | (let ((old-ppss (cdr syntax-ppss-last)) | 438 | (let ((old-ppss (cdr syntax-ppss-last)) |
| 435 | (old-pos (car syntax-ppss-last)) | 439 | (old-pos (car syntax-ppss-last)) |
| 436 | (ppss nil) | 440 | (ppss nil) |
| @@ -567,7 +571,7 @@ running the hook." | |||
| 567 | ;; we may end up calling parse-partial-sexp with a position before | 571 | ;; we may end up calling parse-partial-sexp with a position before |
| 568 | ;; point-min. In that case, just parse from point-min assuming | 572 | ;; point-min. In that case, just parse from point-min assuming |
| 569 | ;; a nil state. | 573 | ;; a nil state. |
| 570 | (parse-partial-sexp (point-min) pos))))) | 574 | (parse-partial-sexp (point-min) pos)))))) |
| 571 | 575 | ||
| 572 | ;; Debugging functions | 576 | ;; Debugging functions |
| 573 | 577 | ||
diff --git a/lisp/epg-config.el b/lisp/epg-config.el index 5fac079d3c0..e92bcd62a66 100644 --- a/lisp/epg-config.el +++ b/lisp/epg-config.el | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | 53 | ||
| 54 | (defcustom epg-gpgconf-program "gpgconf" | 54 | (defcustom epg-gpgconf-program "gpgconf" |
| 55 | "The `gpgconf' executable." | 55 | "The `gpgconf' executable." |
| 56 | :version "25.1" | ||
| 56 | :group 'epg | 57 | :group 'epg |
| 57 | :type 'string) | 58 | :type 'string) |
| 58 | 59 | ||
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 3824c195d39..56317b83a98 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el | |||
| @@ -265,14 +265,16 @@ A typical value would be \(\"JOIN\" \"PART\" \"QUIT\")." | |||
| 265 | (defcustom erc-network-hide-list nil | 265 | (defcustom erc-network-hide-list nil |
| 266 | "A list of IRC networks to hide message types from. | 266 | "A list of IRC networks to hide message types from. |
| 267 | A typical value would be \((\"freenode\" \"MODE\") | 267 | A typical value would be \((\"freenode\" \"MODE\") |
| 268 | (\"OFTC\" \"JOIN\" \"QUIT\"))." | 268 | \(\"OFTC\" \"JOIN\" \"QUIT\"))." |
| 269 | :version "25.1" | ||
| 269 | :group 'erc-ignore | 270 | :group 'erc-ignore |
| 270 | :type 'erc-message-type) | 271 | :type 'erc-message-type) |
| 271 | 272 | ||
| 272 | (defcustom erc-channel-hide-list nil | 273 | (defcustom erc-channel-hide-list nil |
| 273 | "A list of IRC channels to hide message types from. | 274 | "A list of IRC channels to hide message types from. |
| 274 | A typical value would be \((\"#emacs\" \"QUIT\" \"JOIN\") | 275 | A typical value would be \((\"#emacs\" \"QUIT\" \"JOIN\") |
| 275 | (\"#erc\" \"NICK\")." | 276 | \(\"#erc\" \"NICK\")." |
| 277 | :version "25.1" | ||
| 276 | :group 'erc-ignore | 278 | :group 'erc-ignore |
| 277 | :type 'erc-message-type) | 279 | :type 'erc-message-type) |
| 278 | 280 | ||
diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el index aabc5fdb1a2..3e5de0c0097 100644 --- a/lisp/eshell/em-term.el +++ b/lisp/eshell/em-term.el | |||
| @@ -136,6 +136,7 @@ character to the invoked process." | |||
| 136 | "If non-nil, term buffers are destroyed after their processes die. | 136 | "If non-nil, term buffers are destroyed after their processes die. |
| 137 | WARNING: Setting this to non-nil may result in unexpected | 137 | WARNING: Setting this to non-nil may result in unexpected |
| 138 | behavior for short-lived processes, see bug#18108." | 138 | behavior for short-lived processes, see bug#18108." |
| 139 | :version "25.1" | ||
| 139 | :type 'boolean | 140 | :type 'boolean |
| 140 | :group 'eshell-term) | 141 | :group 'eshell-term) |
| 141 | 142 | ||
diff --git a/lisp/files-x.el b/lisp/files-x.el index ed3d49df385..2e1a728356e 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el | |||
| @@ -444,10 +444,8 @@ from the MODE alist ignoring the input argument VALUE." | |||
| 444 | (if (nth 2 variables-file) | 444 | (if (nth 2 variables-file) |
| 445 | (car (last (dir-locals--all-files (car variables-file)))) | 445 | (car (last (dir-locals--all-files (car variables-file)))) |
| 446 | (cadr variables-file))) | 446 | (cadr variables-file))) |
| 447 | ;; Try to make a proper file-name. This doesn't cover all | 447 | ;; Try to make a proper file-name. |
| 448 | ;; wildcards, but it covers the default value of `dir-locals-file'. | 448 | (t (concat dir-locals-file ".el")))) |
| 449 | (t (replace-regexp-in-string | ||
| 450 | "\\*" "" (replace-regexp-in-string "\\?" "-" dir-locals-file))))) | ||
| 451 | ;; I can't be bothered to handle this case right now. | 449 | ;; I can't be bothered to handle this case right now. |
| 452 | ;; Dir locals were set directly from a class. You need to | 450 | ;; Dir locals were set directly from a class. You need to |
| 453 | ;; directly modify the class in dir-locals-class-alist. | 451 | ;; directly modify the class in dir-locals-class-alist. |
diff --git a/lisp/files.el b/lisp/files.el index 9cb46fcd0a9..5a15c71aab6 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -3713,7 +3713,7 @@ VARIABLES list of the class. The list is processed in order. | |||
| 3713 | applied by recursively following these rules." | 3713 | applied by recursively following these rules." |
| 3714 | (setf (alist-get class dir-locals-class-alist) variables)) | 3714 | (setf (alist-get class dir-locals-class-alist) variables)) |
| 3715 | 3715 | ||
| 3716 | (defconst dir-locals-file ".dir-locals*.el" | 3716 | (defconst dir-locals-file ".dir-locals" |
| 3717 | "Pattern for files that contain directory-local variables. | 3717 | "Pattern for files that contain directory-local variables. |
| 3718 | It has to be constant to enforce uniform values across different | 3718 | It has to be constant to enforce uniform values across different |
| 3719 | environments and users. | 3719 | environments and users. |
| @@ -3730,16 +3730,20 @@ return a sorted list of all files matching `dir-locals-file' in | |||
| 3730 | this directory. | 3730 | this directory. |
| 3731 | The returned list is sorted by `string<' order." | 3731 | The returned list is sorted by `string<' order." |
| 3732 | (require 'seq) | 3732 | (require 'seq) |
| 3733 | (let ((default-directory (if (file-directory-p file-or-dir) | 3733 | (let ((dir (if (file-directory-p file-or-dir) |
| 3734 | file-or-dir | 3734 | file-or-dir |
| 3735 | default-directory))) | 3735 | (or (file-name-directory file-or-dir) |
| 3736 | default-directory))) | ||
| 3737 | (file (cond ((not (file-directory-p file-or-dir)) (file-name-nondirectory file-or-dir)) | ||
| 3738 | ((eq system-type 'ms-dos) (dosified-file-name dir-locals-file)) | ||
| 3739 | (t dir-locals-file)))) | ||
| 3736 | (seq-filter (lambda (f) (and (file-readable-p f) | 3740 | (seq-filter (lambda (f) (and (file-readable-p f) |
| 3737 | (file-regular-p f))) | 3741 | (file-regular-p f) |
| 3738 | (file-expand-wildcards | 3742 | (not (file-directory-p f)))) |
| 3739 | (cond ((not (file-directory-p file-or-dir)) file-or-dir) | 3743 | (mapcar (lambda (f) (expand-file-name f dir)) |
| 3740 | ((eq system-type 'ms-dos) (dosified-file-name dir-locals-file)) | 3744 | (nreverse |
| 3741 | (t dir-locals-file)) | 3745 | (let ((completion-regexp-list '("\\.el\\'"))) |
| 3742 | 'full)))) | 3746 | (file-name-all-completions file dir))))))) |
| 3743 | 3747 | ||
| 3744 | (defun dir-locals-find-file (file) | 3748 | (defun dir-locals-find-file (file) |
| 3745 | "Find the directory-local variables for FILE. | 3749 | "Find the directory-local variables for FILE. |
diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 3c1f01d5886..c79835dda49 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el | |||
| @@ -1564,6 +1564,7 @@ START should be at the beginning of a line." | |||
| 1564 | "Put proper face on each string and comment between START and END. | 1564 | "Put proper face on each string and comment between START and END. |
| 1565 | START should be at the beginning of a line." | 1565 | START should be at the beginning of a line." |
| 1566 | (syntax-propertize end) ; Apply any needed syntax-table properties. | 1566 | (syntax-propertize end) ; Apply any needed syntax-table properties. |
| 1567 | (with-syntax-table (or syntax-ppss-table (syntax-table)) | ||
| 1567 | (let ((comment-end-regexp | 1568 | (let ((comment-end-regexp |
| 1568 | (or font-lock-comment-end-skip | 1569 | (or font-lock-comment-end-skip |
| 1569 | (regexp-quote | 1570 | (regexp-quote |
| @@ -1598,7 +1599,7 @@ START should be at the beginning of a line." | |||
| 1598 | font-lock-comment-delimiter-face)))) | 1599 | font-lock-comment-delimiter-face)))) |
| 1599 | (< (point) end)) | 1600 | (< (point) end)) |
| 1600 | (setq state (parse-partial-sexp (point) end nil nil state | 1601 | (setq state (parse-partial-sexp (point) end nil nil state |
| 1601 | 'syntax-table))))) | 1602 | 'syntax-table)))))) |
| 1602 | 1603 | ||
| 1603 | ;;; End of Syntactic fontification functions. | 1604 | ;;; End of Syntactic fontification functions. |
| 1604 | 1605 | ||
diff --git a/lisp/gnus/gnus-fun.el b/lisp/gnus/gnus-fun.el index fa78b5c6e15..a6b27300233 100644 --- a/lisp/gnus/gnus-fun.el +++ b/lisp/gnus/gnus-fun.el | |||
| @@ -44,7 +44,7 @@ | |||
| 44 | "Regexp to match faces in `gnus-x-face-directory' to be omitted." | 44 | "Regexp to match faces in `gnus-x-face-directory' to be omitted." |
| 45 | :version "25.1" | 45 | :version "25.1" |
| 46 | :group 'gnus-fun | 46 | :group 'gnus-fun |
| 47 | :type 'string) | 47 | :type '(choice (const nil) string)) |
| 48 | 48 | ||
| 49 | (defcustom gnus-face-directory (expand-file-name "faces" gnus-directory) | 49 | (defcustom gnus-face-directory (expand-file-name "faces" gnus-directory) |
| 50 | "*Directory where Face PNG files are stored." | 50 | "*Directory where Face PNG files are stored." |
| @@ -56,7 +56,7 @@ | |||
| 56 | "Regexp to match faces in `gnus-face-directory' to be omitted." | 56 | "Regexp to match faces in `gnus-face-directory' to be omitted." |
| 57 | :version "25.1" | 57 | :version "25.1" |
| 58 | :group 'gnus-fun | 58 | :group 'gnus-fun |
| 59 | :type 'string) | 59 | :type '(choice (const nil) string)) |
| 60 | 60 | ||
| 61 | (defcustom gnus-convert-pbm-to-x-face-command "pbmtoxbm %s | compface" | 61 | (defcustom gnus-convert-pbm-to-x-face-command "pbmtoxbm %s | compface" |
| 62 | "Command for converting a PBM to an X-Face." | 62 | "Command for converting a PBM to an X-Face." |
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el index ea5f3155478..31645fcd315 100644 --- a/lisp/gnus/gnus-util.el +++ b/lisp/gnus/gnus-util.el | |||
| @@ -1996,6 +1996,14 @@ to case differences." | |||
| 1996 | (defun gnus-timer--function (timer) | 1996 | (defun gnus-timer--function (timer) |
| 1997 | (elt timer 5))) | 1997 | (elt timer 5))) |
| 1998 | 1998 | ||
| 1999 | (defun gnus-test-list (list predicate) | ||
| 2000 | "To each element of LIST apply PREDICATE. | ||
| 2001 | Return nil if LIST is no list or is empty or some test returns nil; | ||
| 2002 | otherwise, return t." | ||
| 2003 | (when (and list (listp list)) | ||
| 2004 | (let ((result (mapcar predicate list))) | ||
| 2005 | (not (memq nil result))))) | ||
| 2006 | |||
| 1999 | (defun gnus-subsetp (list1 list2) | 2007 | (defun gnus-subsetp (list1 list2) |
| 2000 | "Return t if LIST1 is a subset of LIST2. | 2008 | "Return t if LIST1 is a subset of LIST2. |
| 2001 | Similar to `subsetp' but use member for element test so that this works for | 2009 | Similar to `subsetp' but use member for element test so that this works for |
| @@ -2006,6 +2014,13 @@ lists of strings." | |||
| 2006 | (gnus-subsetp (cdr list1) list2)) | 2014 | (gnus-subsetp (cdr list1) list2)) |
| 2007 | t))) | 2015 | t))) |
| 2008 | 2016 | ||
| 2017 | (defun gnus-setdiff (list1 list2) | ||
| 2018 | "Return member-based set difference of LIST1 and LIST2." | ||
| 2019 | (when (and list1 (listp list1) (listp list2)) | ||
| 2020 | (if (member (car list1) list2) | ||
| 2021 | (gnus-setdiff (cdr list1) list2) | ||
| 2022 | (cons (car list1) (gnus-setdiff (cdr list1) list2))))) | ||
| 2023 | |||
| 2009 | (provide 'gnus-util) | 2024 | (provide 'gnus-util) |
| 2010 | 2025 | ||
| 2011 | ;;; gnus-util.el ends here | 2026 | ;;; gnus-util.el ends here |
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index 1196ea9dfec..5d2ce7ee19f 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el | |||
| @@ -1637,6 +1637,7 @@ this variable. I think." | |||
| 1637 | (const post-mail)) | 1637 | (const post-mail)) |
| 1638 | (checklist :inline t :greedy t | 1638 | (checklist :inline t :greedy t |
| 1639 | (const :format "%v " address) | 1639 | (const :format "%v " address) |
| 1640 | (const cloud) | ||
| 1640 | (const global) | 1641 | (const global) |
| 1641 | (const :format "%v " prompt-address) | 1642 | (const :format "%v " prompt-address) |
| 1642 | (const :format "%v " physical-address) | 1643 | (const :format "%v " physical-address) |
diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el index dbd31629f97..48e6384497e 100644 --- a/lisp/gnus/mml-sec.el +++ b/lisp/gnus/mml-sec.el | |||
| @@ -25,7 +25,9 @@ | |||
| 25 | 25 | ||
| 26 | (eval-when-compile (require 'cl)) | 26 | (eval-when-compile (require 'cl)) |
| 27 | 27 | ||
| 28 | (autoload 'gnus-subsetp "gnus-util") | 28 | (require 'gnus-util) |
| 29 | (require 'epg) | ||
| 30 | |||
| 29 | (autoload 'mail-strip-quoted-names "mail-utils") | 31 | (autoload 'mail-strip-quoted-names "mail-utils") |
| 30 | (autoload 'mml2015-sign "mml2015") | 32 | (autoload 'mml2015-sign "mml2015") |
| 31 | (autoload 'mml2015-encrypt "mml2015") | 33 | (autoload 'mml2015-encrypt "mml2015") |
| @@ -40,6 +42,7 @@ | |||
| 40 | (autoload 'mml-smime-encrypt-query "mml-smime") | 42 | (autoload 'mml-smime-encrypt-query "mml-smime") |
| 41 | (autoload 'mml-smime-verify "mml-smime") | 43 | (autoload 'mml-smime-verify "mml-smime") |
| 42 | (autoload 'mml-smime-verify-test "mml-smime") | 44 | (autoload 'mml-smime-verify-test "mml-smime") |
| 45 | (autoload 'epa--select-keys "epa") | ||
| 43 | 46 | ||
| 44 | (defvar mml-sign-alist | 47 | (defvar mml-sign-alist |
| 45 | '(("smime" mml-smime-sign-buffer mml-smime-sign-query) | 48 | '(("smime" mml-smime-sign-buffer mml-smime-sign-query) |
| @@ -91,7 +94,7 @@ signs and encrypt the message in one step. | |||
| 91 | 94 | ||
| 92 | Note that the output generated by using a `combined' mode is NOT | 95 | Note that the output generated by using a `combined' mode is NOT |
| 93 | understood by all PGP implementations, in particular PGP version | 96 | understood by all PGP implementations, in particular PGP version |
| 94 | 2 does not support it! See Info node `(message)Security' for | 97 | 2 does not support it! See Info node `(message) Security' for |
| 95 | details." | 98 | details." |
| 96 | :version "22.1" | 99 | :version "22.1" |
| 97 | :group 'message | 100 | :group 'message |
| @@ -111,7 +114,9 @@ details." | |||
| 111 | (if (boundp 'password-cache) | 114 | (if (boundp 'password-cache) |
| 112 | password-cache | 115 | password-cache |
| 113 | t) | 116 | t) |
| 114 | "If t, cache passphrase." | 117 | "If t, cache OpenPGP or S/MIME passphrases inside Emacs. |
| 118 | Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead. | ||
| 119 | See Info node `(message) Security'." | ||
| 115 | :group 'message | 120 | :group 'message |
| 116 | :type 'boolean) | 121 | :type 'boolean) |
| 117 | 122 | ||
| @@ -425,6 +430,534 @@ If called with a prefix argument, only encrypt (do NOT sign)." | |||
| 425 | (interactive "P") | 430 | (interactive "P") |
| 426 | (mml-secure-message "pgpauto" (if dontsign 'encrypt 'signencrypt))) | 431 | (mml-secure-message "pgpauto" (if dontsign 'encrypt 'signencrypt))) |
| 427 | 432 | ||
| 433 | ;;; Common functionality for mml1991.el, mml2015.el, mml-smime.el | ||
| 434 | |||
| 435 | (define-obsolete-variable-alias 'mml1991-signers 'mml-secure-openpgp-signers | ||
| 436 | "25.1") | ||
| 437 | (define-obsolete-variable-alias 'mml2015-signers 'mml-secure-openpgp-signers | ||
| 438 | "25.1") | ||
| 439 | (defcustom mml-secure-openpgp-signers nil | ||
| 440 | "A list of your own key ID(s) which will be used to sign OpenPGP messages. | ||
| 441 | If set, it is added to the setting of `mml-secure-openpgp-sign-with-sender'." | ||
| 442 | :group 'mime-security | ||
| 443 | :type '(repeat (string :tag "Key ID"))) | ||
| 444 | |||
| 445 | (define-obsolete-variable-alias 'mml-smime-signers 'mml-secure-smime-signers | ||
| 446 | "25.1") | ||
| 447 | (defcustom mml-secure-smime-signers nil | ||
| 448 | "A list of your own key ID(s) which will be used to sign S/MIME messages. | ||
| 449 | If set, it is added to the setting of `mml-secure-smime-sign-with-sender'." | ||
| 450 | :group 'mime-security | ||
| 451 | :type '(repeat (string :tag "Key ID"))) | ||
| 452 | |||
| 453 | (define-obsolete-variable-alias | ||
| 454 | 'mml1991-encrypt-to-self 'mml-secure-openpgp-encrypt-to-self "25.1") | ||
| 455 | (define-obsolete-variable-alias | ||
| 456 | 'mml2015-encrypt-to-self 'mml-secure-openpgp-encrypt-to-self "25.1") | ||
| 457 | (defcustom mml-secure-openpgp-encrypt-to-self nil | ||
| 458 | "List of own key ID(s) or t; determines additional recipients with OpenPGP. | ||
| 459 | If t, also encrypt to key for message sender; if list, encrypt to those keys. | ||
| 460 | With this variable, you can ensure that you can decrypt your own messages. | ||
| 461 | Alternatives to this variable include Bcc'ing the message to yourself or | ||
| 462 | using the encrypt-to or hidden-encrypt-to option in gpg.conf (see man gpg(1)). | ||
| 463 | Note that this variable and the encrypt-to option give away your identity | ||
| 464 | for *every* encryption without warning, which is not what you want if you are | ||
| 465 | using, e.g., remailers. | ||
| 466 | Also, use of Bcc gives away your identity for *every* encryption without | ||
| 467 | warning, which is a bug, see: | ||
| 468 | https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18718" | ||
| 469 | :group 'mime-security | ||
| 470 | :type '(choice (const :tag "None" nil) | ||
| 471 | (const :tag "From address" t) | ||
| 472 | (repeat (string :tag "Key ID")))) | ||
| 473 | |||
| 474 | (define-obsolete-variable-alias | ||
| 475 | 'mml-smime-encrypt-to-self 'mml-secure-smime-encrypt-to-self "25.1") | ||
| 476 | (defcustom mml-secure-smime-encrypt-to-self nil | ||
| 477 | "List of own key ID(s) or t; determines additional recipients with S/MIME. | ||
| 478 | If t, also encrypt to key for message sender; if list, encrypt to those keys. | ||
| 479 | With this variable, you can ensure that you can decrypt your own messages. | ||
| 480 | Alternatives to this variable include Bcc'ing the message to yourself or | ||
| 481 | using the encrypt-to option in gpgsm.conf (see man gpgsm(1)). | ||
| 482 | Note that this variable and the encrypt-to option give away your identity | ||
| 483 | for *every* encryption without warning, which is not what you want if you are | ||
| 484 | using, e.g., remailers. | ||
| 485 | Also, use of Bcc gives away your identity for *every* encryption without | ||
| 486 | warning, which is a bug, see: | ||
| 487 | https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18718" | ||
| 488 | :group 'mime-security | ||
| 489 | :type '(choice (const :tag "None" nil) | ||
| 490 | (const :tag "From address" t) | ||
| 491 | (repeat (string :tag "Key ID")))) | ||
| 492 | |||
| 493 | (define-obsolete-variable-alias | ||
| 494 | 'mml2015-sign-with-sender 'mml-secure-openpgp-sign-with-sender "25.1") | ||
| 495 | ;mml1991-sign-with-sender did never exist. | ||
| 496 | (defcustom mml-secure-openpgp-sign-with-sender nil | ||
| 497 | "If t, use message sender to find an OpenPGP key to sign with." | ||
| 498 | :group 'mime-security | ||
| 499 | :type 'boolean) | ||
| 500 | |||
| 501 | (define-obsolete-variable-alias | ||
| 502 | 'mml-smime-sign-with-sender 'mml-secure-smime-sign-with-sender "25.1") | ||
| 503 | (defcustom mml-secure-smime-sign-with-sender nil | ||
| 504 | "If t, use message sender to find an S/MIME key to sign with." | ||
| 505 | :group 'mime-security | ||
| 506 | :type 'boolean) | ||
| 507 | |||
| 508 | (define-obsolete-variable-alias | ||
| 509 | 'mml2015-always-trust 'mml-secure-openpgp-always-trust "25.1") | ||
| 510 | ;mml1991-always-trust did never exist. | ||
| 511 | (defcustom mml-secure-openpgp-always-trust t | ||
| 512 | "If t, skip key validation of GnuPG on encryption." | ||
| 513 | :group 'mime-security | ||
| 514 | :type 'boolean) | ||
| 515 | |||
| 516 | (defcustom mml-secure-fail-when-key-problem nil | ||
| 517 | "If t, raise an error if some key is missing or several keys exist. | ||
| 518 | Otherwise, ask the user." | ||
| 519 | :version "25.1" | ||
| 520 | :group 'mime-security | ||
| 521 | :type 'boolean) | ||
| 522 | |||
| 523 | (defcustom mml-secure-key-preferences | ||
| 524 | '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt))) | ||
| 525 | "Protocol- and usage-specific fingerprints of preferred keys. | ||
| 526 | This variable is only relevant if a recipient owns multiple key pairs (for | ||
| 527 | encryption) or you own multiple key pairs (for signing). In such cases, | ||
| 528 | you will be asked which key(s) should be used, and your choice can be | ||
| 529 | customized in this variable." | ||
| 530 | :version "25.1" | ||
| 531 | :group 'mime-security | ||
| 532 | :type '(alist :key-type (symbol :tag "Protocol") :value-type | ||
| 533 | (alist :key-type (symbol :tag "Usage") :value-type | ||
| 534 | (alist :key-type (string :tag "Name") :value-type | ||
| 535 | (repeat (string :tag "Fingerprint")))))) | ||
| 536 | |||
| 537 | (defun mml-secure-cust-usage-lookup (context usage) | ||
| 538 | "Return preferences for CONTEXT and USAGE." | ||
| 539 | (let* ((protocol (epg-context-protocol context)) | ||
| 540 | (protocol-prefs (cdr (assoc protocol mml-secure-key-preferences)))) | ||
| 541 | (assoc usage protocol-prefs))) | ||
| 542 | |||
| 543 | (defun mml-secure-cust-fpr-lookup (context usage name) | ||
| 544 | "Return fingerprints of preferred keys for CONTEXT, USAGE, and NAME." | ||
| 545 | (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage)) | ||
| 546 | (fprs (assoc name (cdr usage-prefs)))) | ||
| 547 | (when fprs | ||
| 548 | (cdr fprs)))) | ||
| 549 | |||
| 550 | (defun mml-secure-cust-record-keys (context usage name keys &optional save) | ||
| 551 | "For CONTEXT, USAGE, and NAME record fingerprint(s) of KEYS. | ||
| 552 | If optional SAVE is not nil, save customized fingerprints. | ||
| 553 | Return keys." | ||
| 554 | (assert keys) | ||
| 555 | (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage)) | ||
| 556 | (curr-fprs (cdr (assoc name (cdr usage-prefs)))) | ||
| 557 | (key-fprs (mapcar 'mml-secure-fingerprint keys)) | ||
| 558 | (new-fprs (gnus-union curr-fprs key-fprs :test 'equal))) | ||
| 559 | (if curr-fprs | ||
| 560 | (setcdr (assoc name (cdr usage-prefs)) new-fprs) | ||
| 561 | (setcdr usage-prefs (cons (cons name new-fprs) (cdr usage-prefs)))) | ||
| 562 | (when save | ||
| 563 | (customize-save-variable | ||
| 564 | 'mml-secure-key-preferences mml-secure-key-preferences)) | ||
| 565 | keys)) | ||
| 566 | |||
| 567 | (defun mml-secure-cust-remove-keys (context usage name) | ||
| 568 | "Remove keys for CONTEXT, USAGE, and NAME. | ||
| 569 | Return t if a customization for NAME was present (and has been removed)." | ||
| 570 | (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage)) | ||
| 571 | (current (assoc name usage-prefs))) | ||
| 572 | (when current | ||
| 573 | (setcdr usage-prefs (remove current (cdr usage-prefs))) | ||
| 574 | t))) | ||
| 575 | |||
| 576 | (defvar mml-secure-secret-key-id-list nil) | ||
| 577 | |||
| 578 | (defun mml-secure-add-secret-key-id (key-id) | ||
| 579 | "Record KEY-ID in list of secret keys." | ||
| 580 | (add-to-list 'mml-secure-secret-key-id-list key-id)) | ||
| 581 | |||
| 582 | (defun mml-secure-clear-secret-key-id-list () | ||
| 583 | "Remove passwords from cache and clear list of secret keys." | ||
| 584 | ;; Loosely based on code inside mml2015-epg-encrypt, | ||
| 585 | ;; mml2015-epg-clear-decrypt, and mml2015-epg-decrypt | ||
| 586 | (dolist (key-id mml-secure-secret-key-id-list nil) | ||
| 587 | (password-cache-remove key-id)) | ||
| 588 | (setq mml-secure-secret-key-id-list nil)) | ||
| 589 | |||
| 590 | (defvar mml1991-cache-passphrase) | ||
| 591 | (defvar mml1991-passphrase-cache-expiry) | ||
| 592 | |||
| 593 | (defun mml-secure-cache-passphrase-p (protocol) | ||
| 594 | "Return t if OpenPGP or S/MIME passphrases should be cached for PROTOCOL. | ||
| 595 | Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead." | ||
| 596 | (or (and (eq 'OpenPGP protocol) | ||
| 597 | (or mml-secure-cache-passphrase | ||
| 598 | (and (boundp 'mml2015-cache-passphrase) | ||
| 599 | mml2015-cache-passphrase) | ||
| 600 | (and (boundp 'mml1991-cache-passphrase) | ||
| 601 | mml1991-cache-passphrase))) | ||
| 602 | (and (eq 'CMS protocol) | ||
| 603 | (or mml-secure-cache-passphrase | ||
| 604 | (and (boundp 'mml-smime-cache-passphrase) | ||
| 605 | mml-smime-cache-passphrase))))) | ||
| 606 | |||
| 607 | (defun mml-secure-cache-expiry-interval (protocol) | ||
| 608 | "Return time in seconds to cache passphrases for PROTOCOL. | ||
| 609 | Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead." | ||
| 610 | (or (and (eq 'OpenPGP protocol) | ||
| 611 | (or (and (boundp 'mml2015-passphrase-cache-expiry) | ||
| 612 | mml2015-passphrase-cache-expiry) | ||
| 613 | (and (boundp 'mml1991-passphrase-cache-expiry) | ||
| 614 | mml1991-passphrase-cache-expiry) | ||
| 615 | mml-secure-passphrase-cache-expiry)) | ||
| 616 | (and (eq 'CMS protocol) | ||
| 617 | (or (and (boundp 'mml-smime-passphrase-cache-expiry) | ||
| 618 | mml-smime-passphrase-cache-expiry) | ||
| 619 | mml-secure-passphrase-cache-expiry)))) | ||
| 620 | |||
| 621 | (defun mml-secure-passphrase-callback (context key-id standard) | ||
| 622 | "Ask for passphrase in CONTEXT for KEY-ID for STANDARD. | ||
| 623 | The passphrase is read and cached." | ||
| 624 | ;; Based on mml2015-epg-passphrase-callback. | ||
| 625 | (if (eq key-id 'SYM) | ||
| 626 | (epg-passphrase-callback-function context key-id nil) | ||
| 627 | (let* ((password-cache-key-id | ||
| 628 | (if (eq key-id 'PIN) | ||
| 629 | "PIN" | ||
| 630 | key-id)) | ||
| 631 | (entry (assoc key-id epg-user-id-alist)) | ||
| 632 | (passphrase | ||
| 633 | (password-read | ||
| 634 | (if (eq key-id 'PIN) | ||
| 635 | "Passphrase for PIN: " | ||
| 636 | (if entry | ||
| 637 | (format "Passphrase for %s %s: " key-id (cdr entry)) | ||
| 638 | (format "Passphrase for %s: " key-id))) | ||
| 639 | ;; TODO: With mml-smime.el, password-cache-key-id is not passed | ||
| 640 | ;; as argument to password-read. | ||
| 641 | ;; Is that on purpose? If so, the following needs to be placed | ||
| 642 | ;; inside an if statement. | ||
| 643 | password-cache-key-id))) | ||
| 644 | (when passphrase | ||
| 645 | (let ((password-cache-expiry (mml-secure-cache-expiry-interval | ||
| 646 | (epg-context-protocol context)))) | ||
| 647 | (password-cache-add password-cache-key-id passphrase)) | ||
| 648 | (mml-secure-add-secret-key-id password-cache-key-id) | ||
| 649 | (copy-sequence passphrase))))) | ||
| 650 | |||
| 651 | (defun mml-secure-check-user-id (key recipient) | ||
| 652 | "Check whether KEY has a non-revoked, non-expired UID for RECIPIENT." | ||
| 653 | ;; Based on mml2015-epg-check-user-id. | ||
| 654 | (let ((uids (epg-key-user-id-list key))) | ||
| 655 | (catch 'break | ||
| 656 | (dolist (uid uids nil) | ||
| 657 | (if (and (stringp (epg-user-id-string uid)) | ||
| 658 | (equal (car (mail-header-parse-address | ||
| 659 | (epg-user-id-string uid))) | ||
| 660 | (car (mail-header-parse-address | ||
| 661 | recipient))) | ||
| 662 | (not (memq (epg-user-id-validity uid) | ||
| 663 | '(revoked expired)))) | ||
| 664 | (throw 'break t)))))) | ||
| 665 | |||
| 666 | (defun mml-secure-secret-key-exists-p (context subkey) | ||
| 667 | "Return t if keyring for CONTEXT contains secret key for public SUBKEY." | ||
| 668 | (let* ((fpr (epg-sub-key-fingerprint subkey)) | ||
| 669 | (candidates (epg-list-keys context fpr 'secret)) | ||
| 670 | (candno (length candidates))) | ||
| 671 | ;; If two or more subkeys with the same fingerprint exist, something is | ||
| 672 | ;; terribly wrong. | ||
| 673 | (when (>= candno 2) | ||
| 674 | (error "Found %d secret keys with same fingerprint %s" candno fpr)) | ||
| 675 | (= 1 candno))) | ||
| 676 | |||
| 677 | (defun mml-secure-check-sub-key (context key usage &optional fingerprint) | ||
| 678 | "Check whether in CONTEXT the public KEY has a usable subkey for USAGE. | ||
| 679 | This is the case if KEY is not disabled, and there is a subkey for | ||
| 680 | USAGE that is neither revoked nor expired. Additionally, if optional | ||
| 681 | FINGERPRINT is present and if it is not the primary key's fingerprint, then | ||
| 682 | the returned subkey must have that FINGERPRINT. FINGERPRINT must consist of | ||
| 683 | hexadecimal digits only (no leading \"0x\" allowed). | ||
| 684 | If USAGE is not `encrypt', then additionally an appropriate secret key must | ||
| 685 | be present in the keyring." | ||
| 686 | ;; Based on mml2015-epg-check-sub-key, extended by | ||
| 687 | ;; - check for secret keys if usage is not 'encrypt and | ||
| 688 | ;; - check for new argument FINGERPRINT. | ||
| 689 | (let* ((subkeys (epg-key-sub-key-list key)) | ||
| 690 | (primary (car subkeys)) | ||
| 691 | (fpr (epg-sub-key-fingerprint primary))) | ||
| 692 | ;; The primary key will be marked as disabled, when the entire | ||
| 693 | ;; key is disabled (see 12 Field, Format of colon listings, in | ||
| 694 | ;; gnupg/doc/DETAILS) | ||
| 695 | (unless (memq 'disabled (epg-sub-key-capability primary)) | ||
| 696 | (catch 'break | ||
| 697 | (dolist (subkey subkeys nil) | ||
| 698 | (if (and (memq usage (epg-sub-key-capability subkey)) | ||
| 699 | (not (memq (epg-sub-key-validity subkey) | ||
| 700 | '(revoked expired))) | ||
| 701 | (or (eq 'encrypt usage) ; Encryption works with public key. | ||
| 702 | ;; In contrast, signing requires secret key. | ||
| 703 | (mml-secure-secret-key-exists-p context subkey)) | ||
| 704 | (or (not fingerprint) | ||
| 705 | (gnus-string-match-p (concat fingerprint "$") fpr) | ||
| 706 | (gnus-string-match-p (concat fingerprint "$") | ||
| 707 | (epg-sub-key-fingerprint subkey)))) | ||
| 708 | (throw 'break t))))))) | ||
| 709 | |||
| 710 | (defun mml-secure-find-usable-keys (context name usage &optional justone) | ||
| 711 | "In CONTEXT return a list of keys for NAME and USAGE. | ||
| 712 | If USAGE is `encrypt' public keys are returned, otherwise secret ones. | ||
| 713 | Only non-revoked and non-expired keys are returned whose primary key is | ||
| 714 | not disabled. | ||
| 715 | NAME can be an e-mail address or a key ID. | ||
| 716 | If NAME just consists of hexadecimal digits (possibly prefixed by \"0x\"), it | ||
| 717 | is treated as key ID for which at most one key must exist in the keyring. | ||
| 718 | Otherwise, NAME is treated as user ID, for which no keys are returned if it | ||
| 719 | is expired or revoked. | ||
| 720 | If optional JUSTONE is not nil, return the first key instead of a list." | ||
| 721 | (let* ((keys (epg-list-keys context name)) | ||
| 722 | (iskeyid (string-match "\\(0x\\)?\\([0-9a-fA-F]\\{8,\\}\\)" name)) | ||
| 723 | (fingerprint (match-string 2 name)) | ||
| 724 | result) | ||
| 725 | (when (and iskeyid (>= (length keys) 2)) | ||
| 726 | (error | ||
| 727 | "Name %s (for %s) looks like a key ID but multiple keys found" | ||
| 728 | name usage)) | ||
| 729 | (catch 'break | ||
| 730 | (dolist (key keys result) | ||
| 731 | (if (and (or iskeyid | ||
| 732 | (mml-secure-check-user-id key name)) | ||
| 733 | (mml-secure-check-sub-key context key usage fingerprint)) | ||
| 734 | (if justone | ||
| 735 | (throw 'break key) | ||
| 736 | (push key result))))))) | ||
| 737 | |||
| 738 | (defun mml-secure-select-preferred-keys (context names usage) | ||
| 739 | "Return list of preferred keys in CONTEXT for NAMES and USAGE. | ||
| 740 | This inspects the keyrings to find keys for each name in NAMES. If several | ||
| 741 | keys are found for a name, `mml-secure-select-keys' is used to look for | ||
| 742 | customized preferences or have the user select preferable ones. | ||
| 743 | When `mml-secure-fail-when-key-problem' is t, fail with an error in | ||
| 744 | case of missing, outdated, or multiple keys." | ||
| 745 | ;; Loosely based on code appearing inside mml2015-epg-sign and | ||
| 746 | ;; mml2015-epg-encrypt. | ||
| 747 | (apply | ||
| 748 | #'nconc | ||
| 749 | (mapcar | ||
| 750 | (lambda (name) | ||
| 751 | (let* ((keys (mml-secure-find-usable-keys context name usage)) | ||
| 752 | (keyno (length keys))) | ||
| 753 | (cond ((= 0 keyno) | ||
| 754 | (when (or mml-secure-fail-when-key-problem | ||
| 755 | (not (y-or-n-p | ||
| 756 | (format "No %s key for %s; skip it? " | ||
| 757 | usage name)))) | ||
| 758 | (error "No %s key for %s" usage name))) | ||
| 759 | ((= 1 keyno) keys) | ||
| 760 | (t (mml-secure-select-keys context name keys usage))))) | ||
| 761 | names))) | ||
| 762 | |||
| 763 | (defun mml-secure-fingerprint (key) | ||
| 764 | "Return fingerprint for public KEY." | ||
| 765 | (epg-sub-key-fingerprint (car (epg-key-sub-key-list key)))) | ||
| 766 | |||
| 767 | (defun mml-secure-filter-keys (keys fprs) | ||
| 768 | "Filter KEYS to subset with fingerprints in FPRS." | ||
| 769 | (when keys | ||
| 770 | (if (member (mml-secure-fingerprint (car keys)) fprs) | ||
| 771 | (cons (car keys) (mml-secure-filter-keys (cdr keys) fprs)) | ||
| 772 | (mml-secure-filter-keys (cdr keys) fprs)))) | ||
| 773 | |||
| 774 | (defun mml-secure-normalize-cust-name (name) | ||
| 775 | "Normalize NAME to be used for customization. | ||
| 776 | Currently, remove ankle brackets." | ||
| 777 | (if (string-match "^<\\(.*\\)>$" name) | ||
| 778 | (match-string 1 name) | ||
| 779 | name)) | ||
| 780 | |||
| 781 | (defun mml-secure-select-keys (context name keys usage) | ||
| 782 | "In CONTEXT for NAME select among KEYS for USAGE. | ||
| 783 | KEYS should be a list with multiple entries. | ||
| 784 | NAME is normalized first as customized keys are inspected. | ||
| 785 | When `mml-secure-fail-when-key-problem' is t, fail with an error in case of | ||
| 786 | outdated or multiple keys." | ||
| 787 | (let* ((nname (mml-secure-normalize-cust-name name)) | ||
| 788 | (fprs (mml-secure-cust-fpr-lookup context usage nname)) | ||
| 789 | (usable-fprs (mapcar 'mml-secure-fingerprint keys))) | ||
| 790 | (if fprs | ||
| 791 | (if (gnus-subsetp fprs usable-fprs) | ||
| 792 | (mml-secure-filter-keys keys fprs) | ||
| 793 | (mml-secure-cust-remove-keys context usage nname) | ||
| 794 | (let ((diff (gnus-setdiff fprs usable-fprs))) | ||
| 795 | (if mml-secure-fail-when-key-problem | ||
| 796 | (error "Customization of %s keys for %s outdated" usage nname) | ||
| 797 | (mml-secure-select-keys-1 | ||
| 798 | context nname keys usage (format "\ | ||
| 799 | Customized keys | ||
| 800 | (%s) | ||
| 801 | for %s not available any more. | ||
| 802 | Select anew. " | ||
| 803 | diff nname))))) | ||
| 804 | (if mml-secure-fail-when-key-problem | ||
| 805 | (error "Multiple %s keys for %s" usage nname) | ||
| 806 | (mml-secure-select-keys-1 | ||
| 807 | context nname keys usage (format "\ | ||
| 808 | Multiple %s keys for: | ||
| 809 | %s | ||
| 810 | Select preferred one(s). " | ||
| 811 | usage nname)))))) | ||
| 812 | |||
| 813 | (defun mml-secure-select-keys-1 (context name keys usage message) | ||
| 814 | "In CONTEXT for NAME let user select among KEYS for USAGE, showing MESSAGE. | ||
| 815 | Return selected keys." | ||
| 816 | (let* ((selected (epa--select-keys message keys)) | ||
| 817 | (selno (length selected)) | ||
| 818 | ;; TODO: y-or-n-p does not always resize the echo area but may | ||
| 819 | ;; truncate the message. Why? The following does not help. | ||
| 820 | ;; yes-or-no-p shows full message, though. | ||
| 821 | (message-truncate-lines nil)) | ||
| 822 | (if selected | ||
| 823 | (if (y-or-n-p | ||
| 824 | (format "%d %s key(s) selected. Store for %s? " | ||
| 825 | selno usage name)) | ||
| 826 | (mml-secure-cust-record-keys context usage name selected 'save) | ||
| 827 | selected) | ||
| 828 | (unless (y-or-n-p | ||
| 829 | (format "No %s key for %s; skip it? " usage name)) | ||
| 830 | (error "No %s key for %s" usage name))))) | ||
| 831 | |||
| 832 | (defun mml-secure-signer-names (protocol sender) | ||
| 833 | "Determine signer names for PROTOCOL and message from SENDER. | ||
| 834 | Returned names may be e-mail addresses or key IDs and are determined based | ||
| 835 | on `mml-secure-openpgp-signers' and `mml-secure-openpgp-sign-with-sender' with | ||
| 836 | OpenPGP or `mml-secure-smime-signers' and `mml-secure-smime-sign-with-sender' | ||
| 837 | with S/MIME." | ||
| 838 | (if (eq 'OpenPGP protocol) | ||
| 839 | (append mml-secure-openpgp-signers | ||
| 840 | (if (and mml-secure-openpgp-sign-with-sender sender) | ||
| 841 | (list (concat "<" sender ">")))) | ||
| 842 | (append mml-secure-smime-signers | ||
| 843 | (if (and mml-secure-smime-sign-with-sender sender) | ||
| 844 | (list (concat "<" sender ">")))))) | ||
| 845 | |||
| 846 | (defun mml-secure-signers (context signer-names) | ||
| 847 | "Determine signing keys in CONTEXT from SIGNER-NAMES. | ||
| 848 | If `mm-sign-option' is `guided', the user is asked to choose. | ||
| 849 | Otherwise, `mml-secure-select-preferred-keys' is used." | ||
| 850 | ;; Based on code appearing inside mml2015-epg-sign and | ||
| 851 | ;; mml2015-epg-encrypt. | ||
| 852 | (if (eq mm-sign-option 'guided) | ||
| 853 | (epa-select-keys context "\ | ||
| 854 | Select keys for signing. | ||
| 855 | If no one is selected, default secret key is used. " | ||
| 856 | signer-names t) | ||
| 857 | (mml-secure-select-preferred-keys context signer-names 'sign))) | ||
| 858 | |||
| 859 | (defun mml-secure-self-recipients (protocol sender) | ||
| 860 | "Determine additional recipients based on encrypt-to-self variables. | ||
| 861 | PROTOCOL specifies OpenPGP or S/MIME for a message from SENDER." | ||
| 862 | (let ((encrypt-to-self | ||
| 863 | (if (eq 'OpenPGP protocol) | ||
| 864 | mml-secure-openpgp-encrypt-to-self | ||
| 865 | mml-secure-smime-encrypt-to-self))) | ||
| 866 | (when encrypt-to-self | ||
| 867 | (if (listp encrypt-to-self) | ||
| 868 | encrypt-to-self | ||
| 869 | (list sender))))) | ||
| 870 | |||
| 871 | (defun mml-secure-recipients (protocol context config sender) | ||
| 872 | "Determine encryption recipients. | ||
| 873 | PROTOCOL specifies OpenPGP or S/MIME with matching CONTEXT and CONFIG | ||
| 874 | for a message from SENDER." | ||
| 875 | ;; Based on code appearing inside mml2015-epg-encrypt. | ||
| 876 | (let ((recipients | ||
| 877 | (apply #'nconc | ||
| 878 | (mapcar | ||
| 879 | (lambda (recipient) | ||
| 880 | (or (epg-expand-group config recipient) | ||
| 881 | (list (concat "<" recipient ">")))) | ||
| 882 | (split-string | ||
| 883 | (or (message-options-get 'message-recipients) | ||
| 884 | (message-options-set 'message-recipients | ||
| 885 | (read-string "Recipients: "))) | ||
| 886 | "[ \f\t\n\r\v,]+"))))) | ||
| 887 | (nconc recipients (mml-secure-self-recipients protocol sender)) | ||
| 888 | (if (eq mm-encrypt-option 'guided) | ||
| 889 | (setq recipients | ||
| 890 | (epa-select-keys context "\ | ||
| 891 | Select recipients for encryption. | ||
| 892 | If no one is selected, symmetric encryption will be performed. " | ||
| 893 | recipients)) | ||
| 894 | (setq recipients | ||
| 895 | (mml-secure-select-preferred-keys context recipients 'encrypt)) | ||
| 896 | (unless recipients | ||
| 897 | (error "No recipient specified"))) | ||
| 898 | recipients)) | ||
| 899 | |||
| 900 | (defun mml-secure-epg-encrypt (protocol cont &optional sign) | ||
| 901 | ;; Based on code appearing inside mml2015-epg-encrypt. | ||
| 902 | (let* ((context (epg-make-context protocol)) | ||
| 903 | (config (epg-configuration)) | ||
| 904 | (sender (message-options-get 'message-sender)) | ||
| 905 | (recipients (mml-secure-recipients protocol context config sender)) | ||
| 906 | (signer-names (mml-secure-signer-names protocol sender)) | ||
| 907 | cipher signers) | ||
| 908 | (when sign | ||
| 909 | (setq signers (mml-secure-signers context signer-names)) | ||
| 910 | (epg-context-set-signers context signers)) | ||
| 911 | (when (eq 'OpenPGP protocol) | ||
| 912 | (epg-context-set-armor context t) | ||
| 913 | (epg-context-set-textmode context t)) | ||
| 914 | (when (mml-secure-cache-passphrase-p protocol) | ||
| 915 | (epg-context-set-passphrase-callback | ||
| 916 | context | ||
| 917 | (cons 'mml-secure-passphrase-callback protocol))) | ||
| 918 | (condition-case error | ||
| 919 | (setq cipher | ||
| 920 | (if (eq 'OpenPGP protocol) | ||
| 921 | (epg-encrypt-string context (buffer-string) recipients sign | ||
| 922 | mml-secure-openpgp-always-trust) | ||
| 923 | (epg-encrypt-string context (buffer-string) recipients)) | ||
| 924 | mml-secure-secret-key-id-list nil) | ||
| 925 | (error | ||
| 926 | (mml-secure-clear-secret-key-id-list) | ||
| 927 | (signal (car error) (cdr error)))) | ||
| 928 | cipher)) | ||
| 929 | |||
| 930 | (defun mml-secure-epg-sign (protocol mode) | ||
| 931 | ;; Based on code appearing inside mml2015-epg-sign. | ||
| 932 | (let* ((context (epg-make-context protocol)) | ||
| 933 | (sender (message-options-get 'message-sender)) | ||
| 934 | (signer-names (mml-secure-signer-names protocol sender)) | ||
| 935 | (signers (mml-secure-signers context signer-names)) | ||
| 936 | signature micalg) | ||
| 937 | (when (eq 'OpenPGP protocol) | ||
| 938 | (epg-context-set-armor context t) | ||
| 939 | (epg-context-set-textmode context t)) | ||
| 940 | (epg-context-set-signers context signers) | ||
| 941 | (when (mml-secure-cache-passphrase-p protocol) | ||
| 942 | (epg-context-set-passphrase-callback | ||
| 943 | context | ||
| 944 | (cons 'mml-secure-passphrase-callback protocol))) | ||
| 945 | (condition-case error | ||
| 946 | (setq signature | ||
| 947 | (if (eq 'OpenPGP protocol) | ||
| 948 | (epg-sign-string context (buffer-string) mode) | ||
| 949 | (epg-sign-string context | ||
| 950 | (mm-replace-in-string (buffer-string) | ||
| 951 | "\n" "\r\n") t)) | ||
| 952 | mml-secure-secret-key-id-list nil) | ||
| 953 | (error | ||
| 954 | (mml-secure-clear-secret-key-id-list) | ||
| 955 | (signal (car error) (cdr error)))) | ||
| 956 | (if (epg-context-result-for context 'sign) | ||
| 957 | (setq micalg (epg-new-signature-digest-algorithm | ||
| 958 | (car (epg-context-result-for context 'sign))))) | ||
| 959 | (cons signature micalg))) | ||
| 960 | |||
| 428 | (provide 'mml-sec) | 961 | (provide 'mml-sec) |
| 429 | 962 | ||
| 430 | ;;; mml-sec.el ends here | 963 | ;;; mml-sec.el ends here |
diff --git a/lisp/gnus/mml-smime.el b/lisp/gnus/mml-smime.el index b19c9e89ba9..2d8f25c5003 100644 --- a/lisp/gnus/mml-smime.el +++ b/lisp/gnus/mml-smime.el | |||
| @@ -32,9 +32,17 @@ | |||
| 32 | (autoload 'message-narrow-to-headers "message") | 32 | (autoload 'message-narrow-to-headers "message") |
| 33 | (autoload 'message-fetch-field "message") | 33 | (autoload 'message-fetch-field "message") |
| 34 | 34 | ||
| 35 | ;; Prefer epg over openssl if it is available as epg uses GnuPG's gpgsm, | ||
| 36 | ;; which features full-fledged certificate management, while openssl requires | ||
| 37 | ;; major manual efforts for certificate revocation and expiry and has bugs | ||
| 38 | ;; as documented under man smime(1). | ||
| 39 | (ignore-errors (require 'epg)) | ||
| 40 | |||
| 35 | (defcustom mml-smime-use (if (featurep 'epg) 'epg 'openssl) | 41 | (defcustom mml-smime-use (if (featurep 'epg) 'epg 'openssl) |
| 36 | "Whether to use OpenSSL or EPG to decrypt S/MIME messages. | 42 | "Whether to use OpenSSL or EasyPG (EPG) to handle S/MIME messages. |
| 37 | Defaults to EPG if it's loaded." | 43 | Defaults to EPG if it's available. |
| 44 | If you think about using OpenSSL, please read the BUGS section in the manual | ||
| 45 | for the `smime' command coming with OpenSSL first. EasyPG is recommended." | ||
| 38 | :group 'mime-security | 46 | :group 'mime-security |
| 39 | :type '(choice (const :tag "EPG" epg) | 47 | :type '(choice (const :tag "EPG" epg) |
| 40 | (const :tag "OpenSSL" openssl))) | 48 | (const :tag "OpenSSL" openssl))) |
| @@ -57,6 +65,9 @@ Defaults to EPG if it's loaded." | |||
| 57 | "If t, cache passphrase." | 65 | "If t, cache passphrase." |
| 58 | :group 'mime-security | 66 | :group 'mime-security |
| 59 | :type 'boolean) | 67 | :type 'boolean) |
| 68 | (make-obsolete-variable 'mml-smime-cache-passphrase | ||
| 69 | 'mml-secure-cache-passphrase | ||
| 70 | "25.1") | ||
| 60 | 71 | ||
| 61 | (defcustom mml-smime-passphrase-cache-expiry mml-secure-passphrase-cache-expiry | 72 | (defcustom mml-smime-passphrase-cache-expiry mml-secure-passphrase-cache-expiry |
| 62 | "How many seconds the passphrase is cached. | 73 | "How many seconds the passphrase is cached. |
| @@ -64,6 +75,9 @@ Whether the passphrase is cached at all is controlled by | |||
| 64 | `mml-smime-cache-passphrase'." | 75 | `mml-smime-cache-passphrase'." |
| 65 | :group 'mime-security | 76 | :group 'mime-security |
| 66 | :type 'integer) | 77 | :type 'integer) |
| 78 | (make-obsolete-variable 'mml-smime-passphrase-cache-expiry | ||
| 79 | 'mml-secure-passphrase-cache-expiry | ||
| 80 | "25.1") | ||
| 67 | 81 | ||
| 68 | (defcustom mml-smime-signers nil | 82 | (defcustom mml-smime-signers nil |
| 69 | "A list of your own key ID which will be used to sign a message." | 83 | "A list of your own key ID which will be used to sign a message." |
| @@ -202,7 +216,7 @@ Whether the passphrase is cached at all is controlled by | |||
| 202 | ""))))) | 216 | ""))))) |
| 203 | (if (setq cert (smime-cert-by-dns who)) | 217 | (if (setq cert (smime-cert-by-dns who)) |
| 204 | (setq result (list 'certfile (buffer-name cert))) | 218 | (setq result (list 'certfile (buffer-name cert))) |
| 205 | (setq bad (gnus-format-message "`%s' not found. " who)))) | 219 | (setq bad (format "`%s' not found. " who)))) |
| 206 | (quit)) | 220 | (quit)) |
| 207 | result)) | 221 | result)) |
| 208 | 222 | ||
| @@ -221,7 +235,7 @@ Whether the passphrase is cached at all is controlled by | |||
| 221 | ""))))) | 235 | ""))))) |
| 222 | (if (setq cert (smime-cert-by-ldap who)) | 236 | (if (setq cert (smime-cert-by-ldap who)) |
| 223 | (setq result (list 'certfile (buffer-name cert))) | 237 | (setq result (list 'certfile (buffer-name cert))) |
| 224 | (setq bad (gnus-format-message "`%s' not found. " who)))) | 238 | (setq bad (format "`%s' not found. " who)))) |
| 225 | (quit)) | 239 | (quit)) |
| 226 | result)) | 240 | result)) |
| 227 | 241 | ||
| @@ -317,83 +331,29 @@ Whether the passphrase is cached at all is controlled by | |||
| 317 | (defvar inhibit-redisplay) | 331 | (defvar inhibit-redisplay) |
| 318 | (defvar password-cache-expiry) | 332 | (defvar password-cache-expiry) |
| 319 | 333 | ||
| 320 | (autoload 'epg-make-context "epg") | 334 | (eval-when-compile |
| 321 | (autoload 'epg-passphrase-callback-function "epg") | 335 | (autoload 'epg-make-context "epg") |
| 322 | (declare-function epg-context-set-signers "epg" (context signers)) | 336 | (autoload 'epg-context-set-armor "epg") |
| 323 | (declare-function epg-context-result-for "epg" (context name)) | 337 | (autoload 'epg-context-set-signers "epg") |
| 324 | (declare-function epg-new-signature-digest-algorithm "epg" (cl-x) t) | 338 | (autoload 'epg-context-result-for "epg") |
| 325 | (declare-function epg-verify-result-to-string "epg" (verify-result)) | 339 | (autoload 'epg-new-signature-digest-algorithm "epg") |
| 326 | (declare-function epg-list-keys "epg" (context &optional name mode)) | 340 | (autoload 'epg-verify-result-to-string "epg") |
| 327 | (declare-function epg-verify-string "epg" | 341 | (autoload 'epg-list-keys "epg") |
| 328 | (context signature &optional signed-text)) | 342 | (autoload 'epg-decrypt-string "epg") |
| 329 | (declare-function epg-sign-string "epg" (context plain &optional mode)) | 343 | (autoload 'epg-verify-string "epg") |
| 330 | (declare-function epg-encrypt-string "epg" | 344 | (autoload 'epg-sign-string "epg") |
| 331 | (context plain recipients &optional sign always-trust)) | 345 | (autoload 'epg-encrypt-string "epg") |
| 332 | (declare-function epg-context-set-passphrase-callback "epg" | 346 | (autoload 'epg-passphrase-callback-function "epg") |
| 333 | (context passphrase-callback)) | 347 | (autoload 'epg-context-set-passphrase-callback "epg") |
| 334 | (declare-function epg-sub-key-fingerprint "epg" (cl-x) t) | 348 | (autoload 'epg-sub-key-fingerprint "epg") |
| 335 | (declare-function epg-configuration "epg-config" ()) | 349 | (autoload 'epg-configuration "epg-config") |
| 336 | (declare-function epg-expand-group "epg-config" (config group)) | 350 | (autoload 'epg-expand-group "epg-config") |
| 337 | (declare-function epa-select-keys "epa" | 351 | (autoload 'epa-select-keys "epa")) |
| 338 | (context prompt &optional names secret)) | ||
| 339 | |||
| 340 | (defvar mml-smime-epg-secret-key-id-list nil) | ||
| 341 | |||
| 342 | (defun mml-smime-epg-passphrase-callback (context key-id ignore) | ||
| 343 | (if (eq key-id 'SYM) | ||
| 344 | (epg-passphrase-callback-function context key-id nil) | ||
| 345 | (let* (entry | ||
| 346 | (passphrase | ||
| 347 | (password-read | ||
| 348 | (if (eq key-id 'PIN) | ||
| 349 | "Passphrase for PIN: " | ||
| 350 | (if (setq entry (assoc key-id epg-user-id-alist)) | ||
| 351 | (format "Passphrase for %s %s: " key-id (cdr entry)) | ||
| 352 | (format "Passphrase for %s: " key-id))) | ||
| 353 | (if (eq key-id 'PIN) | ||
| 354 | "PIN" | ||
| 355 | key-id)))) | ||
| 356 | (when passphrase | ||
| 357 | (let ((password-cache-expiry mml-smime-passphrase-cache-expiry)) | ||
| 358 | (password-cache-add key-id passphrase)) | ||
| 359 | (setq mml-smime-epg-secret-key-id-list | ||
| 360 | (cons key-id mml-smime-epg-secret-key-id-list)) | ||
| 361 | (copy-sequence passphrase))))) | ||
| 362 | 352 | ||
| 363 | (declare-function epg-key-sub-key-list "epg" (key) t) | 353 | (declare-function epg-key-sub-key-list "epg" (key) t) |
| 364 | (declare-function epg-sub-key-capability "epg" (sub-key) t) | 354 | (declare-function epg-sub-key-capability "epg" (sub-key) t) |
| 365 | (declare-function epg-sub-key-validity "epg" (sub-key) t) | 355 | (declare-function epg-sub-key-validity "epg" (sub-key) t) |
| 366 | 356 | ||
| 367 | (defun mml-smime-epg-find-usable-key (keys usage) | ||
| 368 | (catch 'found | ||
| 369 | (while keys | ||
| 370 | (let ((pointer (epg-key-sub-key-list (car keys)))) | ||
| 371 | (while pointer | ||
| 372 | (if (and (memq usage (epg-sub-key-capability (car pointer))) | ||
| 373 | (not (memq (epg-sub-key-validity (car pointer)) | ||
| 374 | '(revoked expired)))) | ||
| 375 | (throw 'found (car keys))) | ||
| 376 | (setq pointer (cdr pointer)))) | ||
| 377 | (setq keys (cdr keys))))) | ||
| 378 | |||
| 379 | ;; XXX: since gpg --list-secret-keys does not return validity of each | ||
| 380 | ;; key, `mml-smime-epg-find-usable-key' defined above is not enough for | ||
| 381 | ;; secret keys. The function `mml-smime-epg-find-usable-secret-key' | ||
| 382 | ;; below looks at appropriate public keys to check usability. | ||
| 383 | (defun mml-smime-epg-find-usable-secret-key (context name usage) | ||
| 384 | (let ((secret-keys (epg-list-keys context name t)) | ||
| 385 | secret-key) | ||
| 386 | (while (and (not secret-key) secret-keys) | ||
| 387 | (if (mml-smime-epg-find-usable-key | ||
| 388 | (epg-list-keys context (epg-sub-key-fingerprint | ||
| 389 | (car (epg-key-sub-key-list | ||
| 390 | (car secret-keys))))) | ||
| 391 | usage) | ||
| 392 | (setq secret-key (car secret-keys) | ||
| 393 | secret-keys nil) | ||
| 394 | (setq secret-keys (cdr secret-keys)))) | ||
| 395 | secret-key)) | ||
| 396 | |||
| 397 | (autoload 'mml-compute-boundary "mml") | 357 | (autoload 'mml-compute-boundary "mml") |
| 398 | 358 | ||
| 399 | ;; We require mm-decode, which requires mm-bodies, which autoloads | 359 | ;; We require mm-decode, which requires mm-bodies, which autoloads |
| @@ -401,146 +361,37 @@ Whether the passphrase is cached at all is controlled by | |||
| 401 | (declare-function message-options-set "message" (symbol value)) | 361 | (declare-function message-options-set "message" (symbol value)) |
| 402 | 362 | ||
| 403 | (defun mml-smime-epg-sign (cont) | 363 | (defun mml-smime-epg-sign (cont) |
| 404 | (let* ((inhibit-redisplay t) | 364 | (let ((inhibit-redisplay t) |
| 405 | (context (epg-make-context 'CMS)) | 365 | (boundary (mml-compute-boundary cont))) |
| 406 | (boundary (mml-compute-boundary cont)) | ||
| 407 | (sender (message-options-get 'message-sender)) | ||
| 408 | (signer-names (or mml-smime-signers | ||
| 409 | (if (and mml-smime-sign-with-sender sender) | ||
| 410 | (list (concat "<" sender ">"))))) | ||
| 411 | signer-key | ||
| 412 | (signers | ||
| 413 | (or (message-options-get 'mml-smime-epg-signers) | ||
| 414 | (message-options-set | ||
| 415 | 'mml-smime-epg-signers | ||
| 416 | (if (eq mm-sign-option 'guided) | ||
| 417 | (epa-select-keys context "\ | ||
| 418 | Select keys for signing. | ||
| 419 | If no one is selected, default secret key is used. " | ||
| 420 | signer-names | ||
| 421 | t) | ||
| 422 | (if (or sender mml-smime-signers) | ||
| 423 | (delq nil | ||
| 424 | (mapcar | ||
| 425 | (lambda (signer) | ||
| 426 | (setq signer-key | ||
| 427 | (mml-smime-epg-find-usable-secret-key | ||
| 428 | context signer 'sign)) | ||
| 429 | (unless (or signer-key | ||
| 430 | (y-or-n-p | ||
| 431 | (format | ||
| 432 | "No secret key for %s; skip it? " | ||
| 433 | signer))) | ||
| 434 | (error "No secret key for %s" signer)) | ||
| 435 | signer-key) | ||
| 436 | signer-names))))))) | ||
| 437 | signature micalg) | ||
| 438 | (epg-context-set-signers context signers) | ||
| 439 | (if mml-smime-cache-passphrase | ||
| 440 | (epg-context-set-passphrase-callback | ||
| 441 | context | ||
| 442 | #'mml-smime-epg-passphrase-callback)) | ||
| 443 | (condition-case error | ||
| 444 | (setq signature (epg-sign-string context | ||
| 445 | (mm-replace-in-string (buffer-string) | ||
| 446 | "\n" "\r\n") | ||
| 447 | t) | ||
| 448 | mml-smime-epg-secret-key-id-list nil) | ||
| 449 | (error | ||
| 450 | (while mml-smime-epg-secret-key-id-list | ||
| 451 | (password-cache-remove (car mml-smime-epg-secret-key-id-list)) | ||
| 452 | (setq mml-smime-epg-secret-key-id-list | ||
| 453 | (cdr mml-smime-epg-secret-key-id-list))) | ||
| 454 | (signal (car error) (cdr error)))) | ||
| 455 | (if (epg-context-result-for context 'sign) | ||
| 456 | (setq micalg (epg-new-signature-digest-algorithm | ||
| 457 | (car (epg-context-result-for context 'sign))))) | ||
| 458 | (goto-char (point-min)) | 366 | (goto-char (point-min)) |
| 459 | (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n" | 367 | (let* ((pair (mml-secure-epg-sign 'CMS cont)) |
| 460 | boundary)) | 368 | (signature (car pair)) |
| 461 | (if micalg | 369 | (micalg (cdr pair))) |
| 462 | (insert (format "\tmicalg=%s; " | 370 | (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n" |
| 463 | (downcase | 371 | boundary)) |
| 464 | (cdr (assq micalg | 372 | (if micalg |
| 465 | epg-digest-algorithm-alist)))))) | 373 | (insert (format "\tmicalg=%s; " |
| 466 | (insert "protocol=\"application/pkcs7-signature\"\n") | 374 | (downcase |
| 467 | (insert (format "\n--%s\n" boundary)) | 375 | (cdr (assq micalg |
| 468 | (goto-char (point-max)) | 376 | epg-digest-algorithm-alist)))))) |
| 469 | (insert (format "\n--%s\n" boundary)) | 377 | (insert "protocol=\"application/pkcs7-signature\"\n") |
| 470 | (insert "Content-Type: application/pkcs7-signature; name=smime.p7s | 378 | (insert (format "\n--%s\n" boundary)) |
| 379 | (goto-char (point-max)) | ||
| 380 | (insert (format "\n--%s\n" boundary)) | ||
| 381 | (insert "Content-Type: application/pkcs7-signature; name=smime.p7s | ||
| 471 | Content-Transfer-Encoding: base64 | 382 | Content-Transfer-Encoding: base64 |
| 472 | Content-Disposition: attachment; filename=smime.p7s | 383 | Content-Disposition: attachment; filename=smime.p7s |
| 473 | 384 | ||
| 474 | ") | 385 | ") |
| 475 | (insert (base64-encode-string signature) "\n") | 386 | (insert (base64-encode-string signature) "\n") |
| 476 | (goto-char (point-max)) | 387 | (goto-char (point-max)) |
| 477 | (insert (format "--%s--\n" boundary)) | 388 | (insert (format "--%s--\n" boundary)) |
| 478 | (goto-char (point-max)))) | 389 | (goto-char (point-max))))) |
| 479 | 390 | ||
| 480 | (defun mml-smime-epg-encrypt (cont) | 391 | (defun mml-smime-epg-encrypt (cont) |
| 481 | (let* ((inhibit-redisplay t) | 392 | (let* ((inhibit-redisplay t) |
| 482 | (context (epg-make-context 'CMS)) | ||
| 483 | (config (epg-configuration)) | ||
| 484 | (recipients (message-options-get 'mml-smime-epg-recipients)) | ||
| 485 | cipher signers | ||
| 486 | (sender (message-options-get 'message-sender)) | ||
| 487 | (signer-names (or mml-smime-signers | ||
| 488 | (if (and mml-smime-sign-with-sender sender) | ||
| 489 | (list (concat "<" sender ">"))))) | ||
| 490 | (boundary (mml-compute-boundary cont)) | 393 | (boundary (mml-compute-boundary cont)) |
| 491 | recipient-key) | 394 | (cipher (mml-secure-epg-encrypt 'CMS cont))) |
| 492 | (unless recipients | ||
| 493 | (setq recipients | ||
| 494 | (apply #'nconc | ||
| 495 | (mapcar | ||
| 496 | (lambda (recipient) | ||
| 497 | (or (epg-expand-group config recipient) | ||
| 498 | (list recipient))) | ||
| 499 | (split-string | ||
| 500 | (or (message-options-get 'message-recipients) | ||
| 501 | (message-options-set 'message-recipients | ||
| 502 | (read-string "Recipients: "))) | ||
| 503 | "[ \f\t\n\r\v,]+")))) | ||
| 504 | (when mml-smime-encrypt-to-self | ||
| 505 | (unless signer-names | ||
| 506 | (error "Neither message sender nor mml-smime-signers are set")) | ||
| 507 | (setq recipients (nconc recipients signer-names))) | ||
| 508 | (if (eq mm-encrypt-option 'guided) | ||
| 509 | (setq recipients | ||
| 510 | (epa-select-keys context "\ | ||
| 511 | Select recipients for encryption. | ||
| 512 | If no one is selected, symmetric encryption will be performed. " | ||
| 513 | recipients)) | ||
| 514 | (setq recipients | ||
| 515 | (mapcar | ||
| 516 | (lambda (recipient) | ||
| 517 | (setq recipient-key (mml-smime-epg-find-usable-key | ||
| 518 | (epg-list-keys context recipient) | ||
| 519 | 'encrypt)) | ||
| 520 | (unless (or recipient-key | ||
| 521 | (y-or-n-p | ||
| 522 | (format "No public key for %s; skip it? " | ||
| 523 | recipient))) | ||
| 524 | (error "No public key for %s" recipient)) | ||
| 525 | recipient-key) | ||
| 526 | recipients)) | ||
| 527 | (unless recipients | ||
| 528 | (error "No recipient specified"))) | ||
| 529 | (message-options-set 'mml-smime-epg-recipients recipients)) | ||
| 530 | (if mml-smime-cache-passphrase | ||
| 531 | (epg-context-set-passphrase-callback | ||
| 532 | context | ||
| 533 | #'mml-smime-epg-passphrase-callback)) | ||
| 534 | (condition-case error | ||
| 535 | (setq cipher | ||
| 536 | (epg-encrypt-string context (buffer-string) recipients) | ||
| 537 | mml-smime-epg-secret-key-id-list nil) | ||
| 538 | (error | ||
| 539 | (while mml-smime-epg-secret-key-id-list | ||
| 540 | (password-cache-remove (car mml-smime-epg-secret-key-id-list)) | ||
| 541 | (setq mml-smime-epg-secret-key-id-list | ||
| 542 | (cdr mml-smime-epg-secret-key-id-list))) | ||
| 543 | (signal (car error) (cdr error)))) | ||
| 544 | (delete-region (point-min) (point-max)) | 395 | (delete-region (point-min) (point-max)) |
| 545 | (goto-char (point-min)) | 396 | (goto-char (point-min)) |
| 546 | (insert "\ | 397 | (insert "\ |
diff --git a/lisp/gnus/mml1991.el b/lisp/gnus/mml1991.el index 6469636451f..bb5c940f173 100644 --- a/lisp/gnus/mml1991.el +++ b/lisp/gnus/mml1991.el | |||
| @@ -63,11 +63,17 @@ | |||
| 63 | 63 | ||
| 64 | (defvar mml1991-cache-passphrase mml-secure-cache-passphrase | 64 | (defvar mml1991-cache-passphrase mml-secure-cache-passphrase |
| 65 | "If t, cache passphrase.") | 65 | "If t, cache passphrase.") |
| 66 | (make-obsolete-variable 'mml1991-cache-passphrase | ||
| 67 | 'mml-secure-cache-passphrase | ||
| 68 | "25.1") | ||
| 66 | 69 | ||
| 67 | (defvar mml1991-passphrase-cache-expiry mml-secure-passphrase-cache-expiry | 70 | (defvar mml1991-passphrase-cache-expiry mml-secure-passphrase-cache-expiry |
| 68 | "How many seconds the passphrase is cached. | 71 | "How many seconds the passphrase is cached. |
| 69 | Whether the passphrase is cached at all is controlled by | 72 | Whether the passphrase is cached at all is controlled by |
| 70 | `mml1991-cache-passphrase'.") | 73 | `mml1991-cache-passphrase'.") |
| 74 | (make-obsolete-variable 'mml1991-passphrase-cache-expiry | ||
| 75 | 'mml-secure-passphrase-cache-expiry | ||
| 76 | "25.1") | ||
| 71 | 77 | ||
| 72 | (defvar mml1991-signers nil | 78 | (defvar mml1991-signers nil |
| 73 | "A list of your own key ID which will be used to sign a message.") | 79 | "A list of your own key ID which will be used to sign a message.") |
| @@ -75,6 +81,7 @@ Whether the passphrase is cached at all is controlled by | |||
| 75 | (defvar mml1991-encrypt-to-self nil | 81 | (defvar mml1991-encrypt-to-self nil |
| 76 | "If t, add your own key ID to recipient list when encryption.") | 82 | "If t, add your own key ID to recipient list when encryption.") |
| 77 | 83 | ||
| 84 | |||
| 78 | ;;; mailcrypt wrapper | 85 | ;;; mailcrypt wrapper |
| 79 | 86 | ||
| 80 | (autoload 'mc-sign-generic "mc-toplev") | 87 | (autoload 'mc-sign-generic "mc-toplev") |
| @@ -255,91 +262,9 @@ Whether the passphrase is cached at all is controlled by | |||
| 255 | (autoload 'epg-configuration "epg-config") | 262 | (autoload 'epg-configuration "epg-config") |
| 256 | (autoload 'epg-expand-group "epg-config") | 263 | (autoload 'epg-expand-group "epg-config") |
| 257 | 264 | ||
| 258 | (defvar mml1991-epg-secret-key-id-list nil) | ||
| 259 | |||
| 260 | (defun mml1991-epg-passphrase-callback (context key-id ignore) | ||
| 261 | (if (eq key-id 'SYM) | ||
| 262 | (epg-passphrase-callback-function context key-id nil) | ||
| 263 | (let* ((entry (assoc key-id epg-user-id-alist)) | ||
| 264 | (passphrase | ||
| 265 | (password-read | ||
| 266 | (format "GnuPG passphrase for %s: " | ||
| 267 | (if entry | ||
| 268 | (cdr entry) | ||
| 269 | key-id)) | ||
| 270 | (if (eq key-id 'PIN) | ||
| 271 | "PIN" | ||
| 272 | key-id)))) | ||
| 273 | (when passphrase | ||
| 274 | (let ((password-cache-expiry mml1991-passphrase-cache-expiry)) | ||
| 275 | (password-cache-add key-id passphrase)) | ||
| 276 | (setq mml1991-epg-secret-key-id-list | ||
| 277 | (cons key-id mml1991-epg-secret-key-id-list)) | ||
| 278 | (copy-sequence passphrase))))) | ||
| 279 | |||
| 280 | (defun mml1991-epg-find-usable-key (keys usage) | ||
| 281 | (catch 'found | ||
| 282 | (while keys | ||
| 283 | (let ((pointer (epg-key-sub-key-list (car keys)))) | ||
| 284 | ;; The primary key will be marked as disabled, when the entire | ||
| 285 | ;; key is disabled (see 12 Field, Format of colon listings, in | ||
| 286 | ;; gnupg/doc/DETAILS) | ||
| 287 | (unless (memq 'disabled (epg-sub-key-capability (car pointer))) | ||
| 288 | (while pointer | ||
| 289 | (if (and (memq usage (epg-sub-key-capability (car pointer))) | ||
| 290 | (not (memq (epg-sub-key-validity (car pointer)) | ||
| 291 | '(revoked expired)))) | ||
| 292 | (throw 'found (car keys))) | ||
| 293 | (setq pointer (cdr pointer))))) | ||
| 294 | (setq keys (cdr keys))))) | ||
| 295 | |||
| 296 | ;; XXX: since gpg --list-secret-keys does not return validity of each | ||
| 297 | ;; key, `mml1991-epg-find-usable-key' defined above is not enough for | ||
| 298 | ;; secret keys. The function `mml1991-epg-find-usable-secret-key' | ||
| 299 | ;; below looks at appropriate public keys to check usability. | ||
| 300 | (defun mml1991-epg-find-usable-secret-key (context name usage) | ||
| 301 | (let ((secret-keys (epg-list-keys context name t)) | ||
| 302 | secret-key) | ||
| 303 | (while (and (not secret-key) secret-keys) | ||
| 304 | (if (mml1991-epg-find-usable-key | ||
| 305 | (epg-list-keys context (epg-sub-key-fingerprint | ||
| 306 | (car (epg-key-sub-key-list | ||
| 307 | (car secret-keys))))) | ||
| 308 | usage) | ||
| 309 | (setq secret-key (car secret-keys) | ||
| 310 | secret-keys nil) | ||
| 311 | (setq secret-keys (cdr secret-keys)))) | ||
| 312 | secret-key)) | ||
| 313 | |||
| 314 | (defun mml1991-epg-sign (cont) | 265 | (defun mml1991-epg-sign (cont) |
| 315 | (let ((context (epg-make-context)) | 266 | (let ((inhibit-redisplay t) |
| 316 | headers cte signer-key signers signature) | 267 | headers cte) |
| 317 | (if (eq mm-sign-option 'guided) | ||
| 318 | (setq signers (epa-select-keys context "Select keys for signing. | ||
| 319 | If no one is selected, default secret key is used. " | ||
| 320 | mml1991-signers t)) | ||
| 321 | (if mml1991-signers | ||
| 322 | (setq signers (delq nil | ||
| 323 | (mapcar | ||
| 324 | (lambda (name) | ||
| 325 | (setq signer-key | ||
| 326 | (mml1991-epg-find-usable-secret-key | ||
| 327 | context name 'sign)) | ||
| 328 | (unless (or signer-key | ||
| 329 | (y-or-n-p | ||
| 330 | (format | ||
| 331 | "No secret key for %s; skip it? " | ||
| 332 | name))) | ||
| 333 | (error "No secret key for %s" name)) | ||
| 334 | signer-key) | ||
| 335 | mml1991-signers))))) | ||
| 336 | (epg-context-set-armor context t) | ||
| 337 | (epg-context-set-textmode context t) | ||
| 338 | (epg-context-set-signers context signers) | ||
| 339 | (if mml1991-cache-passphrase | ||
| 340 | (epg-context-set-passphrase-callback | ||
| 341 | context | ||
| 342 | #'mml1991-epg-passphrase-callback)) | ||
| 343 | ;; Don't sign headers. | 268 | ;; Don't sign headers. |
| 344 | (goto-char (point-min)) | 269 | (goto-char (point-min)) |
| 345 | (when (re-search-forward "^$" nil t) | 270 | (when (re-search-forward "^$" nil t) |
| @@ -352,28 +277,21 @@ If no one is selected, default secret key is used. " | |||
| 352 | (when cte | 277 | (when cte |
| 353 | (setq cte (intern (downcase cte))) | 278 | (setq cte (intern (downcase cte))) |
| 354 | (mm-decode-content-transfer-encoding cte))) | 279 | (mm-decode-content-transfer-encoding cte))) |
| 355 | (condition-case error | 280 | (let* ((pair (mml-secure-epg-sign 'OpenPGP 'clear)) |
| 356 | (setq signature (epg-sign-string context (buffer-string) 'clear) | 281 | (signature (car pair))) |
| 357 | mml1991-epg-secret-key-id-list nil) | 282 | (delete-region (point-min) (point-max)) |
| 358 | (error | 283 | (mm-with-unibyte-current-buffer |
| 359 | (while mml1991-epg-secret-key-id-list | 284 | (insert signature) |
| 360 | (password-cache-remove (car mml1991-epg-secret-key-id-list)) | 285 | (goto-char (point-min)) |
| 361 | (setq mml1991-epg-secret-key-id-list | 286 | (while (re-search-forward "\r+$" nil t) |
| 362 | (cdr mml1991-epg-secret-key-id-list))) | 287 | (replace-match "" t t)) |
| 363 | (signal (car error) (cdr error)))) | 288 | (when cte |
| 364 | (delete-region (point-min) (point-max)) | 289 | (mm-encode-content-transfer-encoding cte)) |
| 365 | (mm-with-unibyte-current-buffer | 290 | (goto-char (point-min)) |
| 366 | (insert signature) | 291 | (when headers |
| 367 | (goto-char (point-min)) | 292 | (insert headers)) |
| 368 | (while (re-search-forward "\r+$" nil t) | 293 | (insert "\n")) |
| 369 | (replace-match "" t t)) | 294 | t))) |
| 370 | (when cte | ||
| 371 | (mm-encode-content-transfer-encoding cte)) | ||
| 372 | (goto-char (point-min)) | ||
| 373 | (when headers | ||
| 374 | (insert headers)) | ||
| 375 | (insert "\n")) | ||
| 376 | t)) | ||
| 377 | 295 | ||
| 378 | (defun mml1991-epg-encrypt (cont &optional sign) | 296 | (defun mml1991-epg-encrypt (cont &optional sign) |
| 379 | (goto-char (point-min)) | 297 | (goto-char (point-min)) |
| @@ -386,78 +304,7 @@ If no one is selected, default secret key is used. " | |||
| 386 | (delete-region (point-min) (point)) | 304 | (delete-region (point-min) (point)) |
| 387 | (when cte | 305 | (when cte |
| 388 | (mm-decode-content-transfer-encoding (intern (downcase cte)))))) | 306 | (mm-decode-content-transfer-encoding (intern (downcase cte)))))) |
| 389 | (let ((context (epg-make-context)) | 307 | (let ((cipher (mml-secure-epg-encrypt 'OpenPGP cont sign))) |
| 390 | (recipients | ||
| 391 | (if (message-options-get 'message-recipients) | ||
| 392 | (split-string | ||
| 393 | (message-options-get 'message-recipients) | ||
| 394 | "[ \f\t\n\r\v,]+"))) | ||
| 395 | recipient-key signer-key cipher signers config) | ||
| 396 | (when mml1991-encrypt-to-self | ||
| 397 | (unless mml1991-signers | ||
| 398 | (error "mml1991-signers is not set")) | ||
| 399 | (setq recipients (nconc recipients mml1991-signers))) | ||
| 400 | ;; We should remove this check if epg-0.0.6 is released. | ||
| 401 | (if (and (condition-case nil | ||
| 402 | (require 'epg-config) | ||
| 403 | (error)) | ||
| 404 | (functionp #'epg-expand-group)) | ||
| 405 | (setq config (epg-configuration) | ||
| 406 | recipients | ||
| 407 | (apply #'nconc | ||
| 408 | (mapcar (lambda (recipient) | ||
| 409 | (or (epg-expand-group config recipient) | ||
| 410 | (list recipient))) | ||
| 411 | recipients)))) | ||
| 412 | (if (eq mm-encrypt-option 'guided) | ||
| 413 | (setq recipients | ||
| 414 | (epa-select-keys context "Select recipients for encryption. | ||
| 415 | If no one is selected, symmetric encryption will be performed. " | ||
| 416 | recipients)) | ||
| 417 | (setq recipients | ||
| 418 | (delq nil (mapcar | ||
| 419 | (lambda (name) | ||
| 420 | (setq recipient-key (mml1991-epg-find-usable-key | ||
| 421 | (epg-list-keys context name) | ||
| 422 | 'encrypt)) | ||
| 423 | (unless (or recipient-key | ||
| 424 | (y-or-n-p | ||
| 425 | (format "No public key for %s; skip it? " | ||
| 426 | name))) | ||
| 427 | (error "No public key for %s" name)) | ||
| 428 | recipient-key) | ||
| 429 | recipients))) | ||
| 430 | (unless recipients | ||
| 431 | (error "No recipient specified"))) | ||
| 432 | (when sign | ||
| 433 | (if (eq mm-sign-option 'guided) | ||
| 434 | (setq signers (epa-select-keys context "Select keys for signing. | ||
| 435 | If no one is selected, default secret key is used. " | ||
| 436 | mml1991-signers t)) | ||
| 437 | (if mml1991-signers | ||
| 438 | (setq signers (delq nil | ||
| 439 | (mapcar | ||
| 440 | (lambda (name) | ||
| 441 | (mml1991-epg-find-usable-secret-key | ||
| 442 | context name 'sign)) | ||
| 443 | mml1991-signers))))) | ||
| 444 | (epg-context-set-signers context signers)) | ||
| 445 | (epg-context-set-armor context t) | ||
| 446 | (epg-context-set-textmode context t) | ||
| 447 | (if mml1991-cache-passphrase | ||
| 448 | (epg-context-set-passphrase-callback | ||
| 449 | context | ||
| 450 | #'mml1991-epg-passphrase-callback)) | ||
| 451 | (condition-case error | ||
| 452 | (setq cipher | ||
| 453 | (epg-encrypt-string context (buffer-string) recipients sign) | ||
| 454 | mml1991-epg-secret-key-id-list nil) | ||
| 455 | (error | ||
| 456 | (while mml1991-epg-secret-key-id-list | ||
| 457 | (password-cache-remove (car mml1991-epg-secret-key-id-list)) | ||
| 458 | (setq mml1991-epg-secret-key-id-list | ||
| 459 | (cdr mml1991-epg-secret-key-id-list))) | ||
| 460 | (signal (car error) (cdr error)))) | ||
| 461 | (delete-region (point-min) (point-max)) | 308 | (delete-region (point-min) (point-max)) |
| 462 | (insert "\n" cipher)) | 309 | (insert "\n" cipher)) |
| 463 | t) | 310 | t) |
diff --git a/lisp/gnus/mml2015.el b/lisp/gnus/mml2015.el index 10ba126ae2b..e2e99771801 100644 --- a/lisp/gnus/mml2015.el +++ b/lisp/gnus/mml2015.el | |||
| @@ -111,6 +111,9 @@ Valid packages include `epg', `pgg' and `mailcrypt'.") | |||
| 111 | "If t, cache passphrase." | 111 | "If t, cache passphrase." |
| 112 | :group 'mime-security | 112 | :group 'mime-security |
| 113 | :type 'boolean) | 113 | :type 'boolean) |
| 114 | (make-obsolete-variable 'mml2015-cache-passphrase | ||
| 115 | 'mml-secure-cache-passphrase | ||
| 116 | "25.1") | ||
| 114 | 117 | ||
| 115 | (defcustom mml2015-passphrase-cache-expiry mml-secure-passphrase-cache-expiry | 118 | (defcustom mml2015-passphrase-cache-expiry mml-secure-passphrase-cache-expiry |
| 116 | "How many seconds the passphrase is cached. | 119 | "How many seconds the passphrase is cached. |
| @@ -118,6 +121,9 @@ Whether the passphrase is cached at all is controlled by | |||
| 118 | `mml2015-cache-passphrase'." | 121 | `mml2015-cache-passphrase'." |
| 119 | :group 'mime-security | 122 | :group 'mime-security |
| 120 | :type 'integer) | 123 | :type 'integer) |
| 124 | (make-obsolete-variable 'mml2015-passphrase-cache-expiry | ||
| 125 | 'mml-secure-passphrase-cache-expiry | ||
| 126 | "25.1") | ||
| 121 | 127 | ||
| 122 | (defcustom mml2015-signers nil | 128 | (defcustom mml2015-signers nil |
| 123 | "A list of your own key ID(s) which will be used to sign a message. | 129 | "A list of your own key ID(s) which will be used to sign a message. |
| @@ -774,99 +780,6 @@ If set, it overrides the setting of `mml2015-sign-with-sender'." | |||
| 774 | (autoload 'epg-expand-group "epg-config") | 780 | (autoload 'epg-expand-group "epg-config") |
| 775 | (autoload 'epa-select-keys "epa") | 781 | (autoload 'epa-select-keys "epa") |
| 776 | 782 | ||
| 777 | (defvar mml2015-epg-secret-key-id-list nil) | ||
| 778 | |||
| 779 | (defun mml2015-epg-passphrase-callback (context key-id ignore) | ||
| 780 | (if (eq key-id 'SYM) | ||
| 781 | (epg-passphrase-callback-function context key-id nil) | ||
| 782 | (let* ((password-cache-key-id | ||
| 783 | (if (eq key-id 'PIN) | ||
| 784 | "PIN" | ||
| 785 | key-id)) | ||
| 786 | entry | ||
| 787 | (passphrase | ||
| 788 | (password-read | ||
| 789 | (if (eq key-id 'PIN) | ||
| 790 | "Passphrase for PIN: " | ||
| 791 | (if (setq entry (assoc key-id epg-user-id-alist)) | ||
| 792 | (format "Passphrase for %s %s: " key-id (cdr entry)) | ||
| 793 | (format "Passphrase for %s: " key-id))) | ||
| 794 | password-cache-key-id))) | ||
| 795 | (when passphrase | ||
| 796 | (let ((password-cache-expiry mml2015-passphrase-cache-expiry)) | ||
| 797 | (password-cache-add password-cache-key-id passphrase)) | ||
| 798 | (setq mml2015-epg-secret-key-id-list | ||
| 799 | (cons password-cache-key-id mml2015-epg-secret-key-id-list)) | ||
| 800 | (copy-sequence passphrase))))) | ||
| 801 | |||
| 802 | (defun mml2015-epg-check-user-id (key recipient) | ||
| 803 | (let ((pointer (epg-key-user-id-list key)) | ||
| 804 | result) | ||
| 805 | (while pointer | ||
| 806 | (if (and (equal (car (mail-header-parse-address | ||
| 807 | (epg-user-id-string (car pointer)))) | ||
| 808 | (car (mail-header-parse-address | ||
| 809 | recipient))) | ||
| 810 | (not (memq (epg-user-id-validity (car pointer)) | ||
| 811 | '(revoked expired)))) | ||
| 812 | (setq result t | ||
| 813 | pointer nil) | ||
| 814 | (setq pointer (cdr pointer)))) | ||
| 815 | result)) | ||
| 816 | |||
| 817 | (defun mml2015-epg-check-sub-key (key usage) | ||
| 818 | (let ((pointer (epg-key-sub-key-list key)) | ||
| 819 | result) | ||
| 820 | ;; The primary key will be marked as disabled, when the entire | ||
| 821 | ;; key is disabled (see 12 Field, Format of colon listings, in | ||
| 822 | ;; gnupg/doc/DETAILS) | ||
| 823 | (unless (memq 'disabled (epg-sub-key-capability (car pointer))) | ||
| 824 | (while pointer | ||
| 825 | (if (and (memq usage (epg-sub-key-capability (car pointer))) | ||
| 826 | (not (memq (epg-sub-key-validity (car pointer)) | ||
| 827 | '(revoked expired)))) | ||
| 828 | (setq result t | ||
| 829 | pointer nil) | ||
| 830 | (setq pointer (cdr pointer))))) | ||
| 831 | result)) | ||
| 832 | |||
| 833 | (defun mml2015-epg-find-usable-key (context name usage | ||
| 834 | &optional name-is-key-id) | ||
| 835 | (let ((keys (epg-list-keys context name)) | ||
| 836 | key) | ||
| 837 | (while keys | ||
| 838 | (if (and (or name-is-key-id | ||
| 839 | ;; Non email user-id can be supplied through | ||
| 840 | ;; mml2015-signers if mml2015-encrypt-to-self is set. | ||
| 841 | ;; Treat it as valid, as it is user's intention. | ||
| 842 | (not (string-match "\\`<" name)) | ||
| 843 | (mml2015-epg-check-user-id (car keys) name)) | ||
| 844 | (mml2015-epg-check-sub-key (car keys) usage)) | ||
| 845 | (setq key (car keys) | ||
| 846 | keys nil) | ||
| 847 | (setq keys (cdr keys)))) | ||
| 848 | key)) | ||
| 849 | |||
| 850 | ;; XXX: since gpg --list-secret-keys does not return validity of each | ||
| 851 | ;; key, `mml2015-epg-find-usable-key' defined above is not enough for | ||
| 852 | ;; secret keys. The function `mml2015-epg-find-usable-secret-key' | ||
| 853 | ;; below looks at appropriate public keys to check usability. | ||
| 854 | (defun mml2015-epg-find-usable-secret-key (context name usage) | ||
| 855 | (let ((secret-keys (epg-list-keys context name t)) | ||
| 856 | secret-key) | ||
| 857 | (while (and (not secret-key) secret-keys) | ||
| 858 | (if (mml2015-epg-find-usable-key | ||
| 859 | context | ||
| 860 | (epg-sub-key-fingerprint | ||
| 861 | (car (epg-key-sub-key-list | ||
| 862 | (car secret-keys)))) | ||
| 863 | usage | ||
| 864 | t) | ||
| 865 | (setq secret-key (car secret-keys) | ||
| 866 | secret-keys nil) | ||
| 867 | (setq secret-keys (cdr secret-keys)))) | ||
| 868 | secret-key)) | ||
| 869 | |||
| 870 | (autoload 'gnus-create-image "gnus-ems") | 783 | (autoload 'gnus-create-image "gnus-ems") |
| 871 | 784 | ||
| 872 | (defun mml2015-epg-key-image (key-id) | 785 | (defun mml2015-epg-key-image (key-id) |
| @@ -921,18 +834,15 @@ If set, it overrides the setting of `mml2015-sign-with-sender'." | |||
| 921 | mm-security-handle 'gnus-info "Corrupted") | 834 | mm-security-handle 'gnus-info "Corrupted") |
| 922 | (throw 'error handle)) | 835 | (throw 'error handle)) |
| 923 | (setq context (epg-make-context)) | 836 | (setq context (epg-make-context)) |
| 924 | (if mml2015-cache-passphrase | 837 | (if (or mml2015-cache-passphrase mml-secure-cache-passphrase) |
| 925 | (epg-context-set-passphrase-callback | 838 | (epg-context-set-passphrase-callback |
| 926 | context | 839 | context |
| 927 | #'mml2015-epg-passphrase-callback)) | 840 | (cons 'mml-secure-passphrase-callback 'OpenPGP))) |
| 928 | (condition-case error | 841 | (condition-case error |
| 929 | (setq plain (epg-decrypt-string context (mm-get-part child)) | 842 | (setq plain (epg-decrypt-string context (mm-get-part child)) |
| 930 | mml2015-epg-secret-key-id-list nil) | 843 | mml-secure-secret-key-id-list nil) |
| 931 | (error | 844 | (error |
| 932 | (while mml2015-epg-secret-key-id-list | 845 | (mml-secure-clear-secret-key-id-list) |
| 933 | (password-cache-remove (car mml2015-epg-secret-key-id-list)) | ||
| 934 | (setq mml2015-epg-secret-key-id-list | ||
| 935 | (cdr mml2015-epg-secret-key-id-list))) | ||
| 936 | (mm-set-handle-multipart-parameter | 846 | (mm-set-handle-multipart-parameter |
| 937 | mm-security-handle 'gnus-info "Failed") | 847 | mm-security-handle 'gnus-info "Failed") |
| 938 | (if (eq (car error) 'quit) | 848 | (if (eq (car error) 'quit) |
| @@ -968,18 +878,15 @@ If set, it overrides the setting of `mml2015-sign-with-sender'." | |||
| 968 | (let ((inhibit-redisplay t) | 878 | (let ((inhibit-redisplay t) |
| 969 | (context (epg-make-context)) | 879 | (context (epg-make-context)) |
| 970 | plain) | 880 | plain) |
| 971 | (if mml2015-cache-passphrase | 881 | (if (or mml2015-cache-passphrase mml-secure-cache-passphrase) |
| 972 | (epg-context-set-passphrase-callback | 882 | (epg-context-set-passphrase-callback |
| 973 | context | 883 | context |
| 974 | #'mml2015-epg-passphrase-callback)) | 884 | (cons 'mml-secure-passphrase-callback 'OpenPGP))) |
| 975 | (condition-case error | 885 | (condition-case error |
| 976 | (setq plain (epg-decrypt-string context (buffer-string)) | 886 | (setq plain (epg-decrypt-string context (buffer-string)) |
| 977 | mml2015-epg-secret-key-id-list nil) | 887 | mml-secure-secret-key-id-list nil) |
| 978 | (error | 888 | (error |
| 979 | (while mml2015-epg-secret-key-id-list | 889 | (mml-secure-clear-secret-key-id-list) |
| 980 | (password-cache-remove (car mml2015-epg-secret-key-id-list)) | ||
| 981 | (setq mml2015-epg-secret-key-id-list | ||
| 982 | (cdr mml2015-epg-secret-key-id-list))) | ||
| 983 | (mm-set-handle-multipart-parameter | 890 | (mm-set-handle-multipart-parameter |
| 984 | mm-security-handle 'gnus-info "Failed") | 891 | mm-security-handle 'gnus-info "Failed") |
| 985 | (if (eq (car error) 'quit) | 892 | (if (eq (car error) 'quit) |
| @@ -1065,176 +972,37 @@ If set, it overrides the setting of `mml2015-sign-with-sender'." | |||
| 1065 | (mml2015-extract-cleartext-signature)))) | 972 | (mml2015-extract-cleartext-signature)))) |
| 1066 | 973 | ||
| 1067 | (defun mml2015-epg-sign (cont) | 974 | (defun mml2015-epg-sign (cont) |
| 1068 | (let* ((inhibit-redisplay t) | 975 | (let ((inhibit-redisplay t) |
| 1069 | (context (epg-make-context)) | 976 | (boundary (mml-compute-boundary cont))) |
| 1070 | (boundary (mml-compute-boundary cont)) | ||
| 1071 | (sender (message-options-get 'message-sender)) | ||
| 1072 | (signer-names (or mml2015-signers | ||
| 1073 | (if (and mml2015-sign-with-sender sender) | ||
| 1074 | (list (concat "<" sender ">"))))) | ||
| 1075 | signer-key | ||
| 1076 | (signers | ||
| 1077 | (or (message-options-get 'mml2015-epg-signers) | ||
| 1078 | (message-options-set | ||
| 1079 | 'mml2015-epg-signers | ||
| 1080 | (if (eq mm-sign-option 'guided) | ||
| 1081 | (epa-select-keys context "\ | ||
| 1082 | Select keys for signing. | ||
| 1083 | If no one is selected, default secret key is used. " | ||
| 1084 | signer-names | ||
| 1085 | t) | ||
| 1086 | (if (or sender mml2015-signers) | ||
| 1087 | (delq nil | ||
| 1088 | (mapcar | ||
| 1089 | (lambda (signer) | ||
| 1090 | (setq signer-key | ||
| 1091 | (mml2015-epg-find-usable-secret-key | ||
| 1092 | context signer 'sign)) | ||
| 1093 | (unless (or signer-key | ||
| 1094 | (y-or-n-p | ||
| 1095 | (format | ||
| 1096 | "No secret key for %s; skip it? " | ||
| 1097 | signer))) | ||
| 1098 | (error "No secret key for %s" signer)) | ||
| 1099 | signer-key) | ||
| 1100 | signer-names))))))) | ||
| 1101 | signature micalg) | ||
| 1102 | (epg-context-set-armor context t) | ||
| 1103 | (epg-context-set-textmode context t) | ||
| 1104 | (epg-context-set-signers context signers) | ||
| 1105 | (if mml2015-cache-passphrase | ||
| 1106 | (epg-context-set-passphrase-callback | ||
| 1107 | context | ||
| 1108 | #'mml2015-epg-passphrase-callback)) | ||
| 1109 | ;; Signed data must end with a newline (RFC 3156, 5). | 977 | ;; Signed data must end with a newline (RFC 3156, 5). |
| 1110 | (goto-char (point-max)) | 978 | (goto-char (point-max)) |
| 1111 | (unless (bolp) | 979 | (unless (bolp) |
| 1112 | (insert "\n")) | 980 | (insert "\n")) |
| 1113 | (condition-case error | 981 | (let* ((pair (mml-secure-epg-sign 'OpenPGP t)) |
| 1114 | (setq signature (epg-sign-string context (buffer-string) t) | 982 | (signature (car pair)) |
| 1115 | mml2015-epg-secret-key-id-list nil) | 983 | (micalg (cdr pair))) |
| 1116 | (error | 984 | (goto-char (point-min)) |
| 1117 | (while mml2015-epg-secret-key-id-list | 985 | (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n" |
| 1118 | (password-cache-remove (car mml2015-epg-secret-key-id-list)) | 986 | boundary)) |
| 1119 | (setq mml2015-epg-secret-key-id-list | 987 | (if micalg |
| 1120 | (cdr mml2015-epg-secret-key-id-list))) | 988 | (insert (format "\tmicalg=pgp-%s; " |
| 1121 | (signal (car error) (cdr error)))) | 989 | (downcase |
| 1122 | (if (epg-context-result-for context 'sign) | 990 | (cdr (assq micalg |
| 1123 | (setq micalg (epg-new-signature-digest-algorithm | 991 | epg-digest-algorithm-alist)))))) |
| 1124 | (car (epg-context-result-for context 'sign))))) | 992 | (insert "protocol=\"application/pgp-signature\"\n") |
| 1125 | (goto-char (point-min)) | 993 | (insert (format "\n--%s\n" boundary)) |
| 1126 | (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n" | 994 | (goto-char (point-max)) |
| 1127 | boundary)) | 995 | (insert (format "\n--%s\n" boundary)) |
| 1128 | (if micalg | 996 | (insert "Content-Type: application/pgp-signature; name=\"signature.asc\"\n\n") |
| 1129 | (insert (format "\tmicalg=pgp-%s; " | 997 | (insert signature) |
| 1130 | (downcase | 998 | (goto-char (point-max)) |
| 1131 | (cdr (assq micalg | 999 | (insert (format "--%s--\n" boundary)) |
| 1132 | epg-digest-algorithm-alist)))))) | 1000 | (goto-char (point-max))))) |
| 1133 | (insert "protocol=\"application/pgp-signature\"\n") | ||
| 1134 | (insert (format "\n--%s\n" boundary)) | ||
| 1135 | (goto-char (point-max)) | ||
| 1136 | (insert (format "\n--%s\n" boundary)) | ||
| 1137 | (insert "Content-Type: application/pgp-signature; name=\"signature.asc\"\n\n") | ||
| 1138 | (insert signature) | ||
| 1139 | (goto-char (point-max)) | ||
| 1140 | (insert (format "--%s--\n" boundary)) | ||
| 1141 | (goto-char (point-max)))) | ||
| 1142 | 1001 | ||
| 1143 | (defun mml2015-epg-encrypt (cont &optional sign) | 1002 | (defun mml2015-epg-encrypt (cont &optional sign) |
| 1144 | (let* ((inhibit-redisplay t) | 1003 | (let* ((inhibit-redisplay t) |
| 1145 | (context (epg-make-context)) | ||
| 1146 | (boundary (mml-compute-boundary cont)) | 1004 | (boundary (mml-compute-boundary cont)) |
| 1147 | (config (epg-configuration)) | 1005 | (cipher (mml-secure-epg-encrypt 'OpenPGP cont sign))) |
| 1148 | (recipients (message-options-get 'mml2015-epg-recipients)) | ||
| 1149 | cipher | ||
| 1150 | (sender (message-options-get 'message-sender)) | ||
| 1151 | (signer-names (or mml2015-signers | ||
| 1152 | (if (and mml2015-sign-with-sender sender) | ||
| 1153 | (list (concat "<" sender ">"))))) | ||
| 1154 | signers | ||
| 1155 | recipient-key signer-key) | ||
| 1156 | (unless recipients | ||
| 1157 | (setq recipients | ||
| 1158 | (apply #'nconc | ||
| 1159 | (mapcar | ||
| 1160 | (lambda (recipient) | ||
| 1161 | (or (epg-expand-group config recipient) | ||
| 1162 | (list (concat "<" recipient ">")))) | ||
| 1163 | (split-string | ||
| 1164 | (or (message-options-get 'message-recipients) | ||
| 1165 | (message-options-set 'message-recipients | ||
| 1166 | (read-string "Recipients: "))) | ||
| 1167 | "[ \f\t\n\r\v,]+")))) | ||
| 1168 | (when mml2015-encrypt-to-self | ||
| 1169 | (unless signer-names | ||
| 1170 | (error "Neither message sender nor mml2015-signers are set")) | ||
| 1171 | (setq recipients (nconc recipients signer-names))) | ||
| 1172 | (if (eq mm-encrypt-option 'guided) | ||
| 1173 | (setq recipients | ||
| 1174 | (epa-select-keys context "\ | ||
| 1175 | Select recipients for encryption. | ||
| 1176 | If no one is selected, symmetric encryption will be performed. " | ||
| 1177 | recipients)) | ||
| 1178 | (setq recipients | ||
| 1179 | (delq nil | ||
| 1180 | (mapcar | ||
| 1181 | (lambda (recipient) | ||
| 1182 | (setq recipient-key (mml2015-epg-find-usable-key | ||
| 1183 | context recipient 'encrypt)) | ||
| 1184 | (unless (or recipient-key | ||
| 1185 | (y-or-n-p | ||
| 1186 | (format "No public key for %s; skip it? " | ||
| 1187 | recipient))) | ||
| 1188 | (error "No public key for %s" recipient)) | ||
| 1189 | recipient-key) | ||
| 1190 | recipients))) | ||
| 1191 | (unless recipients | ||
| 1192 | (error "No recipient specified"))) | ||
| 1193 | (message-options-set 'mml2015-epg-recipients recipients)) | ||
| 1194 | (when sign | ||
| 1195 | (setq signers | ||
| 1196 | (or (message-options-get 'mml2015-epg-signers) | ||
| 1197 | (message-options-set | ||
| 1198 | 'mml2015-epg-signers | ||
| 1199 | (if (eq mm-sign-option 'guided) | ||
| 1200 | (epa-select-keys context "\ | ||
| 1201 | Select keys for signing. | ||
| 1202 | If no one is selected, default secret key is used. " | ||
| 1203 | signer-names | ||
| 1204 | t) | ||
| 1205 | (if (or sender mml2015-signers) | ||
| 1206 | (delq nil | ||
| 1207 | (mapcar | ||
| 1208 | (lambda (signer) | ||
| 1209 | (setq signer-key | ||
| 1210 | (mml2015-epg-find-usable-secret-key | ||
| 1211 | context signer 'sign)) | ||
| 1212 | (unless (or signer-key | ||
| 1213 | (y-or-n-p | ||
| 1214 | (format | ||
| 1215 | "No secret key for %s; skip it? " | ||
| 1216 | signer))) | ||
| 1217 | (error "No secret key for %s" signer)) | ||
| 1218 | signer-key) | ||
| 1219 | signer-names))))))) | ||
| 1220 | (epg-context-set-signers context signers)) | ||
| 1221 | (epg-context-set-armor context t) | ||
| 1222 | (epg-context-set-textmode context t) | ||
| 1223 | (if mml2015-cache-passphrase | ||
| 1224 | (epg-context-set-passphrase-callback | ||
| 1225 | context | ||
| 1226 | #'mml2015-epg-passphrase-callback)) | ||
| 1227 | (condition-case error | ||
| 1228 | (setq cipher | ||
| 1229 | (epg-encrypt-string context (buffer-string) recipients sign | ||
| 1230 | mml2015-always-trust) | ||
| 1231 | mml2015-epg-secret-key-id-list nil) | ||
| 1232 | (error | ||
| 1233 | (while mml2015-epg-secret-key-id-list | ||
| 1234 | (password-cache-remove (car mml2015-epg-secret-key-id-list)) | ||
| 1235 | (setq mml2015-epg-secret-key-id-list | ||
| 1236 | (cdr mml2015-epg-secret-key-id-list))) | ||
| 1237 | (signal (car error) (cdr error)))) | ||
| 1238 | (delete-region (point-min) (point-max)) | 1006 | (delete-region (point-min) (point-max)) |
| 1239 | (goto-char (point-min)) | 1007 | (goto-char (point-min)) |
| 1240 | (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n" | 1008 | (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n" |
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el index 0e10dfdb8be..f56b04568c8 100644 --- a/lisp/gnus/nntp.el +++ b/lisp/gnus/nntp.el | |||
| @@ -1115,24 +1115,14 @@ command whose response triggered the error." | |||
| 1115 | 1115 | ||
| 1116 | (deffoo nntp-request-newgroups (date &optional server) | 1116 | (deffoo nntp-request-newgroups (date &optional server) |
| 1117 | (nntp-with-open-group | 1117 | (nntp-with-open-group |
| 1118 | nil server | 1118 | nil server |
| 1119 | (with-current-buffer nntp-server-buffer | 1119 | (with-current-buffer nntp-server-buffer |
| 1120 | (let* ((time (date-to-time date)) | 1120 | (prog1 |
| 1121 | (ls (- (cadr time) (nth 8 (decode-time time))))) | 1121 | (nntp-send-command |
| 1122 | (cond ((< ls 0) | 1122 | "^\\.\r?\n" "NEWGROUPS" |
| 1123 | (setcar time (1- (car time))) | 1123 | (format-time-string "%y%m%d %H%M%S" (date-to-time date) t) |
| 1124 | (setcar (cdr time) (+ ls 65536))) | 1124 | "GMT") |
| 1125 | ((>= ls 65536) | 1125 | (nntp-decode-text))))) |
| 1126 | (setcar time (1+ (car time))) | ||
| 1127 | (setcar (cdr time) (- ls 65536))) | ||
| 1128 | (t | ||
| 1129 | (setcar (cdr time) ls))) | ||
| 1130 | (prog1 | ||
| 1131 | (nntp-send-command | ||
| 1132 | "^\\.\r?\n" "NEWGROUPS" | ||
| 1133 | (format-time-string "%y%m%d %H%M%S" time) | ||
| 1134 | "GMT") | ||
| 1135 | (nntp-decode-text)))))) | ||
| 1136 | 1126 | ||
| 1137 | (deffoo nntp-request-post (&optional server) | 1127 | (deffoo nntp-request-post (&optional server) |
| 1138 | (nntp-with-open-group | 1128 | (nntp-with-open-group |
diff --git a/lisp/help-fns.el b/lisp/help-fns.el index bc96601a45c..2021885e996 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el | |||
| @@ -918,29 +918,28 @@ if it is given a local binding.\n")))) | |||
| 918 | ;; If the cache element has an mtime, we | 918 | ;; If the cache element has an mtime, we |
| 919 | ;; assume it came from a file. | 919 | ;; assume it came from a file. |
| 920 | (if (nth 2 file) | 920 | (if (nth 2 file) |
| 921 | (setq file (expand-file-name | 921 | ;; (car file) is a directory. |
| 922 | dir-locals-file (car file))) | 922 | (setq file (dir-locals--all-files (car file))) |
| 923 | ;; Otherwise, assume it was set directly. | 923 | ;; Otherwise, assume it was set directly. |
| 924 | (setq file (car file) | 924 | (setq file (car file) |
| 925 | is-directory t))) | 925 | is-directory t))) |
| 926 | (if (null file) | 926 | (if (null file) |
| 927 | (princ ".\n") | 927 | (princ ".\n") |
| 928 | (princ ", set ") | 928 | (princ ", set ") |
| 929 | (let ((files (file-expand-wildcards file))) | 929 | (princ (substitute-command-keys |
| 930 | (princ (substitute-command-keys | 930 | (cond |
| 931 | (cond | 931 | (is-directory "for the directory\n `") |
| 932 | (is-directory "for the directory\n `") | 932 | ;; Many files matched. |
| 933 | ;; Many files matched. | 933 | ((and (consp file) (cdr file)) |
| 934 | ((cdr files) | 934 | (setq file (file-name-directory (car file))) |
| 935 | (setq file (file-name-directory (car files))) | 935 | (format "by one of the\n %s files in the directory\n `" |
| 936 | (format "by a file\n matching `%s' in the directory\n `" | 936 | dir-locals-file)) |
| 937 | dir-locals-file)) | 937 | (t (setq file (car file)) |
| 938 | (t (setq file (car files)) | 938 | "by the file\n `")))) |
| 939 | "by the file\n `")))) | ||
| 940 | (with-current-buffer standard-output | 939 | (with-current-buffer standard-output |
| 941 | (insert-text-button | 940 | (insert-text-button |
| 942 | file 'type 'help-dir-local-var-def | 941 | file 'type 'help-dir-local-var-def |
| 943 | 'help-args (list variable file)))) | 942 | 'help-args (list variable file))) |
| 944 | (princ (substitute-command-keys "'.\n")))) | 943 | (princ (substitute-command-keys "'.\n")))) |
| 945 | (princ (substitute-command-keys | 944 | (princ (substitute-command-keys |
| 946 | " This variable's value is file-local.\n")))) | 945 | " This variable's value is file-local.\n")))) |
diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el index 24ad342d4e0..ae58f1ec7e1 100644 --- a/lisp/international/mule-util.el +++ b/lisp/international/mule-util.el | |||
| @@ -259,7 +259,7 @@ language environment LANG-ENV." | |||
| 259 | (with-coding-priority coding-priority | 259 | (with-coding-priority coding-priority |
| 260 | (detect-coding-region from to))))) | 260 | (detect-coding-region from to))))) |
| 261 | 261 | ||
| 262 | (declare-function internal-char-font "fontset.c" (position &optional ch)) | 262 | (declare-function internal-char-font "font.c" (position &optional ch)) |
| 263 | 263 | ||
| 264 | ;;;###autoload | 264 | ;;;###autoload |
| 265 | (defun char-displayable-p (char) | 265 | (defun char-displayable-p (char) |
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index 05511a84540..5464c38af76 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el | |||
| @@ -694,8 +694,9 @@ Element N specifies the summary line for message N+1.") | |||
| 694 | This is set to nil by default.") | 694 | This is set to nil by default.") |
| 695 | 695 | ||
| 696 | (defcustom rmail-get-coding-function nil | 696 | (defcustom rmail-get-coding-function nil |
| 697 | "Function of no args to try to determine coding system for a message." | 697 | "Function of no args to try to determine coding system for a message. |
| 698 | :type 'function | 698 | If nil, just search for `rmail-mime-charset-pattern'." |
| 699 | :type '(choice (const nil) function) | ||
| 699 | :group 'rmail | 700 | :group 'rmail |
| 700 | :version "24.4") | 701 | :version "24.4") |
| 701 | 702 | ||
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el index c900248c9b6..20029f8e0b5 100644 --- a/lisp/mh-e/mh-e.el +++ b/lisp/mh-e/mh-e.el | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | ;; Author: Bill Wohler <wohler@newt.com> | 6 | ;; Author: Bill Wohler <wohler@newt.com> |
| 7 | ;; Maintainer: Bill Wohler <wohler@newt.com> | 7 | ;; Maintainer: Bill Wohler <wohler@newt.com> |
| 8 | ;; Version: 8.6 | 8 | ;; Version: 8.6+git |
| 9 | ;; Keywords: mail | 9 | ;; Keywords: mail |
| 10 | 10 | ||
| 11 | ;; This file is part of GNU Emacs. | 11 | ;; This file is part of GNU Emacs. |
| @@ -127,7 +127,7 @@ | |||
| 127 | ;; Try to keep variables local to a single file. Provide accessors if | 127 | ;; Try to keep variables local to a single file. Provide accessors if |
| 128 | ;; variables are shared. Use this section as a last resort. | 128 | ;; variables are shared. Use this section as a last resort. |
| 129 | 129 | ||
| 130 | (defconst mh-version "8.6" "Version number of MH-E.") | 130 | (defconst mh-version "8.6+git" "Version number of MH-E.") |
| 131 | 131 | ||
| 132 | ;; Variants | 132 | ;; Variants |
| 133 | 133 | ||
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 26fa0d94b88..2bda97f95d0 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el | |||
| @@ -349,6 +349,7 @@ functionality is not available there." | |||
| 349 | "Whether to open up new windows in a buffer or a new window. | 349 | "Whether to open up new windows in a buffer or a new window. |
| 350 | If non-nil, then open the URL in a new buffer rather than a new window if | 350 | If non-nil, then open the URL in a new buffer rather than a new window if |
| 351 | `browse-url-conkeror' is asked to open it in a new window." | 351 | `browse-url-conkeror' is asked to open it in a new window." |
| 352 | :version "25.1" | ||
| 352 | :type 'boolean | 353 | :type 'boolean |
| 353 | :group 'browse-url) | 354 | :group 'browse-url) |
| 354 | 355 | ||
| @@ -415,6 +416,7 @@ commands reverses the effect of this variable." | |||
| 415 | 416 | ||
| 416 | (defcustom browse-url-conkeror-arguments nil | 417 | (defcustom browse-url-conkeror-arguments nil |
| 417 | "A list of strings to pass to Conkeror as arguments." | 418 | "A list of strings to pass to Conkeror as arguments." |
| 419 | :version "25.1" | ||
| 418 | :type '(repeat (string :tag "Argument")) | 420 | :type '(repeat (string :tag "Argument")) |
| 419 | :group 'browse-url) | 421 | :group 'browse-url) |
| 420 | 422 | ||
diff --git a/lisp/net/newst-reader.el b/lisp/net/newst-reader.el index 1647ef85364..9c29216ccaf 100644 --- a/lisp/net/newst-reader.el +++ b/lisp/net/newst-reader.el | |||
| @@ -69,6 +69,7 @@ This must be one of the functions `newsticker-plainview' or | |||
| 69 | (defcustom newsticker-download-logos | 69 | (defcustom newsticker-download-logos |
| 70 | t | 70 | t |
| 71 | "If non-nil newsticker downloads logo images of subscribed feeds." | 71 | "If non-nil newsticker downloads logo images of subscribed feeds." |
| 72 | :version "25.1" | ||
| 72 | :type 'boolean | 73 | :type 'boolean |
| 73 | :group 'newsticker-reader) | 74 | :group 'newsticker-reader) |
| 74 | 75 | ||
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el index 0e75236154b..4de3d1d1125 100644 --- a/lisp/net/newst-treeview.el +++ b/lisp/net/newst-treeview.el | |||
| @@ -132,9 +132,9 @@ Example: (\"Topmost group\" \"feed1\" (\"subgroup1\" \"feed 2\") | |||
| 132 | 132 | ||
| 133 | (defcustom newsticker-groups-filename | 133 | (defcustom newsticker-groups-filename |
| 134 | nil | 134 | nil |
| 135 | "Name of the newsticker groups settings file. This variable is obsolete." | 135 | "Name of the newsticker groups settings file." |
| 136 | :version "25.1" ; changed default value to nil | 136 | :version "25.1" ; changed default value to nil |
| 137 | :type 'string | 137 | :type '(choice (const nil) string) |
| 138 | :group 'newsticker-treeview) | 138 | :group 'newsticker-treeview) |
| 139 | (make-obsolete-variable 'newsticker-groups-filename 'newsticker-dir "23.1") | 139 | (make-obsolete-variable 'newsticker-groups-filename 'newsticker-dir "23.1") |
| 140 | 140 | ||
diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 2511d673e7e..290a6422bd7 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el | |||
| @@ -1617,7 +1617,9 @@ The preference is a float determined from `shr-prefer-media-type'." | |||
| 1617 | (shr-insert-table (shr-make-table dom sketch-widths t) sketch-widths))) | 1617 | (shr-insert-table (shr-make-table dom sketch-widths t) sketch-widths))) |
| 1618 | 1618 | ||
| 1619 | (defun shr-table-body (dom) | 1619 | (defun shr-table-body (dom) |
| 1620 | (let ((tbodies (dom-by-tag dom 'tbody))) | 1620 | (let ((tbodies (seq-filter (lambda (child) |
| 1621 | (eq (dom-tag child) 'tbody)) | ||
| 1622 | (dom-children dom)))) | ||
| 1621 | (cond | 1623 | (cond |
| 1622 | ((null tbodies) | 1624 | ((null tbodies) |
| 1623 | dom) | 1625 | dom) |
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 7b1aa2a13b0..baebb13dd22 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el | |||
| @@ -284,6 +284,15 @@ The string is used in `tramp-methods'.") | |||
| 284 | (tramp-remote-shell-args ("-c")) | 284 | (tramp-remote-shell-args ("-c")) |
| 285 | (tramp-connection-timeout 10))) | 285 | (tramp-connection-timeout 10))) |
| 286 | ;;;###tramp-autoload | 286 | ;;;###tramp-autoload |
| 287 | (add-to-list | ||
| 288 | 'tramp-methods | ||
| 289 | '("sg" | ||
| 290 | (tramp-login-program "sg") | ||
| 291 | (tramp-login-args (("-") ("%u"))) | ||
| 292 | (tramp-remote-shell "/bin/sh") | ||
| 293 | (tramp-remote-shell-args ("-c")) | ||
| 294 | (tramp-connection-timeout 10))) | ||
| 295 | ;;;###tramp-autoload | ||
| 287 | (add-to-list 'tramp-methods | 296 | (add-to-list 'tramp-methods |
| 288 | '("sudo" | 297 | '("sudo" |
| 289 | (tramp-login-program "sudo") | 298 | (tramp-login-program "sudo") |
| @@ -445,12 +454,17 @@ The string is used in `tramp-methods'.") | |||
| 445 | "Default list of (FUNCTION FILE) pairs to be examined for su methods.") | 454 | "Default list of (FUNCTION FILE) pairs to be examined for su methods.") |
| 446 | 455 | ||
| 447 | ;;;###tramp-autoload | 456 | ;;;###tramp-autoload |
| 457 | (defconst tramp-completion-function-alist-sg | ||
| 458 | '((tramp-parse-etc-group "/etc/group")) | ||
| 459 | "Default list of (FUNCTION FILE) pairs to be examined for sg methods.") | ||
| 460 | |||
| 461 | ;;;###tramp-autoload | ||
| 448 | (defconst tramp-completion-function-alist-putty | 462 | (defconst tramp-completion-function-alist-putty |
| 449 | `((tramp-parse-putty | 463 | `((tramp-parse-putty |
| 450 | ,(if (memq system-type '(windows-nt)) | 464 | ,(if (memq system-type '(windows-nt)) |
| 451 | "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions" | 465 | "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions" |
| 452 | "~/.putty/sessions"))) | 466 | "~/.putty/sessions"))) |
| 453 | "Default list of (FUNCTION REGISTRY) pairs to be examined for putty sessions.") | 467 | "Default list of (FUNCTION REGISTRY) pairs to be examined for putty sessions.") |
| 454 | 468 | ||
| 455 | ;;;###tramp-autoload | 469 | ;;;###tramp-autoload |
| 456 | (eval-after-load 'tramp | 470 | (eval-after-load 'tramp |
| @@ -470,6 +484,7 @@ The string is used in `tramp-methods'.") | |||
| 470 | (tramp-set-completion-function "su" tramp-completion-function-alist-su) | 484 | (tramp-set-completion-function "su" tramp-completion-function-alist-su) |
| 471 | (tramp-set-completion-function "sudo" tramp-completion-function-alist-su) | 485 | (tramp-set-completion-function "sudo" tramp-completion-function-alist-su) |
| 472 | (tramp-set-completion-function "ksu" tramp-completion-function-alist-su) | 486 | (tramp-set-completion-function "ksu" tramp-completion-function-alist-su) |
| 487 | (tramp-set-completion-function "sg" tramp-completion-function-alist-sg) | ||
| 473 | (tramp-set-completion-function | 488 | (tramp-set-completion-function |
| 474 | "krlogin" tramp-completion-function-alist-rsh) | 489 | "krlogin" tramp-completion-function-alist-rsh) |
| 475 | (tramp-set-completion-function "plink" tramp-completion-function-alist-ssh) | 490 | (tramp-set-completion-function "plink" tramp-completion-function-alist-ssh) |
| @@ -5724,5 +5739,7 @@ function cell is returned to be applied on a buffer." | |||
| 5724 | ;; rsync). | 5739 | ;; rsync). |
| 5725 | ;; * Keep a second connection open for out-of-band methods like scp or | 5740 | ;; * Keep a second connection open for out-of-band methods like scp or |
| 5726 | ;; rsync. | 5741 | ;; rsync. |
| 5742 | ;; * Check, whether we could also use "getent passwd" and "getent | ||
| 5743 | ;; group" for user/group name completion. | ||
| 5727 | 5744 | ||
| 5728 | ;;; tramp-sh.el ends here | 5745 | ;;; tramp-sh.el ends here |
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 5c6788082b1..e52f1958592 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el | |||
| @@ -432,6 +432,7 @@ names from FILE for completion. The following predefined FUNCTIONs exists: | |||
| 432 | * `tramp-parse-sknownhosts' for \"~/.ssh2/knownhosts/*\" like files, | 432 | * `tramp-parse-sknownhosts' for \"~/.ssh2/knownhosts/*\" like files, |
| 433 | * `tramp-parse-hosts' for \"/etc/hosts\" like files, | 433 | * `tramp-parse-hosts' for \"/etc/hosts\" like files, |
| 434 | * `tramp-parse-passwd' for \"/etc/passwd\" like files. | 434 | * `tramp-parse-passwd' for \"/etc/passwd\" like files. |
| 435 | * `tramp-parse-etc-group' for \"/etc/group\" like files. | ||
| 435 | * `tramp-parse-netrc' for \"~/.netrc\" like files. | 436 | * `tramp-parse-netrc' for \"~/.netrc\" like files. |
| 436 | * `tramp-parse-putty' for PuTTY registered sessions. | 437 | * `tramp-parse-putty' for PuTTY registered sessions. |
| 437 | 438 | ||
| @@ -509,6 +510,7 @@ This regexp must match both `tramp-initial-end-of-output' and | |||
| 509 | 510 | ||
| 510 | (defcustom tramp-password-prompt-regexp | 511 | (defcustom tramp-password-prompt-regexp |
| 511 | (format "^.*\\(%s\\).*:\^@? *" | 512 | (format "^.*\\(%s\\).*:\^@? *" |
| 513 | ;; `password-word-equivalents' has been introduced with Emacs 24.4. | ||
| 512 | (if (boundp 'password-word-equivalents) | 514 | (if (boundp 'password-word-equivalents) |
| 513 | (regexp-opt (symbol-value 'password-word-equivalents)) | 515 | (regexp-opt (symbol-value 'password-word-equivalents)) |
| 514 | "password\\|passphrase")) | 516 | "password\\|passphrase")) |
| @@ -2645,6 +2647,22 @@ Host is always \"localhost\"." | |||
| 2645 | result)) | 2647 | result)) |
| 2646 | 2648 | ||
| 2647 | ;;;###tramp-autoload | 2649 | ;;;###tramp-autoload |
| 2650 | (defun tramp-parse-etc-group (filename) | ||
| 2651 | "Return a list of (group host) tuples allowed to access. | ||
| 2652 | Host is always \"localhost\"." | ||
| 2653 | (tramp-parse-file filename 'tramp-parse-etc-group-group)) | ||
| 2654 | |||
| 2655 | (defun tramp-parse-etc-group-group () | ||
| 2656 | "Return a (group host) tuple allowed to access. | ||
| 2657 | Host is always \"localhost\"." | ||
| 2658 | (let ((result) | ||
| 2659 | (split (split-string (buffer-substring (point) (point-at-eol)) ":"))) | ||
| 2660 | (when (member (user-login-name) (split-string (nth 3 split) "," 'omit)) | ||
| 2661 | (setq result (list (nth 0 split) "localhost"))) | ||
| 2662 | (forward-line 1) | ||
| 2663 | result)) | ||
| 2664 | |||
| 2665 | ;;;###tramp-autoload | ||
| 2648 | (defun tramp-parse-netrc (filename) | 2666 | (defun tramp-parse-netrc (filename) |
| 2649 | "Return a list of (user host) tuples allowed to access. | 2667 | "Return a list of (user host) tuples allowed to access. |
| 2650 | User may be nil." | 2668 | User may be nil." |
diff --git a/lisp/nxml/nxml-enc.el b/lisp/nxml/nxml-enc.el index bcee0882aa2..6406f57ff63 100644 --- a/lisp/nxml/nxml-enc.el +++ b/lisp/nxml/nxml-enc.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; nxml-enc.el --- XML encoding auto-detection | 1 | ;;; nxml-enc.el --- XML encoding auto-detection -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -68,7 +68,7 @@ | |||
| 68 | (and nxml-non-xml-set-auto-coding-function | 68 | (and nxml-non-xml-set-auto-coding-function |
| 69 | (funcall nxml-non-xml-set-auto-coding-function file-name size)))) | 69 | (funcall nxml-non-xml-set-auto-coding-function file-name size)))) |
| 70 | 70 | ||
| 71 | (defun nxml-set-xml-coding (file-name size) | 71 | (defun nxml-set-xml-coding (_file-name size) |
| 72 | "Function to use as `set-auto-coding-function' when file is known to be XML." | 72 | "Function to use as `set-auto-coding-function' when file is known to be XML." |
| 73 | (nxml-detect-coding-system (+ (point) (min size 1024)))) | 73 | (nxml-detect-coding-system (+ (point) (min size 1024)))) |
| 74 | 74 | ||
diff --git a/lisp/nxml/nxml-glyph.el b/lisp/nxml/nxml-glyph.el deleted file mode 100644 index 4a518218c23..00000000000 --- a/lisp/nxml/nxml-glyph.el +++ /dev/null | |||
| @@ -1,423 +0,0 @@ | |||
| 1 | ;;; nxml-glyph.el --- glyph-handling for nxml-mode | ||
| 2 | |||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: James Clark | ||
| 6 | ;; Keywords: wp, hypermedia, languages, XML | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 13 | ;; (at your option) any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | |||
| 25 | ;; The entry point to this file is `nxml-glyph-display-string'. | ||
| 26 | ;; The current implementation is heuristic due to a lack of | ||
| 27 | ;; Emacs primitives necessary to implement it properly. The user | ||
| 28 | ;; can tweak the heuristics using `nxml-glyph-set-functions'. | ||
| 29 | |||
| 30 | ;;; Code: | ||
| 31 | |||
| 32 | (defconst nxml-ascii-glyph-set | ||
| 33 | [(#x0020 . #x007E)]) | ||
| 34 | |||
| 35 | (defconst nxml-latin1-glyph-set | ||
| 36 | [(#x0020 . #x007E) | ||
| 37 | (#x00A0 . #x00FF)]) | ||
| 38 | |||
| 39 | ;; These were generated by using nxml-insert-target-repertoire-glyph-set | ||
| 40 | ;; on the TARGET[123] files in | ||
| 41 | ;; http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz | ||
| 42 | |||
| 43 | (defconst nxml-misc-fixed-1-glyph-set | ||
| 44 | [(#x0020 . #x007E) | ||
| 45 | (#x00A0 . #x00FF) | ||
| 46 | (#x0100 . #x017F) | ||
| 47 | #x018F #x0192 | ||
| 48 | (#x0218 . #x021B) | ||
| 49 | #x0259 | ||
| 50 | (#x02C6 . #x02C7) | ||
| 51 | (#x02D8 . #x02DD) | ||
| 52 | (#x0374 . #x0375) | ||
| 53 | #x037A #x037E | ||
| 54 | (#x0384 . #x038A) | ||
| 55 | #x038C | ||
| 56 | (#x038E . #x03A1) | ||
| 57 | (#x03A3 . #x03CE) | ||
| 58 | (#x0401 . #x040C) | ||
| 59 | (#x040E . #x044F) | ||
| 60 | (#x0451 . #x045C) | ||
| 61 | (#x045E . #x045F) | ||
| 62 | (#x0490 . #x0491) | ||
| 63 | (#x05D0 . #x05EA) | ||
| 64 | (#x1E02 . #x1E03) | ||
| 65 | (#x1E0A . #x1E0B) | ||
| 66 | (#x1E1E . #x1E1F) | ||
| 67 | (#x1E40 . #x1E41) | ||
| 68 | (#x1E56 . #x1E57) | ||
| 69 | (#x1E60 . #x1E61) | ||
| 70 | (#x1E6A . #x1E6B) | ||
| 71 | (#x1E80 . #x1E85) | ||
| 72 | (#x1EF2 . #x1EF3) | ||
| 73 | (#x2010 . #x2022) | ||
| 74 | #x2026 #x2030 | ||
| 75 | (#x2039 . #x203A) | ||
| 76 | #x20AC #x2116 #x2122 #x2126 | ||
| 77 | (#x215B . #x215E) | ||
| 78 | (#x2190 . #x2193) | ||
| 79 | #x2260 | ||
| 80 | (#x2264 . #x2265) | ||
| 81 | (#x23BA . #x23BD) | ||
| 82 | (#x2409 . #x240D) | ||
| 83 | #x2424 #x2500 #x2502 #x250C #x2510 #x2514 #x2518 #x251C #x2524 #x252C #x2534 #x253C #x2592 #x25C6 #x266A #xFFFD] | ||
| 84 | "Glyph set for TARGET1 glyph repertoire of misc-fixed-* font. | ||
| 85 | This repertoire is supported for the bold and oblique fonts.") | ||
| 86 | |||
| 87 | (defconst nxml-misc-fixed-2-glyph-set | ||
| 88 | [(#x0020 . #x007E) | ||
| 89 | (#x00A0 . #x00FF) | ||
| 90 | (#x0100 . #x017F) | ||
| 91 | #x018F #x0192 | ||
| 92 | (#x01FA . #x01FF) | ||
| 93 | (#x0218 . #x021B) | ||
| 94 | #x0259 | ||
| 95 | (#x02C6 . #x02C7) | ||
| 96 | #x02C9 | ||
| 97 | (#x02D8 . #x02DD) | ||
| 98 | (#x0300 . #x0311) | ||
| 99 | (#x0374 . #x0375) | ||
| 100 | #x037A #x037E | ||
| 101 | (#x0384 . #x038A) | ||
| 102 | #x038C | ||
| 103 | (#x038E . #x03A1) | ||
| 104 | (#x03A3 . #x03CE) | ||
| 105 | #x03D1 | ||
| 106 | (#x03D5 . #x03D6) | ||
| 107 | #x03F1 | ||
| 108 | (#x0401 . #x040C) | ||
| 109 | (#x040E . #x044F) | ||
| 110 | (#x0451 . #x045C) | ||
| 111 | (#x045E . #x045F) | ||
| 112 | (#x0490 . #x0491) | ||
| 113 | (#x05D0 . #x05EA) | ||
| 114 | (#x1E02 . #x1E03) | ||
| 115 | (#x1E0A . #x1E0B) | ||
| 116 | (#x1E1E . #x1E1F) | ||
| 117 | (#x1E40 . #x1E41) | ||
| 118 | (#x1E56 . #x1E57) | ||
| 119 | (#x1E60 . #x1E61) | ||
| 120 | (#x1E6A . #x1E6B) | ||
| 121 | (#x1E80 . #x1E85) | ||
| 122 | (#x1EF2 . #x1EF3) | ||
| 123 | (#x2010 . #x2022) | ||
| 124 | #x2026 #x2030 | ||
| 125 | (#x2032 . #x2034) | ||
| 126 | (#x2039 . #x203A) | ||
| 127 | #x203C #x203E #x2044 | ||
| 128 | (#x2070 . #x2071) | ||
| 129 | (#x2074 . #x208E) | ||
| 130 | (#x20A3 . #x20A4) | ||
| 131 | #x20A7 #x20AC | ||
| 132 | (#x20D0 . #x20D7) | ||
| 133 | #x2102 #x2105 #x2113 | ||
| 134 | (#x2115 . #x2116) | ||
| 135 | #x211A #x211D #x2122 #x2124 #x2126 #x212E | ||
| 136 | (#x215B . #x215E) | ||
| 137 | (#x2190 . #x2195) | ||
| 138 | (#x21A4 . #x21A8) | ||
| 139 | (#x21D0 . #x21D5) | ||
| 140 | (#x2200 . #x2209) | ||
| 141 | (#x220B . #x220C) | ||
| 142 | #x220F | ||
| 143 | (#x2211 . #x2213) | ||
| 144 | #x2215 | ||
| 145 | (#x2218 . #x221A) | ||
| 146 | (#x221D . #x221F) | ||
| 147 | #x2221 | ||
| 148 | (#x2224 . #x222B) | ||
| 149 | #x222E #x223C #x2243 #x2245 | ||
| 150 | (#x2248 . #x2249) | ||
| 151 | #x2259 | ||
| 152 | (#x225F . #x2262) | ||
| 153 | (#x2264 . #x2265) | ||
| 154 | (#x226A . #x226B) | ||
| 155 | (#x2282 . #x228B) | ||
| 156 | #x2295 #x2297 | ||
| 157 | (#x22A4 . #x22A7) | ||
| 158 | (#x22C2 . #x22C3) | ||
| 159 | #x22C5 #x2300 #x2302 | ||
| 160 | (#x2308 . #x230B) | ||
| 161 | #x2310 | ||
| 162 | (#x2320 . #x2321) | ||
| 163 | (#x2329 . #x232A) | ||
| 164 | (#x23BA . #x23BD) | ||
| 165 | (#x2409 . #x240D) | ||
| 166 | #x2424 #x2500 #x2502 #x250C #x2510 #x2514 #x2518 #x251C #x2524 #x252C #x2534 #x253C | ||
| 167 | (#x254C . #x2573) | ||
| 168 | (#x2580 . #x25A1) | ||
| 169 | (#x25AA . #x25AC) | ||
| 170 | (#x25B2 . #x25B3) | ||
| 171 | #x25BA #x25BC #x25C4 #x25C6 | ||
| 172 | (#x25CA . #x25CB) | ||
| 173 | #x25CF | ||
| 174 | (#x25D8 . #x25D9) | ||
| 175 | #x25E6 | ||
| 176 | (#x263A . #x263C) | ||
| 177 | #x2640 #x2642 #x2660 #x2663 | ||
| 178 | (#x2665 . #x2666) | ||
| 179 | (#x266A . #x266B) | ||
| 180 | (#xFB01 . #xFB02) | ||
| 181 | #xFFFD] | ||
| 182 | "Glyph set for TARGET2 glyph repertoire of the misc-fixed-* fonts. | ||
| 183 | This repertoire is supported for the following fonts: | ||
| 184 | 5x7.bdf 5x8.bdf 6x9.bdf 6x10.bdf 6x12.bdf 7x13.bdf 7x14.bdf clR6x12.bdf") | ||
| 185 | |||
| 186 | (defconst nxml-misc-fixed-3-glyph-set | ||
| 187 | [(#x0020 . #x007E) | ||
| 188 | (#x00A0 . #x00FF) | ||
| 189 | (#x0100 . #x01FF) | ||
| 190 | (#x0200 . #x0220) | ||
| 191 | (#x0222 . #x0233) | ||
| 192 | (#x0250 . #x02AD) | ||
| 193 | (#x02B0 . #x02EE) | ||
| 194 | (#x0300 . #x034F) | ||
| 195 | (#x0360 . #x036F) | ||
| 196 | (#x0374 . #x0375) | ||
| 197 | #x037A #x037E | ||
| 198 | (#x0384 . #x038A) | ||
| 199 | #x038C | ||
| 200 | (#x038E . #x03A1) | ||
| 201 | (#x03A3 . #x03CE) | ||
| 202 | (#x03D0 . #x03F6) | ||
| 203 | (#x0400 . #x0486) | ||
| 204 | (#x0488 . #x04CE) | ||
| 205 | (#x04D0 . #x04F5) | ||
| 206 | (#x04F8 . #x04F9) | ||
| 207 | (#x0500 . #x050F) | ||
| 208 | (#x0531 . #x0556) | ||
| 209 | (#x0559 . #x055F) | ||
| 210 | (#x0561 . #x0587) | ||
| 211 | (#x0589 . #x058A) | ||
| 212 | (#x05B0 . #x05B9) | ||
| 213 | (#x05BB . #x05C4) | ||
| 214 | (#x05D0 . #x05EA) | ||
| 215 | (#x05F0 . #x05F4) | ||
| 216 | (#x10D0 . #x10F8) | ||
| 217 | #x10FB | ||
| 218 | (#x1E00 . #x1E9B) | ||
| 219 | (#x1EA0 . #x1EF9) | ||
| 220 | (#x1F00 . #x1F15) | ||
| 221 | (#x1F18 . #x1F1D) | ||
| 222 | (#x1F20 . #x1F45) | ||
| 223 | (#x1F48 . #x1F4D) | ||
| 224 | (#x1F50 . #x1F57) | ||
| 225 | #x1F59 #x1F5B #x1F5D | ||
| 226 | (#x1F5F . #x1F7D) | ||
| 227 | (#x1F80 . #x1FB4) | ||
| 228 | (#x1FB6 . #x1FC4) | ||
| 229 | (#x1FC6 . #x1FD3) | ||
| 230 | (#x1FD6 . #x1FDB) | ||
| 231 | (#x1FDD . #x1FEF) | ||
| 232 | (#x1FF2 . #x1FF4) | ||
| 233 | (#x1FF6 . #x1FFE) | ||
| 234 | (#x2000 . #x200A) | ||
| 235 | (#x2010 . #x2027) | ||
| 236 | (#x202F . #x2052) | ||
| 237 | #x2057 | ||
| 238 | (#x205F . #x2063) | ||
| 239 | (#x2070 . #x2071) | ||
| 240 | (#x2074 . #x208E) | ||
| 241 | (#x20A0 . #x20B1) | ||
| 242 | (#x20D0 . #x20EA) | ||
| 243 | (#x2100 . #x213A) | ||
| 244 | (#x213D . #x214B) | ||
| 245 | (#x2153 . #x2183) | ||
| 246 | (#x2190 . #x21FF) | ||
| 247 | (#x2200 . #x22FF) | ||
| 248 | (#x2300 . #x23CE) | ||
| 249 | (#x2400 . #x2426) | ||
| 250 | (#x2440 . #x244A) | ||
| 251 | (#x2500 . #x25FF) | ||
| 252 | (#x2600 . #x2613) | ||
| 253 | (#x2616 . #x2617) | ||
| 254 | (#x2619 . #x267D) | ||
| 255 | (#x2680 . #x2689) | ||
| 256 | (#x27E6 . #x27EB) | ||
| 257 | (#x27F5 . #x27FF) | ||
| 258 | (#x2A00 . #x2A06) | ||
| 259 | #x2A1D #x2A3F #x303F | ||
| 260 | (#xFB00 . #xFB06) | ||
| 261 | (#xFB13 . #xFB17) | ||
| 262 | (#xFB1D . #xFB36) | ||
| 263 | (#xFB38 . #xFB3C) | ||
| 264 | #xFB3E | ||
| 265 | (#xFB40 . #xFB41) | ||
| 266 | (#xFB43 . #xFB44) | ||
| 267 | (#xFB46 . #xFB4F) | ||
| 268 | (#xFE20 . #xFE23) | ||
| 269 | (#xFF61 . #xFF9F) | ||
| 270 | #xFFFD] | ||
| 271 | "Glyph set for TARGET3 glyph repertoire of the misc-fixed-* fonts. | ||
| 272 | This repertoire is supported for the following fonts: | ||
| 273 | 6x13.bdf 8x13.bdf 9x15.bdf 9x18.bdf 10x20.bdf") | ||
| 274 | |||
| 275 | (defconst nxml-wgl4-glyph-set | ||
| 276 | [(#x0020 . #x007E) | ||
| 277 | (#x00A0 . #x017F) | ||
| 278 | #x0192 | ||
| 279 | (#x01FA . #x01FF) | ||
| 280 | (#x02C6 . #x02C7) | ||
| 281 | #x02C9 | ||
| 282 | (#x02D8 . #x02DB) | ||
| 283 | #x02DD | ||
| 284 | (#x0384 . #x038A) | ||
| 285 | #x038C | ||
| 286 | (#x038E . #x03A1) | ||
| 287 | (#x03A3 . #x03CE) | ||
| 288 | (#x0401 . #x040C) | ||
| 289 | (#x040E . #x044F) | ||
| 290 | (#x0451 . #x045C) | ||
| 291 | (#x045E . #x045F) | ||
| 292 | (#x0490 . #x0491) | ||
| 293 | (#x1E80 . #x1E85) | ||
| 294 | (#x1EF2 . #x1EF3) | ||
| 295 | (#x2013 . #x2015) | ||
| 296 | (#x2017 . #x201E) | ||
| 297 | (#x2020 . #x2022) | ||
| 298 | #x2026 #x2030 | ||
| 299 | (#x2032 . #x2033) | ||
| 300 | (#x2039 . #x203A) | ||
| 301 | #x203C #x203E #x2044 #x207F | ||
| 302 | (#x20A3 . #x20A4) | ||
| 303 | #x20A7 #x20AC #x2105 #x2113 #x2116 #x2122 #x2126 #x212E | ||
| 304 | (#x215B . #x215E) | ||
| 305 | (#x2190 . #x2195) | ||
| 306 | #x21A8 #x2202 #x2206 #x220F | ||
| 307 | (#x2211 . #x2212) | ||
| 308 | #x2215 | ||
| 309 | (#x2219 . #x221A) | ||
| 310 | (#x221E . #x221F) | ||
| 311 | #x2229 #x222B #x2248 | ||
| 312 | (#x2260 . #x2261) | ||
| 313 | (#x2264 . #x2265) | ||
| 314 | #x2302 #x2310 | ||
| 315 | (#x2320 . #x2321) | ||
| 316 | #x2500 #x2502 #x250C #x2510 #x2514 #x2518 #x251C #x2524 | ||
| 317 | #x252C #x2534 #x253C | ||
| 318 | (#x2550 . #x256C) | ||
| 319 | #x2580 #x2584 #x2588 #x258C | ||
| 320 | (#x2590 . #x2593) | ||
| 321 | (#x25A0 . #x25A1) | ||
| 322 | (#x25AA . #x25AC) | ||
| 323 | #x25B2 #x25BA #x25BC #x25C4 | ||
| 324 | (#x25CA . #x25CB) | ||
| 325 | #x25CF | ||
| 326 | (#x25D8 . #x25D9) | ||
| 327 | #x25E6 | ||
| 328 | (#x263A . #x263C) | ||
| 329 | #x2640 #x2642 #x2660 #x2663 | ||
| 330 | (#x2665 . #x2666) | ||
| 331 | (#x266A . #x266B) | ||
| 332 | (#xFB01 . #xFB02)] | ||
| 333 | "Glyph set corresponding to Windows Glyph List 4.") | ||
| 334 | |||
| 335 | (defvar nxml-glyph-set-functions nil | ||
| 336 | "Abnormal hook for determining the set of glyphs in a face. | ||
| 337 | Each function in this hook is called in turn, unless one of them | ||
| 338 | returns non-nil. Each function is called with a single argument | ||
| 339 | FACE. If it can determine the set of glyphs representable by | ||
| 340 | FACE, it must set the variable `nxml-glyph-set' and return | ||
| 341 | non-nil. Otherwise, it must return nil. | ||
| 342 | |||
| 343 | The constants `nxml-ascii-glyph-set', `nxml-latin1-glyph-set', | ||
| 344 | `nxml-misc-fixed-1-glyph-set', `nxml-misc-fixed-2-glyph-set', | ||
| 345 | `nxml-misc-fixed-3-glyph-set' and `nxml-wgl4-glyph-set' are | ||
| 346 | predefined for use by `nxml-glyph-set-functions'.") | ||
| 347 | |||
| 348 | (define-obsolete-variable-alias 'nxml-glyph-set-hook | ||
| 349 | 'nxml-glyph-set-functions "24.3") | ||
| 350 | |||
| 351 | (defvar nxml-glyph-set nil | ||
| 352 | "Used by `nxml-glyph-set-functions' to return set of glyphs in a FACE. | ||
| 353 | This should dynamically bound by any function that runs | ||
| 354 | `nxml-glyph-set-functions'. The value must be either nil representing an | ||
| 355 | empty set or a vector. Each member of the vector is either a single | ||
| 356 | integer or a cons (FIRST . LAST) representing the range of integers | ||
| 357 | from FIRST to LAST. An integer represents a glyph with that Unicode | ||
| 358 | code-point. The vector must be ordered.") | ||
| 359 | |||
| 360 | (defun nxml-x-set-glyph-set (face) | ||
| 361 | (setq nxml-glyph-set | ||
| 362 | (if (equal (face-attribute face :family) "misc-fixed") | ||
| 363 | nxml-misc-fixed-3-glyph-set | ||
| 364 | nxml-wgl4-glyph-set))) | ||
| 365 | |||
| 366 | (defun nxml-w32-set-glyph-set (face) | ||
| 367 | (setq nxml-glyph-set nxml-wgl4-glyph-set)) | ||
| 368 | |||
| 369 | (defun nxml-window-system-set-glyph-set (face) | ||
| 370 | (setq nxml-glyph-set nxml-latin1-glyph-set)) | ||
| 371 | |||
| 372 | (defun nxml-terminal-set-glyph-set (face) | ||
| 373 | (setq nxml-glyph-set nxml-ascii-glyph-set)) | ||
| 374 | |||
| 375 | (add-hook 'nxml-glyph-set-functions | ||
| 376 | (or (cdr (assq window-system | ||
| 377 | '((x . nxml-x-set-glyph-set) | ||
| 378 | (w32 . nxml-w32-set-glyph-set) | ||
| 379 | (nil . nxml-terminal-set-glyph-set)))) | ||
| 380 | 'nxml-window-system-set-glyph-set) | ||
| 381 | t) | ||
| 382 | |||
| 383 | ;;;###autoload | ||
| 384 | (defun nxml-glyph-display-string (n face) | ||
| 385 | "Return a string that can display a glyph for Unicode code-point N. | ||
| 386 | FACE gives the face that will be used for displaying the string. | ||
| 387 | Return nil if the face cannot display a glyph for N." | ||
| 388 | (let ((nxml-glyph-set nil)) | ||
| 389 | (run-hook-with-args-until-success 'nxml-glyph-set-functions face) | ||
| 390 | (and nxml-glyph-set | ||
| 391 | (nxml-glyph-set-contains-p n nxml-glyph-set) | ||
| 392 | (let ((ch (decode-char 'ucs n))) | ||
| 393 | (and ch (string ch)))))) | ||
| 394 | |||
| 395 | (defun nxml-glyph-set-contains-p (n v) | ||
| 396 | (let ((start 0) | ||
| 397 | (end (length v)) | ||
| 398 | found mid mid-val mid-start-val mid-end-val) | ||
| 399 | (while (> end start) | ||
| 400 | (setq mid (+ start | ||
| 401 | (/ (- end start) 2))) | ||
| 402 | (setq mid-val (aref v mid)) | ||
| 403 | (if (consp mid-val) | ||
| 404 | (setq mid-start-val (car mid-val) | ||
| 405 | mid-end-val (cdr mid-val)) | ||
| 406 | (setq mid-start-val mid-val | ||
| 407 | mid-end-val mid-val)) | ||
| 408 | (cond ((and (<= mid-start-val n) | ||
| 409 | (<= n mid-end-val)) | ||
| 410 | (setq found t) | ||
| 411 | (setq start end)) | ||
| 412 | ((< n mid-start-val) | ||
| 413 | (setq end mid)) | ||
| 414 | (t | ||
| 415 | (setq start | ||
| 416 | (if (eq start mid) | ||
| 417 | end | ||
| 418 | mid))))) | ||
| 419 | found)) | ||
| 420 | |||
| 421 | (provide 'nxml-glyph) | ||
| 422 | |||
| 423 | ;;; nxml-glyph.el ends here | ||
diff --git a/lisp/nxml/nxml-maint.el b/lisp/nxml/nxml-maint.el index b81e3113efb..5d24d9b3138 100644 --- a/lisp/nxml/nxml-maint.el +++ b/lisp/nxml/nxml-maint.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; nxml-maint.el --- commands for maintainers of nxml-*.el | 1 | ;;; nxml-maint.el --- commands for maintainers of nxml-*.el -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -24,48 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | ;;; Code: | 25 | ;;; Code: |
| 26 | 26 | ||
| 27 | ;;; Generating files with Unicode char names. | ||
| 28 | |||
| 29 | (require 'nxml-uchnm) | ||
| 30 | |||
| 31 | (defun nxml-create-unicode-char-name-sets (file) | ||
| 32 | "Generate files containing char names from Unicode standard." | ||
| 33 | (interactive "fUnicodeData file: ") | ||
| 34 | (mapc (lambda (block) | ||
| 35 | (let ((nameset (nxml-unicode-block-char-name-set (nth 0 block)))) | ||
| 36 | (save-excursion | ||
| 37 | (find-file (concat (get nameset 'nxml-char-name-set-file) | ||
| 38 | ".el")) | ||
| 39 | (erase-buffer) | ||
| 40 | (insert "(nxml-define-char-name-set '") | ||
| 41 | (prin1 nameset (current-buffer)) | ||
| 42 | (insert "\n '())\n") | ||
| 43 | (goto-char (- (point) 3))))) | ||
| 44 | nxml-unicode-blocks) | ||
| 45 | (save-excursion | ||
| 46 | (find-file file) | ||
| 47 | (goto-char (point-min)) | ||
| 48 | (let ((blocks nxml-unicode-blocks) | ||
| 49 | code name) | ||
| 50 | (while (re-search-forward "^\\([0-9A-F]+\\);\\([^<;][^;]*\\);" | ||
| 51 | nil | ||
| 52 | t) | ||
| 53 | (setq code (string-to-number (match-string 1) 16)) | ||
| 54 | (setq name (match-string 2)) | ||
| 55 | (while (and blocks | ||
| 56 | (> code (nth 2 (car blocks)))) | ||
| 57 | (setq blocks (cdr blocks))) | ||
| 58 | (when (and (<= (nth 1 (car blocks)) code) | ||
| 59 | (<= code (nth 2 (car blocks)))) | ||
| 60 | (save-excursion | ||
| 61 | (find-file (concat (get (nxml-unicode-block-char-name-set | ||
| 62 | (nth 0 (car blocks))) | ||
| 63 | 'nxml-char-name-set-file) | ||
| 64 | ".el")) | ||
| 65 | (insert "(") | ||
| 66 | (prin1 name (current-buffer)) | ||
| 67 | (insert (format " #x%04X)\n " code)))))))) | ||
| 68 | |||
| 69 | ;;; Parsing target repertoire files from ucs-fonts. | 27 | ;;; Parsing target repertoire files from ucs-fonts. |
| 70 | ;; This is for converting the TARGET? files in | 28 | ;; This is for converting the TARGET? files in |
| 71 | ;; http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz | 29 | ;; http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz |
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el index 324350f591c..edc7414bfbf 100644 --- a/lisp/nxml/nxml-mode.el +++ b/lisp/nxml/nxml-mode.el | |||
| @@ -26,14 +26,10 @@ | |||
| 26 | 26 | ||
| 27 | ;;; Code: | 27 | ;;; Code: |
| 28 | 28 | ||
| 29 | (when (featurep 'mucs) | ||
| 30 | (error "nxml-mode is not compatible with Mule-UCS")) | ||
| 31 | |||
| 32 | (eval-when-compile (require 'cl-lib)) | 29 | (eval-when-compile (require 'cl-lib)) |
| 33 | 30 | ||
| 34 | (require 'xmltok) | 31 | (require 'xmltok) |
| 35 | (require 'nxml-enc) | 32 | (require 'nxml-enc) |
| 36 | (require 'nxml-glyph) | ||
| 37 | (require 'nxml-util) | 33 | (require 'nxml-util) |
| 38 | (require 'nxml-rap) | 34 | (require 'nxml-rap) |
| 39 | (require 'nxml-outln) | 35 | (require 'nxml-outln) |
| @@ -41,6 +37,7 @@ | |||
| 41 | ;; So we might as well just require it and silence the compiler. | 37 | ;; So we might as well just require it and silence the compiler. |
| 42 | (provide 'nxml-mode) ; avoid recursive require | 38 | (provide 'nxml-mode) ; avoid recursive require |
| 43 | (require 'rng-nxml) | 39 | (require 'rng-nxml) |
| 40 | (require 'sgml-mode) | ||
| 44 | 41 | ||
| 45 | ;;; Customization | 42 | ;;; Customization |
| 46 | 43 | ||
| @@ -55,9 +52,7 @@ | |||
| 55 | 52 | ||
| 56 | (defcustom nxml-char-ref-display-glyph-flag t | 53 | (defcustom nxml-char-ref-display-glyph-flag t |
| 57 | "Non-nil means display glyph following character reference. | 54 | "Non-nil means display glyph following character reference. |
| 58 | The glyph is displayed in face `nxml-glyph'. The abnormal hook | 55 | The glyph is displayed in face `nxml-glyph'." |
| 59 | `nxml-glyph-set-functions' can be used to change the characters | ||
| 60 | for which glyphs are displayed." | ||
| 61 | :group 'nxml | 56 | :group 'nxml |
| 62 | :type 'boolean) | 57 | :type 'boolean) |
| 63 | 58 | ||
| @@ -153,16 +148,6 @@ This is not used directly, but only via inheritance by other faces." | |||
| 153 | "Face used to highlight text." | 148 | "Face used to highlight text." |
| 154 | :group 'nxml-faces) | 149 | :group 'nxml-faces) |
| 155 | 150 | ||
| 156 | (defface nxml-comment-content | ||
| 157 | '((t (:inherit font-lock-comment-face))) | ||
| 158 | "Face used to highlight the content of comments." | ||
| 159 | :group 'nxml-faces) | ||
| 160 | |||
| 161 | (defface nxml-comment-delimiter | ||
| 162 | '((t (:inherit font-lock-comment-delimiter-face))) | ||
| 163 | "Face used for the delimiters of comments, i.e., <!-- and -->." | ||
| 164 | :group 'nxml-faces) | ||
| 165 | |||
| 166 | (defface nxml-processing-instruction-delimiter | 151 | (defface nxml-processing-instruction-delimiter |
| 167 | '((t (:inherit nxml-delimiter))) | 152 | '((t (:inherit nxml-delimiter))) |
| 168 | "Face used for the delimiters of processing instructions, i.e., <? and ?>." | 153 | "Face used for the delimiters of processing instructions, i.e., <? and ?>." |
| @@ -280,15 +265,6 @@ This includes ths `x' in hex references." | |||
| 280 | "Face used for the delimiters of attribute values." | 265 | "Face used for the delimiters of attribute values." |
| 281 | :group 'nxml-faces) | 266 | :group 'nxml-faces) |
| 282 | 267 | ||
| 283 | (defface nxml-namespace-attribute-value | ||
| 284 | '((t (:inherit nxml-attribute-value))) | ||
| 285 | "Face used for the value of namespace attributes." | ||
| 286 | :group 'nxml-faces) | ||
| 287 | |||
| 288 | (defface nxml-namespace-attribute-value-delimiter | ||
| 289 | '((t (:inherit nxml-attribute-value-delimiter))) | ||
| 290 | "Face used for the delimiters of namespace attribute values." | ||
| 291 | :group 'nxml-faces) | ||
| 292 | 268 | ||
| 293 | (defface nxml-prolog-literal-delimiter | 269 | (defface nxml-prolog-literal-delimiter |
| 294 | '((t (:inherit nxml-delimited-data))) | 270 | '((t (:inherit nxml-delimited-data))) |
| @@ -342,22 +318,19 @@ The delimiters are <! and >." | |||
| 342 | 318 | ||
| 343 | ;;; Global variables | 319 | ;;; Global variables |
| 344 | 320 | ||
| 345 | (defvar nxml-parent-document nil | 321 | (defvar-local nxml-parent-document nil |
| 346 | "The parent document for a part of a modular document. | 322 | "The parent document for a part of a modular document. |
| 347 | Use `nxml-parent-document-set' to set it.") | 323 | Use `nxml-parent-document-set' to set it.") |
| 348 | (make-variable-buffer-local 'nxml-parent-document) | ||
| 349 | (put 'nxml-parent-document 'safe-local-variable 'stringp) | 324 | (put 'nxml-parent-document 'safe-local-variable 'stringp) |
| 350 | 325 | ||
| 351 | (defvar nxml-prolog-regions nil | 326 | (defvar-local nxml-prolog-regions nil |
| 352 | "List of regions in the prolog to be fontified. | 327 | "List of regions in the prolog to be fontified. |
| 353 | See the function `xmltok-forward-prolog' for more information.") | 328 | See the function `xmltok-forward-prolog' for more information.") |
| 354 | (make-variable-buffer-local 'nxml-prolog-regions) | ||
| 355 | 329 | ||
| 356 | (defvar nxml-degraded nil | 330 | (defvar-local nxml-degraded nil |
| 357 | "Non-nil if currently operating in degraded mode. | 331 | "Non-nil if currently operating in degraded mode. |
| 358 | Degraded mode is enabled when an internal error is encountered in the | 332 | Degraded mode is enabled when an internal error is encountered in the |
| 359 | fontification or after-change functions.") | 333 | fontification or after-change functions.") |
| 360 | (make-variable-buffer-local 'nxml-degraded) | ||
| 361 | 334 | ||
| 362 | (defvar nxml-completion-hook nil | 335 | (defvar nxml-completion-hook nil |
| 363 | "Hook run by `nxml-complete'. | 336 | "Hook run by `nxml-complete'. |
| @@ -375,13 +348,12 @@ one of the functions returns nil.") | |||
| 375 | (defvar nxml-end-tag-indent-scan-distance 4000 | 348 | (defvar nxml-end-tag-indent-scan-distance 4000 |
| 376 | "Maximum distance from point to scan backwards when indenting end-tag.") | 349 | "Maximum distance from point to scan backwards when indenting end-tag.") |
| 377 | 350 | ||
| 378 | (defvar nxml-char-ref-extra-display t | 351 | (defvar-local nxml-char-ref-extra-display t |
| 379 | "Non-nil means display extra information for character references. | 352 | "Non-nil means display extra information for character references. |
| 380 | The extra information consists of a tooltip with the character name | 353 | The extra information consists of a tooltip with the character name |
| 381 | and, if `nxml-char-ref-display-glyph-flag' is non-nil, a glyph | 354 | and, if `nxml-char-ref-display-glyph-flag' is non-nil, a glyph |
| 382 | corresponding to the referenced character following the character | 355 | corresponding to the referenced character following the character |
| 383 | reference.") | 356 | reference.") |
| 384 | (make-variable-buffer-local 'nxml-char-ref-extra-display) | ||
| 385 | 357 | ||
| 386 | (defvar nxml-mode-map | 358 | (defvar nxml-mode-map |
| 387 | (let ((map (make-sparse-keymap))) | 359 | (let ((map (make-sparse-keymap))) |
| @@ -415,7 +387,9 @@ reference.") | |||
| 415 | 387 | ||
| 416 | (defsubst nxml-set-face (start end face) | 388 | (defsubst nxml-set-face (start end face) |
| 417 | (when (and face (< start end)) | 389 | (when (and face (< start end)) |
| 418 | (font-lock-append-text-property start end 'face face))) | 390 | ;; Prepend, so the character reference highlighting takes precedence over |
| 391 | ;; the string highlighting applied syntactically. | ||
| 392 | (font-lock-prepend-text-property start end 'face face))) | ||
| 419 | 393 | ||
| 420 | (defun nxml-parent-document-set (parent-document) | 394 | (defun nxml-parent-document-set (parent-document) |
| 421 | "Set `nxml-parent-document' and inherit the DTD &c." | 395 | "Set `nxml-parent-document' and inherit the DTD &c." |
| @@ -519,53 +493,39 @@ Many aspects this mode can be customized using | |||
| 519 | ;; FIXME: Use the fact that we're parsing the document already | 493 | ;; FIXME: Use the fact that we're parsing the document already |
| 520 | ;; rather than using regex-based filtering. | 494 | ;; rather than using regex-based filtering. |
| 521 | (setq-local tildify-foreach-region-function | 495 | (setq-local tildify-foreach-region-function |
| 522 | (apply-partially 'tildify-foreach-ignore-environments | 496 | (apply-partially #'tildify-foreach-ignore-environments |
| 523 | '(("<! *--" . "-- *>") ("<" . ">")))) | 497 | '(("<! *--" . "-- *>") ("<" . ">")))) |
| 524 | (set (make-local-variable 'mode-line-process) '((nxml-degraded "/degraded"))) | 498 | (setq-local mode-line-process '((nxml-degraded "/degraded"))) |
| 525 | ;; We'll determine the fill prefix ourselves | 499 | ;; We'll determine the fill prefix ourselves |
| 526 | (make-local-variable 'adaptive-fill-mode) | 500 | (setq-local adaptive-fill-mode nil) |
| 527 | (setq adaptive-fill-mode nil) | 501 | (setq-local forward-sexp-function #'nxml-forward-balanced-item) |
| 528 | (make-local-variable 'forward-sexp-function) | 502 | (setq-local indent-line-function #'nxml-indent-line) |
| 529 | (setq forward-sexp-function 'nxml-forward-balanced-item) | 503 | (setq-local fill-paragraph-function #'nxml-do-fill-paragraph) |
| 530 | (make-local-variable 'indent-line-function) | ||
| 531 | (setq indent-line-function 'nxml-indent-line) | ||
| 532 | (make-local-variable 'fill-paragraph-function) | ||
| 533 | (setq fill-paragraph-function 'nxml-do-fill-paragraph) | ||
| 534 | ;; Comment support | 504 | ;; Comment support |
| 535 | ;; This doesn't seem to work too well; | 505 | ;; This doesn't seem to work too well; |
| 536 | ;; I think we should probably roll our own nxml-comment-dwim function. | 506 | ;; I think we should probably roll our own nxml-comment-dwim function. |
| 537 | (make-local-variable 'comment-indent-function) | 507 | (setq-local comment-indent-function #'nxml-indent-line) |
| 538 | (setq comment-indent-function 'nxml-indent-line) | 508 | (setq-local comment-start "<!--") |
| 539 | (make-local-variable 'comment-start) | 509 | (setq-local comment-start-skip "<!--[ \t\r\n]*") |
| 540 | (setq comment-start "<!--") | 510 | (setq-local comment-end "-->") |
| 541 | (make-local-variable 'comment-start-skip) | 511 | (setq-local comment-end-skip "[ \t\r\n]*-->") |
| 542 | (setq comment-start-skip "<!--[ \t\r\n]*") | 512 | (setq-local comment-line-break-function #'nxml-newline-and-indent) |
| 543 | (make-local-variable 'comment-end) | 513 | (setq-local comment-quote-nested-function #'nxml-comment-quote-nested) |
| 544 | (setq comment-end "-->") | ||
| 545 | (make-local-variable 'comment-end-skip) | ||
| 546 | (setq comment-end-skip "[ \t\r\n]*-->") | ||
| 547 | (make-local-variable 'comment-line-break-function) | ||
| 548 | (setq comment-line-break-function 'nxml-newline-and-indent) | ||
| 549 | (setq-local comment-quote-nested-function 'nxml-comment-quote-nested) | ||
| 550 | (use-local-map nxml-mode-map) | ||
| 551 | (save-excursion | 514 | (save-excursion |
| 552 | (save-restriction | 515 | (save-restriction |
| 553 | (widen) | 516 | (widen) |
| 554 | (setq nxml-scan-end (copy-marker (point-min) nil)) | ||
| 555 | (with-silent-modifications | 517 | (with-silent-modifications |
| 556 | (nxml-clear-inside (point-min) (point-max)) | ||
| 557 | (nxml-with-invisible-motion | 518 | (nxml-with-invisible-motion |
| 558 | (nxml-scan-prolog))))) | 519 | (nxml-scan-prolog))))) |
| 559 | (add-hook 'completion-at-point-functions | 520 | (setq-local syntax-ppss-table sgml-tag-syntax-table) |
| 560 | #'nxml-completion-at-point-function nil t) | 521 | (setq-local syntax-propertize-function sgml-syntax-propertize-function) |
| 561 | (setq-local syntax-propertize-function #'nxml-after-change) | 522 | (add-hook 'change-major-mode-hook #'nxml-cleanup nil t) |
| 562 | (add-hook 'change-major-mode-hook 'nxml-cleanup nil t) | ||
| 563 | 523 | ||
| 564 | ;; Emacs 23 handles the encoding attribute on the xml declaration | 524 | ;; Emacs 23 handles the encoding attribute on the xml declaration |
| 565 | ;; transparently to nxml-mode, so there is no longer a need for the below | 525 | ;; transparently to nxml-mode, so there is no longer a need for the below |
| 566 | ;; hook. The hook also had the drawback of overriding explicit user | 526 | ;; hook. The hook also had the drawback of overriding explicit user |
| 567 | ;; instruction to save as some encoding other than utf-8. | 527 | ;; instruction to save as some encoding other than utf-8. |
| 568 | ;;(add-hook 'write-contents-hooks 'nxml-prepare-to-save) | 528 | ;;(add-hook 'write-contents-hooks #'nxml-prepare-to-save) |
| 569 | (when (not (and (buffer-file-name) (file-exists-p (buffer-file-name)))) | 529 | (when (not (and (buffer-file-name) (file-exists-p (buffer-file-name)))) |
| 570 | (when (and nxml-default-buffer-file-coding-system | 530 | (when (and nxml-default-buffer-file-coding-system |
| 571 | (not (local-variable-p 'buffer-file-coding-system))) | 531 | (not (local-variable-p 'buffer-file-coding-system))) |
| @@ -575,16 +535,14 @@ Many aspects this mode can be customized using | |||
| 575 | 535 | ||
| 576 | (setq font-lock-defaults | 536 | (setq font-lock-defaults |
| 577 | '(nxml-font-lock-keywords | 537 | '(nxml-font-lock-keywords |
| 578 | t ; keywords-only; we highlight comments and strings here | 538 | nil ; highlight comments and strings based on syntax-tables |
| 579 | nil ; font-lock-keywords-case-fold-search. XML is case sensitive | 539 | nil ; font-lock-keywords-case-fold-search. XML is case sensitive |
| 580 | nil ; no special syntax table | 540 | nil ; no special syntax table |
| 581 | nil ; no automatic syntactic fontification | ||
| 582 | (font-lock-extend-region-functions . (nxml-extend-region)) | 541 | (font-lock-extend-region-functions . (nxml-extend-region)) |
| 583 | (jit-lock-contextually . t) | 542 | (jit-lock-contextually . t) |
| 584 | (font-lock-unfontify-region-function . nxml-unfontify-region))) | 543 | (font-lock-unfontify-region-function . nxml-unfontify-region))) |
| 585 | 544 | ||
| 586 | (rng-nxml-mode-init) | 545 | (with-demoted-errors (rng-nxml-mode-init))) |
| 587 | (nxml-enable-unicode-char-name-sets)) | ||
| 588 | 546 | ||
| 589 | (defun nxml-cleanup () | 547 | (defun nxml-cleanup () |
| 590 | "Clean up after nxml-mode." | 548 | "Clean up after nxml-mode." |
| @@ -596,7 +554,7 @@ Many aspects this mode can be customized using | |||
| 596 | (with-silent-modifications | 554 | (with-silent-modifications |
| 597 | (nxml-with-invisible-motion | 555 | (nxml-with-invisible-motion |
| 598 | (remove-text-properties (point-min) (point-max) '(face))))) | 556 | (remove-text-properties (point-min) (point-max) '(face))))) |
| 599 | (remove-hook 'change-major-mode-hook 'nxml-cleanup t)) | 557 | (remove-hook 'change-major-mode-hook #'nxml-cleanup t)) |
| 600 | 558 | ||
| 601 | (defun nxml-degrade (context err) | 559 | (defun nxml-degrade (context err) |
| 602 | (message "Internal nXML mode error in %s (%s), degrading" | 560 | (message "Internal nXML mode error in %s (%s), degrading" |
| @@ -604,12 +562,7 @@ Many aspects this mode can be customized using | |||
| 604 | (error-message-string err)) | 562 | (error-message-string err)) |
| 605 | (ding) | 563 | (ding) |
| 606 | (setq nxml-degraded t) | 564 | (setq nxml-degraded t) |
| 607 | (setq nxml-prolog-end 1) | 565 | (setq nxml-prolog-end 1)) |
| 608 | (save-excursion | ||
| 609 | (save-restriction | ||
| 610 | (widen) | ||
| 611 | (with-silent-modifications | ||
| 612 | (nxml-clear-inside (point-min) (point-max)))))) | ||
| 613 | 566 | ||
| 614 | ;;; Change management | 567 | ;;; Change management |
| 615 | 568 | ||
| @@ -622,41 +575,6 @@ Many aspects this mode can be customized using | |||
| 622 | (goto-char font-lock-beg) | 575 | (goto-char font-lock-beg) |
| 623 | (set-mark font-lock-end))) | 576 | (set-mark font-lock-end))) |
| 624 | 577 | ||
| 625 | (defun nxml-after-change (start end) | ||
| 626 | ;; Called via syntax-propertize-function. | ||
| 627 | (unless nxml-degraded | ||
| 628 | (nxml-with-degradation-on-error 'nxml-after-change | ||
| 629 | (save-restriction | ||
| 630 | (widen) | ||
| 631 | (nxml-with-invisible-motion | ||
| 632 | (nxml-after-change1 start end)))))) | ||
| 633 | |||
| 634 | (defun nxml-after-change1 (start end) | ||
| 635 | "After-change bookkeeping. | ||
| 636 | Returns a cons cell containing a possibly-enlarged change region. | ||
| 637 | You must call `nxml-extend-region' on this expanded region to obtain | ||
| 638 | the full extent of the area needing refontification. | ||
| 639 | |||
| 640 | For bookkeeping, call this function even when fontification is | ||
| 641 | disabled." | ||
| 642 | ;; If the prolog might have changed, rescan the prolog. | ||
| 643 | (when (<= start | ||
| 644 | ;; Add 2 so as to include the < and following char that | ||
| 645 | ;; start the instance (document element), since changing | ||
| 646 | ;; these can change where the prolog ends. | ||
| 647 | (+ nxml-prolog-end 2)) | ||
| 648 | (nxml-scan-prolog) | ||
| 649 | (setq start (point-min))) | ||
| 650 | |||
| 651 | (when (> end nxml-prolog-end) | ||
| 652 | (goto-char start) | ||
| 653 | (nxml-move-tag-backwards (point-min)) | ||
| 654 | (setq start (point)) | ||
| 655 | (setq end (max (nxml-scan-after-change start end) | ||
| 656 | end))) | ||
| 657 | |||
| 658 | (nxml-debug-change "nxml-after-change1" start end)) | ||
| 659 | |||
| 660 | ;;; Encodings | 578 | ;;; Encodings |
| 661 | 579 | ||
| 662 | (defun nxml-insert-xml-declaration () | 580 | (defun nxml-insert-xml-declaration () |
| @@ -982,11 +900,11 @@ faces appropriately." | |||
| 982 | [1 -1 nxml-entity-ref-name] | 900 | [1 -1 nxml-entity-ref-name] |
| 983 | [-1 nil nxml-entity-ref-delimiter])) | 901 | [-1 nil nxml-entity-ref-delimiter])) |
| 984 | 902 | ||
| 985 | (put 'comment | 903 | ;; (put 'comment |
| 986 | 'nxml-fontify-rule | 904 | ;; 'nxml-fontify-rule |
| 987 | '([nil 4 nxml-comment-delimiter] | 905 | ;; '([nil 4 nxml-comment-delimiter] |
| 988 | [4 -3 nxml-comment-content] | 906 | ;; [4 -3 nxml-comment-content] |
| 989 | [-3 nil nxml-comment-delimiter])) | 907 | ;; [-3 nil nxml-comment-delimiter])) |
| 990 | 908 | ||
| 991 | (put 'processing-instruction | 909 | (put 'processing-instruction |
| 992 | 'nxml-fontify-rule | 910 | 'nxml-fontify-rule |
| @@ -1018,7 +936,7 @@ faces appropriately." | |||
| 1018 | 'nxml-fontify-rule | 936 | 'nxml-fontify-rule |
| 1019 | '([nil nil nxml-attribute-local-name])) | 937 | '([nil nil nxml-attribute-local-name])) |
| 1020 | 938 | ||
| 1021 | (put 'xml-declaration-attribute-value | 939 | (put 'xml-declaration-attribute-value ;FIXME: What is this for? |
| 1022 | 'nxml-fontify-rule | 940 | 'nxml-fontify-rule |
| 1023 | '([nil 1 nxml-attribute-value-delimiter] | 941 | '([nil 1 nxml-attribute-value-delimiter] |
| 1024 | [1 -1 nxml-attribute-value] | 942 | [1 -1 nxml-attribute-value] |
| @@ -1137,28 +1055,11 @@ faces appropriately." | |||
| 1137 | 'nxml-attribute-prefix | 1055 | 'nxml-attribute-prefix |
| 1138 | 'nxml-attribute-colon | 1056 | 'nxml-attribute-colon |
| 1139 | 'nxml-attribute-local-name)) | 1057 | 'nxml-attribute-local-name)) |
| 1140 | (let ((start (xmltok-attribute-value-start att)) | 1058 | (dolist (ref (xmltok-attribute-refs att)) |
| 1141 | (end (xmltok-attribute-value-end att)) | 1059 | (let* ((ref-type (aref ref 0)) |
| 1142 | (refs (xmltok-attribute-refs att)) | 1060 | (ref-start (aref ref 1)) |
| 1143 | (delimiter-face (if namespace-declaration | 1061 | (ref-end (aref ref 2))) |
| 1144 | 'nxml-namespace-attribute-value-delimiter | 1062 | (nxml-apply-fontify-rule ref-type ref-start ref-end)))) |
| 1145 | 'nxml-attribute-value-delimiter)) | ||
| 1146 | (value-face (if namespace-declaration | ||
| 1147 | 'nxml-namespace-attribute-value | ||
| 1148 | 'nxml-attribute-value))) | ||
| 1149 | (when start | ||
| 1150 | (nxml-set-face (1- start) start delimiter-face) | ||
| 1151 | (nxml-set-face end (1+ end) delimiter-face) | ||
| 1152 | (while refs | ||
| 1153 | (let* ((ref (car refs)) | ||
| 1154 | (ref-type (aref ref 0)) | ||
| 1155 | (ref-start (aref ref 1)) | ||
| 1156 | (ref-end (aref ref 2))) | ||
| 1157 | (nxml-set-face start ref-start value-face) | ||
| 1158 | (nxml-apply-fontify-rule ref-type ref-start ref-end) | ||
| 1159 | (setq start ref-end)) | ||
| 1160 | (setq refs (cdr refs))) | ||
| 1161 | (nxml-set-face start end value-face)))) | ||
| 1162 | 1063 | ||
| 1163 | (defun nxml-fontify-qname (start | 1064 | (defun nxml-fontify-qname (start |
| 1164 | colon | 1065 | colon |
| @@ -1599,30 +1500,7 @@ of the line. This expects the xmltok-* variables to be set up as by | |||
| 1599 | (t (back-to-indentation))) | 1500 | (t (back-to-indentation))) |
| 1600 | (current-column)) | 1501 | (current-column)) |
| 1601 | 1502 | ||
| 1602 | ;;; Completion | 1503 | (define-obsolete-function-alias 'nxml-complete #'completion-at-point "26.1") |
| 1603 | |||
| 1604 | (defun nxml-complete () | ||
| 1605 | "Perform completion on the symbol preceding point. | ||
| 1606 | |||
| 1607 | Inserts as many characters as can be completed. However, if not even | ||
| 1608 | one character can be completed, then a buffer with the possibilities | ||
| 1609 | is popped up and the symbol is read from the minibuffer with | ||
| 1610 | completion. If the symbol is complete, then any characters that must | ||
| 1611 | follow the symbol are also inserted. | ||
| 1612 | |||
| 1613 | The name space used for completion and what is treated as a symbol | ||
| 1614 | depends on the context. The contexts in which completion is performed | ||
| 1615 | depend on `nxml-completion-hook'." | ||
| 1616 | (interactive) | ||
| 1617 | (unless (run-hook-with-args-until-success 'nxml-completion-hook) | ||
| 1618 | ;; Eventually we will complete on entity names here. | ||
| 1619 | (ding) | ||
| 1620 | (message "Cannot complete in this context"))) | ||
| 1621 | |||
| 1622 | (defun nxml-completion-at-point-function () | ||
| 1623 | "Call `nxml-complete' to perform completion at point." | ||
| 1624 | (when nxml-bind-meta-tab-to-complete-flag | ||
| 1625 | #'nxml-complete)) | ||
| 1626 | 1504 | ||
| 1627 | ;;; Movement | 1505 | ;;; Movement |
| 1628 | 1506 | ||
| @@ -1674,7 +1552,7 @@ single name. A character reference contains a character number." | |||
| 1674 | (t end))))) | 1552 | (t end))))) |
| 1675 | (nxml-scan-error | 1553 | (nxml-scan-error |
| 1676 | (goto-char (cadr err)) | 1554 | (goto-char (cadr err)) |
| 1677 | (apply 'error (cddr err))))) | 1555 | (apply #'error (cddr err))))) |
| 1678 | 1556 | ||
| 1679 | (defun nxml-backward-single-balanced-item () | 1557 | (defun nxml-backward-single-balanced-item () |
| 1680 | (condition-case err | 1558 | (condition-case err |
| @@ -1696,7 +1574,7 @@ single name. A character reference contains a character number." | |||
| 1696 | (t xmltok-start))))) | 1574 | (t xmltok-start))))) |
| 1697 | (nxml-scan-error | 1575 | (nxml-scan-error |
| 1698 | (goto-char (cadr err)) | 1576 | (goto-char (cadr err)) |
| 1699 | (apply 'error (cddr err))))) | 1577 | (apply #'error (cddr err))))) |
| 1700 | 1578 | ||
| 1701 | (defun nxml-scan-forward-within (end) | 1579 | (defun nxml-scan-forward-within (end) |
| 1702 | (setq end (- end (nxml-end-delimiter-length xmltok-type))) | 1580 | (setq end (- end (nxml-end-delimiter-length xmltok-type))) |
| @@ -1880,7 +1758,7 @@ single name. A character reference contains a character number." | |||
| 1880 | (setq arg (1- arg))) | 1758 | (setq arg (1- arg))) |
| 1881 | (nxml-scan-error | 1759 | (nxml-scan-error |
| 1882 | (goto-char (cadr err)) | 1760 | (goto-char (cadr err)) |
| 1883 | (apply 'error (cddr err)))))) | 1761 | (apply #'error (cddr err)))))) |
| 1884 | 1762 | ||
| 1885 | (defun nxml-backward-up-element (&optional arg) | 1763 | (defun nxml-backward-up-element (&optional arg) |
| 1886 | (interactive "p") | 1764 | (interactive "p") |
| @@ -1909,7 +1787,7 @@ single name. A character reference contains a character number." | |||
| 1909 | (setq arg (1- arg))) | 1787 | (setq arg (1- arg))) |
| 1910 | (nxml-scan-error | 1788 | (nxml-scan-error |
| 1911 | (goto-char (cadr err)) | 1789 | (goto-char (cadr err)) |
| 1912 | (apply 'error (cddr err)))))) | 1790 | (apply #'error (cddr err)))))) |
| 1913 | 1791 | ||
| 1914 | (defun nxml-down-element (&optional arg) | 1792 | (defun nxml-down-element (&optional arg) |
| 1915 | "Move forward down into the content of an element. | 1793 | "Move forward down into the content of an element. |
| @@ -1974,7 +1852,7 @@ Negative ARG means move backward." | |||
| 1974 | (setq arg (1- arg))) | 1852 | (setq arg (1- arg))) |
| 1975 | (nxml-scan-error | 1853 | (nxml-scan-error |
| 1976 | (goto-char (cadr err)) | 1854 | (goto-char (cadr err)) |
| 1977 | (apply 'error (cddr err)))))) | 1855 | (apply #'error (cddr err)))))) |
| 1978 | 1856 | ||
| 1979 | (defun nxml-backward-element (&optional arg) | 1857 | (defun nxml-backward-element (&optional arg) |
| 1980 | "Move backward over one element. | 1858 | "Move backward over one element. |
| @@ -1996,7 +1874,7 @@ Negative ARG means move forward." | |||
| 1996 | (setq arg (1- arg))) | 1874 | (setq arg (1- arg))) |
| 1997 | (nxml-scan-error | 1875 | (nxml-scan-error |
| 1998 | (goto-char (cadr err)) | 1876 | (goto-char (cadr err)) |
| 1999 | (apply 'error (cddr err)))))) | 1877 | (apply #'error (cddr err)))))) |
| 2000 | 1878 | ||
| 2001 | (defun nxml-mark-token-after () | 1879 | (defun nxml-mark-token-after () |
| 2002 | (interactive) | 1880 | (interactive) |
| @@ -2477,116 +2355,15 @@ and attempts to find another possible way to do the markup." | |||
| 2477 | 2355 | ||
| 2478 | ;;; Character names | 2356 | ;;; Character names |
| 2479 | 2357 | ||
| 2480 | (defvar nxml-char-name-ignore-case t) | ||
| 2481 | |||
| 2482 | (defvar nxml-char-name-alist nil | ||
| 2483 | "Alist of character names. | ||
| 2484 | Each member of the list has the form (NAME CODE . NAMESET), | ||
| 2485 | where NAME is a string naming a character, NAMESET is a symbol | ||
| 2486 | identifying a set of names and CODE is an integer specifying the | ||
| 2487 | Unicode scalar value of the named character. | ||
| 2488 | The NAME will only be used for completion if NAMESET has | ||
| 2489 | a non-nil `nxml-char-name-set-enabled' property. | ||
| 2490 | If NAMESET does does not have `nxml-char-name-set-defined' property, | ||
| 2491 | then it must have a `nxml-char-name-set-file' property and `load' | ||
| 2492 | will be applied to the value of this property if the nameset | ||
| 2493 | is enabled.") | ||
| 2494 | |||
| 2495 | (defvar nxml-char-name-table (make-hash-table :test 'eq) | ||
| 2496 | "Hash table for mapping char codes to names. | ||
| 2497 | Each key is a Unicode scalar value. | ||
| 2498 | Each value is a list of pairs of the form (NAMESET . NAME), | ||
| 2499 | where NAMESET is a symbol identifying a set of names, | ||
| 2500 | and NAME is a string naming a character.") | ||
| 2501 | |||
| 2502 | (defvar nxml-autoload-char-name-set-list nil | ||
| 2503 | "List of char namesets that can be autoloaded.") | ||
| 2504 | |||
| 2505 | (defun nxml-enable-char-name-set (nameset) | ||
| 2506 | (put nameset 'nxml-char-name-set-enabled t)) | ||
| 2507 | |||
| 2508 | (defun nxml-disable-char-name-set (nameset) | ||
| 2509 | (put nameset 'nxml-char-name-set-enabled nil)) | ||
| 2510 | |||
| 2511 | (defun nxml-char-name-set-enabled-p (nameset) | ||
| 2512 | (get nameset 'nxml-char-name-set-enabled)) | ||
| 2513 | |||
| 2514 | (defun nxml-autoload-char-name-set (nameset file) | ||
| 2515 | (unless (memq nameset nxml-autoload-char-name-set-list) | ||
| 2516 | (setq nxml-autoload-char-name-set-list | ||
| 2517 | (cons nameset nxml-autoload-char-name-set-list))) | ||
| 2518 | (put nameset 'nxml-char-name-set-file file)) | ||
| 2519 | |||
| 2520 | (defun nxml-define-char-name-set (nameset alist) | ||
| 2521 | "Define a set of character names. | ||
| 2522 | NAMESET is a symbol identifying the set. | ||
| 2523 | ALIST is a list where each member has the form (NAME CODE), | ||
| 2524 | where NAME is a string naming a character and code is an | ||
| 2525 | integer giving the Unicode scalar value of the character." | ||
| 2526 | (when (get nameset 'nxml-char-name-set-defined) | ||
| 2527 | (error "Nameset `%s' already defined" nameset)) | ||
| 2528 | (let ((iter alist)) | ||
| 2529 | (while iter | ||
| 2530 | (let* ((name-code (car iter)) | ||
| 2531 | (name (car name-code)) | ||
| 2532 | (code (cadr name-code))) | ||
| 2533 | (puthash code | ||
| 2534 | (cons (cons nameset name) | ||
| 2535 | (gethash code nxml-char-name-table)) | ||
| 2536 | nxml-char-name-table)) | ||
| 2537 | (setcdr (cdr (car iter)) nameset) | ||
| 2538 | (setq iter (cdr iter)))) | ||
| 2539 | (setq nxml-char-name-alist | ||
| 2540 | (nconc alist nxml-char-name-alist)) | ||
| 2541 | (put nameset 'nxml-char-name-set-defined t)) | ||
| 2542 | |||
| 2543 | (defun nxml-get-char-name (code) | ||
| 2544 | (mapc 'nxml-maybe-load-char-name-set nxml-autoload-char-name-set-list) | ||
| 2545 | (let ((names (gethash code nxml-char-name-table)) | ||
| 2546 | name) | ||
| 2547 | (while (and names (not name)) | ||
| 2548 | (if (nxml-char-name-set-enabled-p (caar names)) | ||
| 2549 | (setq name (cdar names)) | ||
| 2550 | (setq names (cdr names)))) | ||
| 2551 | name)) | ||
| 2552 | |||
| 2553 | (defvar nxml-named-char-history nil) | ||
| 2554 | |||
| 2555 | (defun nxml-insert-named-char (arg) | 2358 | (defun nxml-insert-named-char (arg) |
| 2556 | "Insert a character using its name. | 2359 | "Insert a character using its name. |
| 2557 | The name is read from the minibuffer. | 2360 | The name is read from the minibuffer. |
| 2558 | Normally, inserts the character as a numeric character reference. | 2361 | Normally, inserts the character as a numeric character reference. |
| 2559 | With a prefix argument, inserts the character directly." | 2362 | With a prefix argument, inserts the character directly." |
| 2560 | (interactive "*P") | 2363 | (interactive "*P") |
| 2561 | (mapc 'nxml-maybe-load-char-name-set nxml-autoload-char-name-set-list) | 2364 | (let ((code (read-char-by-name "Character name: "))) |
| 2562 | (let ((name | ||
| 2563 | (let ((completion-ignore-case nxml-char-name-ignore-case)) | ||
| 2564 | (completing-read "Character name: " | ||
| 2565 | nxml-char-name-alist | ||
| 2566 | (lambda (member) | ||
| 2567 | (get (cddr member) 'nxml-char-name-set-enabled)) | ||
| 2568 | t | ||
| 2569 | nil | ||
| 2570 | 'nxml-named-char-history))) | ||
| 2571 | (alist nxml-char-name-alist) | ||
| 2572 | elt code) | ||
| 2573 | (while (and alist (not code)) | ||
| 2574 | (setq elt (assoc name alist)) | ||
| 2575 | (if (get (cddr elt) 'nxml-char-name-set-enabled) | ||
| 2576 | (setq code (cadr elt)) | ||
| 2577 | (setq alist (cdr (member elt alist))))) | ||
| 2578 | (when code | 2365 | (when code |
| 2579 | (insert (if arg | 2366 | (insert (if arg code (format "&#x%X;" code)))))) |
| 2580 | (or (decode-char 'ucs code) | ||
| 2581 | (error "Character %x is not supported by Emacs" | ||
| 2582 | code)) | ||
| 2583 | (format "&#x%X;" code)))))) | ||
| 2584 | |||
| 2585 | (defun nxml-maybe-load-char-name-set (sym) | ||
| 2586 | (when (and (get sym 'nxml-char-name-set-enabled) | ||
| 2587 | (not (get sym 'nxml-char-name-set-defined)) | ||
| 2588 | (stringp (get sym 'nxml-char-name-set-file))) | ||
| 2589 | (load (get sym 'nxml-char-name-set-file)))) | ||
| 2590 | 2367 | ||
| 2591 | (defun nxml-toggle-char-ref-extra-display (arg) | 2368 | (defun nxml-toggle-char-ref-extra-display (arg) |
| 2592 | "Toggle the display of extra information for character references." | 2369 | "Toggle the display of extra information for character references." |
| @@ -2602,9 +2379,11 @@ With a prefix argument, inserts the character directly." | |||
| 2602 | 2379 | ||
| 2603 | (defun nxml-char-ref-display-extra (start end n) | 2380 | (defun nxml-char-ref-display-extra (start end n) |
| 2604 | (when nxml-char-ref-extra-display | 2381 | (when nxml-char-ref-extra-display |
| 2605 | (let ((name (nxml-get-char-name n)) | 2382 | (let ((name (or (get-char-code-property n 'name) |
| 2383 | (get-char-code-property n 'old-name))) | ||
| 2606 | (glyph-string (and nxml-char-ref-display-glyph-flag | 2384 | (glyph-string (and nxml-char-ref-display-glyph-flag |
| 2607 | (nxml-glyph-display-string n 'nxml-glyph))) | 2385 | (char-displayable-p n) |
| 2386 | (string n))) | ||
| 2608 | ov) | 2387 | ov) |
| 2609 | (when (or name glyph-string) | 2388 | (when (or name glyph-string) |
| 2610 | (setq ov (make-overlay start end nil t)) | 2389 | (setq ov (make-overlay start end nil t)) |
diff --git a/lisp/nxml/nxml-outln.el b/lisp/nxml/nxml-outln.el index 962160cb435..289816a1bba 100644 --- a/lisp/nxml/nxml-outln.el +++ b/lisp/nxml/nxml-outln.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; nxml-outln.el --- outline support for nXML mode | 1 | ;;; nxml-outln.el --- outline support for nXML mode -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2004, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2004, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -248,6 +248,16 @@ customize which elements are recognized as sections and headings." | |||
| 248 | (interactive) | 248 | (interactive) |
| 249 | (nxml-transform-subtree-outline '((hide-children . t)))) | 249 | (nxml-transform-subtree-outline '((hide-children . t)))) |
| 250 | 250 | ||
| 251 | ;; These variables are dynamically bound. They are use to pass information to | ||
| 252 | ;; nxml-section-tag-transform-outline-state. | ||
| 253 | |||
| 254 | (defvar nxml-outline-state-transform-exceptions nil) | ||
| 255 | (defvar nxml-target-section-pos nil) | ||
| 256 | (defvar nxml-depth-in-target-section nil) | ||
| 257 | (defvar nxml-outline-state-transform-alist nil) | ||
| 258 | |||
| 259 | (defvar nxml-outline-display-section-tag-function nil) | ||
| 260 | |||
| 251 | (defun nxml-hide-other () | 261 | (defun nxml-hide-other () |
| 252 | "Hide text content other than that directly in the section containing point. | 262 | "Hide text content other than that directly in the section containing point. |
| 253 | Hide headings other than those of ancestors of that section and their | 263 | Hide headings other than those of ancestors of that section and their |
| @@ -275,14 +285,6 @@ customize which elements are recognized as sections and headings." | |||
| 275 | (nxml-transform-buffer-outline '((nil . hide-children) | 285 | (nxml-transform-buffer-outline '((nil . hide-children) |
| 276 | (t . hide-children))))) | 286 | (t . hide-children))))) |
| 277 | 287 | ||
| 278 | ;; These variables are dynamically bound. They are use to pass information to | ||
| 279 | ;; nxml-section-tag-transform-outline-state. | ||
| 280 | |||
| 281 | (defvar nxml-outline-state-transform-exceptions nil) | ||
| 282 | (defvar nxml-target-section-pos nil) | ||
| 283 | (defvar nxml-depth-in-target-section nil) | ||
| 284 | (defvar nxml-outline-state-transform-alist nil) | ||
| 285 | |||
| 286 | (defun nxml-transform-buffer-outline (alist) | 288 | (defun nxml-transform-buffer-outline (alist) |
| 287 | (let ((nxml-target-section-pos nil) | 289 | (let ((nxml-target-section-pos nil) |
| 288 | (nxml-depth-in-target-section 0) | 290 | (nxml-depth-in-target-section 0) |
| @@ -350,7 +352,7 @@ customize which elements are recognized as sections and headings." | |||
| 350 | (defun nxml-section-tag-transform-outline-state (startp | 352 | (defun nxml-section-tag-transform-outline-state (startp |
| 351 | section-start-pos | 353 | section-start-pos |
| 352 | &optional | 354 | &optional |
| 353 | heading-start-pos) | 355 | _heading-start-pos) |
| 354 | (if (not startp) | 356 | (if (not startp) |
| 355 | (setq nxml-depth-in-target-section | 357 | (setq nxml-depth-in-target-section |
| 356 | (and nxml-depth-in-target-section | 358 | (and nxml-depth-in-target-section |
| @@ -427,8 +429,6 @@ customize which elements are recognized as sections and headings." | |||
| 427 | (nxml-outline-error | 429 | (nxml-outline-error |
| 428 | (nxml-report-outline-error "Cannot display outline: %s" err))))) | 430 | (nxml-report-outline-error "Cannot display outline: %s" err))))) |
| 429 | 431 | ||
| 430 | (defvar nxml-outline-display-section-tag-function nil) | ||
| 431 | |||
| 432 | (defun nxml-outline-display-rest (outline-state start-tag-indent tag-qnames) | 432 | (defun nxml-outline-display-rest (outline-state start-tag-indent tag-qnames) |
| 433 | "Display up to and including the end of the current element. | 433 | "Display up to and including the end of the current element. |
| 434 | OUTLINE-STATE can be nil, t, hide-children. START-TAG-INDENT is the | 434 | OUTLINE-STATE can be nil, t, hide-children. START-TAG-INDENT is the |
| @@ -789,7 +789,7 @@ no new overlay will be created." | |||
| 789 | (defun nxml-end-of-heading () | 789 | (defun nxml-end-of-heading () |
| 790 | "Move from the start of the content of the heading to the end. | 790 | "Move from the start of the content of the heading to the end. |
| 791 | Do not move past the end of the line." | 791 | Do not move past the end of the line." |
| 792 | (let ((pos (condition-case err | 792 | (let ((pos (condition-case nil |
| 793 | (and (nxml-scan-element-forward (point) t) | 793 | (and (nxml-scan-element-forward (point) t) |
| 794 | xmltok-start) | 794 | xmltok-start) |
| 795 | (nxml-scan-error nil)))) | 795 | (nxml-scan-error nil)))) |
| @@ -888,7 +888,7 @@ Point is at the end of the tag. `xmltok-start' is the start." | |||
| 888 | (nxml-ensure-scan-up-to-date) | 888 | (nxml-ensure-scan-up-to-date) |
| 889 | (let ((pos (nxml-inside-start (point)))) | 889 | (let ((pos (nxml-inside-start (point)))) |
| 890 | (when pos | 890 | (when pos |
| 891 | (goto-char (1- pos)) | 891 | (goto-char pos) |
| 892 | t)))) | 892 | t)))) |
| 893 | ((progn | 893 | ((progn |
| 894 | (xmltok-forward) | 894 | (xmltok-forward) |
diff --git a/lisp/nxml/nxml-parse.el b/lisp/nxml/nxml-parse.el index 41b2e8ee513..edf012921a9 100644 --- a/lisp/nxml/nxml-parse.el +++ b/lisp/nxml/nxml-parse.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; nxml-parse.el --- XML parser, sharing infrastructure with nxml-mode | 1 | ;;; nxml-parse.el --- XML parser, sharing infrastructure with nxml-mode -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
diff --git a/lisp/nxml/nxml-rap.el b/lisp/nxml/nxml-rap.el index 47b23da62ad..e66289d042a 100644 --- a/lisp/nxml/nxml-rap.el +++ b/lisp/nxml/nxml-rap.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; nxml-rap.el --- low-level support for random access parsing for nXML mode | 1 | ;;; nxml-rap.el --- low-level support for random access parsing for nXML mode -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003-2004, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003-2004, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -46,8 +46,7 @@ | |||
| 46 | ;; look like it scales to large numbers of overlays in a buffer. | 46 | ;; look like it scales to large numbers of overlays in a buffer. |
| 47 | ;; | 47 | ;; |
| 48 | ;; We don't in fact track all these constructs, but only track them in | 48 | ;; We don't in fact track all these constructs, but only track them in |
| 49 | ;; some initial part of the instance. The variable `nxml-scan-end' | 49 | ;; some initial part of the instance. |
| 50 | ;; contains the limit of where we have scanned up to for them. | ||
| 51 | ;; | 50 | ;; |
| 52 | ;; Thus to parse some random point in the file we first ensure that we | 51 | ;; Thus to parse some random point in the file we first ensure that we |
| 53 | ;; have scanned up to that point. Then we search backwards for a | 52 | ;; have scanned up to that point. Then we search backwards for a |
| @@ -74,93 +73,33 @@ | |||
| 74 | 73 | ||
| 75 | (require 'xmltok) | 74 | (require 'xmltok) |
| 76 | (require 'nxml-util) | 75 | (require 'nxml-util) |
| 76 | (require 'sgml-mode) | ||
| 77 | 77 | ||
| 78 | (defvar nxml-prolog-end nil | 78 | (defvar-local nxml-prolog-end nil |
| 79 | "Integer giving position following end of the prolog.") | 79 | "Integer giving position following end of the prolog.") |
| 80 | (make-variable-buffer-local 'nxml-prolog-end) | ||
| 81 | |||
| 82 | (defvar nxml-scan-end nil | ||
| 83 | "Marker giving position up to which we have scanned. | ||
| 84 | nxml-scan-end must be >= nxml-prolog-end. Furthermore, nxml-scan-end | ||
| 85 | must not be an inside position in the following sense. A position is | ||
| 86 | inside if the following character is a part of, but not the first | ||
| 87 | character of, a CDATA section, comment or processing instruction. | ||
| 88 | Furthermore all positions >= nxml-prolog-end and < nxml-scan-end that | ||
| 89 | are inside positions must have a non-nil `nxml-inside' property whose | ||
| 90 | value is a symbol specifying what it is inside. Any characters with a | ||
| 91 | non-nil `fontified' property must have position < nxml-scan-end and | ||
| 92 | the correct face. Dependent regions must also be established for any | ||
| 93 | unclosed constructs starting before nxml-scan-end. | ||
| 94 | There must be no `nxml-inside' properties after nxml-scan-end.") | ||
| 95 | (make-variable-buffer-local 'nxml-scan-end) | ||
| 96 | 80 | ||
| 97 | (defsubst nxml-get-inside (pos) | 81 | (defsubst nxml-get-inside (pos) |
| 98 | (get-text-property pos 'nxml-inside)) | 82 | (save-excursion (nth 8 (syntax-ppss pos)))) |
| 99 | |||
| 100 | (defsubst nxml-clear-inside (start end) | ||
| 101 | (nxml-debug-clear-inside start end) | ||
| 102 | (remove-text-properties start end '(nxml-inside nil))) | ||
| 103 | |||
| 104 | (defsubst nxml-set-inside (start end type) | ||
| 105 | (nxml-debug-set-inside start end) | ||
| 106 | (put-text-property start end 'nxml-inside type)) | ||
| 107 | 83 | ||
| 108 | (defun nxml-inside-end (pos) | 84 | (defun nxml-inside-end (pos) |
| 109 | "Return the end of the inside region containing POS. | 85 | "Return the end of the inside region containing POS. |
| 110 | Return nil if the character at POS is not inside." | 86 | Return nil if the character at POS is not inside." |
| 111 | (if (nxml-get-inside pos) | 87 | (save-excursion |
| 112 | (or (next-single-property-change pos 'nxml-inside) | 88 | (let ((ppss (syntax-ppss pos))) |
| 113 | (point-max)) | 89 | (when (nth 8 ppss) |
| 114 | nil)) | 90 | (goto-char (nth 8 ppss)) |
| 91 | (with-syntax-table sgml-tag-syntax-table | ||
| 92 | (if (nth 3 ppss) | ||
| 93 | (progn (forward-comment 1) (point)) | ||
| 94 | (or (scan-sexps (point) 1) (point-max)))))))) | ||
| 115 | 95 | ||
| 116 | (defun nxml-inside-start (pos) | 96 | (defun nxml-inside-start (pos) |
| 117 | "Return the start of the inside region containing POS. | 97 | "Return the start of the inside region containing POS. |
| 118 | Return nil if the character at POS is not inside." | 98 | Return nil if the character at POS is not inside." |
| 119 | (if (nxml-get-inside pos) | 99 | (save-excursion (nth 8 (syntax-ppss pos)))) |
| 120 | (or (previous-single-property-change (1+ pos) 'nxml-inside) | ||
| 121 | (point-min)) | ||
| 122 | nil)) | ||
| 123 | 100 | ||
| 124 | ;;; Change management | 101 | ;;; Change management |
| 125 | 102 | ||
| 126 | (defun nxml-scan-after-change (start end) | ||
| 127 | "Restore `nxml-scan-end' invariants after a change. | ||
| 128 | The change happened between START and END. | ||
| 129 | Return position after which lexical state is unchanged. | ||
| 130 | END must be > `nxml-prolog-end'. START must be outside | ||
| 131 | any “inside” regions and at the beginning of a token." | ||
| 132 | (if (>= start nxml-scan-end) | ||
| 133 | nxml-scan-end | ||
| 134 | (let ((inside-remove-start start) | ||
| 135 | xmltok-errors) | ||
| 136 | (while (or (when (xmltok-forward-special (min end nxml-scan-end)) | ||
| 137 | (when (memq xmltok-type | ||
| 138 | '(comment | ||
| 139 | cdata-section | ||
| 140 | processing-instruction)) | ||
| 141 | (nxml-clear-inside inside-remove-start | ||
| 142 | (1+ xmltok-start)) | ||
| 143 | (nxml-set-inside (1+ xmltok-start) | ||
| 144 | (point) | ||
| 145 | xmltok-type) | ||
| 146 | (setq inside-remove-start (point))) | ||
| 147 | (if (< (point) (min end nxml-scan-end)) | ||
| 148 | t | ||
| 149 | (setq end (point)) | ||
| 150 | nil)) | ||
| 151 | ;; The end of the change was inside but is now outside. | ||
| 152 | ;; Imagine something really weird like | ||
| 153 | ;; <![CDATA[foo <!-- bar ]]> <![CDATA[ stuff --> <!-- ]]> --> | ||
| 154 | ;; and suppose we deleted "<![CDATA[f" | ||
| 155 | (let ((inside-end (nxml-inside-end end))) | ||
| 156 | (when inside-end | ||
| 157 | (setq end inside-end) | ||
| 158 | t)))) | ||
| 159 | (nxml-clear-inside inside-remove-start end)) | ||
| 160 | (when (> end nxml-scan-end) | ||
| 161 | (set-marker nxml-scan-end end)) | ||
| 162 | end)) | ||
| 163 | |||
| 164 | ;; n-s-p only called from nxml-mode.el, where this variable is defined. | 103 | ;; n-s-p only called from nxml-mode.el, where this variable is defined. |
| 165 | (defvar nxml-prolog-regions) | 104 | (defvar nxml-prolog-regions) |
| 166 | 105 | ||
| @@ -169,10 +108,7 @@ any “inside” regions and at the beginning of a token." | |||
| 169 | (let (xmltok-dtd | 108 | (let (xmltok-dtd |
| 170 | xmltok-errors) | 109 | xmltok-errors) |
| 171 | (setq nxml-prolog-regions (xmltok-forward-prolog)) | 110 | (setq nxml-prolog-regions (xmltok-forward-prolog)) |
| 172 | (setq nxml-prolog-end (point)) | 111 | (setq nxml-prolog-end (point)))) |
| 173 | (nxml-clear-inside (point-min) nxml-prolog-end)) | ||
| 174 | (when (< nxml-scan-end nxml-prolog-end) | ||
| 175 | (set-marker nxml-scan-end nxml-prolog-end))) | ||
| 176 | 112 | ||
| 177 | 113 | ||
| 178 | ;;; Random access parsing | 114 | ;;; Random access parsing |
| @@ -223,14 +159,7 @@ Sets variables like `nxml-token-after'." | |||
| 223 | 159 | ||
| 224 | (defun nxml-tokenize-forward () | 160 | (defun nxml-tokenize-forward () |
| 225 | (let (xmltok-errors) | 161 | (let (xmltok-errors) |
| 226 | (when (and (xmltok-forward) | 162 | (xmltok-forward) |
| 227 | (> (point) nxml-scan-end)) | ||
| 228 | (cond ((memq xmltok-type '(comment | ||
| 229 | cdata-section | ||
| 230 | processing-instruction)) | ||
| 231 | (with-silent-modifications | ||
| 232 | (nxml-set-inside (1+ xmltok-start) (point) xmltok-type)))) | ||
| 233 | (set-marker nxml-scan-end (point))) | ||
| 234 | xmltok-type)) | 163 | xmltok-type)) |
| 235 | 164 | ||
| 236 | (defun nxml-move-tag-backwards (bound) | 165 | (defun nxml-move-tag-backwards (bound) |
| @@ -253,32 +182,12 @@ As a precondition, point must be >= BOUND." | |||
| 253 | Leave point unmoved if it is not inside anything special." | 182 | Leave point unmoved if it is not inside anything special." |
| 254 | (let ((start (nxml-inside-start (point)))) | 183 | (let ((start (nxml-inside-start (point)))) |
| 255 | (when start | 184 | (when start |
| 256 | (goto-char (1- start)) | 185 | (goto-char start) |
| 257 | (when (nxml-get-inside (point)) | 186 | (when (nxml-get-inside (point)) |
| 258 | (error "Char before inside-start at %s had nxml-inside property %s" | 187 | (error "Char before inside-start at %s is still \"inside\"" (point)))))) |
| 259 | (point) | ||
| 260 | (nxml-get-inside (point))))))) | ||
| 261 | 188 | ||
| 262 | (defun nxml-ensure-scan-up-to-date () | 189 | (defun nxml-ensure-scan-up-to-date () |
| 263 | (let ((pos (point))) | 190 | (syntax-propertize (point))) |
| 264 | (when (< nxml-scan-end pos) | ||
| 265 | (save-excursion | ||
| 266 | (goto-char nxml-scan-end) | ||
| 267 | (let (xmltok-errors) | ||
| 268 | (while (when (xmltok-forward-special pos) | ||
| 269 | (when (memq xmltok-type | ||
| 270 | '(comment | ||
| 271 | processing-instruction | ||
| 272 | cdata-section)) | ||
| 273 | (with-silent-modifications | ||
| 274 | (nxml-set-inside (1+ xmltok-start) | ||
| 275 | (point) | ||
| 276 | xmltok-type))) | ||
| 277 | (if (< (point) pos) | ||
| 278 | t | ||
| 279 | (setq pos (point)) | ||
| 280 | nil))) | ||
| 281 | (set-marker nxml-scan-end pos)))))) | ||
| 282 | 191 | ||
| 283 | ;;; Element scanning | 192 | ;;; Element scanning |
| 284 | 193 | ||
diff --git a/lisp/nxml/nxml-uchnm.el b/lisp/nxml/nxml-uchnm.el deleted file mode 100644 index 7d7d785f152..00000000000 --- a/lisp/nxml/nxml-uchnm.el +++ /dev/null | |||
| @@ -1,251 +0,0 @@ | |||
| 1 | ;;; nxml-uchnm.el --- support for Unicode standard cha names in nxml-mode | ||
| 2 | |||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: James Clark | ||
| 6 | ;; Keywords: wp, hypermedia, languages, XML | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 13 | ;; (at your option) any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | |||
| 25 | ;; This enables the use of the character names defined in the Unicode | ||
| 26 | ;; Standard. The use of the names can be controlled on a per-block | ||
| 27 | ;; basis, so as both to reduce memory usage and loading time, | ||
| 28 | ;; and to make completion work better. | ||
| 29 | |||
| 30 | ;;; Code: | ||
| 31 | |||
| 32 | (require 'nxml-mode) | ||
| 33 | |||
| 34 | (defconst nxml-unicode-blocks | ||
| 35 | '(("Basic Latin" #x0000 #x007F) | ||
| 36 | ("Latin-1 Supplement" #x0080 #x00FF) | ||
| 37 | ("Latin Extended-A" #x0100 #x017F) | ||
| 38 | ("Latin Extended-B" #x0180 #x024F) | ||
| 39 | ("IPA Extensions" #x0250 #x02AF) | ||
| 40 | ("Spacing Modifier Letters" #x02B0 #x02FF) | ||
| 41 | ("Combining Diacritical Marks" #x0300 #x036F) | ||
| 42 | ("Greek and Coptic" #x0370 #x03FF) | ||
| 43 | ("Cyrillic" #x0400 #x04FF) | ||
| 44 | ("Cyrillic Supplementary" #x0500 #x052F) | ||
| 45 | ("Armenian" #x0530 #x058F) | ||
| 46 | ("Hebrew" #x0590 #x05FF) | ||
| 47 | ("Arabic" #x0600 #x06FF) | ||
| 48 | ("Syriac" #x0700 #x074F) | ||
| 49 | ("Thaana" #x0780 #x07BF) | ||
| 50 | ("Devanagari" #x0900 #x097F) | ||
| 51 | ("Bengali" #x0980 #x09FF) | ||
| 52 | ("Gurmukhi" #x0A00 #x0A7F) | ||
| 53 | ("Gujarati" #x0A80 #x0AFF) | ||
| 54 | ("Oriya" #x0B00 #x0B7F) | ||
| 55 | ("Tamil" #x0B80 #x0BFF) | ||
| 56 | ("Telugu" #x0C00 #x0C7F) | ||
| 57 | ("Kannada" #x0C80 #x0CFF) | ||
| 58 | ("Malayalam" #x0D00 #x0D7F) | ||
| 59 | ("Sinhala" #x0D80 #x0DFF) | ||
| 60 | ("Thai" #x0E00 #x0E7F) | ||
| 61 | ("Lao" #x0E80 #x0EFF) | ||
| 62 | ("Tibetan" #x0F00 #x0FFF) | ||
| 63 | ("Myanmar" #x1000 #x109F) | ||
| 64 | ("Georgian" #x10A0 #x10FF) | ||
| 65 | ("Hangul Jamo" #x1100 #x11FF) | ||
| 66 | ("Ethiopic" #x1200 #x137F) | ||
| 67 | ("Cherokee" #x13A0 #x13FF) | ||
| 68 | ("Unified Canadian Aboriginal Syllabics" #x1400 #x167F) | ||
| 69 | ("Ogham" #x1680 #x169F) | ||
| 70 | ("Runic" #x16A0 #x16FF) | ||
| 71 | ("Tagalog" #x1700 #x171F) | ||
| 72 | ("Hanunoo" #x1720 #x173F) | ||
| 73 | ("Buhid" #x1740 #x175F) | ||
| 74 | ("Tagbanwa" #x1760 #x177F) | ||
| 75 | ("Khmer" #x1780 #x17FF) | ||
| 76 | ("Mongolian" #x1800 #x18AF) | ||
| 77 | ("Latin Extended Additional" #x1E00 #x1EFF) | ||
| 78 | ("Greek Extended" #x1F00 #x1FFF) | ||
| 79 | ("General Punctuation" #x2000 #x206F) | ||
| 80 | ("Superscripts and Subscripts" #x2070 #x209F) | ||
| 81 | ("Currency Symbols" #x20A0 #x20CF) | ||
| 82 | ("Combining Diacritical Marks for Symbols" #x20D0 #x20FF) | ||
| 83 | ("Letterlike Symbols" #x2100 #x214F) | ||
| 84 | ("Number Forms" #x2150 #x218F) | ||
| 85 | ("Arrows" #x2190 #x21FF) | ||
| 86 | ("Mathematical Operators" #x2200 #x22FF) | ||
| 87 | ("Miscellaneous Technical" #x2300 #x23FF) | ||
| 88 | ("Control Pictures" #x2400 #x243F) | ||
| 89 | ("Optical Character Recognition" #x2440 #x245F) | ||
| 90 | ("Enclosed Alphanumerics" #x2460 #x24FF) | ||
| 91 | ("Box Drawing" #x2500 #x257F) | ||
| 92 | ("Block Elements" #x2580 #x259F) | ||
| 93 | ("Geometric Shapes" #x25A0 #x25FF) | ||
| 94 | ("Miscellaneous Symbols" #x2600 #x26FF) | ||
| 95 | ("Dingbats" #x2700 #x27BF) | ||
| 96 | ("Miscellaneous Mathematical Symbols-A" #x27C0 #x27EF) | ||
| 97 | ("Supplemental Arrows-A" #x27F0 #x27FF) | ||
| 98 | ("Braille Patterns" #x2800 #x28FF) | ||
| 99 | ("Supplemental Arrows-B" #x2900 #x297F) | ||
| 100 | ("Miscellaneous Mathematical Symbols-B" #x2980 #x29FF) | ||
| 101 | ("Supplemental Mathematical Operators" #x2A00 #x2AFF) | ||
| 102 | ("CJK Radicals Supplement" #x2E80 #x2EFF) | ||
| 103 | ("Kangxi Radicals" #x2F00 #x2FDF) | ||
| 104 | ("Ideographic Description Characters" #x2FF0 #x2FFF) | ||
| 105 | ("CJK Symbols and Punctuation" #x3000 #x303F) | ||
| 106 | ("Hiragana" #x3040 #x309F) | ||
| 107 | ("Katakana" #x30A0 #x30FF) | ||
| 108 | ("Bopomofo" #x3100 #x312F) | ||
| 109 | ("Hangul Compatibility Jamo" #x3130 #x318F) | ||
| 110 | ("Kanbun" #x3190 #x319F) | ||
| 111 | ("Bopomofo Extended" #x31A0 #x31BF) | ||
| 112 | ("Katakana Phonetic Extensions" #x31F0 #x31FF) | ||
| 113 | ("Enclosed CJK Letters and Months" #x3200 #x32FF) | ||
| 114 | ("CJK Compatibility" #x3300 #x33FF) | ||
| 115 | ("CJK Unified Ideographs Extension A" #x3400 #x4DBF) | ||
| 116 | ;;("CJK Unified Ideographs" #x4E00 #x9FFF) | ||
| 117 | ("Yi Syllables" #xA000 #xA48F) | ||
| 118 | ("Yi Radicals" #xA490 #xA4CF) | ||
| 119 | ;;("Hangul Syllables" #xAC00 #xD7AF) | ||
| 120 | ;;("High Surrogates" #xD800 #xDB7F) | ||
| 121 | ;;("High Private Use Surrogates" #xDB80 #xDBFF) | ||
| 122 | ;;("Low Surrogates" #xDC00 #xDFFF) | ||
| 123 | ;;("Private Use Area" #xE000 #xF8FF) | ||
| 124 | ;;("CJK Compatibility Ideographs" #xF900 #xFAFF) | ||
| 125 | ("Alphabetic Presentation Forms" #xFB00 #xFB4F) | ||
| 126 | ("Arabic Presentation Forms-A" #xFB50 #xFDFF) | ||
| 127 | ("Variation Selectors" #xFE00 #xFE0F) | ||
| 128 | ("Combining Half Marks" #xFE20 #xFE2F) | ||
| 129 | ("CJK Compatibility Forms" #xFE30 #xFE4F) | ||
| 130 | ("Small Form Variants" #xFE50 #xFE6F) | ||
| 131 | ("Arabic Presentation Forms-B" #xFE70 #xFEFF) | ||
| 132 | ("Halfwidth and Fullwidth Forms" #xFF00 #xFFEF) | ||
| 133 | ("Specials" #xFFF0 #xFFFF) | ||
| 134 | ("Old Italic" #x10300 #x1032F) | ||
| 135 | ("Gothic" #x10330 #x1034F) | ||
| 136 | ("Deseret" #x10400 #x1044F) | ||
| 137 | ("Byzantine Musical Symbols" #x1D000 #x1D0FF) | ||
| 138 | ("Musical Symbols" #x1D100 #x1D1FF) | ||
| 139 | ("Mathematical Alphanumeric Symbols" #x1D400 #x1D7FF) | ||
| 140 | ;;("CJK Unified Ideographs Extension B" #x20000 #x2A6DF) | ||
| 141 | ;;("CJK Compatibility Ideographs Supplement" #x2F800 #x2FA1F) | ||
| 142 | ("Tags" #xE0000 #xE007F) | ||
| 143 | ;;("Supplementary Private Use Area-A" #xF0000 #xFFFFF) | ||
| 144 | ;;("Supplementary Private Use Area-B" #x100000 #x10FFFF) | ||
| 145 | ) | ||
| 146 | "List of Unicode blocks. | ||
| 147 | For each block there is a list (NAME FIRST LAST), where | ||
| 148 | NAME is a string giving the official name of the block, | ||
| 149 | FIRST is the first code-point and LAST is the last code-point. | ||
| 150 | Blocks containing only characters with algorithmic names or no names | ||
| 151 | are omitted.") | ||
| 152 | |||
| 153 | (defun nxml-unicode-block-char-name-set (name) | ||
| 154 | "Return a symbol for a block whose official Unicode name is NAME. | ||
| 155 | The symbol is generated by downcasing and replacing each space | ||
| 156 | by a hyphen." | ||
| 157 | (intern (replace-regexp-in-string " " "-" (downcase name)))) | ||
| 158 | |||
| 159 | ;; This is intended to be a superset of the coverage | ||
| 160 | ;; of existing standard entity sets. | ||
| 161 | (defvar nxml-enabled-unicode-blocks-default | ||
| 162 | '(basic-latin | ||
| 163 | latin-1-supplement | ||
| 164 | latin-extended-a | ||
| 165 | latin-extended-b | ||
| 166 | ipa-extensions | ||
| 167 | spacing-modifier-letters | ||
| 168 | combining-diacritical-marks | ||
| 169 | greek-and-coptic | ||
| 170 | cyrillic | ||
| 171 | general-punctuation | ||
| 172 | superscripts-and-subscripts | ||
| 173 | currency-symbols | ||
| 174 | combining-diacritical-marks-for-symbols | ||
| 175 | letterlike-symbols | ||
| 176 | number-forms | ||
| 177 | arrows | ||
| 178 | mathematical-operators | ||
| 179 | miscellaneous-technical | ||
| 180 | control-pictures | ||
| 181 | optical-character-recognition | ||
| 182 | enclosed-alphanumerics | ||
| 183 | box-drawing | ||
| 184 | block-elements | ||
| 185 | geometric-shapes | ||
| 186 | miscellaneous-symbols | ||
| 187 | dingbats | ||
| 188 | miscellaneous-mathematical-symbols-a | ||
| 189 | supplemental-arrows-a | ||
| 190 | supplemental-arrows-b | ||
| 191 | miscellaneous-mathematical-symbols-b | ||
| 192 | supplemental-mathematical-operators | ||
| 193 | cjk-symbols-and-punctuation | ||
| 194 | alphabetic-presentation-forms | ||
| 195 | variation-selectors | ||
| 196 | small-form-variants | ||
| 197 | specials | ||
| 198 | mathematical-alphanumeric-symbols) | ||
| 199 | "Default value for `nxml-enabled-unicode-blocks'.") | ||
| 200 | |||
| 201 | (mapc (lambda (block) | ||
| 202 | (nxml-autoload-char-name-set | ||
| 203 | (nxml-unicode-block-char-name-set (car block)) | ||
| 204 | (expand-file-name | ||
| 205 | (format "nxml/%05X-%05X" | ||
| 206 | (nth 1 block) | ||
| 207 | (nth 2 block)) | ||
| 208 | data-directory))) | ||
| 209 | nxml-unicode-blocks) | ||
| 210 | |||
| 211 | ;; Internal flag to control whether customize reloads the character tables. | ||
| 212 | ;; Should be set the first time the | ||
| 213 | (defvar nxml-internal-unicode-char-name-sets-enabled nil) | ||
| 214 | |||
| 215 | (defcustom nxml-enabled-unicode-blocks nxml-enabled-unicode-blocks-default | ||
| 216 | "List of Unicode blocks for which Unicode character names are enabled. | ||
| 217 | Each block is identified by a symbol derived from the name | ||
| 218 | of the block by downcasing and replacing each space by a hyphen." | ||
| 219 | :group 'nxml | ||
| 220 | :set (lambda (sym value) | ||
| 221 | (set-default 'nxml-enabled-unicode-blocks value) | ||
| 222 | (when nxml-internal-unicode-char-name-sets-enabled | ||
| 223 | (nxml-enable-unicode-char-name-sets))) | ||
| 224 | :type (cons 'set | ||
| 225 | (mapcar (lambda (block) | ||
| 226 | `(const :tag ,(format "%s (%04X-%04X)" | ||
| 227 | (nth 0 block) | ||
| 228 | (nth 1 block) | ||
| 229 | (nth 2 block)) | ||
| 230 | ,(nxml-unicode-block-char-name-set | ||
| 231 | (nth 0 block)))) | ||
| 232 | nxml-unicode-blocks))) | ||
| 233 | |||
| 234 | ;;;###autoload | ||
| 235 | (defun nxml-enable-unicode-char-name-sets () | ||
| 236 | "Enable the use of Unicode standard names for characters. | ||
| 237 | The Unicode blocks for which names are enabled is controlled by | ||
| 238 | the variable `nxml-enabled-unicode-blocks'." | ||
| 239 | (interactive) | ||
| 240 | (setq nxml-internal-unicode-char-name-sets-enabled t) | ||
| 241 | (mapc (lambda (block) | ||
| 242 | (nxml-disable-char-name-set | ||
| 243 | (nxml-unicode-block-char-name-set (car block)))) | ||
| 244 | nxml-unicode-blocks) | ||
| 245 | (mapc (lambda (nameset) | ||
| 246 | (nxml-enable-char-name-set nameset)) | ||
| 247 | nxml-enabled-unicode-blocks)) | ||
| 248 | |||
| 249 | (provide 'nxml-uchnm) | ||
| 250 | |||
| 251 | ;;; nxml-uchnm.el ends here | ||
diff --git a/lisp/nxml/nxml-util.el b/lisp/nxml/nxml-util.el index 14b887ea085..282d4952bf7 100644 --- a/lisp/nxml/nxml-util.el +++ b/lisp/nxml/nxml-util.el | |||
| @@ -36,20 +36,6 @@ | |||
| 36 | `(nxml-debug "%s: %S" ,name | 36 | `(nxml-debug "%s: %S" ,name |
| 37 | (buffer-substring-no-properties ,start ,end)))) | 37 | (buffer-substring-no-properties ,start ,end)))) |
| 38 | 38 | ||
| 39 | (defmacro nxml-debug-set-inside (start end) | ||
| 40 | (when nxml-debug | ||
| 41 | `(let ((overlay (make-overlay ,start ,end))) | ||
| 42 | (overlay-put overlay 'face '(:background "red")) | ||
| 43 | (overlay-put overlay 'nxml-inside-debug t) | ||
| 44 | (nxml-debug-change "nxml-set-inside" ,start ,end)))) | ||
| 45 | |||
| 46 | (defmacro nxml-debug-clear-inside (start end) | ||
| 47 | (when nxml-debug | ||
| 48 | `(cl-loop for overlay in (overlays-in ,start ,end) | ||
| 49 | if (overlay-get overlay 'nxml-inside-debug) | ||
| 50 | do (delete-overlay overlay) | ||
| 51 | finally (nxml-debug-change "nxml-clear-inside" ,start ,end)))) | ||
| 52 | |||
| 53 | (defun nxml-make-namespace (str) | 39 | (defun nxml-make-namespace (str) |
| 54 | "Return a symbol for the namespace URI STR. | 40 | "Return a symbol for the namespace URI STR. |
| 55 | STR must be a string. If STR is the empty string, return nil. | 41 | STR must be a string. If STR is the empty string, return nil. |
diff --git a/lisp/nxml/rng-cmpct.el b/lisp/nxml/rng-cmpct.el index 39aee9780ff..a699e9e3d96 100644 --- a/lisp/nxml/rng-cmpct.el +++ b/lisp/nxml/rng-cmpct.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-cmpct.el --- parsing of RELAX NG Compact Syntax schemas | 1 | ;;; rng-cmpct.el --- parsing of RELAX NG Compact Syntax schemas -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
diff --git a/lisp/nxml/rng-dt.el b/lisp/nxml/rng-dt.el index 07166e38fea..a3cb8bc6aa5 100644 --- a/lisp/nxml/rng-dt.el +++ b/lisp/nxml/rng-dt.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-dt.el --- datatype library interface for RELAX NG | 1 | ;;; rng-dt.el --- datatype library interface for RELAX NG -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -57,7 +57,7 @@ a datatype library.") | |||
| 57 | (t | 57 | (t |
| 58 | (rng-dt-error "There is no built-in datatype %s" name)))) | 58 | (rng-dt-error "There is no built-in datatype %s" name)))) |
| 59 | 59 | ||
| 60 | (put (rng-make-datatypes-uri "") 'rng-dt-compile 'rng-dt-builtin-compile) | 60 | (put (rng-make-datatypes-uri "") 'rng-dt-compile #'rng-dt-builtin-compile) |
| 61 | 61 | ||
| 62 | (provide 'rng-dt) | 62 | (provide 'rng-dt) |
| 63 | 63 | ||
diff --git a/lisp/nxml/rng-loc.el b/lisp/nxml/rng-loc.el index 553d8ca359d..376e9169d37 100644 --- a/lisp/nxml/rng-loc.el +++ b/lisp/nxml/rng-loc.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-loc.el --- locate the schema to use for validation | 1 | ;;; rng-loc.el --- Locate the schema to use for validation -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -31,10 +31,9 @@ | |||
| 31 | (require 'rng-util) | 31 | (require 'rng-util) |
| 32 | (require 'xmltok) | 32 | (require 'xmltok) |
| 33 | 33 | ||
| 34 | (defvar rng-current-schema-file-name nil | 34 | (defvar-local rng-current-schema-file-name nil |
| 35 | "Filename of schema being used for current buffer. | 35 | "Filename of schema being used for current buffer. |
| 36 | It is nil if using a vacuous schema.") | 36 | It is nil if using a vacuous schema.") |
| 37 | (make-variable-buffer-local 'rng-current-schema-file-name) | ||
| 38 | 37 | ||
| 39 | (defvar rng-schema-locating-files-default | 38 | (defvar rng-schema-locating-files-default |
| 40 | (list "schemas.xml" (expand-file-name "schema/schemas.xml" data-directory)) | 39 | (list "schemas.xml" (expand-file-name "schema/schemas.xml" data-directory)) |
| @@ -233,11 +232,11 @@ or nil." | |||
| 233 | rules)))))))) | 232 | rules)))))))) |
| 234 | best-so-far)) | 233 | best-so-far)) |
| 235 | 234 | ||
| 236 | (put 'documentElement 'rng-rule-matcher 'rng-match-document-element-rule) | 235 | (put 'documentElement 'rng-rule-matcher #'rng-match-document-element-rule) |
| 237 | (put 'namespace 'rng-rule-matcher 'rng-match-namespace-rule) | 236 | (put 'namespace 'rng-rule-matcher #'rng-match-namespace-rule) |
| 238 | (put 'uri 'rng-rule-matcher 'rng-match-uri-rule) | 237 | (put 'uri 'rng-rule-matcher #'rng-match-uri-rule) |
| 239 | (put 'transformURI 'rng-rule-matcher 'rng-match-transform-uri-rule) | 238 | (put 'transformURI 'rng-rule-matcher #'rng-match-transform-uri-rule) |
| 240 | (put 'default 'rng-rule-matcher 'rng-match-default-rule) | 239 | (put 'default 'rng-rule-matcher #'rng-match-default-rule) |
| 241 | 240 | ||
| 242 | (defun rng-match-document-element-rule (props) | 241 | (defun rng-match-document-element-rule (props) |
| 243 | (let ((document-element (rng-document-element)) | 242 | (let ((document-element (rng-document-element)) |
diff --git a/lisp/nxml/rng-maint.el b/lisp/nxml/rng-maint.el index 165ca8930a4..32a041e0c17 100644 --- a/lisp/nxml/rng-maint.el +++ b/lisp/nxml/rng-maint.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-maint.el --- commands for RELAX NG maintainers | 1 | ;;; rng-maint.el --- commands for RELAX NG maintainers -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
diff --git a/lisp/nxml/rng-match.el b/lisp/nxml/rng-match.el index df9c0192557..d2b629e8d83 100644 --- a/lisp/nxml/rng-match.el +++ b/lisp/nxml/rng-match.el | |||
| @@ -56,9 +56,8 @@ Used to detect invalid recursive references.") | |||
| 56 | ;;; Inline functions | 56 | ;;; Inline functions |
| 57 | 57 | ||
| 58 | (defsubst rng-update-match-state (new-state) | 58 | (defsubst rng-update-match-state (new-state) |
| 59 | (if (and (eq new-state rng-not-allowed-ipattern) | 59 | (if (eq new-state rng-not-allowed-ipattern) |
| 60 | (not (eq rng-match-state rng-not-allowed-ipattern))) | 60 | (eq rng-match-state rng-not-allowed-ipattern) |
| 61 | nil | ||
| 62 | (setq rng-match-state new-state) | 61 | (setq rng-match-state new-state) |
| 63 | t)) | 62 | t)) |
| 64 | 63 | ||
diff --git a/lisp/nxml/rng-nxml.el b/lisp/nxml/rng-nxml.el index fe90dffb555..954a1eb9599 100644 --- a/lisp/nxml/rng-nxml.el +++ b/lisp/nxml/rng-nxml.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-nxml.el --- make nxml-mode take advantage of rng-validate-mode | 1 | ;;; rng-nxml.el --- make nxml-mode take advantage of rng-validate-mode -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -33,6 +33,7 @@ | |||
| 33 | (require 'rng-valid) | 33 | (require 'rng-valid) |
| 34 | (require 'nxml-mode) | 34 | (require 'nxml-mode) |
| 35 | (require 'rng-loc) | 35 | (require 'rng-loc) |
| 36 | (require 'sgml-mode) | ||
| 36 | 37 | ||
| 37 | (defcustom rng-nxml-auto-validate-flag t | 38 | (defcustom rng-nxml-auto-validate-flag t |
| 38 | "Non-nil means automatically turn on validation with nxml-mode." | 39 | "Non-nil means automatically turn on validation with nxml-mode." |
| @@ -65,6 +66,9 @@ Complete on start-tag names regardless.") | |||
| 65 | ["Validation" rng-validate-mode | 66 | ["Validation" rng-validate-mode |
| 66 | :style toggle | 67 | :style toggle |
| 67 | :selected rng-validate-mode] | 68 | :selected rng-validate-mode] |
| 69 | ["Electric Pairs" sgml-electric-tag-pair-mode | ||
| 70 | :style toggle | ||
| 71 | :selected sgml-electric-tag-pair-mode] | ||
| 68 | "---" | 72 | "---" |
| 69 | ("Set Schema" | 73 | ("Set Schema" |
| 70 | ["Automatically" rng-auto-set-schema] | 74 | ["Automatically" rng-auto-set-schema] |
| @@ -107,25 +111,15 @@ Validation will be enabled if `rng-nxml-auto-validate-flag' is non-nil." | |||
| 107 | 'append) | 111 | 'append) |
| 108 | (cond (rng-nxml-auto-validate-flag | 112 | (cond (rng-nxml-auto-validate-flag |
| 109 | (rng-validate-mode 1) | 113 | (rng-validate-mode 1) |
| 110 | (add-hook 'nxml-completion-hook 'rng-complete nil t) | 114 | (add-hook 'completion-at-point-functions #'rng-completion-at-point nil t) |
| 111 | (add-hook 'nxml-in-mixed-content-hook 'rng-in-mixed-content-p nil t)) | 115 | (add-hook 'nxml-in-mixed-content-hook #'rng-in-mixed-content-p nil t)) |
| 112 | (t | 116 | (t |
| 113 | (rng-validate-mode 0) | 117 | (rng-validate-mode 0) |
| 114 | (remove-hook 'nxml-completion-hook 'rng-complete t) | 118 | (remove-hook 'completion-at-point-functions #'rng-completion-at-point t) |
| 115 | (remove-hook 'nxml-in-mixed-content-hook 'rng-in-mixed-content-p t)))) | 119 | (remove-hook 'nxml-in-mixed-content-hook #'rng-in-mixed-content-p t)))) |
| 116 | |||
| 117 | (defvar rng-tag-history nil) | ||
| 118 | (defvar rng-attribute-name-history nil) | ||
| 119 | (defvar rng-attribute-value-history nil) | ||
| 120 | |||
| 121 | (defvar rng-complete-target-names nil) | ||
| 122 | (defvar rng-complete-name-attribute-flag nil) | ||
| 123 | (defvar rng-complete-extra-strings nil) | ||
| 124 | 120 | ||
| 125 | (defun rng-complete () | 121 | (defun rng-completion-at-point () |
| 126 | "Complete the string before point using the current schema. | 122 | "Return completion data for the string before point using the current schema." |
| 127 | Return non-nil if in a context it understands." | ||
| 128 | (interactive) | ||
| 129 | (and rng-validate-mode | 123 | (and rng-validate-mode |
| 130 | (let ((lt-pos (save-excursion (search-backward "<" nil t))) | 124 | (let ((lt-pos (save-excursion (search-backward "<" nil t))) |
| 131 | xmltok-dtd) | 125 | xmltok-dtd) |
| @@ -145,53 +139,48 @@ Return non-nil if in a context it understands." | |||
| 145 | t)) | 139 | t)) |
| 146 | 140 | ||
| 147 | (defun rng-complete-tag (lt-pos) | 141 | (defun rng-complete-tag (lt-pos) |
| 148 | (let (rng-complete-extra-strings) | 142 | (let ((extra-strings |
| 149 | (when (and (= lt-pos (1- (point))) | 143 | (when (and (= lt-pos (1- (point))) |
| 150 | rng-complete-end-tags-after-< | 144 | rng-complete-end-tags-after-< |
| 151 | rng-open-elements | 145 | rng-open-elements |
| 152 | (not (eq (car rng-open-elements) t)) | 146 | (not (eq (car rng-open-elements) t)) |
| 153 | (or rng-collecting-text | 147 | (or rng-collecting-text |
| 154 | (rng-match-save | 148 | (rng-match-save |
| 155 | (rng-match-end-tag)))) | 149 | (rng-match-end-tag)))) |
| 156 | (setq rng-complete-extra-strings | 150 | (list (concat "/" |
| 157 | (cons (concat "/" | 151 | (if (caar rng-open-elements) |
| 158 | (if (caar rng-open-elements) | 152 | (concat (caar rng-open-elements) |
| 159 | (concat (caar rng-open-elements) | 153 | ":" |
| 160 | ":" | 154 | (cdar rng-open-elements)) |
| 161 | (cdar rng-open-elements)) | 155 | (cdar rng-open-elements))))))) |
| 162 | (cdar rng-open-elements))) | ||
| 163 | rng-complete-extra-strings))) | ||
| 164 | (when (save-excursion | 156 | (when (save-excursion |
| 165 | (re-search-backward rng-in-start-tag-name-regex | 157 | (re-search-backward rng-in-start-tag-name-regex |
| 166 | lt-pos | 158 | lt-pos |
| 167 | t)) | 159 | t)) |
| 168 | (and rng-collecting-text (rng-flush-text)) | 160 | (and rng-collecting-text (rng-flush-text)) |
| 169 | (let ((completion | 161 | (let ((target-names (rng-match-possible-start-tag-names))) |
| 170 | (let ((rng-complete-target-names | 162 | `(,(1+ lt-pos) |
| 171 | (rng-match-possible-start-tag-names)) | 163 | ,(save-excursion (skip-chars-forward "[[:alnum:]_.-:]") (point)) |
| 172 | (rng-complete-name-attribute-flag nil)) | 164 | ,(apply-partially #'rng-complete-qname-function |
| 173 | (rng-complete-before-point (1+ lt-pos) | 165 | target-names nil extra-strings) |
| 174 | 'rng-complete-qname-function | 166 | :exit-function |
| 175 | "Tag: " | 167 | ,(lambda (completion status) |
| 176 | nil | 168 | (cond |
| 177 | 'rng-tag-history))) | 169 | ((not (eq status 'finished)) nil) |
| 178 | name) | 170 | ((rng-qname-p completion) |
| 179 | (when completion | 171 | (let ((name (rng-expand-qname completion |
| 180 | (cond ((rng-qname-p completion) | 172 | t |
| 181 | (setq name (rng-expand-qname completion | 173 | #'rng-start-tag-expand-recover))) |
| 182 | t | 174 | (when (and name |
| 183 | 'rng-start-tag-expand-recover)) | 175 | (rng-match-start-tag-open name) |
| 184 | (when (and name | 176 | (or (not (rng-match-start-tag-close)) |
| 185 | (rng-match-start-tag-open name) | 177 | ;; need a namespace decl on the root element |
| 186 | (or (not (rng-match-start-tag-close)) | 178 | (and (car name) |
| 187 | ;; need a namespace decl on the root element | 179 | (not rng-open-elements)))) |
| 188 | (and (car name) | 180 | ;; attributes are required |
| 189 | (not rng-open-elements)))) | 181 | (insert " ")))) |
| 190 | ;; attributes are required | 182 | ((member completion extra-strings) |
| 191 | (insert " "))) | 183 | (insert ">"))))))))) |
| 192 | ((member completion rng-complete-extra-strings) | ||
| 193 | (insert ">"))))) | ||
| 194 | t))) | ||
| 195 | 184 | ||
| 196 | (defconst rng-in-end-tag-name-regex | 185 | (defconst rng-in-end-tag-name-regex |
| 197 | (replace-regexp-in-string | 186 | (replace-regexp-in-string |
| @@ -216,29 +205,18 @@ Return non-nil if in a context it understands." | |||
| 216 | (concat (caar rng-open-elements) | 205 | (concat (caar rng-open-elements) |
| 217 | ":" | 206 | ":" |
| 218 | (cdar rng-open-elements)) | 207 | (cdar rng-open-elements)) |
| 219 | (cdar rng-open-elements))) | 208 | (cdar rng-open-elements)))) |
| 220 | (end-tag-name | 209 | `(,(+ (match-beginning 0) 2) |
| 221 | (buffer-substring-no-properties (+ (match-beginning 0) 2) | 210 | ,(save-excursion (skip-chars-forward "[[:alnum:]_.-:]") (point)) |
| 222 | (point)))) | 211 | ,(list start-tag-name) ;Sole completion candidate. |
| 223 | (cond ((or (> (length end-tag-name) | 212 | :exit-function |
| 224 | (length start-tag-name)) | 213 | ,(lambda (_completion status) |
| 225 | (not (string= (substring start-tag-name | 214 | (when (eq status 'finished) |
| 226 | 0 | 215 | (unless (eq (char-after) ?>) (insert ">")) |
| 227 | (length end-tag-name)) | 216 | (when (not (or rng-collecting-text |
| 228 | end-tag-name))) | 217 | (rng-match-end-tag))) |
| 229 | (message "Expected end-tag %s" | 218 | (message "Element \"%s\" is incomplete" |
| 230 | (rng-quote-string | 219 | start-tag-name)))))))))) |
| 231 | (concat "</" start-tag-name ">"))) | ||
| 232 | (ding)) | ||
| 233 | (t | ||
| 234 | (delete-region (- (point) (length end-tag-name)) | ||
| 235 | (point)) | ||
| 236 | (insert start-tag-name ">") | ||
| 237 | (when (not (or rng-collecting-text | ||
| 238 | (rng-match-end-tag))) | ||
| 239 | (message "Element %s is incomplete" | ||
| 240 | (rng-quote-string start-tag-name)))))))) | ||
| 241 | t)) | ||
| 242 | 220 | ||
| 243 | (defconst rng-in-attribute-regex | 221 | (defconst rng-in-attribute-regex |
| 244 | (replace-regexp-in-string | 222 | (replace-regexp-in-string |
| @@ -260,22 +238,24 @@ Return non-nil if in a context it understands." | |||
| 260 | rng-undeclared-prefixes) | 238 | rng-undeclared-prefixes) |
| 261 | (and (rng-adjust-state-for-attribute lt-pos | 239 | (and (rng-adjust-state-for-attribute lt-pos |
| 262 | attribute-start) | 240 | attribute-start) |
| 263 | (let ((rng-complete-target-names | 241 | (let ((target-names |
| 264 | (rng-match-possible-attribute-names)) | 242 | (rng-match-possible-attribute-names)) |
| 265 | (rng-complete-extra-strings | 243 | (extra-strings |
| 266 | (mapcar (lambda (prefix) | 244 | (mapcar (lambda (prefix) |
| 267 | (if prefix | 245 | (if prefix |
| 268 | (concat "xmlns:" prefix) | 246 | (concat "xmlns:" prefix) |
| 269 | "xmlns")) | 247 | "xmlns")) |
| 270 | rng-undeclared-prefixes)) | 248 | rng-undeclared-prefixes))) |
| 271 | (rng-complete-name-attribute-flag t)) | 249 | `(,attribute-start |
| 272 | (rng-complete-before-point attribute-start | 250 | ,(save-excursion (skip-chars-forward "[[:alnum:]_.-:]") (point)) |
| 273 | 'rng-complete-qname-function | 251 | ,(apply-partially #'rng-complete-qname-function |
| 274 | "Attribute: " | 252 | target-names t extra-strings) |
| 275 | nil | 253 | :exit-function |
| 276 | 'rng-attribute-name-history)) | 254 | ,(lambda (_completion status) |
| 277 | (insert "=\""))) | 255 | (when (and (eq status 'finished) |
| 278 | t)) | 256 | (not (looking-at "="))) |
| 257 | (insert "=\"\"") | ||
| 258 | (forward-char -1))))))))) | ||
| 279 | 259 | ||
| 280 | (defconst rng-in-attribute-value-regex | 260 | (defconst rng-in-attribute-value-regex |
| 281 | (replace-regexp-in-string | 261 | (replace-regexp-in-string |
| @@ -292,43 +272,40 @@ Return non-nil if in a context it understands." | |||
| 292 | (defun rng-complete-attribute-value (lt-pos) | 272 | (defun rng-complete-attribute-value (lt-pos) |
| 293 | (when (save-excursion | 273 | (when (save-excursion |
| 294 | (re-search-backward rng-in-attribute-value-regex lt-pos t)) | 274 | (re-search-backward rng-in-attribute-value-regex lt-pos t)) |
| 295 | (let ((name-start (match-beginning 1)) | 275 | (let* ((name-start (match-beginning 1)) |
| 296 | (name-end (match-end 1)) | 276 | (name-end (match-end 1)) |
| 297 | (colon (match-beginning 2)) | 277 | (colon (match-beginning 2)) |
| 298 | (value-start (1+ (match-beginning 3)))) | 278 | (value-start (1+ (match-beginning 3))) |
| 279 | (exit-function | ||
| 280 | (lambda (_completion status) | ||
| 281 | (when (eq status 'finished) | ||
| 282 | (let ((delim (char-before value-start))) | ||
| 283 | (unless (eq (char-after) delim) (insert delim))))))) | ||
| 299 | (and (rng-adjust-state-for-attribute lt-pos | 284 | (and (rng-adjust-state-for-attribute lt-pos |
| 300 | name-start) | 285 | name-start) |
| 301 | (if (string= (buffer-substring-no-properties name-start | 286 | (if (string= (buffer-substring-no-properties name-start |
| 302 | (or colon name-end)) | 287 | (or colon name-end)) |
| 303 | "xmlns") | 288 | "xmlns") |
| 304 | (rng-complete-before-point | 289 | `(,value-start ,(point) |
| 305 | value-start | 290 | ,(rng-strings-to-completion-table |
| 306 | (rng-strings-to-completion-alist | 291 | (rng-possible-namespace-uris |
| 307 | (rng-possible-namespace-uris | 292 | (and colon |
| 308 | (and colon | 293 | (buffer-substring-no-properties (1+ colon) name-end)))) |
| 309 | (buffer-substring-no-properties (1+ colon) name-end)))) | 294 | :exit-function ,exit-function) |
| 310 | "Namespace URI: " | ||
| 311 | nil | ||
| 312 | 'rng-namespace-uri-history) | ||
| 313 | (rng-adjust-state-for-attribute-value name-start | 295 | (rng-adjust-state-for-attribute-value name-start |
| 314 | colon | 296 | colon |
| 315 | name-end) | 297 | name-end) |
| 316 | (rng-complete-before-point | 298 | `(,value-start ,(point) |
| 317 | value-start | 299 | ,(rng-strings-to-completion-table |
| 318 | (rng-strings-to-completion-alist | 300 | (rng-match-possible-value-strings)) |
| 319 | (rng-match-possible-value-strings)) | 301 | :exit-function ,exit-function)))))) |
| 320 | "Value: " | ||
| 321 | nil | ||
| 322 | 'rng-attribute-value-history)) | ||
| 323 | (insert (char-before value-start)))) | ||
| 324 | t)) | ||
| 325 | 302 | ||
| 326 | (defun rng-possible-namespace-uris (prefix) | 303 | (defun rng-possible-namespace-uris (prefix) |
| 327 | (let ((ns (if prefix (nxml-ns-get-prefix prefix) | 304 | (let ((ns (if prefix (nxml-ns-get-prefix prefix) |
| 328 | (nxml-ns-get-default)))) | 305 | (nxml-ns-get-default)))) |
| 329 | (if (and ns (memq prefix (nxml-ns-changed-prefixes))) | 306 | (if (and ns (memq prefix (nxml-ns-changed-prefixes))) |
| 330 | (list (nxml-namespace-name ns)) | 307 | (list (nxml-namespace-name ns)) |
| 331 | (mapcar 'nxml-namespace-name | 308 | (mapcar #'nxml-namespace-name |
| 332 | (delq nxml-xml-namespace-uri | 309 | (delq nxml-xml-namespace-uri |
| 333 | (rng-match-possible-namespace-uris)))))) | 310 | (rng-match-possible-namespace-uris)))))) |
| 334 | 311 | ||
| @@ -349,7 +326,7 @@ Return non-nil if in a context it understands." | |||
| 349 | (recover-fun (funcall recover-fun prefix (cdr qname))))) | 326 | (recover-fun (funcall recover-fun prefix (cdr qname))))) |
| 350 | (cons (and defaultp (nxml-ns-get-default)) (cdr qname))))) | 327 | (cons (and defaultp (nxml-ns-get-default)) (cdr qname))))) |
| 351 | 328 | ||
| 352 | (defun rng-start-tag-expand-recover (prefix local-name) | 329 | (defun rng-start-tag-expand-recover (_prefix local-name) |
| 353 | (let ((ns (rng-match-infer-start-tag-namespace local-name))) | 330 | (let ((ns (rng-match-infer-start-tag-namespace local-name))) |
| 354 | (and ns | 331 | (and ns |
| 355 | (cons ns local-name)))) | 332 | (cons ns local-name)))) |
| @@ -386,7 +363,7 @@ set `xmltok-dtd'. Returns the position of the end of the token." | |||
| 386 | (save-restriction | 363 | (save-restriction |
| 387 | (widen) | 364 | (widen) |
| 388 | (nxml-with-invisible-motion | 365 | (nxml-with-invisible-motion |
| 389 | (if (= pos 1) | 366 | (if (= pos (point-min)) |
| 390 | (rng-set-initial-state) | 367 | (rng-set-initial-state) |
| 391 | (let ((state (get-text-property (1- pos) 'rng-state))) | 368 | (let ((state (get-text-property (1- pos) 'rng-state))) |
| 392 | (cond (state | 369 | (cond (state |
| @@ -501,24 +478,21 @@ set `xmltok-dtd'. Returns the position of the end of the token." | |||
| 501 | (and (or (not prefix) ns) | 478 | (and (or (not prefix) ns) |
| 502 | (rng-match-attribute-name (cons ns local-name))))) | 479 | (rng-match-attribute-name (cons ns local-name))))) |
| 503 | 480 | ||
| 504 | (defun rng-complete-qname-function (string predicate flag) | 481 | (defun rng-complete-qname-function (candidates attributes-flag extra-strings |
| 505 | (let ((alist (mapcar (lambda (name) (cons name nil)) | 482 | string predicate flag) |
| 506 | (rng-generate-qname-list string)))) | 483 | (complete-with-action flag |
| 507 | (cond ((not flag) | 484 | (rng-generate-qname-list |
| 508 | (try-completion string alist predicate)) | 485 | string candidates attributes-flag extra-strings) |
| 509 | ((eq flag t) | 486 | string predicate)) |
| 510 | (all-completions string alist predicate)) | 487 | |
| 511 | ((eq flag 'lambda) | 488 | (defun rng-generate-qname-list (&optional string candidates attribute-flag extra-strings) |
| 512 | (and (assoc string alist) t))))) | ||
| 513 | |||
| 514 | (defun rng-generate-qname-list (&optional string) | ||
| 515 | (let ((forced-prefix (and string | 489 | (let ((forced-prefix (and string |
| 516 | (string-match ":" string) | 490 | (string-match ":" string) |
| 517 | (> (match-beginning 0) 0) | 491 | (> (match-beginning 0) 0) |
| 518 | (substring string | 492 | (substring string |
| 519 | 0 | 493 | 0 |
| 520 | (match-beginning 0)))) | 494 | (match-beginning 0)))) |
| 521 | (namespaces (mapcar 'car rng-complete-target-names)) | 495 | (namespaces (mapcar #'car candidates)) |
| 522 | ns-prefixes-alist ns-prefixes iter ns prefer) | 496 | ns-prefixes-alist ns-prefixes iter ns prefer) |
| 523 | (while namespaces | 497 | (while namespaces |
| 524 | (setq ns (car namespaces)) | 498 | (setq ns (car namespaces)) |
| @@ -526,7 +500,7 @@ set `xmltok-dtd'. Returns the position of the end of the token." | |||
| 526 | (setq ns-prefixes-alist | 500 | (setq ns-prefixes-alist |
| 527 | (cons (cons ns (nxml-ns-prefixes-for | 501 | (cons (cons ns (nxml-ns-prefixes-for |
| 528 | ns | 502 | ns |
| 529 | rng-complete-name-attribute-flag)) | 503 | attribute-flag)) |
| 530 | ns-prefixes-alist))) | 504 | ns-prefixes-alist))) |
| 531 | (setq namespaces (delq ns (cdr namespaces)))) | 505 | (setq namespaces (delq ns (cdr namespaces)))) |
| 532 | (setq iter ns-prefixes-alist) | 506 | (setq iter ns-prefixes-alist) |
| @@ -546,12 +520,12 @@ set `xmltok-dtd'. Returns the position of the end of the token." | |||
| 546 | (setcdr ns-prefixes (list prefer))) | 520 | (setcdr ns-prefixes (list prefer))) |
| 547 | ;; Unless it's an attribute with a non-nil namespace, | 521 | ;; Unless it's an attribute with a non-nil namespace, |
| 548 | ;; allow no prefix for this namespace. | 522 | ;; allow no prefix for this namespace. |
| 549 | (unless rng-complete-name-attribute-flag | 523 | (unless attribute-flag |
| 550 | (setcdr ns-prefixes (cons nil (cdr ns-prefixes)))))) | 524 | (setcdr ns-prefixes (cons nil (cdr ns-prefixes)))))) |
| 551 | (setq iter (cdr iter))) | 525 | (setq iter (cdr iter))) |
| 552 | (rng-uniquify-equal | 526 | (rng-uniquify-equal |
| 553 | (sort (apply 'append | 527 | (sort (apply #'append |
| 554 | (cons rng-complete-extra-strings | 528 | (cons extra-strings |
| 555 | (mapcar (lambda (name) | 529 | (mapcar (lambda (name) |
| 556 | (if (car name) | 530 | (if (car name) |
| 557 | (mapcar (lambda (prefix) | 531 | (mapcar (lambda (prefix) |
| @@ -563,7 +537,7 @@ set `xmltok-dtd'. Returns the position of the end of the token." | |||
| 563 | (cdr (assoc (car name) | 537 | (cdr (assoc (car name) |
| 564 | ns-prefixes-alist))) | 538 | ns-prefixes-alist))) |
| 565 | (list (cdr name)))) | 539 | (list (cdr name)))) |
| 566 | rng-complete-target-names))) | 540 | candidates))) |
| 567 | 'string<)))) | 541 | 'string<)))) |
| 568 | 542 | ||
| 569 | (defun rng-get-preferred-unused-prefix (ns) | 543 | (defun rng-get-preferred-unused-prefix (ns) |
| @@ -582,10 +556,8 @@ set `xmltok-dtd'. Returns the position of the end of the token." | |||
| 582 | nil)))) | 556 | nil)))) |
| 583 | prefix)) | 557 | prefix)) |
| 584 | 558 | ||
| 585 | (defun rng-strings-to-completion-alist (strings) | 559 | (defun rng-strings-to-completion-table (strings) |
| 586 | (mapcar (lambda (s) (cons s s)) | 560 | (mapcar #'rng-escape-string strings)) |
| 587 | (rng-uniquify-equal (sort (mapcar 'rng-escape-string strings) | ||
| 588 | 'string<)))) | ||
| 589 | 561 | ||
| 590 | (provide 'rng-nxml) | 562 | (provide 'rng-nxml) |
| 591 | 563 | ||
diff --git a/lisp/nxml/rng-parse.el b/lisp/nxml/rng-parse.el index cde749db672..3ae4b5cc9c4 100644 --- a/lisp/nxml/rng-parse.el +++ b/lisp/nxml/rng-parse.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-parse.el --- parse an XML file and validate it against a schema | 1 | ;;; rng-parse.el --- parse an XML file and validate it against a schema -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
diff --git a/lisp/nxml/rng-pttrn.el b/lisp/nxml/rng-pttrn.el index f358d3c87d4..e847f5e02a8 100644 --- a/lisp/nxml/rng-pttrn.el +++ b/lisp/nxml/rng-pttrn.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-pttrn.el --- RELAX NG patterns | 1 | ;;; rng-pttrn.el --- RELAX NG patterns -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
diff --git a/lisp/nxml/rng-uri.el b/lisp/nxml/rng-uri.el index 75cf23f888d..8fc0a01e293 100644 --- a/lisp/nxml/rng-uri.el +++ b/lisp/nxml/rng-uri.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-uri.el --- URI parsing and manipulation | 1 | ;;; rng-uri.el --- URI parsing and manipulation -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
diff --git a/lisp/nxml/rng-util.el b/lisp/nxml/rng-util.el index 4c14e2b6597..c5d4b6567ed 100644 --- a/lisp/nxml/rng-util.el +++ b/lisp/nxml/rng-util.el | |||
| @@ -82,69 +82,6 @@ LIST is not modified." | |||
| 82 | (cons item nil)))))))) | 82 | (cons item nil)))))))) |
| 83 | list))) | 83 | list))) |
| 84 | 84 | ||
| 85 | (defun rng-complete-before-point (start table prompt &optional predicate hist) | ||
| 86 | "Complete text between START and point. | ||
| 87 | Replaces the text between START and point with a string chosen using a | ||
| 88 | completion table and, when needed, input read from the user with the | ||
| 89 | minibuffer. | ||
| 90 | Returns the new string if either a complete and unique completion was | ||
| 91 | determined automatically or input was read from the user. Otherwise, | ||
| 92 | returns nil. | ||
| 93 | TABLE is an alist, a symbol bound to a function or an obarray as with | ||
| 94 | the function `completing-read'. | ||
| 95 | PROMPT is the string to prompt with if user input is needed. | ||
| 96 | PREDICATE is nil or a function as with `completing-read'. | ||
| 97 | HIST, if non-nil, specifies a history list as with `completing-read'." | ||
| 98 | (let* ((orig (buffer-substring-no-properties start (point))) | ||
| 99 | (completion (try-completion orig table predicate))) | ||
| 100 | (cond ((not completion) | ||
| 101 | (if (string= orig "") | ||
| 102 | (message "No completions available") | ||
| 103 | (message "No completion for %s" (rng-quote-string orig))) | ||
| 104 | (ding) | ||
| 105 | nil) | ||
| 106 | ((eq completion t) orig) | ||
| 107 | ((not (string= completion orig)) | ||
| 108 | (delete-region start (point)) | ||
| 109 | (insert completion) | ||
| 110 | (cond ((not (rng-completion-exact-p completion table predicate)) | ||
| 111 | (message "Incomplete") | ||
| 112 | nil) | ||
| 113 | ((eq (try-completion completion table predicate) t) | ||
| 114 | completion) | ||
| 115 | (t | ||
| 116 | (message "Complete but not unique") | ||
| 117 | nil))) | ||
| 118 | (t | ||
| 119 | (setq completion | ||
| 120 | (let ((saved-minibuffer-setup-hook | ||
| 121 | (default-value 'minibuffer-setup-hook))) | ||
| 122 | (add-hook 'minibuffer-setup-hook | ||
| 123 | 'minibuffer-completion-help | ||
| 124 | t) | ||
| 125 | (unwind-protect | ||
| 126 | (completing-read prompt | ||
| 127 | table | ||
| 128 | predicate | ||
| 129 | nil | ||
| 130 | orig | ||
| 131 | hist) | ||
| 132 | (setq-default minibuffer-setup-hook | ||
| 133 | saved-minibuffer-setup-hook)))) | ||
| 134 | (delete-region start (point)) | ||
| 135 | (insert completion) | ||
| 136 | completion)))) | ||
| 137 | |||
| 138 | (defun rng-completion-exact-p (string table predicate) | ||
| 139 | (cond ((symbolp table) | ||
| 140 | (funcall table string predicate 'lambda)) | ||
| 141 | ((vectorp table) | ||
| 142 | (intern-soft string table)) | ||
| 143 | (t (assoc string table)))) | ||
| 144 | |||
| 145 | (defun rng-quote-string (s) | ||
| 146 | (concat "\"" s "\"")) | ||
| 147 | |||
| 148 | (defun rng-escape-string (s) | 85 | (defun rng-escape-string (s) |
| 149 | (replace-regexp-in-string "[&\"<>]" | 86 | (replace-regexp-in-string "[&\"<>]" |
| 150 | (lambda (match) | 87 | (lambda (match) |
diff --git a/lisp/nxml/rng-valid.el b/lisp/nxml/rng-valid.el index 1020cad2089..946bf791ff8 100644 --- a/lisp/nxml/rng-valid.el +++ b/lisp/nxml/rng-valid.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-valid.el --- real-time validation of XML using RELAX NG | 1 | ;;; rng-valid.el --- real-time validation of XML using RELAX NG -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -430,13 +430,13 @@ The schema is set like `rng-auto-set-schema'." | |||
| 430 | (when (buffer-live-p buffer) ; bug#13999 | 430 | (when (buffer-live-p buffer) ; bug#13999 |
| 431 | (with-current-buffer buffer | 431 | (with-current-buffer buffer |
| 432 | (if rng-validate-mode | 432 | (if rng-validate-mode |
| 433 | (if (let ((rng-validate-display-point (point)) | 433 | (if (let ((rng-validate-display-point (point)) |
| 434 | (rng-validate-display-modified-p (buffer-modified-p))) | 434 | (rng-validate-display-modified-p (buffer-modified-p))) |
| 435 | (rng-do-some-validation 'rng-validate-while-idle-continue-p)) | 435 | (rng-do-some-validation 'rng-validate-while-idle-continue-p)) |
| 436 | (force-mode-line-update) | 436 | (force-mode-line-update) |
| 437 | (rng-validate-done)) | 437 | (rng-validate-done)) |
| 438 | ;; must have done kill-all-local-variables | 438 | ;; Must have done kill-all-local-variables. |
| 439 | (rng-kill-timers))))) | 439 | (rng-kill-timers))))) |
| 440 | 440 | ||
| 441 | (defun rng-validate-quick-while-idle (buffer) | 441 | (defun rng-validate-quick-while-idle (buffer) |
| 442 | (when (buffer-live-p buffer) ; bug#13999 | 442 | (when (buffer-live-p buffer) ; bug#13999 |
| @@ -709,7 +709,7 @@ Return t if there is work to do, nil otherwise." | |||
| 709 | 709 | ||
| 710 | ;; If we don't do this, then the front delimiter can move | 710 | ;; If we don't do this, then the front delimiter can move |
| 711 | ;; past the end delimiter. | 711 | ;; past the end delimiter. |
| 712 | (defun rng-error-modified (overlay after-p beg end &optional pre-change-len) | 712 | (defun rng-error-modified (overlay after-p _beg _end &optional _pre-change-len) |
| 713 | (when (and after-p | 713 | (when (and after-p |
| 714 | (overlay-start overlay) ; check not deleted | 714 | (overlay-start overlay) ; check not deleted |
| 715 | (>= (overlay-start overlay) | 715 | (>= (overlay-start overlay) |
| @@ -1138,9 +1138,8 @@ as empty-element." | |||
| 1138 | (rng-match-start-tag-open required) | 1138 | (rng-match-start-tag-open required) |
| 1139 | (rng-match-after) | 1139 | (rng-match-after) |
| 1140 | (rng-match-start-tag-open name)) | 1140 | (rng-match-start-tag-open name)) |
| 1141 | (rng-mark-invalid (concat "Missing element " | 1141 | (rng-mark-invalid (format "Missing element \"%s\"" |
| 1142 | (rng-quote-string | 1142 | (rng-name-to-string required)) |
| 1143 | (rng-name-to-string required))) | ||
| 1144 | xmltok-start | 1143 | xmltok-start |
| 1145 | (1+ xmltok-start))) | 1144 | (1+ xmltok-start))) |
| 1146 | ((and (rng-match-optionalize-elements) | 1145 | ((and (rng-match-optionalize-elements) |
| @@ -1177,16 +1176,14 @@ as empty-element." | |||
| 1177 | (cond ((not required-attributes) | 1176 | (cond ((not required-attributes) |
| 1178 | "Required attributes missing") | 1177 | "Required attributes missing") |
| 1179 | ((not (cdr required-attributes)) | 1178 | ((not (cdr required-attributes)) |
| 1180 | (concat "Missing attribute " | 1179 | (format "Missing attribute \"%s\"" |
| 1181 | (rng-quote-string | 1180 | (rng-name-to-string (car required-attributes) t))) |
| 1182 | (rng-name-to-string (car required-attributes) t)))) | ||
| 1183 | (t | 1181 | (t |
| 1184 | (concat "Missing attributes " | 1182 | (format "Missing attributes \"%s\"" |
| 1185 | (mapconcat (lambda (nm) | 1183 | (mapconcat (lambda (nm) |
| 1186 | (rng-quote-string | 1184 | (rng-name-to-string nm t)) |
| 1187 | (rng-name-to-string nm t))) | ||
| 1188 | required-attributes | 1185 | required-attributes |
| 1189 | ", ")))))) | 1186 | "\", \"")))))) |
| 1190 | 1187 | ||
| 1191 | (defun rng-process-end-tag (&optional partial) | 1188 | (defun rng-process-end-tag (&optional partial) |
| 1192 | (cond ((not rng-open-elements) | 1189 | (cond ((not rng-open-elements) |
| @@ -1229,8 +1226,7 @@ as empty-element." | |||
| 1229 | (defun rng-missing-element-message () | 1226 | (defun rng-missing-element-message () |
| 1230 | (let ((element (rng-match-required-element-name))) | 1227 | (let ((element (rng-match-required-element-name))) |
| 1231 | (if element | 1228 | (if element |
| 1232 | (concat "Missing element " | 1229 | (format "Missing element \"%s\"" (rng-name-to-string element)) |
| 1233 | (rng-quote-string (rng-name-to-string element))) | ||
| 1234 | "Required child elements missing"))) | 1230 | "Required child elements missing"))) |
| 1235 | 1231 | ||
| 1236 | (defun rng-recover-mismatched-end-tag () | 1232 | (defun rng-recover-mismatched-end-tag () |
| @@ -1258,17 +1254,16 @@ as empty-element." | |||
| 1258 | 1254 | ||
| 1259 | (defun rng-mark-missing-end-tags (missing) | 1255 | (defun rng-mark-missing-end-tags (missing) |
| 1260 | (rng-mark-not-well-formed | 1256 | (rng-mark-not-well-formed |
| 1261 | (format "Missing end-tag%s %s" | 1257 | (format "Missing end-tag%s \"%s\"" |
| 1262 | (if (null (cdr missing)) "" "s") | 1258 | (if (null (cdr missing)) "" "s") |
| 1263 | (mapconcat (lambda (name) | 1259 | (mapconcat (lambda (name) |
| 1264 | (rng-quote-string | 1260 | (if (car name) |
| 1265 | (if (car name) | 1261 | (concat (car name) |
| 1266 | (concat (car name) | 1262 | ":" |
| 1267 | ":" | 1263 | (cdr name)) |
| 1268 | (cdr name)) | 1264 | (cdr name))) |
| 1269 | (cdr name)))) | ||
| 1270 | missing | 1265 | missing |
| 1271 | ", ")) | 1266 | "\", \"")) |
| 1272 | xmltok-start | 1267 | xmltok-start |
| 1273 | (+ xmltok-start 2))) | 1268 | (+ xmltok-start 2))) |
| 1274 | 1269 | ||
diff --git a/lisp/nxml/rng-xsd.el b/lisp/nxml/rng-xsd.el index 378319851a0..c0989ae1073 100644 --- a/lisp/nxml/rng-xsd.el +++ b/lisp/nxml/rng-xsd.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; rng-xsd.el --- W3C XML Schema datatypes library for RELAX NG | 1 | ;;; rng-xsd.el --- W3C XML Schema datatypes library for RELAX NG -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -42,7 +42,7 @@ | |||
| 42 | ;;;###autoload | 42 | ;;;###autoload |
| 43 | (put 'http://www.w3.org/2001/XMLSchema-datatypes | 43 | (put 'http://www.w3.org/2001/XMLSchema-datatypes |
| 44 | 'rng-dt-compile | 44 | 'rng-dt-compile |
| 45 | 'rng-xsd-compile) | 45 | #'rng-xsd-compile) |
| 46 | 46 | ||
| 47 | ;;;###autoload | 47 | ;;;###autoload |
| 48 | (defun rng-xsd-compile (name params) | 48 | (defun rng-xsd-compile (name params) |
| @@ -50,9 +50,9 @@ | |||
| 50 | NAME is a symbol giving the local name of the datatype. PARAMS is a | 50 | NAME is a symbol giving the local name of the datatype. PARAMS is a |
| 51 | list of pairs (PARAM-NAME . PARAM-VALUE) where PARAM-NAME is a symbol | 51 | list of pairs (PARAM-NAME . PARAM-VALUE) where PARAM-NAME is a symbol |
| 52 | giving the name of the parameter and PARAM-VALUE is a string giving | 52 | giving the name of the parameter and PARAM-VALUE is a string giving |
| 53 | its value. If NAME or PARAMS are invalid, it calls rng-dt-error | 53 | its value. If NAME or PARAMS are invalid, it calls `rng-dt-error' |
| 54 | passing it arguments in the same style as format; the value from | 54 | passing it arguments in the same style as format; the value from |
| 55 | rng-dt-error will be returned. Otherwise, it returns a list. The | 55 | `rng-dt-error' will be returned. Otherwise, it returns a list. The |
| 56 | first member of the list is t if any string is a legal value for the | 56 | first member of the list is t if any string is a legal value for the |
| 57 | datatype and nil otherwise. The second argument is a symbol; this | 57 | datatype and nil otherwise. The second argument is a symbol; this |
| 58 | symbol will be called as a function passing it a string followed by | 58 | symbol will be called as a function passing it a string followed by |
diff --git a/lisp/nxml/xmltok.el b/lisp/nxml/xmltok.el index 8fc66c99a45..f12905a86d0 100644 --- a/lisp/nxml/xmltok.el +++ b/lisp/nxml/xmltok.el | |||
| @@ -34,10 +34,7 @@ | |||
| 34 | ;; preceding part of the instance. This allows the instance to be | 34 | ;; preceding part of the instance. This allows the instance to be |
| 35 | ;; parsed incrementally. The main entry point is `xmltok-forward': | 35 | ;; parsed incrementally. The main entry point is `xmltok-forward': |
| 36 | ;; this can be called at any point in the instance provided it is | 36 | ;; this can be called at any point in the instance provided it is |
| 37 | ;; between tokens. The other entry point is `xmltok-forward-special' | 37 | ;; between tokens. |
| 38 | ;; which skips over tokens other comments, processing instructions or | ||
| 39 | ;; CDATA sections (i.e. the constructs in an instance that can contain | ||
| 40 | ;; less than signs that don't start a token). | ||
| 41 | ;; | 38 | ;; |
| 42 | ;; This is a non-validating XML 1.0 processor. It does not resolve | 39 | ;; This is a non-validating XML 1.0 processor. It does not resolve |
| 43 | ;; parameter entities (including the external DTD subset) and it does | 40 | ;; parameter entities (including the external DTD subset) and it does |
| @@ -262,11 +259,10 @@ and VALUE-END, otherwise a STRING giving the value." | |||
| 262 | (vector message start end)) | 259 | (vector message start end)) |
| 263 | 260 | ||
| 264 | (defun xmltok-add-error (message &optional start end) | 261 | (defun xmltok-add-error (message &optional start end) |
| 265 | (setq xmltok-errors | 262 | (push (xmltok-make-error message |
| 266 | (cons (xmltok-make-error message | 263 | (or start xmltok-start) |
| 267 | (or start xmltok-start) | 264 | (or end (point))) |
| 268 | (or end (point))) | 265 | xmltok-errors)) |
| 269 | xmltok-errors))) | ||
| 270 | 266 | ||
| 271 | (defun xmltok-forward () | 267 | (defun xmltok-forward () |
| 272 | (setq xmltok-start (point)) | 268 | (setq xmltok-start (point)) |
| @@ -308,18 +304,6 @@ and VALUE-END, otherwise a STRING giving the value." | |||
| 308 | (goto-char (point-max)) | 304 | (goto-char (point-max)) |
| 309 | (setq xmltok-type 'data))))) | 305 | (setq xmltok-type 'data))))) |
| 310 | 306 | ||
| 311 | (defun xmltok-forward-special (bound) | ||
| 312 | "Scan forward past the first special token starting at or after point. | ||
| 313 | Return nil if there is no special token that starts before BOUND. | ||
| 314 | CDATA sections, processing instructions and comments (and indeed | ||
| 315 | anything starting with < following by ? or !) count as special. | ||
| 316 | Return the type of the token." | ||
| 317 | (when (re-search-forward "<[?!]" (1+ bound) t) | ||
| 318 | (setq xmltok-start (match-beginning 0)) | ||
| 319 | (goto-char (1+ xmltok-start)) | ||
| 320 | (let ((case-fold-search nil)) | ||
| 321 | (xmltok-scan-after-lt)))) | ||
| 322 | |||
| 323 | (eval-when-compile | 307 | (eval-when-compile |
| 324 | 308 | ||
| 325 | ;; A symbolic regexp is represented by a list whose CAR is the string | 309 | ;; A symbolic regexp is represented by a list whose CAR is the string |
| @@ -739,19 +723,10 @@ Return the type of the token." | |||
| 739 | (setq xmltok-type 'processing-instruction)) | 723 | (setq xmltok-type 'processing-instruction)) |
| 740 | 724 | ||
| 741 | (defun xmltok-scan-after-comment-open () | 725 | (defun xmltok-scan-after-comment-open () |
| 742 | (let ((found-- (search-forward "--" nil 'move))) | 726 | (while (and (re-search-forward "--\\(>\\)?" nil 'move) |
| 743 | (setq xmltok-type | 727 | (not (match-end 1))) |
| 744 | (cond ((or (eq (char-after) ?>) (not found--)) | 728 | (xmltok-add-error "`--' not followed by `>'" (match-beginning 0))) |
| 745 | (goto-char (1+ (point))) | 729 | (setq xmltok-type 'comment)) |
| 746 | 'comment) | ||
| 747 | (t | ||
| 748 | ;; just include the <!-- in the token | ||
| 749 | (goto-char (+ xmltok-start 4)) | ||
| 750 | ;; Need do this after the goto-char because | ||
| 751 | ;; marked error should just apply to <!-- | ||
| 752 | (xmltok-add-error "First following `--' not followed by `>'") | ||
| 753 | (goto-char (point-max)) | ||
| 754 | 'comment))))) | ||
| 755 | 730 | ||
| 756 | (defun xmltok-scan-attributes () | 731 | (defun xmltok-scan-attributes () |
| 757 | (let ((recovering nil) | 732 | (let ((recovering nil) |
diff --git a/lisp/nxml/xsd-regexp.el b/lisp/nxml/xsd-regexp.el index e91e6b77a7d..a3f476d00be 100644 --- a/lisp/nxml/xsd-regexp.el +++ b/lisp/nxml/xsd-regexp.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; xsd-regexp.el --- translate W3C XML Schema regexps to Emacs regexps | 1 | ;;; xsd-regexp.el --- translate W3C XML Schema regexps to Emacs regexps -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -147,7 +147,7 @@ ranges are merged wherever possible." | |||
| 147 | (defun xsdre-range-list-difference (orig subtract) | 147 | (defun xsdre-range-list-difference (orig subtract) |
| 148 | "Return a range-list for the difference of two range-lists." | 148 | "Return a range-list for the difference of two range-lists." |
| 149 | (when orig | 149 | (when orig |
| 150 | (let (new head next first last) | 150 | (let (new head first last) |
| 151 | (while orig | 151 | (while orig |
| 152 | (setq head (car orig)) | 152 | (setq head (car orig)) |
| 153 | (setq first (xsdre-range-first head)) | 153 | (setq first (xsdre-range-first head)) |
| @@ -745,7 +745,7 @@ Code is inserted into the current buffer." | |||
| 745 | (save-excursion | 745 | (save-excursion |
| 746 | (goto-char start) | 746 | (goto-char start) |
| 747 | (down-list 2) | 747 | (down-list 2) |
| 748 | (while (condition-case err | 748 | (while (condition-case nil |
| 749 | (progn | 749 | (progn |
| 750 | (forward-sexp) | 750 | (forward-sexp) |
| 751 | t) | 751 | t) |
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 9e175a20e22..8f0b4f13b9e 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el | |||
| @@ -245,11 +245,8 @@ Blank lines separate paragraphs. Semicolons start comments. | |||
| 245 | ;; Font-locking support. | 245 | ;; Font-locking support. |
| 246 | 246 | ||
| 247 | (defun elisp--font-lock-flush-elisp-buffers (&optional file) | 247 | (defun elisp--font-lock-flush-elisp-buffers (&optional file) |
| 248 | ;; FIXME: Aren't we only ever called from after-load-functions? | 248 | ;; We're only ever called from after-load-functions, load-in-progress can |
| 249 | ;; Don't flush during load unless called from after-load-functions. | 249 | ;; still be t in case of nested loads. |
| 250 | ;; In that case, FILE is non-nil. It's somehow strange that | ||
| 251 | ;; load-in-progress is t when an after-load-function is called since | ||
| 252 | ;; that should run *after* the load... | ||
| 253 | (when (or (not load-in-progress) file) | 250 | (when (or (not load-in-progress) file) |
| 254 | ;; FIXME: If the loaded file did not define any macros, there shouldn't | 251 | ;; FIXME: If the loaded file did not define any macros, there shouldn't |
| 255 | ;; be any need to font-lock-flush all the Elisp buffers. | 252 | ;; be any need to font-lock-flush all the Elisp buffers. |
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index 2db7220de5c..271033b15f8 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el | |||
| @@ -1794,7 +1794,6 @@ Two variables control the processing we do on each file: the value of | |||
| 1794 | interesting (it returns non-nil if so) and `tags-loop-operate' is a form to | 1794 | interesting (it returns non-nil if so) and `tags-loop-operate' is a form to |
| 1795 | evaluate to operate on an interesting file. If the latter evaluates to | 1795 | evaluate to operate on an interesting file. If the latter evaluates to |
| 1796 | nil, we exit; otherwise we scan the next file." | 1796 | nil, we exit; otherwise we scan the next file." |
| 1797 | (declare (obsolete "use `xref-find-definitions' interface instead." "25.1")) | ||
| 1798 | (interactive) | 1797 | (interactive) |
| 1799 | (let (new | 1798 | (let (new |
| 1800 | ;; Non-nil means we have finished one file | 1799 | ;; Non-nil means we have finished one file |
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index c22de2f77ac..1a0385e167e 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el | |||
| @@ -1742,6 +1742,7 @@ and source-file directory for your debugger." | |||
| 1742 | (defcustom gud-guiler-command-name "guile" | 1742 | (defcustom gud-guiler-command-name "guile" |
| 1743 | "File name for executing the Guile debugger. | 1743 | "File name for executing the Guile debugger. |
| 1744 | This should be an executable on your path, or an absolute file name." | 1744 | This should be an executable on your path, or an absolute file name." |
| 1745 | :version "25.1" | ||
| 1745 | :type 'string | 1746 | :type 'string |
| 1746 | :group 'gud) | 1747 | :group 'gud) |
| 1747 | 1748 | ||
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el index 43cf42c048b..8a87eb9770a 100644 --- a/lisp/progmodes/hideif.el +++ b/lisp/progmodes/hideif.el | |||
| @@ -138,7 +138,7 @@ | |||
| 138 | 138 | ||
| 139 | (defcustom hide-ifdef-exclude-define-regexp nil | 139 | (defcustom hide-ifdef-exclude-define-regexp nil |
| 140 | "Ignore #define names if those names match this exclusion pattern." | 140 | "Ignore #define names if those names match this exclusion pattern." |
| 141 | :type 'string | 141 | :type '(choice (const nil) string) |
| 142 | :version "25.1") | 142 | :version "25.1") |
| 143 | 143 | ||
| 144 | (defcustom hide-ifdef-expand-reinclusion-protection t | 144 | (defcustom hide-ifdef-expand-reinclusion-protection t |
| @@ -1581,14 +1581,17 @@ Refer to `hide-ifdef-expand-reinclusion-protection' for more details." | |||
| 1581 | result)) | 1581 | result)) |
| 1582 | 1582 | ||
| 1583 | (defun hif-evaluate-macro (rstart rend) | 1583 | (defun hif-evaluate-macro (rstart rend) |
| 1584 | "Evaluate the macro expansion result for a region. | 1584 | "Evaluate the macro expansion result for the active region. |
| 1585 | If no region active, find the current #ifdefs and evaluate the result. | 1585 | If no region active, find the current #ifdefs and evaluate the result. |
| 1586 | Currently it supports only math calculations, strings or argumented macros can | 1586 | Currently it supports only math calculations, strings or argumented macros can |
| 1587 | not be expanded." | 1587 | not be expanded." |
| 1588 | (interactive "r") | 1588 | (interactive |
| 1589 | (if (use-region-p) | ||
| 1590 | (list (region-beginning) (region-end)) | ||
| 1591 | '(nil nil))) | ||
| 1589 | (let ((case-fold-search nil)) | 1592 | (let ((case-fold-search nil)) |
| 1590 | (save-excursion | 1593 | (save-excursion |
| 1591 | (unless mark-active | 1594 | (unless (use-region-p) |
| 1592 | (setq rstart nil rend nil) | 1595 | (setq rstart nil rend nil) |
| 1593 | (beginning-of-line) | 1596 | (beginning-of-line) |
| 1594 | (when (and (re-search-forward hif-macro-expr-prefix-regexp nil t) | 1597 | (when (and (re-search-forward hif-macro-expr-prefix-regexp nil t) |
| @@ -1844,9 +1847,13 @@ This allows #ifdef VAR to be hidden." | |||
| 1844 | 1847 | ||
| 1845 | (defun hide-ifdef-undef (start end) | 1848 | (defun hide-ifdef-undef (start end) |
| 1846 | "Undefine a VAR so that #ifdef VAR would not be included." | 1849 | "Undefine a VAR so that #ifdef VAR would not be included." |
| 1847 | (interactive "r") | 1850 | (interactive |
| 1851 | (if (use-region-p) | ||
| 1852 | (list (region-beginning) (region-end)) | ||
| 1853 | '(nil nil))) | ||
| 1848 | (let* ((symstr | 1854 | (let* ((symstr |
| 1849 | (or (and mark-active | 1855 | (or (and (number-or-marker-p start) |
| 1856 | (number-or-marker-p end) | ||
| 1850 | (buffer-substring-no-properties start end)) | 1857 | (buffer-substring-no-properties start end)) |
| 1851 | (read-string "Undefine what? " (current-word)))) | 1858 | (read-string "Undefine what? " (current-word)))) |
| 1852 | (sym (and symstr | 1859 | (sym (and symstr |
| @@ -1915,7 +1922,7 @@ Return as (TOP . BOTTOM) the extent of ifdef block." | |||
| 1915 | With optional prefix argument ARG, also hide the #ifdefs themselves." | 1922 | With optional prefix argument ARG, also hide the #ifdefs themselves." |
| 1916 | (interactive "P\nr") | 1923 | (interactive "P\nr") |
| 1917 | (let ((hide-ifdef-lines arg)) | 1924 | (let ((hide-ifdef-lines arg)) |
| 1918 | (if mark-active | 1925 | (if (use-region-p) |
| 1919 | (let ((hif-recurse-level (1+ hif-recurse-level))) | 1926 | (let ((hif-recurse-level (1+ hif-recurse-level))) |
| 1920 | (hif-recurse-on start end t) | 1927 | (hif-recurse-on start end t) |
| 1921 | (setq mark-active nil)) | 1928 | (setq mark-active nil)) |
| @@ -1931,8 +1938,12 @@ With optional prefix argument ARG, also hide the #ifdefs themselves." | |||
| 1931 | 1938 | ||
| 1932 | (defun show-ifdef-block (&optional start end) | 1939 | (defun show-ifdef-block (&optional start end) |
| 1933 | "Show the ifdef block (true or false part) enclosing or before the cursor." | 1940 | "Show the ifdef block (true or false part) enclosing or before the cursor." |
| 1934 | (interactive "r") | 1941 | (interactive |
| 1935 | (if mark-active | 1942 | (if (use-region-p) |
| 1943 | (list (region-beginning) (region-end)) | ||
| 1944 | '(nil nil))) | ||
| 1945 | (if (and (number-or-marker-p start) | ||
| 1946 | (number-or-marker-p end)) | ||
| 1936 | (progn | 1947 | (progn |
| 1937 | (dolist (o (overlays-in start end)) | 1948 | (dolist (o (overlays-in start end)) |
| 1938 | (if (overlay-get o 'hide-ifdef) | 1949 | (if (overlay-get o 'hide-ifdef) |
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el index 2f12df47723..718b33932ed 100644 --- a/lisp/progmodes/prog-mode.el +++ b/lisp/progmodes/prog-mode.el | |||
| @@ -202,6 +202,7 @@ is immediately after the symbol. The prettification will be | |||
| 202 | reapplied as soon as point moves away from the symbol. If | 202 | reapplied as soon as point moves away from the symbol. If |
| 203 | set to nil, the prettification persists even when point is | 203 | set to nil, the prettification persists even when point is |
| 204 | on the symbol." | 204 | on the symbol." |
| 205 | :version "25.1" | ||
| 205 | :type '(choice (const :tag "Never unprettify" nil) | 206 | :type '(choice (const :tag "Never unprettify" nil) |
| 206 | (const :tag "Unprettify when point is inside" t) | 207 | (const :tag "Unprettify when point is inside" t) |
| 207 | (const :tag "Unprettify when point is inside or at right edge" right-edge)) | 208 | (const :tag "Unprettify when point is inside or at right edge" right-edge)) |
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index fe28ed776b2..85f390746d9 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el | |||
| @@ -156,10 +156,11 @@ end it with `/'. DIR must be one of `project-roots' or | |||
| 156 | 156 | ||
| 157 | (defgroup project-vc nil | 157 | (defgroup project-vc nil |
| 158 | "Project implementation using the VC package." | 158 | "Project implementation using the VC package." |
| 159 | :version "25.1" | ||
| 159 | :group 'tools) | 160 | :group 'tools) |
| 160 | 161 | ||
| 161 | (defcustom project-vc-ignores nil | 162 | (defcustom project-vc-ignores nil |
| 162 | "List ot patterns to include in `project-ignores'." | 163 | "List of patterns to include in `project-ignores'." |
| 163 | :type '(repeat string) | 164 | :type '(repeat string) |
| 164 | :safe 'listp) | 165 | :safe 'listp) |
| 165 | 166 | ||
| @@ -263,7 +264,6 @@ DIRS must contain directory names." | |||
| 263 | (symbol-value var))) | 264 | (symbol-value var))) |
| 264 | 265 | ||
| 265 | (declare-function grep-read-files "grep") | 266 | (declare-function grep-read-files "grep") |
| 266 | (declare-function xref-collect-matches "xref") | ||
| 267 | (declare-function xref--show-xrefs "xref") | 267 | (declare-function xref--show-xrefs "xref") |
| 268 | (declare-function xref-backend-identifier-at-point "xref") | 268 | (declare-function xref-backend-identifier-at-point "xref") |
| 269 | (declare-function xref--find-ignores-arguments "xref") | 269 | (declare-function xref--find-ignores-arguments "xref") |
| @@ -294,8 +294,8 @@ pattern to search for." | |||
| 294 | (project--find-regexp-in dirs regexp pr))) | 294 | (project--find-regexp-in dirs regexp pr))) |
| 295 | 295 | ||
| 296 | (defun project--read-regexp () | 296 | (defun project--read-regexp () |
| 297 | (read-regexp "Find regexp" | 297 | (let ((id (xref-backend-identifier-at-point (xref-find-backend)))) |
| 298 | (xref-backend-identifier-at-point (xref-find-backend)))) | 298 | (read-regexp "Find regexp" (and id (regexp-quote id))))) |
| 299 | 299 | ||
| 300 | (defun project--find-regexp-in (dirs regexp project) | 300 | (defun project--find-regexp-in (dirs regexp project) |
| 301 | (require 'grep) | 301 | (require 'grep) |
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 4984c9908bf..a8c65fa23a9 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -715,6 +715,7 @@ It makes underscores and dots word constituent chars.") | |||
| 715 | 715 | ||
| 716 | (defcustom python-indent-guess-indent-offset-verbose t | 716 | (defcustom python-indent-guess-indent-offset-verbose t |
| 717 | "Non-nil means to emit a warning when indentation guessing fails." | 717 | "Non-nil means to emit a warning when indentation guessing fails." |
| 718 | :version "25.1" | ||
| 718 | :type 'boolean | 719 | :type 'boolean |
| 719 | :group 'python | 720 | :group 'python |
| 720 | :safe' booleanp) | 721 | :safe' booleanp) |
| @@ -1999,6 +2000,7 @@ hosts PATH before starting processes. Values defined in | |||
| 1999 | here. Normally you wont use this variable directly unless you | 2000 | here. Normally you wont use this variable directly unless you |
| 2000 | plan to ensure a particular set of paths to all Python shell | 2001 | plan to ensure a particular set of paths to all Python shell |
| 2001 | executed through tramp connections." | 2002 | executed through tramp connections." |
| 2003 | :version "25.1" | ||
| 2002 | :type '(repeat string) | 2004 | :type '(repeat string) |
| 2003 | :group 'python) | 2005 | :group 'python) |
| 2004 | 2006 | ||
| @@ -2042,8 +2044,8 @@ virtualenv." | |||
| 2042 | (defun python-shell-calculate-pythonpath () | 2044 | (defun python-shell-calculate-pythonpath () |
| 2043 | "Calculate the PYTHONPATH using `python-shell-extra-pythonpaths'." | 2045 | "Calculate the PYTHONPATH using `python-shell-extra-pythonpaths'." |
| 2044 | (let ((pythonpath | 2046 | (let ((pythonpath |
| 2045 | (tramp-compat-split-string | 2047 | (split-string |
| 2046 | (or (getenv "PYTHONPATH") "") path-separator))) | 2048 | (or (getenv "PYTHONPATH") "") path-separator 'omit))) |
| 2047 | (python-shell--add-to-path-with-priority | 2049 | (python-shell--add-to-path-with-priority |
| 2048 | pythonpath python-shell-extra-pythonpaths) | 2050 | pythonpath python-shell-extra-pythonpaths) |
| 2049 | (mapconcat 'identity pythonpath path-separator))) | 2051 | (mapconcat 'identity pythonpath path-separator))) |
| @@ -2114,7 +2116,7 @@ appends `python-shell-remote-exec-path' instead of `exec-path'." | |||
| 2114 | (md5 tramp-end-of-output))) | 2116 | (md5 tramp-end-of-output))) |
| 2115 | unset vars item) | 2117 | unset vars item) |
| 2116 | (while env | 2118 | (while env |
| 2117 | (setq item (tramp-compat-split-string (car env) "=")) | 2119 | (setq item (split-string (car env) "=" 'omit)) |
| 2118 | (setcdr item (mapconcat 'identity (cdr item) "=")) | 2120 | (setcdr item (mapconcat 'identity (cdr item) "=")) |
| 2119 | (if (and (stringp (cdr item)) (not (string-equal (cdr item) ""))) | 2121 | (if (and (stringp (cdr item)) (not (string-equal (cdr item) ""))) |
| 2120 | (push (format "%s %s" (car item) (cdr item)) vars) | 2122 | (push (format "%s %s" (car item) (cdr item)) vars) |
| @@ -2621,6 +2623,7 @@ current process to not hang waiting for output by safeguarding | |||
| 2621 | interactive actions can be performed. This is useful to safely | 2623 | interactive actions can be performed. This is useful to safely |
| 2622 | attach setup code for long-running processes that eventually | 2624 | attach setup code for long-running processes that eventually |
| 2623 | provide a shell." | 2625 | provide a shell." |
| 2626 | :version "25.1" | ||
| 2624 | :type 'hook | 2627 | :type 'hook |
| 2625 | :group 'python) | 2628 | :group 'python) |
| 2626 | 2629 | ||
| @@ -3258,18 +3261,22 @@ the full statement in the case of imports." | |||
| 3258 | (list "pypy") | 3261 | (list "pypy") |
| 3259 | "List of disabled interpreters. | 3262 | "List of disabled interpreters. |
| 3260 | When a match is found, native completion is disabled." | 3263 | When a match is found, native completion is disabled." |
| 3264 | :version "25.1" | ||
| 3261 | :type '(repeat string)) | 3265 | :type '(repeat string)) |
| 3262 | 3266 | ||
| 3263 | (defcustom python-shell-completion-native-enable t | 3267 | (defcustom python-shell-completion-native-enable t |
| 3264 | "Enable readline based native completion." | 3268 | "Enable readline based native completion." |
| 3269 | :version "25.1" | ||
| 3265 | :type 'boolean) | 3270 | :type 'boolean) |
| 3266 | 3271 | ||
| 3267 | (defcustom python-shell-completion-native-output-timeout 5.0 | 3272 | (defcustom python-shell-completion-native-output-timeout 5.0 |
| 3268 | "Time in seconds to wait for completion output before giving up." | 3273 | "Time in seconds to wait for completion output before giving up." |
| 3274 | :version "25.1" | ||
| 3269 | :type 'float) | 3275 | :type 'float) |
| 3270 | 3276 | ||
| 3271 | (defcustom python-shell-completion-native-try-output-timeout 1.0 | 3277 | (defcustom python-shell-completion-native-try-output-timeout 1.0 |
| 3272 | "Time in seconds to wait for *trying* native completion output." | 3278 | "Time in seconds to wait for *trying* native completion output." |
| 3279 | :version "25.1" | ||
| 3273 | :type 'float) | 3280 | :type 'float) |
| 3274 | 3281 | ||
| 3275 | (defvar python-shell-completion-native-redirect-buffer | 3282 | (defvar python-shell-completion-native-redirect-buffer |
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 8f08b7c9e60..53f8a6bb4c0 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el | |||
| @@ -1830,7 +1830,7 @@ It will be properly highlighted even when the call omits parens.") | |||
| 1830 | "\\)\\s *") | 1830 | "\\)\\s *") |
| 1831 | "Regexp to match text that can be followed by a regular expression.")) | 1831 | "Regexp to match text that can be followed by a regular expression.")) |
| 1832 | 1832 | ||
| 1833 | (defun ruby-syntax-propertize-function (start end) | 1833 | (defun ruby-syntax-propertize (start end) |
| 1834 | "Syntactic keywords for Ruby mode. See `syntax-propertize-function'." | 1834 | "Syntactic keywords for Ruby mode. See `syntax-propertize-function'." |
| 1835 | (let (case-fold-search) | 1835 | (let (case-fold-search) |
| 1836 | (goto-char start) | 1836 | (goto-char start) |
| @@ -1856,6 +1856,8 @@ It will be properly highlighted even when the call omits parens.") | |||
| 1856 | (zerop (skip-syntax-backward "w_"))) | 1856 | (zerop (skip-syntax-backward "w_"))) |
| 1857 | (memq (preceding-char) '(?@ ?$)))) | 1857 | (memq (preceding-char) '(?@ ?$)))) |
| 1858 | (string-to-syntax "_")))) | 1858 | (string-to-syntax "_")))) |
| 1859 | ;; Backtick method redefinition. | ||
| 1860 | ("^[ \t]*def +\\(`\\)" (1 "_")) | ||
| 1859 | ;; Regular expressions. Start with matching unescaped slash. | 1861 | ;; Regular expressions. Start with matching unescaped slash. |
| 1860 | ("\\(?:\\=\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(/\\)" | 1862 | ("\\(?:\\=\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(/\\)" |
| 1861 | (1 (let ((state (save-excursion (syntax-ppss (match-beginning 1))))) | 1863 | (1 (let ((state (save-excursion (syntax-ppss (match-beginning 1))))) |
| @@ -1891,6 +1893,9 @@ It will be properly highlighted even when the call omits parens.") | |||
| 1891 | (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end))))) | 1893 | (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end))))) |
| 1892 | (point) end))) | 1894 | (point) end))) |
| 1893 | 1895 | ||
| 1896 | (define-obsolete-function-alias | ||
| 1897 | 'ruby-syntax-propertize-function 'ruby-syntax-propertize "25.1") | ||
| 1898 | |||
| 1894 | (defun ruby-syntax-propertize-heredoc (limit) | 1899 | (defun ruby-syntax-propertize-heredoc (limit) |
| 1895 | (let ((ppss (syntax-ppss)) | 1900 | (let ((ppss (syntax-ppss)) |
| 1896 | (res '())) | 1901 | (res '())) |
| @@ -2252,7 +2257,7 @@ See `font-lock-syntax-table'.") | |||
| 2252 | (setq-local font-lock-keywords ruby-font-lock-keywords) | 2257 | (setq-local font-lock-keywords ruby-font-lock-keywords) |
| 2253 | (setq-local font-lock-syntax-table ruby-font-lock-syntax-table) | 2258 | (setq-local font-lock-syntax-table ruby-font-lock-syntax-table) |
| 2254 | 2259 | ||
| 2255 | (setq-local syntax-propertize-function #'ruby-syntax-propertize-function)) | 2260 | (setq-local syntax-propertize-function #'ruby-syntax-propertize)) |
| 2256 | 2261 | ||
| 2257 | ;;; Invoke ruby-mode when appropriate | 2262 | ;;; Invoke ruby-mode when appropriate |
| 2258 | 2263 | ||
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index fe39122d24f..2bccd857576 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el | |||
| @@ -76,6 +76,7 @@ | |||
| 76 | (require 'semantic/symref)) ;; for hit-lines slot | 76 | (require 'semantic/symref)) ;; for hit-lines slot |
| 77 | 77 | ||
| 78 | (defgroup xref nil "Cross-referencing commands" | 78 | (defgroup xref nil "Cross-referencing commands" |
| 79 | :version "25.1" | ||
| 79 | :group 'tools) | 80 | :group 'tools) |
| 80 | 81 | ||
| 81 | 82 | ||
| @@ -510,11 +511,18 @@ references displayed in the current *xref* buffer." | |||
| 510 | (let ((fr (read-regexp "Xref query-replace (regexp)" ".*"))) | 511 | (let ((fr (read-regexp "Xref query-replace (regexp)" ".*"))) |
| 511 | (list fr | 512 | (list fr |
| 512 | (read-regexp (format "Xref query-replace (regexp) %s with: " fr))))) | 513 | (read-regexp (format "Xref query-replace (regexp) %s with: " fr))))) |
| 513 | (let (pairs item) | 514 | (let ((reporter (make-progress-reporter (format "Saving search results...") |
| 515 | 0 (line-number-at-pos (point-max)))) | ||
| 516 | (counter 0) | ||
| 517 | pairs item) | ||
| 514 | (unwind-protect | 518 | (unwind-protect |
| 515 | (progn | 519 | (progn |
| 516 | (save-excursion | 520 | (save-excursion |
| 517 | (goto-char (point-min)) | 521 | (goto-char (point-min)) |
| 522 | ;; TODO: This list should be computed on-demand instead. | ||
| 523 | ;; As long as the UI just iterates through matches one by | ||
| 524 | ;; one, there's no need to compute them all in advance. | ||
| 525 | ;; Then we can throw away the reporter. | ||
| 518 | (while (setq item (xref--search-property 'xref-item)) | 526 | (while (setq item (xref--search-property 'xref-item)) |
| 519 | (when (xref-match-length item) | 527 | (when (xref-match-length item) |
| 520 | (save-excursion | 528 | (save-excursion |
| @@ -534,9 +542,11 @@ references displayed in the current *xref* buffer." | |||
| 534 | (line-end-position)) | 542 | (line-end-position)) |
| 535 | (xref-item-summary item)) | 543 | (xref-item-summary item)) |
| 536 | (user-error "Search results out of date")) | 544 | (user-error "Search results out of date")) |
| 545 | (progress-reporter-update reporter (cl-incf counter)) | ||
| 537 | (push (cons beg end) pairs))))) | 546 | (push (cons beg end) pairs))))) |
| 538 | (setq pairs (nreverse pairs))) | 547 | (setq pairs (nreverse pairs))) |
| 539 | (unless pairs (user-error "No suitable matches here")) | 548 | (unless pairs (user-error "No suitable matches here")) |
| 549 | (progress-reporter-done reporter) | ||
| 540 | (xref--query-replace-1 from to pairs)) | 550 | (xref--query-replace-1 from to pairs)) |
| 541 | (dolist (pair pairs) | 551 | (dolist (pair pairs) |
| 542 | (move-marker (car pair) nil) | 552 | (move-marker (car pair) nil) |
| @@ -712,9 +722,9 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)." | |||
| 712 | 722 | ||
| 713 | (defvar xref--read-pattern-history nil) | 723 | (defvar xref--read-pattern-history nil) |
| 714 | 724 | ||
| 715 | (defun xref--show-xrefs (xrefs window) | 725 | (defun xref--show-xrefs (xrefs window &optional always-show-list) |
| 716 | (cond | 726 | (cond |
| 717 | ((not (cdr xrefs)) | 727 | ((and (not (cdr xrefs)) (not always-show-list)) |
| 718 | (xref-push-marker-stack) | 728 | (xref-push-marker-stack) |
| 719 | (xref--pop-to-location (car xrefs) window)) | 729 | (xref--pop-to-location (car xrefs) window)) |
| 720 | (t | 730 | (t |
| @@ -865,11 +875,12 @@ tools are used, and when." | |||
| 865 | (mapc #'kill-buffer | 875 | (mapc #'kill-buffer |
| 866 | (cl-set-difference (buffer-list) orig-buffers))))) | 876 | (cl-set-difference (buffer-list) orig-buffers))))) |
| 867 | 877 | ||
| 878 | ;;;###autoload | ||
| 868 | (defun xref-collect-matches (regexp files dir ignores) | 879 | (defun xref-collect-matches (regexp files dir ignores) |
| 869 | "Collect matches for REGEXP inside FILES in DIR. | 880 | "Collect matches for REGEXP inside FILES in DIR. |
| 870 | FILES is a string with glob patterns separated by spaces. | 881 | FILES is a string with glob patterns separated by spaces. |
| 871 | IGNORES is a list of glob patterns." | 882 | IGNORES is a list of glob patterns." |
| 872 | (cl-assert (directory-name-p dir)) | 883 | ;; DIR can also be a regular file for now; let's not advertise that. |
| 873 | (require 'semantic/fw) | 884 | (require 'semantic/fw) |
| 874 | (grep-compute-defaults) | 885 | (grep-compute-defaults) |
| 875 | (defvar grep-find-template) | 886 | (defvar grep-find-template) |
| @@ -884,6 +895,8 @@ IGNORES is a list of glob patterns." | |||
| 884 | (orig-buffers (buffer-list)) | 895 | (orig-buffers (buffer-list)) |
| 885 | (buf (get-buffer-create " *xref-grep*")) | 896 | (buf (get-buffer-create " *xref-grep*")) |
| 886 | (grep-re (caar grep-regexp-alist)) | 897 | (grep-re (caar grep-regexp-alist)) |
| 898 | (counter 0) | ||
| 899 | reporter | ||
| 887 | hits) | 900 | hits) |
| 888 | (with-current-buffer buf | 901 | (with-current-buffer buf |
| 889 | (erase-buffer) | 902 | (erase-buffer) |
| @@ -893,9 +906,17 @@ IGNORES is a list of glob patterns." | |||
| 893 | (push (cons (string-to-number (match-string 2)) | 906 | (push (cons (string-to-number (match-string 2)) |
| 894 | (match-string 1)) | 907 | (match-string 1)) |
| 895 | hits))) | 908 | hits))) |
| 909 | (setq reporter (make-progress-reporter | ||
| 910 | (format "Collecting search results...") | ||
| 911 | 0 (length hits))) | ||
| 896 | (unwind-protect | 912 | (unwind-protect |
| 897 | (cl-mapcan (lambda (hit) (xref--collect-matches hit regexp)) | 913 | (cl-mapcan (lambda (hit) |
| 914 | (prog1 | ||
| 915 | (progress-reporter-update reporter counter) | ||
| 916 | (cl-incf counter)) | ||
| 917 | (xref--collect-matches hit regexp)) | ||
| 898 | (nreverse hits)) | 918 | (nreverse hits)) |
| 919 | (progress-reporter-done reporter) | ||
| 899 | ;; TODO: Same as above. | 920 | ;; TODO: Same as above. |
| 900 | (mapc #'kill-buffer | 921 | (mapc #'kill-buffer |
| 901 | (cl-set-difference (buffer-list) orig-buffers))))) | 922 | (cl-set-difference (buffer-list) orig-buffers))))) |
| @@ -921,23 +942,24 @@ IGNORES is a list of glob patterns." | |||
| 921 | (defun xref--find-ignores-arguments (ignores dir) | 942 | (defun xref--find-ignores-arguments (ignores dir) |
| 922 | ;; `shell-quote-argument' quotes the tilde as well. | 943 | ;; `shell-quote-argument' quotes the tilde as well. |
| 923 | (cl-assert (not (string-match-p "\\`~" dir))) | 944 | (cl-assert (not (string-match-p "\\`~" dir))) |
| 924 | (concat | 945 | (when ignores |
| 925 | (shell-quote-argument "(") | 946 | (concat |
| 926 | " -path " | 947 | (shell-quote-argument "(") |
| 927 | (mapconcat | 948 | " -path " |
| 928 | (lambda (ignore) | 949 | (mapconcat |
| 929 | (when (string-match-p "/\\'" ignore) | 950 | (lambda (ignore) |
| 930 | (setq ignore (concat ignore "*"))) | 951 | (when (string-match-p "/\\'" ignore) |
| 931 | (if (string-match "\\`\\./" ignore) | 952 | (setq ignore (concat ignore "*"))) |
| 932 | (setq ignore (replace-match dir t t ignore)) | 953 | (if (string-match "\\`\\./" ignore) |
| 933 | (unless (string-prefix-p "*" ignore) | 954 | (setq ignore (replace-match dir t t ignore)) |
| 934 | (setq ignore (concat "*/" ignore)))) | 955 | (unless (string-prefix-p "*" ignore) |
| 935 | (shell-quote-argument ignore)) | 956 | (setq ignore (concat "*/" ignore)))) |
| 936 | ignores | 957 | (shell-quote-argument ignore)) |
| 937 | " -o -path ") | 958 | ignores |
| 938 | " " | 959 | " -o -path ") |
| 939 | (shell-quote-argument ")") | 960 | " " |
| 940 | " -prune -o ")) | 961 | (shell-quote-argument ")") |
| 962 | " -prune -o "))) | ||
| 941 | 963 | ||
| 942 | (defun xref--regexp-to-extended (str) | 964 | (defun xref--regexp-to-extended (str) |
| 943 | (replace-regexp-in-string | 965 | (replace-regexp-in-string |
diff --git a/lisp/rect.el b/lisp/rect.el index 789d0e9082d..73790f2f92a 100644 --- a/lisp/rect.el +++ b/lisp/rect.el | |||
| @@ -403,6 +403,7 @@ With a prefix (or a FILL) argument, also fill too short lines." | |||
| 403 | 403 | ||
| 404 | (defcustom rectangle-preview t | 404 | (defcustom rectangle-preview t |
| 405 | "If non-nil, `string-rectangle' will show an-the-fly preview." | 405 | "If non-nil, `string-rectangle' will show an-the-fly preview." |
| 406 | :version "25.1" | ||
| 406 | :type 'boolean) | 407 | :type 'boolean) |
| 407 | 408 | ||
| 408 | (defun rectangle--string-preview () | 409 | (defun rectangle--string-preview () |
diff --git a/lisp/term/screen.el b/lisp/term/screen.el index 704fbefb0ad..7f681154d6e 100644 --- a/lisp/term/screen.el +++ b/lisp/term/screen.el | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | "Extra capabilities supported under \"screen\". | 7 | "Extra capabilities supported under \"screen\". |
| 8 | Some features of screen depend on the terminal emulator in which | 8 | Some features of screen depend on the terminal emulator in which |
| 9 | it runs, which can change when the screen session is moved to another tty." | 9 | it runs, which can change when the screen session is moved to another tty." |
| 10 | :version "25.1" | ||
| 10 | :type xterm--extra-capabilities-type | 11 | :type xterm--extra-capabilities-type |
| 11 | :group 'xterm) | 12 | :group 'xterm) |
| 12 | 13 | ||
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index 104f98311a8..e06423ccfdd 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el | |||
| @@ -65,6 +65,7 @@ using the OSC 52 sequence. | |||
| 65 | If you select a region larger than this size, it won't be copied to your system | 65 | If you select a region larger than this size, it won't be copied to your system |
| 66 | clipboard. Since clipboard data is base 64 encoded, the actual number of | 66 | clipboard. Since clipboard data is base 64 encoded, the actual number of |
| 67 | string bytes that can be copied is 3/4 of this value." | 67 | string bytes that can be copied is 3/4 of this value." |
| 68 | :version "25.1" | ||
| 68 | :type 'integer) | 69 | :type 'integer) |
| 69 | 70 | ||
| 70 | (defconst xterm-paste-ending-sequence "\e[201~" | 71 | (defconst xterm-paste-ending-sequence "\e[201~" |
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index 48c24844a68..d402fb19955 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el | |||
| @@ -257,13 +257,13 @@ | |||
| 257 | (if (not sassy) | 257 | (if (not sassy) |
| 258 | ;; We don't allow / as first char, so as not to | 258 | ;; We don't allow / as first char, so as not to |
| 259 | ;; take a comment as the beginning of a selector. | 259 | ;; take a comment as the beginning of a selector. |
| 260 | "[^@/:{} \t\n][^:{}]+" | 260 | "[^@/:{}() \t\n][^:{}()]+" |
| 261 | ;; Same as for non-sassy except we do want to allow { and } | 261 | ;; Same as for non-sassy except we do want to allow { and } |
| 262 | ;; chars in selectors in the case of #{$foo} | 262 | ;; chars in selectors in the case of #{$foo} |
| 263 | ;; variable interpolation! | 263 | ;; variable interpolation! |
| 264 | (concat "\\(?:" scss--hash-re | 264 | (concat "\\(?:" scss--hash-re |
| 265 | "\\|[^@/:{} \t\n#]\\)" | 265 | "\\|[^@/:{}() \t\n#]\\)" |
| 266 | "[^:{}#]*\\(?:" scss--hash-re "[^:{}#]*\\)*")) | 266 | "[^:{}()#]*\\(?:" scss--hash-re "[^:{}()#]*\\)*")) |
| 267 | ;; Even though pseudo-elements should be prefixed by ::, a | 267 | ;; Even though pseudo-elements should be prefixed by ::, a |
| 268 | ;; single colon is accepted for backward compatibility. | 268 | ;; single colon is accepted for backward compatibility. |
| 269 | "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids | 269 | "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids |
| @@ -271,8 +271,8 @@ | |||
| 271 | "\\|\\::" (regexp-opt css-pseudo-element-ids t) "\\)" | 271 | "\\|\\::" (regexp-opt css-pseudo-element-ids t) "\\)" |
| 272 | "\\(?:([^)]+)\\)?" | 272 | "\\(?:([^)]+)\\)?" |
| 273 | (if (not sassy) | 273 | (if (not sassy) |
| 274 | "[^:{}\n]*" | 274 | "[^:{}()\n]*" |
| 275 | (concat "[^:{}\n#]*\\(?:" scss--hash-re "[^:{}\n#]*\\)*")) | 275 | (concat "[^:{}()\n#]*\\(?:" scss--hash-re "[^:{}()\n#]*\\)*")) |
| 276 | "\\)*" | 276 | "\\)*" |
| 277 | "\\)\\(?:\n[ \t]*\\)*{") | 277 | "\\)\\(?:\n[ \t]*\\)*{") |
| 278 | (1 'css-selector keep)) | 278 | (1 'css-selector keep)) |
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index 98a01e8d83f..f729760e9ca 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el | |||
| @@ -862,11 +862,12 @@ Return non-nil if we skipped over matched tags." | |||
| 862 | (if endp | 862 | (if endp |
| 863 | (when (sgml-skip-tag-backward 1) (forward-char 1) t) | 863 | (when (sgml-skip-tag-backward 1) (forward-char 1) t) |
| 864 | (with-syntax-table sgml-tag-syntax-table | 864 | (with-syntax-table sgml-tag-syntax-table |
| 865 | (up-list -1) | 865 | (let ((forward-sexp-function nil)) |
| 866 | (when (sgml-skip-tag-forward 1) | 866 | (up-list -1) |
| 867 | (backward-sexp 1) | 867 | (when (sgml-skip-tag-forward 1) |
| 868 | (forward-char 2) | 868 | (backward-sexp 1) |
| 869 | t)))) | 869 | (forward-char 2) |
| 870 | t))))) | ||
| 870 | (clones (get-char-property (point) 'text-clones))) | 871 | (clones (get-char-property (point) 'text-clones))) |
| 871 | (when (and match | 872 | (when (and match |
| 872 | (/= cl-end cl-start) | 873 | (/= cl-end cl-start) |
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el index eb799c09510..598060e9ec8 100644 --- a/lisp/textmodes/tildify.el +++ b/lisp/textmodes/tildify.el | |||
| @@ -417,7 +417,7 @@ current `case-fold-search' setting." | |||
| 417 | "A list of predicate functions for `tildify-space' function." | 417 | "A list of predicate functions for `tildify-space' function." |
| 418 | :version "25.1" | 418 | :version "25.1" |
| 419 | :group 'tildify | 419 | :group 'tildify |
| 420 | :type '(repeat 'function)) | 420 | :type '(repeat function)) |
| 421 | 421 | ||
| 422 | (defcustom tildify-double-space-undos t | 422 | (defcustom tildify-double-space-undos t |
| 423 | "Weather `tildify-space' should undo hard space when space is typed again." | 423 | "Weather `tildify-space' should undo hard space when space is typed again." |
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el index 9794d002149..1686c02ada3 100644 --- a/lisp/thingatpt.el +++ b/lisp/thingatpt.el | |||
| @@ -280,8 +280,8 @@ If nil, construct the regexp from `thing-at-point-uri-schemes'.") | |||
| 280 | "finger://" "fish://" "ftp://" "geo:" "git://" "go:" "gopher://" | 280 | "finger://" "fish://" "ftp://" "geo:" "git://" "go:" "gopher://" |
| 281 | "h323:" "http://" "https://" "im:" "imap://" "info:" "ipp:" | 281 | "h323:" "http://" "https://" "im:" "imap://" "info:" "ipp:" |
| 282 | "irc://" "irc6://" "ircs://" "iris.beep:" "jar:" "ldap://" | 282 | "irc://" "irc6://" "ircs://" "iris.beep:" "jar:" "ldap://" |
| 283 | "ldaps://" "mailto:" "mid:" "mtqp://" "mupdate://" "news:" | 283 | "ldaps://" "magnet:" "mailto:" "mid:" "mtqp://" "mupdate://" |
| 284 | "nfs://" "nntp://" "opaquelocktoken:" "pop://" "pres:" | 284 | "news:" "nfs://" "nntp://" "opaquelocktoken:" "pop://" "pres:" |
| 285 | "resource://" "rmi://" "rsync://" "rtsp://" "rtspu://" "service:" | 285 | "resource://" "rmi://" "rsync://" "rtsp://" "rtspu://" "service:" |
| 286 | "sftp://" "sip:" "sips:" "smb://" "sms:" "snmp://" "soap.beep://" | 286 | "sftp://" "sip:" "sips:" "smb://" "sms:" "snmp://" "soap.beep://" |
| 287 | "soap.beeps://" "ssh://" "svn://" "svn+ssh://" "tag:" "tel:" | 287 | "soap.beeps://" "ssh://" "svn://" "svn+ssh://" "tag:" "tel:" |
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index 46c993e1f5f..d58942c3a2b 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | 5 | ||
| 6 | ;; This file is part of GNU Emacs. | 6 | ;; This file is part of GNU Emacs. |
| 7 | 7 | ||
| 8 | ;; Maintainer's Time-stamp: <2006-04-12 20:30:56 rms> | ||
| 9 | ;; Maintainer: Stephen Gildea <gildea@stop.mail-abuse.org> | 8 | ;; Maintainer: Stephen Gildea <gildea@stop.mail-abuse.org> |
| 10 | ;; Keywords: tools | 9 | ;; Keywords: tools |
| 11 | 10 | ||
| @@ -27,7 +26,6 @@ | |||
| 27 | ;; A template in a file can be updated with a new time stamp when | 26 | ;; A template in a file can be updated with a new time stamp when |
| 28 | ;; you save the file. For example: | 27 | ;; you save the file. For example: |
| 29 | ;; static char *ts = "sdmain.c Time-stamp: <2001-08-13 10:20:51 gildea>"; | 28 | ;; static char *ts = "sdmain.c Time-stamp: <2001-08-13 10:20:51 gildea>"; |
| 30 | ;; See the top of `time-stamp.el' for another example. | ||
| 31 | 29 | ||
| 32 | ;; To use time-stamping, add this line to your init file: | 30 | ;; To use time-stamping, add this line to your init file: |
| 33 | ;; (add-hook 'before-save-hook 'time-stamp) | 31 | ;; (add-hook 'before-save-hook 'time-stamp) |
| @@ -121,9 +119,12 @@ If nil, no notification is given." | |||
| 121 | :group 'time-stamp) | 119 | :group 'time-stamp) |
| 122 | 120 | ||
| 123 | (defcustom time-stamp-time-zone nil | 121 | (defcustom time-stamp-time-zone nil |
| 124 | "If non-nil, a string naming the timezone to be used by \\[time-stamp]. | 122 | "The time zone to be used by \\[time-stamp]. |
| 125 | Format is the same as that used by the environment variable TZ on your system." | 123 | Its format is that of the ZONE argument of the `format-time-string' function," |
| 126 | :type '(choice (const nil) string) | 124 | :type '(choice (const :tag "Emacs local time" nil) |
| 125 | (const :tag "Universal Time" t) | ||
| 126 | (const :tag "system wall clock time" wall) | ||
| 127 | (string :tag "TZ environment variable value")) | ||
| 127 | :group 'time-stamp | 128 | :group 'time-stamp |
| 128 | :version "20.1") | 129 | :version "20.1") |
| 129 | ;;;###autoload(put 'time-stamp-time-zone 'safe-local-variable 'string-or-null-p) | 130 | ;;;###autoload(put 'time-stamp-time-zone 'safe-local-variable 'string-or-null-p) |
| @@ -412,6 +413,8 @@ With ARG, turn time stamping on if and only if arg is positive." | |||
| 412 | (> (prefix-numeric-value arg) 0))) | 413 | (> (prefix-numeric-value arg) 0))) |
| 413 | (message "time-stamp is now %s." (if time-stamp-active "active" "off"))) | 414 | (message "time-stamp is now %s." (if time-stamp-active "active" "off"))) |
| 414 | 415 | ||
| 416 | (defun time-stamp--format (format time) | ||
| 417 | (format-time-string format time time-stamp-time-zone)) | ||
| 415 | 418 | ||
| 416 | (defun time-stamp-string (&optional ts-format) | 419 | (defun time-stamp-string (&optional ts-format) |
| 417 | "Generate the new string to be inserted by \\[time-stamp]. | 420 | "Generate the new string to be inserted by \\[time-stamp]. |
| @@ -420,8 +423,7 @@ format the string." | |||
| 420 | (or ts-format | 423 | (or ts-format |
| 421 | (setq ts-format time-stamp-format)) | 424 | (setq ts-format time-stamp-format)) |
| 422 | (if (stringp ts-format) | 425 | (if (stringp ts-format) |
| 423 | (format-time-string (time-stamp-string-preprocess ts-format) | 426 | (time-stamp--format (time-stamp-string-preprocess ts-format) nil) |
| 424 | nil time-stamp-time-zone) | ||
| 425 | ;; handle version 1 compatibility | 427 | ;; handle version 1 compatibility |
| 426 | (cond ((or (eq time-stamp-old-format-warn 'error) | 428 | (cond ((or (eq time-stamp-old-format-warn 'error) |
| 427 | (and (eq time-stamp-old-format-warn 'ask) | 429 | (and (eq time-stamp-old-format-warn 'ask) |
| @@ -515,32 +517,32 @@ and all `time-stamp-format' compatibility." | |||
| 515 | "%%") | 517 | "%%") |
| 516 | ((eq cur-char ?a) ;day of week | 518 | ((eq cur-char ?a) ;day of week |
| 517 | (if change-case | 519 | (if change-case |
| 518 | (format-time-string "%#a" time) | 520 | (time-stamp--format "%#a" time) |
| 519 | (or alt-form (not (string-equal field-width "")) | 521 | (or alt-form (not (string-equal field-width "")) |
| 520 | (time-stamp-conv-warn "%a" "%:a")) | 522 | (time-stamp-conv-warn "%a" "%:a")) |
| 521 | (if (and alt-form (not (string-equal field-width ""))) | 523 | (if (and alt-form (not (string-equal field-width ""))) |
| 522 | "" ;discourage "%:3a" | 524 | "" ;discourage "%:3a" |
| 523 | (format-time-string "%A" time)))) | 525 | (time-stamp--format "%A" time)))) |
| 524 | ((eq cur-char ?A) | 526 | ((eq cur-char ?A) |
| 525 | (if alt-form | 527 | (if alt-form |
| 526 | (format-time-string "%A" time) | 528 | (time-stamp--format "%A" time) |
| 527 | (or change-case (not (string-equal field-width "")) | 529 | (or change-case (not (string-equal field-width "")) |
| 528 | (time-stamp-conv-warn "%A" "%#A")) | 530 | (time-stamp-conv-warn "%A" "%#A")) |
| 529 | (format-time-string "%#A" time))) | 531 | (time-stamp--format "%#A" time))) |
| 530 | ((eq cur-char ?b) ;month name | 532 | ((eq cur-char ?b) ;month name |
| 531 | (if change-case | 533 | (if change-case |
| 532 | (format-time-string "%#b" time) | 534 | (time-stamp--format "%#b" time) |
| 533 | (or alt-form (not (string-equal field-width "")) | 535 | (or alt-form (not (string-equal field-width "")) |
| 534 | (time-stamp-conv-warn "%b" "%:b")) | 536 | (time-stamp-conv-warn "%b" "%:b")) |
| 535 | (if (and alt-form (not (string-equal field-width ""))) | 537 | (if (and alt-form (not (string-equal field-width ""))) |
| 536 | "" ;discourage "%:3b" | 538 | "" ;discourage "%:3b" |
| 537 | (format-time-string "%B" time)))) | 539 | (time-stamp--format "%B" time)))) |
| 538 | ((eq cur-char ?B) | 540 | ((eq cur-char ?B) |
| 539 | (if alt-form | 541 | (if alt-form |
| 540 | (format-time-string "%B" time) | 542 | (time-stamp--format "%B" time) |
| 541 | (or change-case (not (string-equal field-width "")) | 543 | (or change-case (not (string-equal field-width "")) |
| 542 | (time-stamp-conv-warn "%B" "%#B")) | 544 | (time-stamp-conv-warn "%B" "%#B")) |
| 543 | (format-time-string "%#B" time))) | 545 | (time-stamp--format "%#B" time))) |
| 544 | ((eq cur-char ?d) ;day of month, 1-31 | 546 | ((eq cur-char ?d) ;day of month, 1-31 |
| 545 | (time-stamp-do-number cur-char alt-form field-width time)) | 547 | (time-stamp-do-number cur-char alt-form field-width time)) |
| 546 | ((eq cur-char ?H) ;hour, 0-23 | 548 | ((eq cur-char ?H) ;hour, 0-23 |
| @@ -554,27 +556,27 @@ and all `time-stamp-format' compatibility." | |||
| 554 | ((eq cur-char ?p) ;am or pm | 556 | ((eq cur-char ?p) ;am or pm |
| 555 | (or change-case | 557 | (or change-case |
| 556 | (time-stamp-conv-warn "%p" "%#p")) | 558 | (time-stamp-conv-warn "%p" "%#p")) |
| 557 | (format-time-string "%#p" time)) | 559 | (time-stamp--format "%#p" time)) |
| 558 | ((eq cur-char ?P) ;AM or PM | 560 | ((eq cur-char ?P) ;AM or PM |
| 559 | (format-time-string "%p" time)) | 561 | (time-stamp--format "%p" time)) |
| 560 | ((eq cur-char ?S) ;seconds, 00-60 | 562 | ((eq cur-char ?S) ;seconds, 00-60 |
| 561 | (time-stamp-do-number cur-char alt-form field-width time)) | 563 | (time-stamp-do-number cur-char alt-form field-width time)) |
| 562 | ((eq cur-char ?w) ;weekday number, Sunday is 0 | 564 | ((eq cur-char ?w) ;weekday number, Sunday is 0 |
| 563 | (format-time-string "%w" time)) | 565 | (time-stamp--format "%w" time)) |
| 564 | ((eq cur-char ?y) ;year | 566 | ((eq cur-char ?y) ;year |
| 565 | (or alt-form (not (string-equal field-width "")) | 567 | (or alt-form (not (string-equal field-width "")) |
| 566 | (time-stamp-conv-warn "%y" "%:y")) | 568 | (time-stamp-conv-warn "%y" "%:y")) |
| 567 | (string-to-number (format-time-string "%Y" time))) | 569 | (string-to-number (time-stamp--format "%Y" time))) |
| 568 | ((eq cur-char ?Y) ;4-digit year, new style | 570 | ((eq cur-char ?Y) ;4-digit year, new style |
| 569 | (string-to-number (format-time-string "%Y" time))) | 571 | (string-to-number (time-stamp--format "%Y" time))) |
| 570 | ((eq cur-char ?z) ;time zone lower case | 572 | ((eq cur-char ?z) ;time zone lower case |
| 571 | (if change-case | 573 | (if change-case |
| 572 | "" ;discourage %z variations | 574 | "" ;discourage %z variations |
| 573 | (format-time-string "%#Z" time))) | 575 | (time-stamp--format "%#Z" time))) |
| 574 | ((eq cur-char ?Z) | 576 | ((eq cur-char ?Z) |
| 575 | (if change-case | 577 | (if change-case |
| 576 | (format-time-string "%#Z" time) | 578 | (time-stamp--format "%#Z" time) |
| 577 | (format-time-string "%Z" time))) | 579 | (time-stamp--format "%Z" time))) |
| 578 | ((eq cur-char ?f) ;buffer-file-name, base name only | 580 | ((eq cur-char ?f) ;buffer-file-name, base name only |
| 579 | (if buffer-file-name | 581 | (if buffer-file-name |
| 580 | (file-name-nondirectory buffer-file-name) | 582 | (file-name-nondirectory buffer-file-name) |
| @@ -634,7 +636,7 @@ width specification or \"\". TIME is the time to convert." | |||
| 634 | (format "%%:%c" format-char))) | 636 | (format "%%:%c" format-char))) |
| 635 | (if (and alt-form (not (string-equal field-width ""))) | 637 | (if (and alt-form (not (string-equal field-width ""))) |
| 636 | "" ;discourage "%:2d" and the like | 638 | "" ;discourage "%:2d" and the like |
| 637 | (string-to-number (format-time-string format-string time))))) | 639 | (string-to-number (time-stamp--format format-string time))))) |
| 638 | 640 | ||
| 639 | (defvar time-stamp-conversion-warn t | 641 | (defvar time-stamp-conversion-warn t |
| 640 | "Warn about soon-to-be-unsupported forms in `time-stamp-format'. | 642 | "Warn about soon-to-be-unsupported forms in `time-stamp-format'. |
diff --git a/lisp/url/url-tramp.el b/lisp/url/url-tramp.el index 9e191579d47..192a0459f33 100644 --- a/lisp/url/url-tramp.el +++ b/lisp/url/url-tramp.el | |||
| @@ -30,11 +30,11 @@ | |||
| 30 | 30 | ||
| 31 | ;;;###autoload | 31 | ;;;###autoload |
| 32 | (defcustom url-tramp-protocols '("ftp" "ssh" "scp" "rsync" "telnet") | 32 | (defcustom url-tramp-protocols '("ftp" "ssh" "scp" "rsync" "telnet") |
| 33 | "List of URL protocols the work is handled by Tramp. | 33 | "List of URL protocols for which the work is handled by Tramp. |
| 34 | They must also be covered by `url-handler-regexp'." | 34 | They must also be covered by `url-handler-regexp'." |
| 35 | :group 'url | 35 | :group 'url |
| 36 | :version "25.1" | 36 | :version "25.1" |
| 37 | :type '(list string)) | 37 | :type '(repeat string)) |
| 38 | 38 | ||
| 39 | (defun url-tramp-convert-url-to-tramp (url) | 39 | (defun url-tramp-convert-url-to-tramp (url) |
| 40 | "Convert URL to a Tramp file name." | 40 | "Convert URL to a Tramp file name." |