aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorStephen Leake2019-04-11 14:00:02 -0700
committerStephen Leake2019-04-11 14:00:02 -0700
commit7ba7def5caf7ec9d9bebffff489f0a658229fbda (patch)
treee0cfcb59937ca0528fb81769d7d48a904a91f5dc /lisp
parent7768581172e11be52b1fcd8224f4594e126bbdb7 (diff)
parentde238b39e335c6814283faa171b35145f124edf2 (diff)
downloademacs-7ba7def5caf7ec9d9bebffff489f0a658229fbda.tar.gz
emacs-7ba7def5caf7ec9d9bebffff489f0a658229fbda.zip
Merge commit 'de238b39e335c6814283faa171b35145f124edf2'
Diffstat (limited to 'lisp')
-rw-r--r--lisp/autorevert.el54
-rw-r--r--lisp/button.el10
-rw-r--r--lisp/desktop.el13
-rw-r--r--lisp/dired.el13
-rw-r--r--lisp/disp-table.el14
-rw-r--r--lisp/elide-head.el2
-rw-r--r--lisp/emacs-lisp/nadvice.el7
-rw-r--r--lisp/emulation/cua-base.el19
-rw-r--r--lisp/eshell/em-alias.el8
-rw-r--r--lisp/eshell/em-banner.el2
-rw-r--r--lisp/eshell/em-cmpl.el2
-rw-r--r--lisp/eshell/em-dirs.el5
-rw-r--r--lisp/eshell/em-glob.el2
-rw-r--r--lisp/eshell/em-hist.el22
-rw-r--r--lisp/eshell/em-ls.el3
-rw-r--r--lisp/eshell/em-pred.el8
-rw-r--r--lisp/eshell/em-prompt.el2
-rw-r--r--lisp/eshell/em-rebind.el2
-rw-r--r--lisp/eshell/em-script.el10
-rw-r--r--lisp/eshell/em-smart.el2
-rw-r--r--lisp/eshell/em-term.el4
-rw-r--r--lisp/eshell/em-tramp.el2
-rw-r--r--lisp/eshell/em-unix.el5
-rw-r--r--lisp/eshell/esh-arg.el96
-rw-r--r--lisp/eshell/esh-cmd.el6
-rw-r--r--lisp/eshell/esh-ext.el20
-rw-r--r--lisp/eshell/esh-io.el5
-rw-r--r--lisp/eshell/esh-mode.el35
-rw-r--r--lisp/eshell/esh-module.el4
-rw-r--r--lisp/eshell/esh-opt.el12
-rw-r--r--lisp/eshell/esh-proc.el61
-rw-r--r--lisp/eshell/esh-util.el18
-rw-r--r--lisp/eshell/esh-var.el21
-rw-r--r--lisp/eshell/eshell.el21
-rw-r--r--lisp/faces.el20
-rw-r--r--lisp/files.el3
-rw-r--r--lisp/frame.el42
-rw-r--r--lisp/gnus/gnus-agent.el91
-rw-r--r--lisp/gnus/gnus-dup.el11
-rw-r--r--lisp/gnus/gnus-group.el6
-rw-r--r--lisp/gnus/gnus-start.el15
-rw-r--r--lisp/gnus/gnus-sum.el230
-rw-r--r--lisp/gnus/mm-view.el31
-rw-r--r--lisp/gnus/nnmail.el2
-rw-r--r--lisp/gnus/nnml.el16
-rw-r--r--lisp/gnus/nnrss.el18
-rw-r--r--lisp/indent.el5
-rw-r--r--lisp/info.el2
-rw-r--r--lisp/international/quail.el17
-rw-r--r--lisp/leim/quail/sami.el2
-rw-r--r--lisp/net/tramp-adb.el64
-rw-r--r--lisp/net/tramp-archive.el4
-rw-r--r--lisp/net/tramp-gvfs.el18
-rw-r--r--lisp/net/tramp-sh.el16
-rw-r--r--lisp/net/tramp.el19
-rw-r--r--lisp/newcomment.el8
-rw-r--r--lisp/printing.el1758
-rw-r--r--lisp/progmodes/bug-reference.el6
-rw-r--r--lisp/progmodes/compile.el5
-rw-r--r--lisp/progmodes/grep.el12
-rw-r--r--lisp/progmodes/js.el1200
-rw-r--r--lisp/progmodes/python.el40
-rw-r--r--lisp/progmodes/sh-script.el3
-rw-r--r--lisp/progmodes/verilog-mode.el6
-rw-r--r--lisp/replace.el34
-rw-r--r--lisp/simple.el10
-rw-r--r--lisp/subr.el6
-rw-r--r--lisp/vc/diff-mode.el204
-rw-r--r--lisp/vc/log-edit.el2
-rw-r--r--lisp/vc/vc.el17
-rw-r--r--lisp/wid-edit.el5
-rw-r--r--lisp/window.el4
-rw-r--r--lisp/xml.el4
73 files changed, 2466 insertions, 2000 deletions
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index bc7c616ecb7..4fb865e8adb 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -343,10 +343,11 @@ This has been reported by a file notification event.")
343 343
344;; Functions: 344;; Functions:
345 345
346(defun auto-revert-remove-current-buffer () 346(defun auto-revert-remove-current-buffer (&optional buffer)
347 "Remove dead buffer from `auto-revert-buffer-list'." 347 "Remove BUFFER from `auto-revert-buffer-list'.
348BUFFER defaults to `current-buffer'."
348 (setq auto-revert-buffer-list 349 (setq auto-revert-buffer-list
349 (delq (current-buffer) auto-revert-buffer-list))) 350 (delq (or buffer (current-buffer)) auto-revert-buffer-list)))
350 351
351;;;###autoload 352;;;###autoload
352(define-minor-mode auto-revert-mode 353(define-minor-mode auto-revert-mode
@@ -464,7 +465,7 @@ If `global-auto-revert-non-file-buffers' is non-nil, this mode
464may also revert some non-file buffers, as described in the 465may also revert some non-file buffers, as described in the
465documentation of that variable. It ignores buffers with modes 466documentation of that variable. It ignores buffers with modes
466matching `global-auto-revert-ignore-modes', and buffers with a 467matching `global-auto-revert-ignore-modes', and buffers with a
467non-nil vale of `global-auto-revert-ignore-buffer'. 468non-nil value of `global-auto-revert-ignore-buffer'.
468 469
469When a buffer is reverted, a message is generated. This can be 470When a buffer is reverted, a message is generated. This can be
470suppressed by setting `auto-revert-verbose' to nil. 471suppressed by setting `auto-revert-verbose' to nil.
@@ -509,7 +510,7 @@ will use an up-to-date value of `auto-revert-interval'"
509 (ignore-errors 510 (ignore-errors
510 (file-notify-rm-watch auto-revert-notify-watch-descriptor))))) 511 (file-notify-rm-watch auto-revert-notify-watch-descriptor)))))
511 auto-revert-notify-watch-descriptor-hash-list) 512 auto-revert-notify-watch-descriptor-hash-list)
512 (remove-hook 'kill-buffer-hook #'auto-revert-notify-rm-watch)) 513 (remove-hook 'kill-buffer-hook #'auto-revert-notify-rm-watch t))
513 (setq auto-revert-notify-watch-descriptor nil 514 (setq auto-revert-notify-watch-descriptor nil
514 auto-revert-notify-modified-p nil)) 515 auto-revert-notify-modified-p nil))
515 516
@@ -772,10 +773,12 @@ the timer when no buffers need to be checked."
772 (setq bufs (delq nil 773 (setq bufs (delq nil
773 (mapcar 774 (mapcar
774 (lambda (buf) 775 (lambda (buf)
775 (with-current-buffer buf 776 (and (buffer-live-p buf)
776 (and (or (not (file-remote-p default-directory)) 777 (with-current-buffer buf
777 (file-remote-p default-directory nil t)) 778 (and
778 buf))) 779 (or (not (file-remote-p default-directory))
780 (file-remote-p default-directory nil t))
781 buf))))
779 bufs))) 782 bufs)))
780 ;; Partition `bufs' into two halves depending on whether or not 783 ;; Partition `bufs' into two halves depending on whether or not
781 ;; the buffers are in `auto-revert-remaining-buffers'. The two 784 ;; the buffers are in `auto-revert-remaining-buffers'. The two
@@ -792,24 +795,23 @@ the timer when no buffers need to be checked."
792 (not (and auto-revert-stop-on-user-input 795 (not (and auto-revert-stop-on-user-input
793 (input-pending-p)))) 796 (input-pending-p))))
794 (let ((buf (car bufs))) 797 (let ((buf (car bufs)))
795 (with-current-buffer buf 798 (if (not (buffer-live-p buf))
796 (if (buffer-live-p buf)
797 (progn
798 ;; Test if someone has turned off Auto-Revert Mode
799 ;; in a non-standard way, for example by changing
800 ;; major mode.
801 (if (and (not auto-revert-mode)
802 (not auto-revert-tail-mode)
803 (memq buf auto-revert-buffer-list))
804 (auto-revert-remove-current-buffer))
805 (when (auto-revert-active-p)
806 ;; Enable file notification.
807 (when (and auto-revert-use-notify
808 (not auto-revert-notify-watch-descriptor))
809 (auto-revert-notify-add-watch))
810 (auto-revert-handler)))
811 ;; Remove dead buffer from `auto-revert-buffer-list'. 799 ;; Remove dead buffer from `auto-revert-buffer-list'.
812 (auto-revert-remove-current-buffer)))) 800 (auto-revert-remove-current-buffer buf)
801 (with-current-buffer buf
802 ;; Test if someone has turned off Auto-Revert Mode
803 ;; in a non-standard way, for example by changing
804 ;; major mode.
805 (if (and (not auto-revert-mode)
806 (not auto-revert-tail-mode)
807 (memq buf auto-revert-buffer-list))
808 (auto-revert-remove-current-buffer))
809 (when (auto-revert-active-p)
810 ;; Enable file notification.
811 (when (and auto-revert-use-notify
812 (not auto-revert-notify-watch-descriptor))
813 (auto-revert-notify-add-watch))
814 (auto-revert-handler)))))
813 (setq bufs (cdr bufs))) 815 (setq bufs (cdr bufs)))
814 (setq auto-revert-remaining-buffers bufs) 816 (setq auto-revert-remaining-buffers bufs)
815 ;; Check if we should cancel the timer. 817 ;; Check if we should cancel the timer.
diff --git a/lisp/button.el b/lisp/button.el
index c46f3d9a52b..921e84dfa68 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -382,10 +382,12 @@ Also see `make-text-button'."
382If the button at POS is a text property button, the return value 382If the button at POS is a text property button, the return value
383is a marker pointing to POS." 383is a marker pointing to POS."
384 (let ((button (get-char-property pos 'button))) 384 (let ((button (get-char-property pos 'button)))
385 (if (or (overlayp button) (null button)) 385 (and button (get-char-property pos 'category)
386 button 386 (if (overlayp button)
387 ;; Must be a text-property button; return a marker pointing to it. 387 button
388 (copy-marker pos t)))) 388 ;; Must be a text-property button;
389 ;; return a marker pointing to it.
390 (copy-marker pos t)))))
389 391
390(defun next-button (pos &optional count-current) 392(defun next-button (pos &optional count-current)
391 "Return the next button after position POS in the current buffer. 393 "Return the next button after position POS in the current buffer.
diff --git a/lisp/desktop.el b/lisp/desktop.el
index acabde5eb2f..97c057e2013 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -856,6 +856,19 @@ QUOTE may be `may' (value may be quoted),
856 `',(cdr el) (cdr el))) 856 `',(cdr el) (cdr el)))
857 pass1))) 857 pass1)))
858 (cons 'may `[,@(mapcar #'cdr pass1)])))) 858 (cons 'may `[,@(mapcar #'cdr pass1)]))))
859 ((and (recordp value) (symbolp (aref value 0)))
860 (let* ((pass1 (let ((res ()))
861 (dotimes (i (length value))
862 (push (desktop--v2s (aref value i)) res))
863 (nreverse res)))
864 (special (assq nil pass1)))
865 (if special
866 (cons nil `(record
867 ,@(mapcar (lambda (el)
868 (if (eq (car el) 'must)
869 `',(cdr el) (cdr el)))
870 pass1)))
871 (cons 'may (apply #'record (mapcar #'cdr pass1))))))
859 ((consp value) 872 ((consp value)
860 (let ((p value) 873 (let ((p value)
861 newlist 874 newlist
diff --git a/lisp/dired.el b/lisp/dired.el
index fc0b71238ba..63082fe3927 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -774,6 +774,15 @@ as an argument to `dired-goto-file'."
774 (file-name-as-directory (abbreviate-file-name filename)) 774 (file-name-as-directory (abbreviate-file-name filename))
775 (abbreviate-file-name filename))))) 775 (abbreviate-file-name filename)))))
776 776
777(defun dired-grep-read-files ()
778 "Use file at point as the file for grep's default file-name pattern suggestion.
779If a directory or nothing is found at point, return nil."
780 (let ((file-name (dired-file-name-at-point)))
781 (if (and file-name
782 (not (file-directory-p file-name)))
783 file-name)))
784(put 'dired-mode 'grep-read-files 'dired-grep-read-files)
785
777;;;###autoload (define-key ctl-x-map "d" 'dired) 786;;;###autoload (define-key ctl-x-map "d" 'dired)
778;;;###autoload 787;;;###autoload
779(defun dired (dirname &optional switches) 788(defun dired (dirname &optional switches)
@@ -1269,8 +1278,8 @@ If HDR is non-nil, insert a header line with the directory name."
1269 ;; as indicated by `ls-lisp-use-insert-directory-program'. 1278 ;; as indicated by `ls-lisp-use-insert-directory-program'.
1270 (not (and (featurep 'ls-lisp) 1279 (not (and (featurep 'ls-lisp)
1271 (null ls-lisp-use-insert-directory-program))) 1280 (null ls-lisp-use-insert-directory-program)))
1272 (not (and (featurep 'eshell) 1281 ;; FIXME: Big ugly hack for Eshell's eshell-ls-use-in-dired.
1273 (bound-and-true-p eshell-ls-use-in-dired))) 1282 (not (bound-and-true-p eshell-ls-use-in-dired))
1274 (or (file-remote-p dir) 1283 (or (file-remote-p dir)
1275 (if (eq dired-use-ls-dired 'unspecified) 1284 (if (eq dired-use-ls-dired 'unspecified)
1276 ;; Check whether "ls --dired" gives exit code 0, and 1285 ;; Check whether "ls --dired" gives exit code 0, and
diff --git a/lisp/disp-table.el b/lisp/disp-table.el
index 476c0cb9861..4a597506774 100644
--- a/lisp/disp-table.el
+++ b/lisp/disp-table.el
@@ -175,8 +175,8 @@ in the default way after this call."
175(defun standard-display-g1 (c sc) 175(defun standard-display-g1 (c sc)
176 "Display character C as character SC in the g1 character set. 176 "Display character C as character SC in the g1 character set.
177This function assumes that your terminal uses the SO/SI characters; 177This function assumes that your terminal uses the SO/SI characters;
178it is meaningless for an X frame." 178it is meaningless for a graphical frame."
179 (if (memq window-system '(x w32 ns)) 179 (if (display-graphic-p)
180 (error "Cannot use string glyphs in a windowing system")) 180 (error "Cannot use string glyphs in a windowing system"))
181 (or standard-display-table 181 (or standard-display-table
182 (setq standard-display-table (make-display-table))) 182 (setq standard-display-table (make-display-table)))
@@ -186,9 +186,9 @@ it is meaningless for an X frame."
186;;;###autoload 186;;;###autoload
187(defun standard-display-graphic (c gc) 187(defun standard-display-graphic (c gc)
188 "Display character C as character GC in graphics character set. 188 "Display character C as character GC in graphics character set.
189This function assumes VT100-compatible escapes; it is meaningless for an 189This function assumes VT100-compatible escapes; it is meaningless
190X frame." 190for a graphical frame."
191 (if (memq window-system '(x w32 ns)) 191 (if (display-graphic-p)
192 (error "Cannot use string glyphs in a windowing system")) 192 (error "Cannot use string glyphs in a windowing system"))
193 (or standard-display-table 193 (or standard-display-table
194 (setq standard-display-table (make-display-table))) 194 (setq standard-display-table (make-display-table)))
@@ -276,7 +276,7 @@ in `.emacs'."
276 (progn 276 (progn
277 (standard-display-default 277 (standard-display-default
278 (unibyte-char-to-multibyte 160) (unibyte-char-to-multibyte 255)) 278 (unibyte-char-to-multibyte 160) (unibyte-char-to-multibyte 255))
279 (unless (or (memq window-system '(x w32 ns))) 279 (unless (display-graphic-p)
280 (and (terminal-coding-system) 280 (and (terminal-coding-system)
281 (set-terminal-coding-system nil)))) 281 (set-terminal-coding-system nil))))
282 282
@@ -289,7 +289,7 @@ in `.emacs'."
289 ;; unless some other has been specified. 289 ;; unless some other has been specified.
290 (if (equal current-language-environment "English") 290 (if (equal current-language-environment "English")
291 (set-language-environment "latin-1")) 291 (set-language-environment "latin-1"))
292 (unless (or noninteractive (memq window-system '(x w32 ns))) 292 (unless (or noninteractive (display-graphic-p))
293 ;; Send those codes literally to a character-based terminal. 293 ;; Send those codes literally to a character-based terminal.
294 ;; If we are using single-byte characters, 294 ;; If we are using single-byte characters,
295 ;; it doesn't matter which coding system we use. 295 ;; it doesn't matter which coding system we use.
diff --git a/lisp/elide-head.el b/lisp/elide-head.el
index 82d08190a63..c1678c003db 100644
--- a/lisp/elide-head.el
+++ b/lisp/elide-head.el
@@ -52,7 +52,7 @@
52(defcustom elide-head-headers-to-hide 52(defcustom elide-head-headers-to-hide
53 '(("is free software[:;] you can redistribute it" . ; GNU boilerplate 53 '(("is free software[:;] you can redistribute it" . ; GNU boilerplate
54 "\\(Boston, MA 0211\\(1-1307\\|0-1301\\), USA\\|\ 54 "\\(Boston, MA 0211\\(1-1307\\|0-1301\\), USA\\|\
55If not, see <http://www\\.gnu\\.org/licenses/>\\)\\.") 55If not, see <https?://www\\.gnu\\.org/licenses/>\\)\\.")
56 ("The Regents of the University of California\\. All rights reserved\\." . 56 ("The Regents of the University of California\\. All rights reserved\\." .
57 "SUCH DAMAGE\\.") ; BSD 57 "SUCH DAMAGE\\.") ; BSD
58 ("Permission is hereby granted, free of charge" . ; X11 58 ("Permission is hereby granted, free of charge" . ; X11
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index bb647b012e1..2278e389cef 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -36,6 +36,11 @@
36 36
37;;; Code: 37;;; Code:
38 38
39;; The autoloads.el mechanism which adds package--builtin-versions
40;; maintenance to loaddefs.el doesn't work for preloaded packages (such
41;; as this one), so we have to do it by hand!
42(push (purecopy '(nadvice 1 0)) package--builtin-versions)
43
39;;;; Lightweight advice/hook 44;;;; Lightweight advice/hook
40(defvar advice--where-alist 45(defvar advice--where-alist
41 '((:around "\300\301\302\003#\207" 5) 46 '((:around "\300\301\302\003#\207" 5)
@@ -241,6 +246,8 @@ different, but `function-equal' will hopefully ignore those differences.")
241 (if (local-variable-p var) (symbol-value var) 246 (if (local-variable-p var) (symbol-value var)
242 (setq advice--buffer-local-function-sample 247 (setq advice--buffer-local-function-sample
243 ;; This function acts like the t special value in buffer-local hooks. 248 ;; This function acts like the t special value in buffer-local hooks.
249 ;; FIXME: Provide an `advice-bottom' function that's like
250 ;; `advice-cd*r' but also follows through this proxy.
244 (lambda (&rest args) (apply (default-value var) args))))) 251 (lambda (&rest args) (apply (default-value var) args)))))
245 252
246(eval-and-compile 253(eval-and-compile
diff --git a/lisp/emulation/cua-base.el b/lisp/emulation/cua-base.el
index 302ef123865..105e1ab43d8 100644
--- a/lisp/emulation/cua-base.el
+++ b/lisp/emulation/cua-base.el
@@ -427,7 +427,7 @@ and after the region marked by the rectangle to search."
427 427
428(defcustom cua-rectangle-modifier-key 'meta 428(defcustom cua-rectangle-modifier-key 'meta
429 "Modifier key used for rectangle commands bindings. 429 "Modifier key used for rectangle commands bindings.
430On non-window systems, always use the meta modifier. 430On non-window systems, use `cua-rectangle-terminal-modifier-key'.
431Must be set prior to enabling CUA." 431Must be set prior to enabling CUA."
432 :type '(choice (const :tag "Meta key" meta) 432 :type '(choice (const :tag "Meta key" meta)
433 (const :tag "Alt key" alt) 433 (const :tag "Alt key" alt)
@@ -435,6 +435,16 @@ Must be set prior to enabling CUA."
435 (const :tag "Super key" super)) 435 (const :tag "Super key" super))
436 :group 'cua) 436 :group 'cua)
437 437
438(defcustom cua-rectangle-terminal-modifier-key 'meta
439 "Modifier key used for rectangle commands bindings in terminals.
440Must be set prior to enabling CUA."
441 :type '(choice (const :tag "Meta key" meta)
442 (const :tag "Alt key" alt)
443 (const :tag "Hyper key" hyper)
444 (const :tag "Super key" super))
445 :group 'cua
446 :version "27.1")
447
438(defcustom cua-enable-rectangle-auto-help t 448(defcustom cua-enable-rectangle-auto-help t
439 "If non-nil, automatically show help for region, rectangle and global mark." 449 "If non-nil, automatically show help for region, rectangle and global mark."
440 :type 'boolean 450 :type 'boolean
@@ -1237,10 +1247,9 @@ If ARG is the atom `-', scroll upward by nearly full screen."
1237(defun cua--init-keymaps () 1247(defun cua--init-keymaps ()
1238 ;; Cache actual rectangle modifier key. 1248 ;; Cache actual rectangle modifier key.
1239 (setq cua--rectangle-modifier-key 1249 (setq cua--rectangle-modifier-key
1240 (if (and cua-rectangle-modifier-key 1250 (if (eq (framep (selected-frame)) t)
1241 (memq window-system '(x))) 1251 cua-rectangle-terminal-modifier-key
1242 cua-rectangle-modifier-key 1252 cua-rectangle-modifier-key))
1243 'meta))
1244 ;; C-return always toggles rectangle mark 1253 ;; C-return always toggles rectangle mark
1245 (define-key cua-global-keymap cua-rectangle-mark-key 'cua-set-rectangle-mark) 1254 (define-key cua-global-keymap cua-rectangle-mark-key 'cua-set-rectangle-mark)
1246 (unless (eq cua--rectangle-modifier-key 'meta) 1255 (unless (eq cua--rectangle-modifier-key 'meta)
diff --git a/lisp/eshell/em-alias.el b/lisp/eshell/em-alias.el
index dbffd52aa76..c465d464d6a 100644
--- a/lisp/eshell/em-alias.el
+++ b/lisp/eshell/em-alias.el
@@ -90,7 +90,7 @@
90 90
91;;; Code: 91;;; Code:
92 92
93(require 'eshell) 93(require 'esh-mode)
94 94
95;;;###autoload 95;;;###autoload
96(progn 96(progn
@@ -141,12 +141,12 @@ file named by `eshell-aliases-file'.")
141(defvar eshell-failed-commands-alist nil 141(defvar eshell-failed-commands-alist nil
142 "An alist of command name failures.") 142 "An alist of command name failures.")
143 143
144(defun eshell-alias-initialize () 144(defun eshell-alias-initialize () ;Called from `eshell-mode' via intern-soft!
145 "Initialize the alias handling code." 145 "Initialize the alias handling code."
146 (make-local-variable 'eshell-failed-commands-alist) 146 (make-local-variable 'eshell-failed-commands-alist)
147 (add-hook 'eshell-alternate-command-hook 'eshell-fix-bad-commands t t) 147 (add-hook 'eshell-alternate-command-hook #'eshell-fix-bad-commands t t)
148 (eshell-read-aliases-list) 148 (eshell-read-aliases-list)
149 (add-hook 'eshell-named-command-hook 'eshell-maybe-replace-by-alias t t) 149 (add-hook 'eshell-named-command-hook #'eshell-maybe-replace-by-alias t t)
150 (make-local-variable 'eshell-complex-commands) 150 (make-local-variable 'eshell-complex-commands)
151 (add-to-list 'eshell-complex-commands 'eshell-command-aliased-p)) 151 (add-to-list 'eshell-complex-commands 'eshell-command-aliased-p))
152 152
diff --git a/lisp/eshell/em-banner.el b/lisp/eshell/em-banner.el
index 4a0b265ae0e..c284c1bd70d 100644
--- a/lisp/eshell/em-banner.el
+++ b/lisp/eshell/em-banner.el
@@ -71,7 +71,7 @@ This can be any sexp, and should end with at least two newlines."
71 :type 'hook 71 :type 'hook
72 :group 'eshell-banner) 72 :group 'eshell-banner)
73 73
74(defun eshell-banner-initialize () 74(defun eshell-banner-initialize () ;Called from `eshell-mode' via intern-soft!
75 "Output a welcome banner on initialization." 75 "Output a welcome banner on initialization."
76 ;; it's important to use `eshell-interactive-print' rather than 76 ;; it's important to use `eshell-interactive-print' rather than
77 ;; `insert', because `insert' doesn't know how to interact with the 77 ;; `insert', because `insert' doesn't know how to interact with the
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index 25a6e88c8e6..e3bfd8d9d48 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -244,7 +244,7 @@ to writing a completion function."
244 (let ((completion-at-point-functions '(lisp-completion-at-point))) 244 (let ((completion-at-point-functions '(lisp-completion-at-point)))
245 (completion-at-point))) 245 (completion-at-point)))
246 246
247(defun eshell-cmpl-initialize () 247(defun eshell-cmpl-initialize () ;Called from `eshell-mode' via intern-soft!
248 "Initialize the completions module." 248 "Initialize the completions module."
249 (set (make-local-variable 'pcomplete-command-completion-function) 249 (set (make-local-variable 'pcomplete-command-completion-function)
250 eshell-command-completion-function) 250 eshell-command-completion-function)
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 937bc981c53..c28fd72f45c 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -42,7 +42,8 @@
42 42
43;;; Code: 43;;; Code:
44 44
45(require 'eshell) 45(require 'esh-mode) ;For eshell-directory-name
46(require 'esh-var) ;For eshell-variable-aliases-list
46(require 'ring) 47(require 'ring)
47(require 'esh-opt) 48(require 'esh-opt)
48 49
@@ -169,7 +170,7 @@ Thus, this does not include the current directory.")
169 170
170;;; Functions: 171;;; Functions:
171 172
172(defun eshell-dirs-initialize () 173(defun eshell-dirs-initialize () ;Called from `eshell-mode' via intern-soft!
173 "Initialize the builtin functions for Eshell." 174 "Initialize the builtin functions for Eshell."
174 (make-local-variable 'eshell-variable-aliases-list) 175 (make-local-variable 'eshell-variable-aliases-list)
175 (setq eshell-variable-aliases-list 176 (setq eshell-variable-aliases-list
diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el
index f03243a6af4..99c52ea0d30 100644
--- a/lisp/eshell/em-glob.el
+++ b/lisp/eshell/em-glob.el
@@ -125,7 +125,7 @@ This option slows down recursive glob processing by quite a bit."
125 125
126;;; Functions: 126;;; Functions:
127 127
128(defun eshell-glob-initialize () 128(defun eshell-glob-initialize () ;Called from `eshell-mode' via intern-soft!
129 "Initialize the extended globbing code." 129 "Initialize the extended globbing code."
130 ;; it's important that `eshell-glob-chars-list' come first 130 ;; it's important that `eshell-glob-chars-list' come first
131 (when (boundp 'eshell-special-chars-outside-quoting) 131 (when (boundp 'eshell-special-chars-outside-quoting)
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el
index 05579eed32a..614faaa131e 100644
--- a/lisp/eshell/em-hist.el
+++ b/lisp/eshell/em-hist.el
@@ -59,6 +59,7 @@
59 59
60(require 'ring) 60(require 'ring)
61(require 'esh-opt) 61(require 'esh-opt)
62(require 'esh-mode)
62(require 'em-pred) 63(require 'em-pred)
63(require 'eshell) 64(require 'eshell)
64 65
@@ -192,7 +193,6 @@ element, regardless of any text on the command line. In that case,
192(defvar eshell-isearch-map 193(defvar eshell-isearch-map
193 (let ((map (copy-keymap isearch-mode-map))) 194 (let ((map (copy-keymap isearch-mode-map)))
194 (define-key map [(control ?m)] 'eshell-isearch-return) 195 (define-key map [(control ?m)] 'eshell-isearch-return)
195 (define-key map [return] 'eshell-isearch-return)
196 (define-key map [(control ?r)] 'eshell-isearch-repeat-backward) 196 (define-key map [(control ?r)] 'eshell-isearch-repeat-backward)
197 (define-key map [(control ?s)] 'eshell-isearch-repeat-forward) 197 (define-key map [(control ?s)] 'eshell-isearch-repeat-forward)
198 (define-key map [(control ?g)] 'eshell-isearch-abort) 198 (define-key map [(control ?g)] 'eshell-isearch-abort)
@@ -216,11 +216,11 @@ Returns non-nil if INPUT is blank."
216Returns nil if INPUT is prepended by blank space, otherwise non-nil." 216Returns nil if INPUT is prepended by blank space, otherwise non-nil."
217 (not (string-match-p "\\`\\s-+" input))) 217 (not (string-match-p "\\`\\s-+" input)))
218 218
219(defun eshell-hist-initialize () 219(defun eshell-hist-initialize () ;Called from `eshell-mode' via intern-soft!
220 "Initialize the history management code for one Eshell buffer." 220 "Initialize the history management code for one Eshell buffer."
221 (when (eshell-using-module 'eshell-cmpl) 221 (when (eshell-using-module 'eshell-cmpl)
222 (add-hook 'pcomplete-try-first-hook 222 (add-hook 'pcomplete-try-first-hook
223 'eshell-complete-history-reference nil t)) 223 #'eshell-complete-history-reference nil t))
224 224
225 (if (and (eshell-using-module 'eshell-rebind) 225 (if (and (eshell-using-module 'eshell-rebind)
226 (not eshell-non-interactive-p)) 226 (not eshell-non-interactive-p))
@@ -235,11 +235,13 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
235 (lambda () 235 (lambda ()
236 (if (>= (point) eshell-last-output-end) 236 (if (>= (point) eshell-last-output-end)
237 (setq overriding-terminal-local-map 237 (setq overriding-terminal-local-map
238 eshell-isearch-map)))) nil t) 238 eshell-isearch-map))))
239 nil t)
239 (add-hook 'isearch-mode-end-hook 240 (add-hook 'isearch-mode-end-hook
240 (function 241 (function
241 (lambda () 242 (lambda ()
242 (setq overriding-terminal-local-map nil))) nil t)) 243 (setq overriding-terminal-local-map nil)))
244 nil t))
243 (define-key eshell-mode-map [up] 'eshell-previous-matching-input-from-input) 245 (define-key eshell-mode-map [up] 'eshell-previous-matching-input-from-input)
244 (define-key eshell-mode-map [down] 'eshell-next-matching-input-from-input) 246 (define-key eshell-mode-map [down] 'eshell-next-matching-input-from-input)
245 (define-key eshell-mode-map [(control up)] 'eshell-previous-input) 247 (define-key eshell-mode-map [(control up)] 'eshell-previous-input)
@@ -288,17 +290,17 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
288 (if eshell-history-file-name 290 (if eshell-history-file-name
289 (eshell-read-history nil t)) 291 (eshell-read-history nil t))
290 292
291 (add-hook 'eshell-exit-hook 'eshell-write-history nil t)) 293 (add-hook 'eshell-exit-hook #'eshell-write-history nil t))
292 294
293 (unless eshell-history-ring 295 (unless eshell-history-ring
294 (setq eshell-history-ring (make-ring eshell-history-size))) 296 (setq eshell-history-ring (make-ring eshell-history-size)))
295 297
296 (add-hook 'eshell-exit-hook 'eshell-write-history nil t) 298 (add-hook 'eshell-exit-hook #'eshell-write-history nil t)
297 299
298 (add-hook 'kill-emacs-hook 'eshell-save-some-history) 300 (add-hook 'kill-emacs-hook #'eshell-save-some-history)
299 301
300 (make-local-variable 'eshell-input-filter-functions) 302 (make-local-variable 'eshell-input-filter-functions)
301 (add-hook 'eshell-input-filter-functions 'eshell-add-to-history nil t) 303 (add-hook 'eshell-input-filter-functions #'eshell-add-to-history nil t)
302 304
303 (define-key eshell-command-map [(control ?l)] 'eshell-list-history) 305 (define-key eshell-command-map [(control ?l)] 'eshell-list-history)
304 (define-key eshell-command-map [(control ?x)] 'eshell-get-next-from-history)) 306 (define-key eshell-command-map [(control ?x)] 'eshell-get-next-from-history))
@@ -754,7 +756,7 @@ matched."
754 (setq nth (eshell-hist-word-reference nth))) 756 (setq nth (eshell-hist-word-reference nth)))
755 (unless (numberp mth) 757 (unless (numberp mth)
756 (setq mth (eshell-hist-word-reference mth))) 758 (setq mth (eshell-hist-word-reference mth)))
757 (cons (mapconcat 'identity (eshell-sublist textargs nth mth) " ") 759 (cons (mapconcat #'identity (eshell-sublist textargs nth mth) " ")
758 end)))) 760 end))))
759 761
760(defun eshell-hist-parse-modifier (hist reference) 762(defun eshell-hist-parse-modifier (hist reference)
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index 5e4bbdc87ef..89969d32582 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -29,7 +29,8 @@
29(require 'cl-lib) 29(require 'cl-lib)
30(require 'esh-util) 30(require 'esh-util)
31(require 'esh-opt) 31(require 'esh-opt)
32(eval-when-compile (require 'eshell)) 32(require 'esh-proc)
33(require 'esh-cmd)
33 34
34;;;###autoload 35;;;###autoload
35(progn 36(progn
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index dd3351b14d3..9bc856a2966 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -46,9 +46,7 @@
46 46
47;;; Code: 47;;; Code:
48 48
49(require 'esh-util) 49(require 'esh-mode)
50(require 'esh-arg)
51(eval-when-compile (require 'eshell))
52 50
53;;;###autoload 51;;;###autoload
54(progn 52(progn
@@ -247,10 +245,10 @@ EXAMPLES:
247 (lambda () 245 (lambda ()
248 (insert eshell-modifier-help-string))))) 246 (insert eshell-modifier-help-string)))))
249 247
250(defun eshell-pred-initialize () 248(defun eshell-pred-initialize () ;Called from `eshell-mode' via intern-soft!
251 "Initialize the predicate/modifier code." 249 "Initialize the predicate/modifier code."
252 (add-hook 'eshell-parse-argument-hook 250 (add-hook 'eshell-parse-argument-hook
253 'eshell-parse-arg-modifier t t) 251 #'eshell-parse-arg-modifier t t)
254 (define-key eshell-command-map [(meta ?q)] 'eshell-display-predicate-help) 252 (define-key eshell-command-map [(meta ?q)] 'eshell-display-predicate-help)
255 (define-key eshell-command-map [(meta ?m)] 'eshell-display-modifier-help)) 253 (define-key eshell-command-map [(meta ?m)] 'eshell-display-modifier-help))
256 254
diff --git a/lisp/eshell/em-prompt.el b/lisp/eshell/em-prompt.el
index a3035205adb..adc68b6c856 100644
--- a/lisp/eshell/em-prompt.el
+++ b/lisp/eshell/em-prompt.el
@@ -99,7 +99,7 @@ arriving, or after."
99 99
100;;; Functions: 100;;; Functions:
101 101
102(defun eshell-prompt-initialize () 102(defun eshell-prompt-initialize () ;Called from `eshell-mode' via intern-soft!
103 "Initialize the prompting code." 103 "Initialize the prompting code."
104 (unless eshell-non-interactive-p 104 (unless eshell-non-interactive-p
105 (add-hook 'eshell-post-command-hook 'eshell-emit-prompt nil t) 105 (add-hook 'eshell-post-command-hook 'eshell-emit-prompt nil t)
diff --git a/lisp/eshell/em-rebind.el b/lisp/eshell/em-rebind.el
index 9cb16174f20..a817edbcc99 100644
--- a/lisp/eshell/em-rebind.el
+++ b/lisp/eshell/em-rebind.el
@@ -145,7 +145,7 @@ This is default behavior of shells like bash."
145 145
146;;; Functions: 146;;; Functions:
147 147
148(defun eshell-rebind-initialize () 148(defun eshell-rebind-initialize () ;Called from `eshell-mode' via intern-soft!
149 "Initialize the inputting code." 149 "Initialize the inputting code."
150 (unless eshell-non-interactive-p 150 (unless eshell-non-interactive-p
151 (add-hook 'eshell-mode-hook 'eshell-setup-input-keymap nil t) 151 (add-hook 'eshell-mode-hook 'eshell-setup-input-keymap nil t)
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index bab26222baf..4a3b84e10e3 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -23,8 +23,7 @@
23 23
24;;; Code: 24;;; Code:
25 25
26(require 'eshell) 26(require 'esh-mode)
27(require 'esh-opt)
28 27
29;;;###autoload 28;;;###autoload
30(progn 29(progn
@@ -57,7 +56,7 @@ This includes when running `eshell-command'."
57 56
58;;; Functions: 57;;; Functions:
59 58
60(defun eshell-script-initialize () 59(defun eshell-script-initialize () ;Called from `eshell-mode' via intern-soft!
61 "Initialize the script parsing code." 60 "Initialize the script parsing code."
62 (make-local-variable 'eshell-interpreter-alist) 61 (make-local-variable 'eshell-interpreter-alist)
63 (setq eshell-interpreter-alist 62 (setq eshell-interpreter-alist
@@ -73,13 +72,14 @@ This includes when running `eshell-command'."
73 ;; to ruin it for other modules 72 ;; to ruin it for other modules
74 (let (eshell-inside-quote-regexp 73 (let (eshell-inside-quote-regexp
75 eshell-outside-quote-regexp) 74 eshell-outside-quote-regexp)
76 (and (not eshell-non-interactive-p) 75 (and (not (bound-and-true-p eshell-non-interactive-p))
77 eshell-login-script 76 eshell-login-script
78 (file-readable-p eshell-login-script) 77 (file-readable-p eshell-login-script)
79 (eshell-do-eval 78 (eshell-do-eval
80 (list 'eshell-commands 79 (list 'eshell-commands
81 (catch 'eshell-replace-command 80 (catch 'eshell-replace-command
82 (eshell-source-file eshell-login-script))) t)) 81 (eshell-source-file eshell-login-script)))
82 t))
83 (and eshell-rc-script 83 (and eshell-rc-script
84 (file-readable-p eshell-rc-script) 84 (file-readable-p eshell-rc-script)
85 (eshell-do-eval 85 (eshell-do-eval
diff --git a/lisp/eshell/em-smart.el b/lisp/eshell/em-smart.el
index 420f8850504..c7965b4187c 100644
--- a/lisp/eshell/em-smart.el
+++ b/lisp/eshell/em-smart.el
@@ -166,7 +166,7 @@ The options are `begin', `after' or `end'."
166 166
167;;; Functions: 167;;; Functions:
168 168
169(defun eshell-smart-initialize () 169(defun eshell-smart-initialize () ;Called from `eshell-mode' via intern-soft!
170 "Setup Eshell smart display." 170 "Setup Eshell smart display."
171 (unless eshell-non-interactive-p 171 (unless eshell-non-interactive-p
172 ;; override a few variables, since they would interfere with the 172 ;; override a few variables, since they would interfere with the
diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el
index 8af783eaf80..dea90405ad7 100644
--- a/lisp/eshell/em-term.el
+++ b/lisp/eshell/em-term.el
@@ -147,7 +147,7 @@ behavior for short-lived processes, see bug#18108."
147 147
148;;; Functions: 148;;; Functions:
149 149
150(defun eshell-term-initialize () 150(defun eshell-term-initialize () ;Called from `eshell-mode' via intern-soft!
151 "Initialize the `term' interface code." 151 "Initialize the `term' interface code."
152 (make-local-variable 'eshell-interpreter-alist) 152 (make-local-variable 'eshell-interpreter-alist)
153 (setq eshell-interpreter-alist 153 (setq eshell-interpreter-alist
@@ -191,7 +191,7 @@ allowed."
191 (term-exec term-buf program program nil args) 191 (term-exec term-buf program program nil args)
192 (let ((proc (get-buffer-process term-buf))) 192 (let ((proc (get-buffer-process term-buf)))
193 (if (and proc (eq 'run (process-status proc))) 193 (if (and proc (eq 'run (process-status proc)))
194 (set-process-sentinel proc 'eshell-term-sentinel) 194 (set-process-sentinel proc #'eshell-term-sentinel)
195 (error "Failed to invoke visual command"))) 195 (error "Failed to invoke visual command")))
196 (term-char-mode) 196 (term-char-mode)
197 (if eshell-escape-control-x 197 (if eshell-escape-control-x
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index 603b7627d5d..c7916360ee6 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -46,7 +46,7 @@
46 :tag "TRAMP Eshell features" 46 :tag "TRAMP Eshell features"
47 :group 'eshell-module)) 47 :group 'eshell-module))
48 48
49(defun eshell-tramp-initialize () 49(defun eshell-tramp-initialize () ;Called from `eshell-mode' via intern-soft!
50 "Initialize the TRAMP-using commands code." 50 "Initialize the TRAMP-using commands code."
51 (when (eshell-using-module 'eshell-cmpl) 51 (when (eshell-using-module 'eshell-cmpl)
52 (add-hook 'pcomplete-try-first-hook 52 (add-hook 'pcomplete-try-first-hook
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index e4c4265d702..25221817218 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -35,8 +35,7 @@
35 35
36;;; Code: 36;;; Code:
37 37
38(require 'eshell) 38(require 'esh-mode)
39(require 'esh-opt)
40(require 'pcomplete) 39(require 'pcomplete)
41 40
42;;;###autoload 41;;;###autoload
@@ -140,7 +139,7 @@ Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine."
140 139
141;;; Functions: 140;;; Functions:
142 141
143(defun eshell-unix-initialize () 142(defun eshell-unix-initialize () ;Called from `eshell-mode' via intern-soft!
144 "Initialize the UNIX support/emulation code." 143 "Initialize the UNIX support/emulation code."
145 (when (eshell-using-module 'eshell-cmpl) 144 (when (eshell-using-module 'eshell-cmpl)
146 (add-hook 'pcomplete-try-first-hook 145 (add-hook 'pcomplete-try-first-hook
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el
index 360202b6539..026edc59808 100644
--- a/lisp/eshell/esh-arg.el
+++ b/lisp/eshell/esh-arg.el
@@ -25,9 +25,9 @@
25;; hook `eshell-parse-argument-hook'. For a good example of this, see 25;; hook `eshell-parse-argument-hook'. For a good example of this, see
26;; `eshell-parse-drive-letter', defined in eshell-dirs.el. 26;; `eshell-parse-drive-letter', defined in eshell-dirs.el.
27 27
28(provide 'esh-arg) 28;;; Code:
29 29
30(require 'esh-mode) 30(require 'esh-util)
31 31
32(defgroup eshell-arg nil 32(defgroup eshell-arg nil
33 "Argument parsing involves transforming the arguments passed on the 33 "Argument parsing involves transforming the arguments passed on the
@@ -36,6 +36,48 @@ yield the values intended."
36 :tag "Argument parsing" 36 :tag "Argument parsing"
37 :group 'eshell) 37 :group 'eshell)
38 38
39;;; Internal Variables:
40
41(defvar eshell-current-argument nil)
42(defvar eshell-current-modifiers nil)
43(defvar eshell-arg-listified nil)
44(defvar eshell-nested-argument nil)
45(defvar eshell-current-quoted nil)
46(defvar eshell-inside-quote-regexp nil)
47(defvar eshell-outside-quote-regexp nil)
48
49;;; User Variables:
50
51(defcustom eshell-arg-load-hook nil
52 "A hook that gets run when `eshell-arg' is loaded."
53 :version "24.1" ; removed eshell-arg-initialize
54 :type 'hook
55 :group 'eshell-arg)
56
57(defcustom eshell-delimiter-argument-list '(?\; ?& ?\| ?\> ?\s ?\t ?\n)
58 "List of characters to recognize as argument separators."
59 :type '(repeat character)
60 :group 'eshell-arg)
61
62(defcustom eshell-special-chars-inside-quoting '(?\\ ?\")
63 "Characters which are still special inside double quotes."
64 :type '(repeat character)
65 :group 'eshell-arg)
66
67(defcustom eshell-special-chars-outside-quoting
68 (append eshell-delimiter-argument-list '(?# ?! ?\\ ?\" ?\'))
69 "Characters that require escaping outside of double quotes.
70Without escaping them, they will introduce a change in the argument."
71 :type '(repeat character)
72 :group 'eshell-arg)
73
74(defsubst eshell-arg-delimiter (&optional pos)
75 "Return non-nil if POS is an argument delimiter.
76If POS is nil, the location of point is checked."
77 (let ((pos (or pos (point))))
78 (or (= pos (point-max))
79 (memq (char-after pos) eshell-delimiter-argument-list))))
80
39(defcustom eshell-parse-argument-hook 81(defcustom eshell-parse-argument-hook
40 (list 82 (list
41 ;; a term such as #<buffer NAME>, or #<process NAME> is a buffer 83 ;; a term such as #<buffer NAME>, or #<process NAME> is a buffer
@@ -113,47 +155,13 @@ treated as a literal character."
113 :type 'hook 155 :type 'hook
114 :group 'eshell-arg) 156 :group 'eshell-arg)
115 157
116;;; Code:
117
118;;; User Variables:
119
120(defcustom eshell-arg-load-hook nil
121 "A hook that gets run when `eshell-arg' is loaded."
122 :version "24.1" ; removed eshell-arg-initialize
123 :type 'hook
124 :group 'eshell-arg)
125
126(defcustom eshell-delimiter-argument-list '(?\; ?& ?\| ?\> ?\s ?\t ?\n)
127 "List of characters to recognize as argument separators."
128 :type '(repeat character)
129 :group 'eshell-arg)
130
131(defcustom eshell-special-chars-inside-quoting '(?\\ ?\")
132 "Characters which are still special inside double quotes."
133 :type '(repeat character)
134 :group 'eshell-arg)
135
136(defcustom eshell-special-chars-outside-quoting
137 (append eshell-delimiter-argument-list '(?# ?! ?\\ ?\" ?\'))
138 "Characters that require escaping outside of double quotes.
139Without escaping them, they will introduce a change in the argument."
140 :type '(repeat character)
141 :group 'eshell-arg)
142
143;;; Internal Variables:
144
145(defvar eshell-current-argument nil)
146(defvar eshell-current-modifiers nil)
147(defvar eshell-arg-listified nil)
148(defvar eshell-nested-argument nil)
149(defvar eshell-current-quoted nil)
150(defvar eshell-inside-quote-regexp nil)
151(defvar eshell-outside-quote-regexp nil)
152
153;;; Functions: 158;;; Functions:
154 159
155(defun eshell-arg-initialize () 160(defun eshell-arg-initialize () ;Called from `eshell-mode' via intern-soft!
156 "Initialize the argument parsing code." 161 "Initialize the argument parsing code."
162 ;; This is supposedly run after enabling esh-mode, when eshell-mode-map
163 ;; already exists.
164 (defvar eshell-command-map)
157 (define-key eshell-command-map [(meta ?b)] 'eshell-insert-buffer-name) 165 (define-key eshell-command-map [(meta ?b)] 'eshell-insert-buffer-name)
158 (set (make-local-variable 'eshell-inside-quote-regexp) nil) 166 (set (make-local-variable 'eshell-inside-quote-regexp) nil)
159 (set (make-local-variable 'eshell-outside-quote-regexp) nil)) 167 (set (make-local-variable 'eshell-outside-quote-regexp) nil))
@@ -195,13 +203,6 @@ Without escaping them, they will introduce a change in the argument."
195 (setq eshell-current-argument argument)) 203 (setq eshell-current-argument argument))
196 (throw 'eshell-arg-done t)) 204 (throw 'eshell-arg-done t))
197 205
198(defsubst eshell-arg-delimiter (&optional pos)
199 "Return non-nil if POS is an argument delimiter.
200If POS is nil, the location of point is checked."
201 (let ((pos (or pos (point))))
202 (or (= pos (point-max))
203 (memq (char-after pos) eshell-delimiter-argument-list))))
204
205(defun eshell-quote-argument (string) 206(defun eshell-quote-argument (string)
206 "Return STRING with magic characters quoted. 207 "Return STRING with magic characters quoted.
207Magic characters are those in `eshell-special-chars-outside-quoting'." 208Magic characters are those in `eshell-special-chars-outside-quoting'."
@@ -405,4 +406,5 @@ If the form has no `type', the syntax is parsed as if `type' were
405 (char-to-string (char-after))))) 406 (char-to-string (char-after)))))
406 (goto-char end))))))) 407 (goto-char end)))))))
407 408
409(provide 'esh-arg)
408;;; esh-arg.el ends here 410;;; esh-arg.el ends here
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 1ed5d5d7018..6e03bda22b7 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -105,6 +105,8 @@
105 (require 'eldoc)) 105 (require 'eldoc))
106(require 'esh-arg) 106(require 'esh-arg)
107(require 'esh-proc) 107(require 'esh-proc)
108(require 'esh-module)
109(require 'esh-io)
108(require 'esh-ext) 110(require 'esh-ext)
109 111
110(eval-when-compile 112(eval-when-compile
@@ -285,7 +287,7 @@ otherwise t.")
285 "Return currently running command process, if non-Lisp." 287 "Return currently running command process, if non-Lisp."
286 eshell-last-async-proc) 288 eshell-last-async-proc)
287 289
288(defun eshell-cmd-initialize () 290(defun eshell-cmd-initialize () ;Called from `eshell-mode' via intern-soft!
289 "Initialize the Eshell command processing module." 291 "Initialize the Eshell command processing module."
290 (set (make-local-variable 'eshell-current-command) nil) 292 (set (make-local-variable 'eshell-current-command) nil)
291 (set (make-local-variable 'eshell-command-name) nil) 293 (set (make-local-variable 'eshell-command-name) nil)
@@ -1337,7 +1339,7 @@ messages, and errors."
1337 (eshell-print "\n")) 1339 (eshell-print "\n"))
1338 (eshell-close-handles 0 (list 'quote result))))) 1340 (eshell-close-handles 0 (list 'quote result)))))
1339 1341
1340(defalias 'eshell-lisp-command* 'eshell-lisp-command) 1342(defalias 'eshell-lisp-command* #'eshell-lisp-command)
1341 1343
1342(provide 'esh-cmd) 1344(provide 'esh-cmd)
1343 1345
diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el
index 35ebd36b291..978fc55c4de 100644
--- a/lisp/eshell/esh-ext.el
+++ b/lisp/eshell/esh-ext.el
@@ -31,17 +31,12 @@
31 31
32;;; Code: 32;;; Code:
33 33
34(provide 'esh-ext)
35
36(require 'esh-util) 34(require 'esh-util)
37 35
38(eval-when-compile 36(eval-when-compile (require 'cl-lib))
39 (require 'cl-lib)
40 (require 'esh-cmd))
41(require 'esh-io) 37(require 'esh-io)
42(require 'esh-arg) 38(require 'esh-arg)
43(require 'esh-opt) 39(require 'esh-opt)
44(require 'esh-proc)
45 40
46(defgroup eshell-ext nil 41(defgroup eshell-ext nil
47 "External commands are invoked when operating system executables are 42 "External commands are invoked when operating system executables are
@@ -177,9 +172,9 @@ external version."
177 172
178;;; Functions: 173;;; Functions:
179 174
180(defun eshell-ext-initialize () 175(defun eshell-ext-initialize () ;Called from `eshell-mode' via intern-soft!
181 "Initialize the external command handling code." 176 "Initialize the external command handling code."
182 (add-hook 'eshell-named-command-hook 'eshell-explicit-command nil t)) 177 (add-hook 'eshell-named-command-hook #'eshell-explicit-command nil t))
183 178
184(defun eshell-explicit-command (command args) 179(defun eshell-explicit-command (command args)
185 "If a command name begins with `*', call it externally always. 180 "If a command name begins with `*', call it externally always.
@@ -193,8 +188,6 @@ This bypasses all Lisp functions and aliases."
193 (error "%s: external command not found" 188 (error "%s: external command not found"
194 (substring command 1)))))) 189 (substring command 1))))))
195 190
196(autoload 'eshell-close-handles "esh-io")
197
198(defun eshell-remote-command (command args) 191(defun eshell-remote-command (command args)
199 "Insert output from a remote COMMAND, using ARGS. 192 "Insert output from a remote COMMAND, using ARGS.
200A remote command is something that executes on a different machine. 193A remote command is something that executes on a different machine.
@@ -211,7 +204,7 @@ causing the user to wonder if anything's really going on..."
211 (progn 204 (progn
212 (setq exitcode 205 (setq exitcode
213 (shell-command 206 (shell-command
214 (mapconcat 'shell-quote-argument 207 (mapconcat #'shell-quote-argument
215 (append (list command) args) " ") 208 (append (list command) args) " ")
216 outbuf errbuf)) 209 outbuf errbuf))
217 (eshell-print (with-current-buffer outbuf (buffer-string))) 210 (eshell-print (with-current-buffer outbuf (buffer-string)))
@@ -235,6 +228,8 @@ causing the user to wonder if anything's really going on..."
235 (cl-assert interp) 228 (cl-assert interp)
236 (if (functionp (car interp)) 229 (if (functionp (car interp))
237 (apply (car interp) (append (cdr interp) args)) 230 (apply (car interp) (append (cdr interp) args))
231 (require 'esh-proc)
232 (declare-function eshell-gather-process-output "esh-proc" (command args))
238 (eshell-gather-process-output 233 (eshell-gather-process-output
239 (car interp) (append (cdr interp) args))))) 234 (car interp) (append (cdr interp) args)))))
240 235
@@ -249,7 +244,7 @@ Adds the given PATH to $PATH.")
249 (if args 244 (if args
250 (progn 245 (progn
251 (setq eshell-path-env (getenv "PATH") 246 (setq eshell-path-env (getenv "PATH")
252 args (mapconcat 'identity args path-separator) 247 args (mapconcat #'identity args path-separator)
253 eshell-path-env 248 eshell-path-env
254 (if prepend 249 (if prepend
255 (concat args path-separator eshell-path-env) 250 (concat args path-separator eshell-path-env)
@@ -336,4 +331,5 @@ line of the form #!<interp>."
336 (cdr interp))))) 331 (cdr interp)))))
337 (or interp (list fullname))))))) 332 (or interp (list fullname)))))))
338 333
334(provide 'esh-ext)
339;;; esh-ext.el ends here 335;;; esh-ext.el ends here
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index c33e7325a82..ce1d021384d 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -68,8 +68,6 @@
68 68
69;;; Code: 69;;; Code:
70 70
71(provide 'esh-io)
72
73(require 'esh-arg) 71(require 'esh-arg)
74(require 'esh-util) 72(require 'esh-util)
75 73
@@ -171,7 +169,7 @@ not be added to this variable."
171 169
172;;; Functions: 170;;; Functions:
173 171
174(defun eshell-io-initialize () 172(defun eshell-io-initialize () ;Called from `eshell-mode' via intern-soft!
175 "Initialize the I/O subsystem code." 173 "Initialize the I/O subsystem code."
176 (add-hook 'eshell-parse-argument-hook 174 (add-hook 'eshell-parse-argument-hook
177 'eshell-parse-redirection nil t) 175 'eshell-parse-redirection nil t)
@@ -511,4 +509,5 @@ Returns what was actually sent, or nil if nothing was sent."
511 (eshell-output-object-to-target object (car target)) 509 (eshell-output-object-to-target object (car target))
512 (setq target (cdr target)))))) 510 (setq target (cdr target))))))
513 511
512(provide 'esh-io)
514;;; esh-io.el ends here 513;;; esh-io.el ends here
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index 30298763a53..cff29bed1b6 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -58,13 +58,10 @@
58 58
59;;; Code: 59;;; Code:
60 60
61(provide 'esh-mode)
62
63(require 'esh-util) 61(require 'esh-util)
64(require 'esh-module) 62(require 'esh-module)
65(require 'esh-cmd) 63(require 'esh-cmd)
66(require 'esh-io) 64(require 'esh-arg) ;For eshell-parse-arguments
67(require 'esh-var)
68 65
69(defgroup eshell-mode nil 66(defgroup eshell-mode nil
70 "This module contains code for handling input from the user." 67 "This module contains code for handling input from the user."
@@ -202,6 +199,12 @@ This is used by `eshell-watch-for-password-prompt'."
202 :type 'boolean 199 :type 'boolean
203 :group 'eshell-mode) 200 :group 'eshell-mode)
204 201
202(defcustom eshell-directory-name
203 (locate-user-emacs-file "eshell/" ".eshell/")
204 "The directory where Eshell control files should be kept."
205 :type 'directory
206 :group 'eshell)
207
205(defvar eshell-first-time-p t 208(defvar eshell-first-time-p t
206 "A variable which is non-nil the first time Eshell is loaded.") 209 "A variable which is non-nil the first time Eshell is loaded.")
207 210
@@ -292,7 +295,7 @@ and the hook `eshell-exit-hook'."
292 ;; It's fine to run this unconditionally since it can be customized 295 ;; It's fine to run this unconditionally since it can be customized
293 ;; via the `eshell-kill-processes-on-exit' variable. 296 ;; via the `eshell-kill-processes-on-exit' variable.
294 (and (fboundp 'eshell-query-kill-processes) 297 (and (fboundp 'eshell-query-kill-processes)
295 (not (memq 'eshell-query-kill-processes eshell-exit-hook)) 298 (not (memq #'eshell-query-kill-processes eshell-exit-hook))
296 (eshell-query-kill-processes)) 299 (eshell-query-kill-processes))
297 (run-hooks 'eshell-exit-hook)) 300 (run-hooks 'eshell-exit-hook))
298 301
@@ -334,7 +337,6 @@ and the hook `eshell-exit-hook'."
334 (define-key eshell-command-map [(control ?b)] 'eshell-backward-argument) 337 (define-key eshell-command-map [(control ?b)] 'eshell-backward-argument)
335 (define-key eshell-command-map [(control ?e)] 'eshell-show-maximum-output) 338 (define-key eshell-command-map [(control ?e)] 'eshell-show-maximum-output)
336 (define-key eshell-command-map [(control ?f)] 'eshell-forward-argument) 339 (define-key eshell-command-map [(control ?f)] 'eshell-forward-argument)
337 (define-key eshell-command-map [return] 'eshell-copy-old-input)
338 (define-key eshell-command-map [(control ?m)] 'eshell-copy-old-input) 340 (define-key eshell-command-map [(control ?m)] 'eshell-copy-old-input)
339 (define-key eshell-command-map [(control ?o)] 'eshell-kill-output) 341 (define-key eshell-command-map [(control ?o)] 'eshell-kill-output)
340 (define-key eshell-command-map [(control ?r)] 'eshell-show-output) 342 (define-key eshell-command-map [(control ?r)] 'eshell-show-output)
@@ -410,23 +412,23 @@ and the hook `eshell-exit-hook'."
410 (when (and load-hook (boundp load-hook)) 412 (when (and load-hook (boundp load-hook))
411 (if (memq initfunc (symbol-value load-hook)) (setq initfunc nil)) 413 (if (memq initfunc (symbol-value load-hook)) (setq initfunc nil))
412 (run-hooks load-hook)) 414 (run-hooks load-hook))
413 ;; So we don't need the -initialize functions on the hooks (b#5375). 415 ;; So we don't need the -initialize functions on the hooks (bug#5375).
414 (and initfunc (fboundp initfunc) (funcall initfunc)))) 416 (and initfunc (fboundp initfunc) (funcall initfunc))))
415 417
416 (if eshell-send-direct-to-subprocesses 418 (if eshell-send-direct-to-subprocesses
417 (add-hook 'pre-command-hook 'eshell-intercept-commands t t)) 419 (add-hook 'pre-command-hook #'eshell-intercept-commands t t))
418 420
419 (if eshell-scroll-to-bottom-on-input 421 (if eshell-scroll-to-bottom-on-input
420 (add-hook 'pre-command-hook 'eshell-preinput-scroll-to-bottom t t)) 422 (add-hook 'pre-command-hook #'eshell-preinput-scroll-to-bottom t t))
421 423
422 (when eshell-scroll-show-maximum-output 424 (when eshell-scroll-show-maximum-output
423 (set (make-local-variable 'scroll-conservatively) 1000)) 425 (set (make-local-variable 'scroll-conservatively) 1000))
424 426
425 (when eshell-status-in-mode-line 427 (when eshell-status-in-mode-line
426 (add-hook 'eshell-pre-command-hook 'eshell-command-started nil t) 428 (add-hook 'eshell-pre-command-hook #'eshell-command-started nil t)
427 (add-hook 'eshell-post-command-hook 'eshell-command-finished nil t)) 429 (add-hook 'eshell-post-command-hook #'eshell-command-finished nil t))
428 430
429 (add-hook 'kill-buffer-hook 'eshell-kill-buffer-function t t) 431 (add-hook 'kill-buffer-hook #'eshell-kill-buffer-function t t)
430 432
431 (if eshell-first-time-p 433 (if eshell-first-time-p
432 (run-hooks 'eshell-first-time-mode-hook)) 434 (run-hooks 'eshell-first-time-mode-hook))
@@ -451,10 +453,10 @@ and the hook `eshell-exit-hook'."
451 (if eshell-send-direct-to-subprocesses 453 (if eshell-send-direct-to-subprocesses
452 (progn 454 (progn
453 (setq eshell-send-direct-to-subprocesses nil) 455 (setq eshell-send-direct-to-subprocesses nil)
454 (remove-hook 'pre-command-hook 'eshell-intercept-commands t) 456 (remove-hook 'pre-command-hook #'eshell-intercept-commands t)
455 (message "Sending subprocess input on RET")) 457 (message "Sending subprocess input on RET"))
456 (setq eshell-send-direct-to-subprocesses t) 458 (setq eshell-send-direct-to-subprocesses t)
457 (add-hook 'pre-command-hook 'eshell-intercept-commands t t) 459 (add-hook 'pre-command-hook #'eshell-intercept-commands t t)
458 (message "Sending subprocess input directly"))) 460 (message "Sending subprocess input directly")))
459 461
460(defun eshell-self-insert-command () 462(defun eshell-self-insert-command ()
@@ -543,7 +545,7 @@ and the hook `eshell-exit-hook'."
543 "Push a mark at the end of the last input text." 545 "Push a mark at the end of the last input text."
544 (push-mark (1- eshell-last-input-end) t)) 546 (push-mark (1- eshell-last-input-end) t))
545 547
546(custom-add-option 'eshell-pre-command-hook 'eshell-push-command-mark) 548(custom-add-option 'eshell-pre-command-hook #'eshell-push-command-mark)
547 549
548(defsubst eshell-goto-input-start () 550(defsubst eshell-goto-input-start ()
549 "Goto the start of the last command input. 551 "Goto the start of the last command input.
@@ -551,7 +553,7 @@ Putting this function on `eshell-pre-command-hook' will mimic Plan 9's
5519term behavior." 5539term behavior."
552 (goto-char eshell-last-input-start)) 554 (goto-char eshell-last-input-start))
553 555
554(custom-add-option 'eshell-pre-command-hook 'eshell-push-command-mark) 556(custom-add-option 'eshell-pre-command-hook #'eshell-goto-input-start)
555 557
556(defsubst eshell-interactive-print (string) 558(defsubst eshell-interactive-print (string)
557 "Print STRING to the eshell display buffer." 559 "Print STRING to the eshell display buffer."
@@ -1021,4 +1023,5 @@ This function could be in the list `eshell-output-filter-functions'."
1021(custom-add-option 'eshell-output-filter-functions 1023(custom-add-option 'eshell-output-filter-functions
1022 'eshell-handle-ansi-color) 1024 'eshell-handle-ansi-color)
1023 1025
1026(provide 'esh-mode)
1024;;; esh-mode.el ends here 1027;;; esh-mode.el ends here
diff --git a/lisp/eshell/esh-module.el b/lisp/eshell/esh-module.el
index 2583044a446..1911a49a3a4 100644
--- a/lisp/eshell/esh-module.el
+++ b/lisp/eshell/esh-module.el
@@ -22,9 +22,6 @@
22 22
23;;; Code: 23;;; Code:
24 24
25(provide 'esh-module)
26
27(require 'eshell)
28(require 'esh-util) 25(require 'esh-util)
29 26
30(defgroup eshell-module nil 27(defgroup eshell-module nil
@@ -101,4 +98,5 @@ customization group. Example: `eshell-cmpl' for that module."
101 (unload-feature module) 98 (unload-feature module)
102 (message "Unloading %s...done" (symbol-name module)))))) 99 (message "Unloading %s...done" (symbol-name module))))))
103 100
101(provide 'esh-module)
104;;; esh-module.el ends here 102;;; esh-module.el ends here
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index a023a3c5d2e..3ea5873cafd 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -23,9 +23,6 @@
23 23
24;;; Code: 24;;; Code:
25 25
26(provide 'esh-opt)
27
28(require 'esh-ext)
29 26
30;; Unused. 27;; Unused.
31;; (defgroup eshell-opt nil 28;; (defgroup eshell-opt nil
@@ -36,6 +33,10 @@
36 33
37;;; User Functions: 34;;; User Functions:
38 35
36;; Macro expansion of eshell-eval-using-options refers to eshell-stringify-list
37;; defined in esh-util.
38(require 'esh-util)
39
39(defmacro eshell-eval-using-options (name macro-args options &rest body-forms) 40(defmacro eshell-eval-using-options (name macro-args options &rest body-forms)
40 "Process NAME's MACRO-ARGS using a set of command line OPTIONS. 41 "Process NAME's MACRO-ARGS using a set of command line OPTIONS.
41After doing so, stores settings in local symbols as declared by OPTIONS; 42After doing so, stores settings in local symbols as declared by OPTIONS;
@@ -127,6 +128,8 @@ let-bound variable `args'."
127(defun eshell--do-opts (name options args) 128(defun eshell--do-opts (name options args)
128 "Helper function for `eshell-eval-using-options'. 129 "Helper function for `eshell-eval-using-options'.
129This code doesn't really need to be macro expanded everywhere." 130This code doesn't really need to be macro expanded everywhere."
131 (require 'esh-ext)
132 (declare-function eshell-external-command "esh-ext" (command args))
130 (let ((ext-command 133 (let ((ext-command
131 (catch 'eshell-ext-command 134 (catch 'eshell-ext-command
132 (let ((usage-msg 135 (let ((usage-msg
@@ -145,6 +148,8 @@ This code doesn't really need to be macro expanded everywhere."
145 148
146(defun eshell-show-usage (name options) 149(defun eshell-show-usage (name options)
147 "Display the usage message for NAME, using OPTIONS." 150 "Display the usage message for NAME, using OPTIONS."
151 (require 'esh-ext)
152 (declare-function eshell-search-path "esh-ext" (name))
148 (let ((usage (format "usage: %s %s\n\n" name 153 (let ((usage (format "usage: %s %s\n\n" name
149 (cadr (memq ':usage options)))) 154 (cadr (memq ':usage options))))
150 (extcmd (memq ':external options)) 155 (extcmd (memq ':external options))
@@ -273,4 +278,5 @@ switch is unrecognized."
273 (setq index (1+ index)))))))) 278 (setq index (1+ index))))))))
274 (nconc (mapcar #'cdr opt-vals) eshell--args))) 279 (nconc (mapcar #'cdr opt-vals) eshell--args)))
275 280
281(provide 'esh-opt)
276;;; esh-opt.el ends here 282;;; esh-opt.el ends here
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index 3432582cf4b..d538ae32b37 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -23,9 +23,7 @@
23 23
24;;; Code: 24;;; Code:
25 25
26(provide 'esh-proc) 26(require 'esh-io)
27
28(require 'esh-cmd)
29 27
30(defgroup eshell-proc nil 28(defgroup eshell-proc nil
31 "When Eshell invokes external commands, it always does so 29 "When Eshell invokes external commands, it always does so
@@ -118,14 +116,17 @@ information, for example."
118Runs `eshell-reset-after-proc' and `eshell-kill-hook', passing arguments 116Runs `eshell-reset-after-proc' and `eshell-kill-hook', passing arguments
119PROC and STATUS to functions on the latter." 117PROC and STATUS to functions on the latter."
120 ;; Was there till 24.1, but it is not optional. 118 ;; Was there till 24.1, but it is not optional.
121 (if (memq 'eshell-reset-after-proc eshell-kill-hook) 119 (if (memq #'eshell-reset-after-proc eshell-kill-hook)
122 (setq eshell-kill-hook (delq 'eshell-reset-after-proc eshell-kill-hook))) 120 (setq eshell-kill-hook (delq #'eshell-reset-after-proc eshell-kill-hook)))
123 (eshell-reset-after-proc status) 121 (eshell-reset-after-proc status)
124 (run-hook-with-args 'eshell-kill-hook proc status)) 122 (run-hook-with-args 'eshell-kill-hook proc status))
125 123
126(defun eshell-proc-initialize () 124(defun eshell-proc-initialize () ;Called from `eshell-mode' via intern-soft!
127 "Initialize the process handling code." 125 "Initialize the process handling code."
128 (make-local-variable 'eshell-process-list) 126 (make-local-variable 'eshell-process-list)
127 ;; This is supposedly run after enabling esh-mode, when eshell-command-map
128 ;; already exists.
129 (defvar eshell-command-map)
129 (define-key eshell-command-map [(meta ?i)] 'eshell-insert-process) 130 (define-key eshell-command-map [(meta ?i)] 'eshell-insert-process)
130 (define-key eshell-command-map [(control ?c)] 'eshell-interrupt-process) 131 (define-key eshell-command-map [(control ?c)] 'eshell-interrupt-process)
131 (define-key eshell-command-map [(control ?k)] 'eshell-kill-process) 132 (define-key eshell-command-map [(control ?k)] 'eshell-kill-process)
@@ -139,9 +140,11 @@ PROC and STATUS to functions on the latter."
139 "Reset the command input location after a process terminates. 140 "Reset the command input location after a process terminates.
140The signals which will cause this to happen are matched by 141The signals which will cause this to happen are matched by
141`eshell-reset-signals'." 142`eshell-reset-signals'."
142 (if (and (stringp status) 143 (when (and (stringp status)
143 (string-match eshell-reset-signals status)) 144 (string-match eshell-reset-signals status))
144 (eshell-reset))) 145 (require 'esh-mode)
146 (declare-function eshell-reset "esh-mode" (&optional no-hooks))
147 (eshell-reset)))
145 148
146(defun eshell-wait-for-process (&rest procs) 149(defun eshell-wait-for-process (&rest procs)
147 "Wait until PROC has successfully completed." 150 "Wait until PROC has successfully completed."
@@ -209,7 +212,8 @@ The prompt will be set to PROMPT."
209 (function 212 (function
210 (lambda (proc) 213 (lambda (proc)
211 (cons (process-name proc) t))) 214 (cons (process-name proc) t)))
212 (process-list)) nil t)) 215 (process-list))
216 nil t))
213 217
214(defun eshell-insert-process (process) 218(defun eshell-insert-process (process)
215 "Insert the name of PROCESS into the current buffer at point." 219 "Insert the name of PROCESS into the current buffer at point."
@@ -220,10 +224,12 @@ The prompt will be set to PROMPT."
220 224
221(defsubst eshell-record-process-object (object) 225(defsubst eshell-record-process-object (object)
222 "Record OBJECT as now running." 226 "Record OBJECT as now running."
223 (if (and (eshell-processp object) 227 (when (and (eshell-processp object)
224 eshell-current-subjob-p) 228 eshell-current-subjob-p)
225 (eshell-interactive-print 229 (require 'esh-mode)
226 (format "[%s] %d\n" (process-name object) (process-id object)))) 230 (declare-function eshell-interactive-print "esh-mode" (string))
231 (eshell-interactive-print
232 (format "[%s] %d\n" (process-name object) (process-id object))))
227 (setq eshell-process-list 233 (setq eshell-process-list
228 (cons (list object eshell-current-handles 234 (cons (list object eshell-current-handles
229 eshell-current-subjob-p nil nil) 235 eshell-current-subjob-p nil nil)
@@ -254,7 +260,7 @@ the full name of a command, otherwise just the nondirectory part must match.")
254(defun eshell-needs-pipe-p (command) 260(defun eshell-needs-pipe-p (command)
255 "Return non-nil if COMMAND needs `process-connection-type' to be nil. 261 "Return non-nil if COMMAND needs `process-connection-type' to be nil.
256See `eshell-needs-pipe'." 262See `eshell-needs-pipe'."
257 (and eshell-in-pipeline-p 263 (and (bound-and-true-p eshell-in-pipeline-p)
258 (not (eq eshell-in-pipeline-p 'first)) 264 (not (eq eshell-in-pipeline-p 'first))
259 ;; FIXME should this return non-nil for anything that is 265 ;; FIXME should this return non-nil for anything that is
260 ;; neither 'first nor 'last? See bug#1388 discussion. 266 ;; neither 'first nor 'last? See bug#1388 discussion.
@@ -267,6 +273,8 @@ See `eshell-needs-pipe'."
267 273
268(defun eshell-gather-process-output (command args) 274(defun eshell-gather-process-output (command args)
269 "Gather the output from COMMAND + ARGS." 275 "Gather the output from COMMAND + ARGS."
276 (require 'esh-var)
277 (declare-function eshell-environment-variables "esh-var" ())
270 (unless (and (file-executable-p command) 278 (unless (and (file-executable-p command)
271 (file-regular-p (file-truename command))) 279 (file-regular-p (file-truename command)))
272 (error "%s: not an executable file" command)) 280 (error "%s: not an executable file" command))
@@ -283,14 +291,14 @@ See `eshell-needs-pipe'."
283 (unless (eshell-needs-pipe-p command) 291 (unless (eshell-needs-pipe-p command)
284 process-connection-type)) 292 process-connection-type))
285 (command (file-local-name (expand-file-name command)))) 293 (command (file-local-name (expand-file-name command))))
286 (apply 'start-file-process 294 (apply #'start-file-process
287 (file-name-nondirectory command) nil command args))) 295 (file-name-nondirectory command) nil command args)))
288 (eshell-record-process-object proc) 296 (eshell-record-process-object proc)
289 (set-process-buffer proc (current-buffer)) 297 (set-process-buffer proc (current-buffer))
290 (if (eshell-interactive-output-p) 298 (set-process-filter proc (if (eshell-interactive-output-p)
291 (set-process-filter proc 'eshell-output-filter) 299 #'eshell-output-filter
292 (set-process-filter proc 'eshell-insertion-filter)) 300 #'eshell-insertion-filter))
293 (set-process-sentinel proc 'eshell-sentinel) 301 (set-process-sentinel proc #'eshell-sentinel)
294 (run-hook-with-args 'eshell-exec-hook proc) 302 (run-hook-with-args 'eshell-exec-hook proc)
295 (when (fboundp 'process-coding-system) 303 (when (fboundp 'process-coding-system)
296 (let ((coding-systems (process-coding-system proc))) 304 (let ((coding-systems (process-coding-system proc)))
@@ -325,14 +333,14 @@ See `eshell-needs-pipe'."
325 (set-buffer oldbuf) 333 (set-buffer oldbuf)
326 (run-hook-with-args 'eshell-exec-hook command) 334 (run-hook-with-args 'eshell-exec-hook command)
327 (setq exit-status 335 (setq exit-status
328 (apply 'call-process-region 336 (apply #'call-process-region
329 (append (list eshell-last-sync-output-start (point) 337 (append (list eshell-last-sync-output-start (point)
330 command t 338 command t
331 eshell-scratch-buffer nil) 339 eshell-scratch-buffer nil)
332 args))) 340 args)))
333 ;; When in a pipeline, record the place where the output of 341 ;; When in a pipeline, record the place where the output of
334 ;; this process will begin. 342 ;; this process will begin.
335 (and eshell-in-pipeline-p 343 (and (bound-and-true-p eshell-in-pipeline-p)
336 (set-marker eshell-last-sync-output-start (point))) 344 (set-marker eshell-last-sync-output-start (point)))
337 ;; Simulate the effect of the process filter. 345 ;; Simulate the effect of the process filter.
338 (when (numberp exit-status) 346 (when (numberp exit-status)
@@ -349,11 +357,14 @@ See `eshell-needs-pipe'."
349 (setq lbeg lend) 357 (setq lbeg lend)
350 (set-buffer proc-buf)) 358 (set-buffer proc-buf))
351 (set-buffer oldbuf)) 359 (set-buffer oldbuf))
360 (require 'esh-mode)
361 (declare-function eshell-update-markers "esh-mode" (pmark))
362 (defvar eshell-last-output-end) ;Defined in esh-mode.el.
352 (eshell-update-markers eshell-last-output-end) 363 (eshell-update-markers eshell-last-output-end)
353 ;; Simulate the effect of eshell-sentinel. 364 ;; Simulate the effect of eshell-sentinel.
354 (eshell-close-handles (if (numberp exit-status) exit-status -1)) 365 (eshell-close-handles (if (numberp exit-status) exit-status -1))
355 (eshell-kill-process-function command exit-status) 366 (eshell-kill-process-function command exit-status)
356 (or eshell-in-pipeline-p 367 (or (bound-and-true-p eshell-in-pipeline-p)
357 (setq eshell-last-sync-output-start nil)) 368 (setq eshell-last-sync-output-start nil))
358 (if (not (numberp exit-status)) 369 (if (not (numberp exit-status))
359 (error "%s: external command failed: %s" command exit-status)) 370 (error "%s: external command failed: %s" command exit-status))
@@ -540,7 +551,11 @@ See the variable `eshell-kill-processes-on-exit'."
540(defun eshell-send-eof-to-process () 551(defun eshell-send-eof-to-process ()
541 "Send EOF to process." 552 "Send EOF to process."
542 (interactive) 553 (interactive)
554 (require 'esh-mode)
555 (declare-function eshell-send-input "esh-mode"
556 (&optional use-region queue-p no-newline))
543 (eshell-send-input nil nil t) 557 (eshell-send-input nil nil t)
544 (eshell-process-interact 'process-send-eof)) 558 (eshell-process-interact 'process-send-eof))
545 559
560(provide 'esh-proc)
546;;; esh-proc.el ends here 561;;; esh-proc.el ends here
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 118978e77d0..6f355c70a42 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -478,24 +478,22 @@ list."
478 (insert-file-contents (or filename eshell-hosts-file)) 478 (insert-file-contents (or filename eshell-hosts-file))
479 (goto-char (point-min)) 479 (goto-char (point-min))
480 (while (re-search-forward 480 (while (re-search-forward
481 "^\\([^#[:space:]]+\\)\\s-+\\(\\S-+\\)\\(\\s-*\\(\\S-+\\)\\)?" nil t) 481 ;; "^ \t\\([^# \t\n]+\\)[ \t]+\\([^ \t\n]+\\)\\([ \t]*\\([^ \t\n]+\\)\\)?"
482 (if (match-string 1) 482 "^[ \t]*\\([^# \t\n]+\\)[ \t]+\\([^ \t\n].+\\)" nil t)
483 (cl-pushnew (match-string 1) hosts :test #'equal)) 483 (push (cons (match-string 1)
484 (if (match-string 2) 484 (split-string (match-string 2)))
485 (cl-pushnew (match-string 2) hosts :test #'equal)) 485 hosts)))
486 (if (match-string 4) 486 (nreverse hosts)))
487 (cl-pushnew (match-string 4) hosts :test #'equal))))
488 (sort hosts #'string-lessp)))
489 487
490(defun eshell-read-hosts (file result-var timestamp-var) 488(defun eshell-read-hosts (file result-var timestamp-var)
491 "Read the contents of /etc/passwd for user names." 489 "Read the contents of /etc/hosts for host names."
492 (if (or (not (symbol-value result-var)) 490 (if (or (not (symbol-value result-var))
493 (not (symbol-value timestamp-var)) 491 (not (symbol-value timestamp-var))
494 (time-less-p 492 (time-less-p
495 (symbol-value timestamp-var) 493 (symbol-value timestamp-var)
496 (file-attribute-modification-time (file-attributes file)))) 494 (file-attribute-modification-time (file-attributes file))))
497 (progn 495 (progn
498 (set result-var (eshell-read-hosts-file file)) 496 (set result-var (apply #'nconc (eshell-read-hosts-file file)))
499 (set timestamp-var (current-time)))) 497 (set timestamp-var (current-time))))
500 (symbol-value result-var)) 498 (symbol-value result-var))
501 499
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index d8be72e3596..b08a5d242fe 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -105,11 +105,12 @@
105 105
106;;; Code: 106;;; Code:
107 107
108(provide 'esh-var)
109
110(require 'esh-util) 108(require 'esh-util)
111(require 'esh-cmd) 109(require 'esh-cmd)
112(require 'esh-opt) 110(require 'esh-opt)
111(require 'esh-module)
112(require 'esh-arg)
113(require 'esh-io)
113 114
114(require 'pcomplete) 115(require 'pcomplete)
115(require 'env) 116(require 'env)
@@ -198,7 +199,7 @@ function), and the arguments passed to this function would be the list
198 199
199;;; Functions: 200;;; Functions:
200 201
201(defun eshell-var-initialize () 202(defun eshell-var-initialize () ;Called from `eshell-mode' via intern-soft!
202 "Initialize the variable handle code." 203 "Initialize the variable handle code."
203 ;; Break the association with our parent's environment. Otherwise, 204 ;; Break the association with our parent's environment. Otherwise,
204 ;; changing a variable will affect all of Emacs. 205 ;; changing a variable will affect all of Emacs.
@@ -206,6 +207,9 @@ function), and the arguments passed to this function would be the list
206 (set (make-local-variable 'process-environment) 207 (set (make-local-variable 'process-environment)
207 (eshell-copy-environment))) 208 (eshell-copy-environment)))
208 209
210 ;; This is supposedly run after enabling esh-mode, when eshell-command-map
211 ;; already exists.
212 (defvar eshell-command-map)
209 (define-key eshell-command-map [(meta ?v)] 'eshell-insert-envvar) 213 (define-key eshell-command-map [(meta ?v)] 'eshell-insert-envvar)
210 214
211 (set (make-local-variable 'eshell-special-chars-inside-quoting) 215 (set (make-local-variable 'eshell-special-chars-inside-quoting)
@@ -213,16 +217,16 @@ function), and the arguments passed to this function would be the list
213 (set (make-local-variable 'eshell-special-chars-outside-quoting) 217 (set (make-local-variable 'eshell-special-chars-outside-quoting)
214 (append eshell-special-chars-outside-quoting '(?$))) 218 (append eshell-special-chars-outside-quoting '(?$)))
215 219
216 (add-hook 'eshell-parse-argument-hook 'eshell-interpolate-variable t t) 220 (add-hook 'eshell-parse-argument-hook #'eshell-interpolate-variable t t)
217 221
218 (add-hook 'eshell-prepare-command-hook 222 (add-hook 'eshell-prepare-command-hook
219 'eshell-handle-local-variables nil t) 223 #'eshell-handle-local-variables nil t)
220 224
221 (when (eshell-using-module 'eshell-cmpl) 225 (when (eshell-using-module 'eshell-cmpl)
222 (add-hook 'pcomplete-try-first-hook 226 (add-hook 'pcomplete-try-first-hook
223 'eshell-complete-variable-reference nil t) 227 #'eshell-complete-variable-reference nil t)
224 (add-hook 'pcomplete-try-first-hook 228 (add-hook 'pcomplete-try-first-hook
225 'eshell-complete-variable-assignment nil t))) 229 #'eshell-complete-variable-assignment nil t)))
226 230
227(defun eshell-handle-local-variables () 231(defun eshell-handle-local-variables ()
228 "Allow for the syntax `VAR=val <command> <args>'." 232 "Allow for the syntax `VAR=val <command> <args>'."
@@ -532,7 +536,7 @@ For example, to retrieve the second element of a user's record in
532 (setq separator (caar indices) 536 (setq separator (caar indices)
533 refs (cdr refs))) 537 refs (cdr refs)))
534 (setq value 538 (setq value
535 (mapcar 'eshell-convert 539 (mapcar #'eshell-convert
536 (split-string value separator))))) 540 (split-string value separator)))))
537 (cond 541 (cond
538 ((< (length refs) 0) 542 ((< (length refs) 0)
@@ -618,4 +622,5 @@ For example, to retrieve the second element of a user's record in
618 (setq pcomplete-stub (substring arg pos)) 622 (setq pcomplete-stub (substring arg pos))
619 (throw 'pcomplete-completions (pcomplete-entries))))) 623 (throw 'pcomplete-completions (pcomplete-entries)))))
620 624
625(provide 'esh-var)
621;;; esh-var.el ends here 626;;; esh-var.el ends here
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index 45168007565..db20f7d9ec5 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -175,7 +175,10 @@
175(eval-when-compile 175(eval-when-compile
176 (require 'cl-lib)) 176 (require 'cl-lib))
177(require 'esh-util) 177(require 'esh-util)
178(require 'esh-mode) 178(require 'esh-module) ;For eshell-using-module
179(require 'esh-proc) ;For eshell-wait-for-process
180(require 'esh-io) ;For eshell-last-command-status
181(require 'esh-cmd)
179 182
180(defgroup eshell nil 183(defgroup eshell nil
181 "Command shell implemented entirely in Emacs Lisp. 184 "Command shell implemented entirely in Emacs Lisp.
@@ -217,12 +220,6 @@ shells such as bash, zsh, rc, 4dos."
217 :type 'string 220 :type 'string
218 :group 'eshell) 221 :group 'eshell)
219 222
220(defcustom eshell-directory-name
221 (locate-user-emacs-file "eshell/" ".eshell/")
222 "The directory where Eshell control files should be kept."
223 :type 'directory
224 :group 'eshell)
225
226;;;_* Running Eshell 223;;;_* Running Eshell
227;; 224;;
228;; There are only three commands used to invoke Eshell. The first two 225;; There are only three commands used to invoke Eshell. The first two
@@ -256,11 +253,12 @@ buffer selected (or created)."
256 buf)) 253 buf))
257 254
258(defun eshell-return-exits-minibuffer () 255(defun eshell-return-exits-minibuffer ()
256 ;; This is supposedly run after enabling esh-mode, when eshell-mode-map
257 ;; already exists.
258 (defvar eshell-mode-map)
259 (define-key eshell-mode-map [(control ?g)] 'abort-recursive-edit) 259 (define-key eshell-mode-map [(control ?g)] 'abort-recursive-edit)
260 (define-key eshell-mode-map [return] 'exit-minibuffer)
261 (define-key eshell-mode-map [(control ?m)] 'exit-minibuffer) 260 (define-key eshell-mode-map [(control ?m)] 'exit-minibuffer)
262 (define-key eshell-mode-map [(control ?j)] 'exit-minibuffer) 261 (define-key eshell-mode-map [(control ?j)] 'exit-minibuffer)
263 (define-key eshell-mode-map [(meta return)] 'exit-minibuffer)
264 (define-key eshell-mode-map [(meta control ?m)] 'exit-minibuffer)) 262 (define-key eshell-mode-map [(meta control ?m)] 'exit-minibuffer))
265 263
266(defvar eshell-non-interactive-p nil 264(defvar eshell-non-interactive-p nil
@@ -275,7 +273,6 @@ non-interactive sessions, such as when using `eshell-command'.")
275 "Execute the Eshell command string COMMAND. 273 "Execute the Eshell command string COMMAND.
276With prefix ARG, insert output into the current buffer at point." 274With prefix ARG, insert output into the current buffer at point."
277 (interactive) 275 (interactive)
278 (require 'esh-cmd)
279 (unless arg 276 (unless arg
280 (setq arg current-prefix-arg)) 277 (setq arg current-prefix-arg))
281 (let ((eshell-non-interactive-p t)) 278 (let ((eshell-non-interactive-p t))
@@ -363,7 +360,8 @@ corresponding to a successful execution."
363 (let ((result (eshell-do-eval 360 (let ((result (eshell-do-eval
364 (list 'eshell-commands 361 (list 'eshell-commands
365 (list 'eshell-command-to-value 362 (list 'eshell-command-to-value
366 (eshell-parse-command command))) t))) 363 (eshell-parse-command command)))
364 t)))
367 (cl-assert (eq (car result) 'quote)) 365 (cl-assert (eq (car result) 'quote))
368 (if (and status-var (symbolp status-var)) 366 (if (and status-var (symbolp status-var))
369 (set status-var eshell-last-command-status)) 367 (set status-var eshell-last-command-status))
@@ -404,5 +402,4 @@ Emacs."
404(run-hooks 'eshell-load-hook) 402(run-hooks 'eshell-load-hook)
405 403
406(provide 'eshell) 404(provide 'eshell)
407
408;;; eshell.el ends here 405;;; eshell.el ends here
diff --git a/lisp/faces.el b/lisp/faces.el
index ab6c384c802..fa526c35061 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -55,6 +55,7 @@ This means to treat a terminal of type TYPE as if it were of type ALIAS."
55 :group 'terminals 55 :group 'terminals
56 :version "25.1") 56 :version "25.1")
57 57
58(declare-function display-graphic-p "frame" (&optional display))
58(declare-function xw-defined-colors "term/common-win" (&optional frame)) 59(declare-function xw-defined-colors "term/common-win" (&optional frame))
59 60
60(defvar help-xref-stack-item) 61(defvar help-xref-stack-item)
@@ -1239,7 +1240,7 @@ of a global face. Value is the new attribute value."
1239 ;; explicitly in VALID, using color approximation code 1240 ;; explicitly in VALID, using color approximation code
1240 ;; in tty-colors.el. 1241 ;; in tty-colors.el.
1241 (when (and (memq attribute '(:foreground :background)) 1242 (when (and (memq attribute '(:foreground :background))
1242 (not (memq (window-system frame) '(x w32 ns))) 1243 (not (display-graphic-p frame))
1243 (not (member new-value 1244 (not (member new-value
1244 '("unspecified" 1245 '("unspecified"
1245 "unspecified-fg" "unspecified-bg")))) 1246 "unspecified-fg" "unspecified-bg"))))
@@ -1833,7 +1834,7 @@ The argument FRAME specifies which frame to try.
1833The value may be different for frames on different display types. 1834The value may be different for frames on different display types.
1834If FRAME doesn't support colors, the value is nil. 1835If FRAME doesn't support colors, the value is nil.
1835If FRAME is nil, that stands for the selected frame." 1836If FRAME is nil, that stands for the selected frame."
1836 (if (memq (framep (or frame (selected-frame))) '(x w32 ns)) 1837 (if (display-graphic-p frame)
1837 (xw-defined-colors frame) 1838 (xw-defined-colors frame)
1838 (mapcar 'car (tty-color-alist frame)))) 1839 (mapcar 'car (tty-color-alist frame))))
1839(defalias 'x-defined-colors 'defined-colors) 1840(defalias 'x-defined-colors 'defined-colors)
@@ -1877,7 +1878,7 @@ or one of the strings \"unspecified-fg\" or \"unspecified-bg\".
1877 1878
1878If FRAME is omitted or nil, use the selected frame." 1879If FRAME is omitted or nil, use the selected frame."
1879 (unless (member color '(unspecified "unspecified-bg" "unspecified-fg")) 1880 (unless (member color '(unspecified "unspecified-bg" "unspecified-fg"))
1880 (if (member (framep (or frame (selected-frame))) '(x w32 ns)) 1881 (if (display-graphic-p frame)
1881 (xw-color-defined-p color frame) 1882 (xw-color-defined-p color frame)
1882 (numberp (tty-color-translate color frame))))) 1883 (numberp (tty-color-translate color frame)))))
1883(defalias 'x-color-defined-p 'color-defined-p) 1884(defalias 'x-color-defined-p 'color-defined-p)
@@ -1903,7 +1904,7 @@ return value is nil."
1903 (cond 1904 (cond
1904 ((member color '(unspecified "unspecified-fg" "unspecified-bg")) 1905 ((member color '(unspecified "unspecified-fg" "unspecified-bg"))
1905 nil) 1906 nil)
1906 ((memq (framep (or frame (selected-frame))) '(x w32 ns)) 1907 ((display-graphic-p frame)
1907 (xw-color-values color frame)) 1908 (xw-color-values color frame))
1908 (t 1909 (t
1909 (tty-color-values color frame)))) 1910 (tty-color-values color frame))))
@@ -1917,7 +1918,7 @@ return value is nil."
1917The optional argument DISPLAY specifies which display to ask about. 1918The optional argument DISPLAY specifies which display to ask about.
1918DISPLAY should be either a frame or a display name (a string). 1919DISPLAY should be either a frame or a display name (a string).
1919If omitted or nil, that stands for the selected frame's display." 1920If omitted or nil, that stands for the selected frame's display."
1920 (if (memq (framep-on-display display) '(x w32 ns)) 1921 (if (display-graphic-p display)
1921 (xw-display-color-p display) 1922 (xw-display-color-p display)
1922 (tty-display-color-p display))) 1923 (tty-display-color-p display)))
1923(defalias 'x-display-color-p 'display-color-p) 1924(defalias 'x-display-color-p 'display-color-p)
@@ -1928,12 +1929,9 @@ If omitted or nil, that stands for the selected frame's display."
1928 "Return non-nil if frames on DISPLAY can display shades of gray. 1929 "Return non-nil if frames on DISPLAY can display shades of gray.
1929DISPLAY should be either a frame or a display name (a string). 1930DISPLAY should be either a frame or a display name (a string).
1930If omitted or nil, that stands for the selected frame's display." 1931If omitted or nil, that stands for the selected frame's display."
1931 (let ((frame-type (framep-on-display display))) 1932 (if (display-graphic-p display)
1932 (cond 1933 (x-display-grayscale-p display)
1933 ((memq frame-type '(x w32 ns)) 1934 (> (tty-color-gray-shades display) 2)))
1934 (x-display-grayscale-p display))
1935 (t
1936 (> (tty-color-gray-shades display) 2)))))
1937 1935
1938(defun read-color (&optional prompt convert-to-RGB allow-empty-name msg) 1936(defun read-color (&optional prompt convert-to-RGB allow-empty-name msg)
1939 "Read a color name or RGB triplet. 1937 "Read a color name or RGB triplet.
diff --git a/lisp/files.el b/lisp/files.el
index 1dae57593a0..b81550e297c 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2705,9 +2705,8 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|CBR\\|7Z\\)\\'" . archive-mo
2705 ("\\.dbk\\'" . xml-mode) 2705 ("\\.dbk\\'" . xml-mode)
2706 ("\\.dtd\\'" . sgml-mode) 2706 ("\\.dtd\\'" . sgml-mode)
2707 ("\\.ds\\(ss\\)?l\\'" . dsssl-mode) 2707 ("\\.ds\\(ss\\)?l\\'" . dsssl-mode)
2708 ("\\.jsm?\\'" . javascript-mode) 2708 ("\\.js[mx]?\\'" . javascript-mode)
2709 ("\\.json\\'" . javascript-mode) 2709 ("\\.json\\'" . javascript-mode)
2710 ("\\.jsx\\'" . js-jsx-mode)
2711 ("\\.[ds]?vh?\\'" . verilog-mode) 2710 ("\\.[ds]?vh?\\'" . verilog-mode)
2712 ("\\.by\\'" . bovine-grammar-mode) 2711 ("\\.by\\'" . bovine-grammar-mode)
2713 ("\\.wy\\'" . wisent-grammar-mode) 2712 ("\\.wy\\'" . wisent-grammar-mode)
diff --git a/lisp/frame.el b/lisp/frame.el
index 6cb12473725..b5c936a51eb 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -974,7 +974,7 @@ recently selected windows nor the buffer list."
974 (select-frame frame norecord) 974 (select-frame frame norecord)
975 (raise-frame frame) 975 (raise-frame frame)
976 ;; Ensure, if possible, that FRAME gets input focus. 976 ;; Ensure, if possible, that FRAME gets input focus.
977 (when (memq (window-system frame) '(x w32 ns)) 977 (when (display-multi-frame-p frame)
978 (x-focus-frame frame)) 978 (x-focus-frame frame))
979 ;; Move mouse cursor if necessary. 979 ;; Move mouse cursor if necessary.
980 (cond 980 (cond
@@ -1027,16 +1027,15 @@ that variable should be nil."
1027 "Do whatever is right to suspend the current frame. 1027 "Do whatever is right to suspend the current frame.
1028Calls `suspend-emacs' if invoked from the controlling tty device, 1028Calls `suspend-emacs' if invoked from the controlling tty device,
1029`suspend-tty' from a secondary tty device, and 1029`suspend-tty' from a secondary tty device, and
1030`iconify-or-deiconify-frame' from an X frame." 1030`iconify-or-deiconify-frame' from a graphical frame."
1031 (interactive) 1031 (interactive)
1032 (let ((type (framep (selected-frame)))) 1032 (cond
1033 (cond 1033 ((display-multi-frame-p) (iconify-or-deiconify-frame))
1034 ((memq type '(x ns w32)) (iconify-or-deiconify-frame)) 1034 ((eq (framep (selected-frame)) t)
1035 ((eq type t) 1035 (if (controlling-tty-p)
1036 (if (controlling-tty-p) 1036 (suspend-emacs)
1037 (suspend-emacs) 1037 (suspend-tty)))
1038 (suspend-tty))) 1038 (t (suspend-emacs))))
1039 (t (suspend-emacs)))))
1040 1039
1041(defun make-frame-names-alist () 1040(defun make-frame-names-alist ()
1042 ;; Only consider the frames on the same display. 1041 ;; Only consider the frames on the same display.
@@ -1856,6 +1855,14 @@ for FRAME."
1856 1855
1857;;;; Frame/display capabilities. 1856;;;; Frame/display capabilities.
1858 1857
1858;; These functions should make the features they test explicit in
1859;; their names, so that when capabilities or the corresponding Emacs
1860;; features change, it will be easy to find all the tests for such
1861;; capabilities by a simple text search. See more about the history
1862;; and the intent of these functions in
1863;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2019-04/msg00004.html
1864;; or in https://debbugs.gnu.org/cgi/bugreport.cgi?bug=35058#17.
1865
1859(declare-function msdos-mouse-p "dosfns.c") 1866(declare-function msdos-mouse-p "dosfns.c")
1860 1867
1861(defun display-mouse-p (&optional display) 1868(defun display-mouse-p (&optional display)
@@ -1906,6 +1913,7 @@ frame's display)."
1906 (fboundp 'image-mask-p) 1913 (fboundp 'image-mask-p)
1907 (fboundp 'image-size))) 1914 (fboundp 'image-size)))
1908 1915
1916(defalias 'display-blink-cursor-p 'display-graphic-p)
1909(defalias 'display-multi-frame-p 'display-graphic-p) 1917(defalias 'display-multi-frame-p 'display-graphic-p)
1910(defalias 'display-multi-font-p 'display-graphic-p) 1918(defalias 'display-multi-font-p 'display-graphic-p)
1911 1919
@@ -1927,6 +1935,16 @@ frame's display)."
1927 (t 1935 (t
1928 nil)))) 1936 nil))))
1929 1937
1938(defun display-symbol-keys-p (&optional display)
1939 "Return non-nil if DISPLAY supports symbol names as keys.
1940This means that, for example, DISPLAY can differentiate between
1941the keybinding RET and [return]."
1942 (let ((frame-type (framep-on-display display)))
1943 (or (memq frame-type '(x w32 ns pc))
1944 ;; MS-DOS and MS-Windows terminals have built-in support for
1945 ;; function (symbol) keys
1946 (memq system-type '(ms-dos windows-nt)))))
1947
1930(declare-function x-display-screens "xfns.c" (&optional terminal)) 1948(declare-function x-display-screens "xfns.c" (&optional terminal))
1931 1949
1932(defun display-screens (&optional display) 1950(defun display-screens (&optional display)
@@ -2083,7 +2101,7 @@ If DISPLAY is omitted or nil, it defaults to the selected frame's display."
2083 ((eq frame-type 'pc) 2101 ((eq frame-type 'pc)
2084 4) 2102 4)
2085 (t 2103 (t
2086 (truncate (log (length (tty-color-alist)) 2)))))) 2104 (logb (length (tty-color-alist)))))))
2087 2105
2088(declare-function x-display-color-cells "xfns.c" (&optional terminal)) 2106(declare-function x-display-color-cells "xfns.c" (&optional terminal))
2089 2107
@@ -2546,7 +2564,7 @@ terminals, cursor blinking is controlled by the terminal."
2546 :init-value (not (or noninteractive 2564 :init-value (not (or noninteractive
2547 no-blinking-cursor 2565 no-blinking-cursor
2548 (eq system-type 'ms-dos) 2566 (eq system-type 'ms-dos)
2549 (not (memq window-system '(x w32 ns))))) 2567 (not (display-blink-cursor-p))))
2550 :initialize 'custom-initialize-delay 2568 :initialize 'custom-initialize-delay
2551 :group 'cursor 2569 :group 'cursor
2552 :global t 2570 :global t
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index 879e1fe2052..9f7d2c9df7d 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -276,7 +276,7 @@ Actually a hash table holding subjects mapped to t.")
276(defmacro gnus-agent-with-refreshed-group (group &rest body) 276(defmacro gnus-agent-with-refreshed-group (group &rest body)
277 "Performs the body then updates the group's line in the group 277 "Performs the body then updates the group's line in the group
278buffer. Automatically blocks multiple updates due to recursion." 278buffer. Automatically blocks multiple updates due to recursion."
279`(prog1 (let ((gnus-agent-inhibit-update-total-fetched-for t)) ,@body) 279 `(prog1 (let ((gnus-agent-inhibit-update-total-fetched-for t)) ,@body)
280 (when (and gnus-agent-need-update-total-fetched-for 280 (when (and gnus-agent-need-update-total-fetched-for
281 (not gnus-agent-inhibit-update-total-fetched-for)) 281 (not gnus-agent-inhibit-update-total-fetched-for))
282 (with-current-buffer gnus-group-buffer 282 (with-current-buffer gnus-group-buffer
@@ -311,9 +311,10 @@ buffer. Automatically blocks multiple updates due to recursion."
311(defun gnus-agent-cat-set-property (category property value) 311(defun gnus-agent-cat-set-property (category property value)
312 (if value 312 (if value
313 (setcdr (or (assq property category) 313 (setcdr (or (assq property category)
314 (let ((cell (cons property nil))) 314 (let ((cell (cons property nil)))
315 (setcdr category (cons cell (cdr category))) 315 (setcdr category (cons cell (cdr category)))
316 cell)) value) 316 cell))
317 value)
317 (let ((category category)) 318 (let ((category category))
318 (while (cond ((eq property (caadr category)) 319 (while (cond ((eq property (caadr category))
319 (setcdr category (cddr category)) 320 (setcdr category (cddr category))
@@ -378,7 +379,8 @@ manipulated as follows:
378 (setcdr (or (assq 'agent-groups category) 379 (setcdr (or (assq 'agent-groups category)
379 (let ((cell (cons 'agent-groups nil))) 380 (let ((cell (cons 'agent-groups nil)))
380 (setcdr category (cons cell (cdr category))) 381 (setcdr category (cons cell (cdr category)))
381 cell)) new-g)) 382 cell))
383 new-g))
382 (t 384 (t
383 (let ((groups groups)) 385 (let ((groups groups))
384 (while groups 386 (while groups
@@ -395,7 +397,8 @@ manipulated as follows:
395 (setcdr (or (assq 'agent-groups category) 397 (setcdr (or (assq 'agent-groups category)
396 (let ((cell (cons 'agent-groups nil))) 398 (let ((cell (cons 'agent-groups nil)))
397 (setcdr category (cons cell (cdr category))) 399 (setcdr category (cons cell (cdr category)))
398 cell)) groups)))))) 400 cell))
401 groups))))))
399 402
400(defsubst gnus-agent-cat-make (name &optional default-agent-predicate) 403(defsubst gnus-agent-cat-make (name &optional default-agent-predicate)
401 (list name `(agent-predicate . ,(or default-agent-predicate 'false)))) 404 (list name `(agent-predicate . ,(or default-agent-predicate 'false))))
@@ -1557,11 +1560,8 @@ downloaded into the agent."
1557 (skip-chars-forward " ") 1560 (skip-chars-forward " ")
1558 (setq crosses nil) 1561 (setq crosses nil)
1559 (while (looking-at "\\([^: \n]+\\):\\([0-9]+\\) *") 1562 (while (looking-at "\\([^: \n]+\\):\\([0-9]+\\) *")
1560 (push (cons (buffer-substring (match-beginning 1) 1563 (push (cons (match-string 1)
1561 (match-end 1)) 1564 (string-to-number (match-string 2)))
1562 (string-to-number
1563 (buffer-substring (match-beginning 2)
1564 (match-end 2))))
1565 crosses) 1565 crosses)
1566 (goto-char (match-end 0))) 1566 (goto-char (match-end 0)))
1567 (gnus-agent-crosspost crosses (caar pos) date))) 1567 (gnus-agent-crosspost crosses (caar pos) date)))
@@ -2939,7 +2939,7 @@ The following commands are available:
2939 'or) 2939 'or)
2940 ((memq (car predicate) gnus-category-not) 2940 ((memq (car predicate) gnus-category-not)
2941 'not)) 2941 'not))
2942 ,@(mapcar 'gnus-category-make-function-1 (cdr predicate)))) 2942 ,@(mapcar #'gnus-category-make-function-1 (cdr predicate))))
2943 (t 2943 (t
2944 (error "Unknown predicate type: %s" predicate)))) 2944 (error "Unknown predicate type: %s" predicate))))
2945 2945
@@ -2965,7 +2965,7 @@ return read articles, nil when it is known to always return read
2965articles, and t_nil when the function may return both read and unread 2965articles, and t_nil when the function may return both read and unread
2966articles." 2966articles."
2967 (let ((func (car function)) 2967 (let ((func (car function))
2968 (args (mapcar 'gnus-function-implies-unread-1 (cdr function)))) 2968 (args (mapcar #'gnus-function-implies-unread-1 (cdr function))))
2969 (cond ((eq func 'and) 2969 (cond ((eq func 'and)
2970 (cond ((memq t args) ; if any argument returns only unread articles 2970 (cond ((memq t args) ; if any argument returns only unread articles
2971 ;; then that argument constrains the result to only unread articles. 2971 ;; then that argument constrains the result to only unread articles.
@@ -3151,38 +3151,37 @@ FORCE is equivalent to setting the expiration predicates to true."
3151 (nov-file (concat dir ".overview")) 3151 (nov-file (concat dir ".overview"))
3152 (cnt 0) 3152 (cnt 0)
3153 (completed -1) 3153 (completed -1)
3154 dlist 3154 type
3155 type) 3155
3156 3156 ;; The normal article alist contains elements that look like
3157 ;; The normal article alist contains elements that look like 3157 ;; (article# . fetch_date) I need to combine other
3158 ;; (article# . fetch_date) I need to combine other 3158 ;; information with this list. For example, a flag indicating
3159 ;; information with this list. For example, a flag indicating 3159 ;; that a particular article MUST BE KEPT. To do this, I'm
3160 ;; that a particular article MUST BE KEPT. To do this, I'm 3160 ;; going to transform the elements to look like (article#
3161 ;; going to transform the elements to look like (article# 3161 ;; fetch_date keep_flag NOV_entry_position) Later, I'll reverse
3162 ;; fetch_date keep_flag NOV_entry_position) Later, I'll reverse 3162 ;; the process to generate the expired article alist.
3163 ;; the process to generate the expired article alist. 3163 (dlist
3164 3164 (nconc
3165 ;; Convert the alist elements to (article# fetch_date nil 3165 ;; Convert the alist elements to (article# fetch_date nil nil).
3166 ;; nil). 3166 (mapcar (lambda (e)
3167 (setq dlist (mapcar (lambda (e) 3167 (list (car e) (cdr e) nil nil))
3168 (list (car e) (cdr e) nil nil)) alist)) 3168 alist)
3169 3169
3170 ;; Convert the keep lists to elements that look like (article# 3170 ;; Convert the keep lists to elements that look like (article#
3171 ;; nil keep_flag nil) then append it to the expanded dlist 3171 ;; nil keep_flag nil) then append it to the expanded dlist
3172 ;; These statements are sorted by ascending precedence of the 3172 ;; These statements are sorted by ascending precedence of the
3173 ;; keep_flag. 3173 ;; keep_flag.
3174 (setq dlist (nconc dlist 3174 (mapcar (lambda (e)
3175 (mapcar (lambda (e) 3175 (list e nil 'unread nil))
3176 (list e nil 'unread nil)) 3176 unreads)
3177 unreads))) 3177
3178 (setq dlist (nconc dlist 3178 (mapcar (lambda (e)
3179 (mapcar (lambda (e) 3179 (list e nil 'marked nil))
3180 (list e nil 'marked nil)) 3180 marked)
3181 marked))) 3181
3182 (setq dlist (nconc dlist 3182 (mapcar (lambda (e)
3183 (mapcar (lambda (e) 3183 (list e nil 'special nil))
3184 (list e nil 'special nil)) 3184 specials))))
3185 specials)))
3186 3185
3187 (set-buffer overview) 3186 (set-buffer overview)
3188 (erase-buffer) 3187 (erase-buffer)
@@ -3391,7 +3390,7 @@ article alist" type) actions))
3391 (when actions 3390 (when actions
3392 (gnus-agent-message 8 "gnus-agent-expire: %s:%d: %s" 3391 (gnus-agent-message 8 "gnus-agent-expire: %s:%d: %s"
3393 decoded article-number 3392 decoded article-number
3394 (mapconcat 'identity actions ", "))))) 3393 (mapconcat #'identity actions ", ")))))
3395 (t 3394 (t
3396 (gnus-agent-message 3395 (gnus-agent-message
3397 10 "gnus-agent-expire: %s:%d: Article kept as \ 3396 10 "gnus-agent-expire: %s:%d: Article kept as \
@@ -3624,7 +3623,7 @@ If CACHED-HEADER is nil, articles are only excluded if the article itself
3624has been fetched." 3623has been fetched."
3625 3624
3626 ;; Logically equivalent to: (gnus-sorted-difference articles (mapcar 3625 ;; Logically equivalent to: (gnus-sorted-difference articles (mapcar
3627 ;; 'car gnus-agent-article-alist)) 3626 ;; #'car gnus-agent-article-alist))
3628 3627
3629 ;; Functionally, I don't need to construct a temp list using mapcar. 3628 ;; Functionally, I don't need to construct a temp list using mapcar.
3630 3629
diff --git a/lisp/gnus/gnus-dup.el b/lisp/gnus/gnus-dup.el
index 49022124e97..4981614a17f 100644
--- a/lisp/gnus/gnus-dup.el
+++ b/lisp/gnus/gnus-dup.el
@@ -107,7 +107,7 @@ seen in the same session."
107 107
108(defun gnus-dup-enter-articles () 108(defun gnus-dup-enter-articles ()
109 "Enter articles from the current group for future duplicate suppression." 109 "Enter articles from the current group for future duplicate suppression."
110 (unless gnus-dup-list 110 (unless gnus-dup-hashtb
111 (gnus-dup-open)) 111 (gnus-dup-open))
112 (setq gnus-dup-list-dirty t) ; mark list for saving 112 (setq gnus-dup-list-dirty t) ; mark list for saving
113 (let (msgid) 113 (let (msgid)
@@ -133,7 +133,7 @@ seen in the same session."
133 133
134(defun gnus-dup-suppress-articles () 134(defun gnus-dup-suppress-articles ()
135 "Mark duplicate articles as read." 135 "Mark duplicate articles as read."
136 (unless gnus-dup-list 136 (unless gnus-dup-hashtb
137 (gnus-dup-open)) 137 (gnus-dup-open))
138 (gnus-message 8 "Suppressing duplicates...") 138 (gnus-message 8 "Suppressing duplicates...")
139 (let ((auto (and gnus-newsgroup-auto-expire 139 (let ((auto (and gnus-newsgroup-auto-expire
@@ -152,9 +152,10 @@ seen in the same session."
152 152
153(defun gnus-dup-unsuppress-article (article) 153(defun gnus-dup-unsuppress-article (article)
154 "Stop suppression of ARTICLE." 154 "Stop suppression of ARTICLE."
155 (let* ((header (gnus-data-header (gnus-data-find article))) 155 (let (header id)
156 (id (when header (mail-header-id header)))) 156 (when (and gnus-dup-hashtb
157 (when id 157 (setq header (gnus-data-header (gnus-data-find article)))
158 (setq id (mail-header-id header)))
158 (setq gnus-dup-list-dirty t) 159 (setq gnus-dup-list-dirty t)
159 (setq gnus-dup-list (delete id gnus-dup-list)) 160 (setq gnus-dup-list (delete id gnus-dup-list))
160 (remhash id gnus-dup-hashtb)))) 161 (remhash id gnus-dup-hashtb))))
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 0be38541745..144496bdd2a 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -2560,7 +2560,11 @@ If FAR, it is likely that the group is not on the current line.
2560If TEST-MARKED, the line must be marked." 2560If TEST-MARKED, the line must be marked."
2561 (when group 2561 (when group
2562 (let ((start (point)) 2562 (let ((start (point))
2563 (active (and (gethash group gnus-active-hashtb) 2563 (active (and (or
2564 ;; some kind of group may be only there.
2565 (gethash group gnus-active-hashtb)
2566 ;; all groups (but with exception) are there.
2567 (gethash group gnus-newsrc-hashtb))
2564 group))) 2568 group)))
2565 (beginning-of-line) 2569 (beginning-of-line)
2566 (cond 2570 (cond
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 9b1be650673..2beb685822f 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -2145,12 +2145,15 @@ The info element is shared with the same element of
2145 (condition-case () 2145 (condition-case ()
2146 (if (and (stringp (progn 2146 (if (and (stringp (progn
2147 (setq group (read cur) 2147 (setq group (read cur)
2148 group (cond ((numberp group) 2148 group
2149 (number-to-string group)) 2149 (encode-coding-string
2150 ((symbolp group) 2150 (cond ((numberp group)
2151 (symbol-name group)) 2151 (number-to-string group))
2152 ((stringp group) 2152 ((symbolp group)
2153 group))))) 2153 (symbol-name group))
2154 ((stringp group)
2155 group))
2156 'latin-1))))
2154 (numberp (setq max (read cur))) 2157 (numberp (setq max (read cur)))
2155 (numberp (setq min (read cur))) 2158 (numberp (setq min (read cur)))
2156 (null (progn 2159 (null (progn
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index f5853a24305..b8aa302f11a 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -27,7 +27,34 @@
27(require 'cl-lib) 27(require 'cl-lib)
28 28
29(defvar tool-bar-mode) 29(defvar tool-bar-mode)
30(defvar gnus-category-predicate-alist)
31(defvar gnus-category-predicate-cache)
32(defvar gnus-inhibit-article-treatments)
33(defvar gnus-inhibit-demon)
34(defvar gnus-tmp-article-number)
35(defvar gnus-tmp-closing-bracket)
36(defvar gnus-tmp-current)
37(defvar gnus-tmp-dummy)
38(defvar gnus-tmp-expirable)
39(defvar gnus-tmp-from)
40(defvar gnus-tmp-group-name)
30(defvar gnus-tmp-header) 41(defvar gnus-tmp-header)
42(defvar gnus-tmp-indentation)
43(defvar gnus-tmp-level)
44(defvar gnus-tmp-lines)
45(defvar gnus-tmp-number)
46(defvar gnus-tmp-opening-bracket)
47(defvar gnus-tmp-process)
48(defvar gnus-tmp-replied)
49(defvar gnus-tmp-score)
50(defvar gnus-tmp-score-char)
51(defvar gnus-tmp-subject)
52(defvar gnus-tmp-subject-or-nil)
53(defvar gnus-tmp-unread)
54(defvar gnus-tmp-unread-and-unselected)
55(defvar gnus-tmp-unread-and-unticked)
56(defvar gnus-tmp-user-defined)
57(defvar gnus-use-article-prefetch)
31 58
32(require 'gnus) 59(require 'gnus)
33(require 'gnus-group) 60(require 'gnus-group)
@@ -784,7 +811,7 @@ score file."
784 :group 'gnus-score-default 811 :group 'gnus-score-default
785 :type 'integer) 812 :type 'integer)
786 813
787(defun gnus-widget-reversible-match (widget value) 814(defun gnus-widget-reversible-match (_widget value)
788 "Ignoring WIDGET, convert VALUE to internal form. 815 "Ignoring WIDGET, convert VALUE to internal form.
789VALUE should have the form `FOO' or `(not FOO)', where FOO is an symbol." 816VALUE should have the form `FOO' or `(not FOO)', where FOO is an symbol."
790 ;; (debug value) 817 ;; (debug value)
@@ -794,7 +821,7 @@ VALUE should have the form `FOO' or `(not FOO)', where FOO is an symbol."
794 (eq (nth 0 value) 'not) 821 (eq (nth 0 value) 'not)
795 (symbolp (nth 1 value))))) 822 (symbolp (nth 1 value)))))
796 823
797(defun gnus-widget-reversible-to-internal (widget value) 824(defun gnus-widget-reversible-to-internal (_widget value)
798 "Ignoring WIDGET, convert VALUE to internal form. 825 "Ignoring WIDGET, convert VALUE to internal form.
799VALUE should have the form `FOO' or `(not FOO)', where FOO is an atom. 826VALUE should have the form `FOO' or `(not FOO)', where FOO is an atom.
800FOO is converted to (FOO nil) and (not FOO) is converted to (FOO t)." 827FOO is converted to (FOO nil) and (not FOO) is converted to (FOO t)."
@@ -803,7 +830,7 @@ FOO is converted to (FOO nil) and (not FOO) is converted to (FOO t)."
803 (list value nil) 830 (list value nil)
804 (list (nth 1 value) t))) 831 (list (nth 1 value) t)))
805 832
806(defun gnus-widget-reversible-to-external (widget value) 833(defun gnus-widget-reversible-to-external (_widget value)
807 "Ignoring WIDGET, convert VALUE to external form. 834 "Ignoring WIDGET, convert VALUE to external form.
808VALUE should have the form `(FOO nil)' or `(FOO t)', where FOO is an atom. 835VALUE should have the form `(FOO nil)' or `(FOO t)', where FOO is an atom.
809\(FOO nil) is converted to FOO and (FOO t) is converted to (not FOO)." 836\(FOO nil) is converted to FOO and (FOO t) is converted to (not FOO)."
@@ -1385,7 +1412,8 @@ the normal Gnus MIME machinery."
1385 (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from))) 1412 (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
1386 ?s) 1413 ?s)
1387 (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from)) 1414 (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
1388 gnus-tmp-from) ?s) 1415 gnus-tmp-from)
1416 ?s)
1389 (?F gnus-tmp-from ?s) 1417 (?F gnus-tmp-from ?s)
1390 (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s) 1418 (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
1391 (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s) 1419 (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
@@ -1397,12 +1425,15 @@ the normal Gnus MIME machinery."
1397 (?k (gnus-summary-line-message-size gnus-tmp-header) ?s) 1425 (?k (gnus-summary-line-message-size gnus-tmp-header) ?s)
1398 (?L gnus-tmp-lines ?s) 1426 (?L gnus-tmp-lines ?s)
1399 (?Z (or (nnir-article-rsv (mail-header-number gnus-tmp-header)) 1427 (?Z (or (nnir-article-rsv (mail-header-number gnus-tmp-header))
1400 0) ?d) 1428 0)
1429 ?d)
1401 (?G (or (nnir-article-group (mail-header-number gnus-tmp-header)) 1430 (?G (or (nnir-article-group (mail-header-number gnus-tmp-header))
1402 "") ?s) 1431 "")
1432 ?s)
1403 (?g (or (gnus-group-short-name 1433 (?g (or (gnus-group-short-name
1404 (nnir-article-group (mail-header-number gnus-tmp-header))) 1434 (nnir-article-group (mail-header-number gnus-tmp-header)))
1405 "") ?s) 1435 "")
1436 ?s)
1406 (?O gnus-tmp-downloaded ?c) 1437 (?O gnus-tmp-downloaded ?c)
1407 (?I gnus-tmp-indentation ?s) 1438 (?I gnus-tmp-indentation ?s)
1408 (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s) 1439 (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
@@ -1427,7 +1458,8 @@ the normal Gnus MIME machinery."
1427 (?P (gnus-pick-line-number) ?d) 1458 (?P (gnus-pick-line-number) ?d)
1428 (?B gnus-tmp-thread-tree-header-string ?s) 1459 (?B gnus-tmp-thread-tree-header-string ?s)
1429 (user-date (gnus-user-date 1460 (user-date (gnus-user-date
1430 ,(macroexpand '(mail-header-date gnus-tmp-header))) ?s)) 1461 ,(macroexpand '(mail-header-date gnus-tmp-header)))
1462 ?s))
1431 "An alist of format specifications that can appear in summary lines. 1463 "An alist of format specifications that can appear in summary lines.
1432These are paired with what variables they correspond with, along with 1464These are paired with what variables they correspond with, along with
1433the type of the variable (string, integer, character, etc).") 1465the type of the variable (string, integer, character, etc).")
@@ -1672,6 +1704,7 @@ For example:
1672(eval-when-compile 1704(eval-when-compile
1673 ;; Bind features so that require will believe that gnus-sum has 1705 ;; Bind features so that require will believe that gnus-sum has
1674 ;; already been loaded (avoids infinite recursion) 1706 ;; already been loaded (avoids infinite recursion)
1707 (with-no-warnings (defvar features)) ;Not just a local variable.
1675 (let ((features (cons 'gnus-sum features))) 1708 (let ((features (cons 'gnus-sum features)))
1676 (require 'gnus-art))) 1709 (require 'gnus-art)))
1677 1710
@@ -3107,18 +3140,16 @@ The following commands are available:
3107 3140
3108(defun gnus-summary-make-local-variables () 3141(defun gnus-summary-make-local-variables ()
3109 "Make all the local summary buffer variables." 3142 "Make all the local summary buffer variables."
3110 (let (global) 3143 (dolist (local gnus-summary-local-variables)
3111 (dolist (local gnus-summary-local-variables) 3144 (if (consp local)
3112 (if (consp local) 3145 (let ((global (if (eq (cdr local) 'global)
3113 (progn 3146 ;; Copy the global value of the variable.
3114 (if (eq (cdr local) 'global) 3147 (symbol-value (car local))
3115 ;; Copy the global value of the variable. 3148 ;; Use the value from the list.
3116 (setq global (symbol-value (car local))) 3149 (eval (cdr local)))))
3117 ;; Use the value from the list. 3150 (set (make-local-variable (car local)) global))
3118 (setq global (eval (cdr local)))) 3151 ;; Simple nil-valued local variable.
3119 (set (make-local-variable (car local)) global)) 3152 (set (make-local-variable local) nil))))
3120 ;; Simple nil-valued local variable.
3121 (set (make-local-variable local) nil)))))
3122 3153
3123;; Summary data functions. 3154;; Summary data functions.
3124 3155
@@ -3525,13 +3556,12 @@ buffer that was in action when the last article was fetched."
3525 (score-file gnus-current-score-file) 3556 (score-file gnus-current-score-file)
3526 (default-charset gnus-newsgroup-charset) 3557 (default-charset gnus-newsgroup-charset)
3527 vlist) 3558 vlist)
3528 (let ((locals gnus-newsgroup-variables)) 3559 (dolist (local gnus-newsgroup-variables)
3529 (while locals 3560 (push (eval (if (consp local) (car local)
3530 (if (consp (car locals)) 3561 local)
3531 (push (eval (caar locals)) vlist) 3562 t)
3532 (push (eval (car locals)) vlist)) 3563 vlist))
3533 (setq locals (cdr locals))) 3564 (setq vlist (nreverse vlist))
3534 (setq vlist (nreverse vlist)))
3535 (with-temp-buffer 3565 (with-temp-buffer
3536 (setq gnus-newsgroup-name name 3566 (setq gnus-newsgroup-name name
3537 gnus-newsgroup-marked marked 3567 gnus-newsgroup-marked marked
@@ -3546,12 +3576,11 @@ buffer that was in action when the last article was fetched."
3546 gnus-reffed-article-number reffed 3576 gnus-reffed-article-number reffed
3547 gnus-current-score-file score-file 3577 gnus-current-score-file score-file
3548 gnus-newsgroup-charset default-charset) 3578 gnus-newsgroup-charset default-charset)
3549 (let ((locals gnus-newsgroup-variables)) 3579 (dolist (local gnus-newsgroup-variables)
3550 (while locals 3580 (set (if (consp local)
3551 (if (consp (car locals)) 3581 (car local)
3552 (set (caar locals) (pop vlist)) 3582 local)
3553 (set (car locals) (pop vlist))) 3583 (pop vlist)))))))
3554 (setq locals (cdr locals))))))))
3555 3584
3556(defun gnus-summary-article-unread-p (article) 3585(defun gnus-summary-article-unread-p (article)
3557 "Say whether ARTICLE is unread or not." 3586 "Say whether ARTICLE is unread or not."
@@ -3639,19 +3668,23 @@ buffer that was in action when the last article was fetched."
3639 pos))) 3668 pos)))
3640 (setq gnus-summary-mark-positions pos)))) 3669 (setq gnus-summary-mark-positions pos))))
3641 3670
3642(defun gnus-summary-insert-dummy-line (gnus-tmp-subject gnus-tmp-number) 3671(defun gnus-summary-insert-dummy-line (subject number)
3643 "Insert a dummy root in the summary buffer." 3672 "Insert a dummy root in the summary buffer."
3644 (beginning-of-line) 3673 (beginning-of-line)
3645 (add-text-properties 3674 (add-text-properties
3646 (point) (progn (eval gnus-summary-dummy-line-format-spec) (point)) 3675 (point) (let ((gnus-tmp-subject subject)
3647 (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number))) 3676 (gnus-tmp-number number))
3677 (eval gnus-summary-dummy-line-format-spec t)
3678 (point))
3679 (list 'gnus-number number 'gnus-intangible number)))
3648 3680
3649(defun gnus-summary-extract-address-component (from) 3681(defun gnus-summary-extract-address-component (from)
3650 (or (car (funcall gnus-extract-address-components from)) 3682 (or (car (funcall gnus-extract-address-components from))
3651 from)) 3683 from))
3652 3684
3653(defun gnus-summary-from-or-to-or-newsgroups (header gnus-tmp-from) 3685(defun gnus-summary-from-or-to-or-newsgroups (header from)
3654 (let ((mail-parse-charset gnus-newsgroup-charset) 3686 (let ((gnus-tmp-from from)
3687 (mail-parse-charset gnus-newsgroup-charset)
3655 ;; Is it really necessary to do this next part for each summary line? 3688 ;; Is it really necessary to do this next part for each summary line?
3656 ;; Luckily, doesn't seem to slow things down much. 3689 ;; Luckily, doesn't seem to slow things down much.
3657 (mail-parse-ignored-charsets 3690 (mail-parse-ignored-charsets
@@ -3678,25 +3711,31 @@ buffer that was in action when the last article was fetched."
3678 (and 3711 (and
3679 (memq 'Newsgroups gnus-extra-headers) 3712 (memq 'Newsgroups gnus-extra-headers)
3680 (eq (car (gnus-find-method-for-group 3713 (eq (car (gnus-find-method-for-group
3681 gnus-newsgroup-name)) 'nntp) 3714 gnus-newsgroup-name))
3715 'nntp)
3682 (gnus-group-real-name gnus-newsgroup-name)))) 3716 (gnus-group-real-name gnus-newsgroup-name))))
3683 (concat gnus-summary-newsgroup-prefix newsgroups))))) 3717 (concat gnus-summary-newsgroup-prefix newsgroups)))))
3684 (bidi-string-mark-left-to-right 3718 (bidi-string-mark-left-to-right
3685 (inline 3719 (inline
3686 (gnus-summary-extract-address-component gnus-tmp-from)))))) 3720 (gnus-summary-extract-address-component gnus-tmp-from))))))
3687 3721
3688(defun gnus-summary-insert-line (gnus-tmp-header 3722(defun gnus-summary-insert-line (header level current undownloaded
3689 gnus-tmp-level gnus-tmp-current 3723 unread replied expirable subject-or-nil
3690 undownloaded gnus-tmp-unread gnus-tmp-replied 3724 &optional dummy score process)
3691 gnus-tmp-expirable gnus-tmp-subject-or-nil 3725 (if (>= level (length gnus-thread-indent-array))
3692 &optional gnus-tmp-dummy gnus-tmp-score
3693 gnus-tmp-process)
3694 (if (>= gnus-tmp-level (length gnus-thread-indent-array))
3695 (gnus-make-thread-indent-array (max (* 2 (length gnus-thread-indent-array)) 3726 (gnus-make-thread-indent-array (max (* 2 (length gnus-thread-indent-array))
3696 gnus-tmp-level))) 3727 level)))
3697 (let* ((gnus-tmp-indentation (aref gnus-thread-indent-array gnus-tmp-level)) 3728 (let* ((gnus-tmp-header header)
3729 (gnus-tmp-level level)
3730 (gnus-tmp-current current)
3731 (gnus-tmp-unread unread)
3732 (gnus-tmp-expirable expirable)
3733 (gnus-tmp-subject-or-nil subject-or-nil)
3734 (gnus-tmp-dummy dummy)
3735 (gnus-tmp-process process)
3736 (gnus-tmp-indentation (aref gnus-thread-indent-array gnus-tmp-level))
3698 (gnus-tmp-lines (mail-header-lines gnus-tmp-header)) 3737 (gnus-tmp-lines (mail-header-lines gnus-tmp-header))
3699 (gnus-tmp-score (or gnus-tmp-score gnus-summary-default-score 0)) 3738 (gnus-tmp-score (or score gnus-summary-default-score 0))
3700 (gnus-tmp-score-char 3739 (gnus-tmp-score-char
3701 (if (or (null gnus-summary-default-score) 3740 (if (or (null gnus-summary-default-score)
3702 (<= (abs (- gnus-tmp-score gnus-summary-default-score)) 3741 (<= (abs (- gnus-tmp-score gnus-summary-default-score))
@@ -3709,7 +3748,7 @@ buffer that was in action when the last article was fetched."
3709 (cond (gnus-tmp-process gnus-process-mark) 3748 (cond (gnus-tmp-process gnus-process-mark)
3710 ((memq gnus-tmp-current gnus-newsgroup-cached) 3749 ((memq gnus-tmp-current gnus-newsgroup-cached)
3711 gnus-cached-mark) 3750 gnus-cached-mark)
3712 (gnus-tmp-replied gnus-replied-mark) 3751 (replied gnus-replied-mark)
3713 ((memq gnus-tmp-current gnus-newsgroup-forwarded) 3752 ((memq gnus-tmp-current gnus-newsgroup-forwarded)
3714 gnus-forwarded-mark) 3753 gnus-forwarded-mark)
3715 ((memq gnus-tmp-current gnus-newsgroup-saved) 3754 ((memq gnus-tmp-current gnus-newsgroup-saved)
@@ -4461,7 +4500,7 @@ Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise."
4461 ;; build complete threads - if the roots haven't been expired by the 4500 ;; build complete threads - if the roots haven't been expired by the
4462 ;; server, that is. 4501 ;; server, that is.
4463 (let ((mail-parse-charset gnus-newsgroup-charset) 4502 (let ((mail-parse-charset gnus-newsgroup-charset)
4464 id heads) 4503 heads)
4465 (maphash 4504 (maphash
4466 (lambda (id refs) 4505 (lambda (id refs)
4467 (when (not (car refs)) 4506 (when (not (car refs))
@@ -4485,7 +4524,6 @@ Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise."
4485;; on the beginning of the line. 4524;; on the beginning of the line.
4486(defsubst gnus-nov-parse-line (number dependencies &optional force-new) 4525(defsubst gnus-nov-parse-line (number dependencies &optional force-new)
4487 (let ((eol (point-at-eol)) 4526 (let ((eol (point-at-eol))
4488 (buffer (current-buffer))
4489 header references in-reply-to) 4527 header references in-reply-to)
4490 4528
4491 ;; overview: [num subject from date id refs chars lines misc] 4529 ;; overview: [num subject from date id refs chars lines misc]
@@ -4940,8 +4978,16 @@ Note that THREAD must never, ever be anything else than a variable -
4940using some other form will lead to serious barfage." 4978using some other form will lead to serious barfage."
4941 (or (symbolp thread) (signal 'wrong-type-argument '(symbolp thread))) 4979 (or (symbolp thread) (signal 'wrong-type-argument '(symbolp thread)))
4942 ;; (8% speedup to gnus-summary-prepare, just for fun :-) 4980 ;; (8% speedup to gnus-summary-prepare, just for fun :-)
4943 (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207" 4981 (cond
4944 (vector thread) 2)) 4982 ((and (boundp 'lexical-binding) lexical-binding)
4983 ;; FIXME: This version could be a "defsubst" rather than a macro.
4984 `(#[257 "\211:\203\16\0\211@;\203\15\0A@@\207"
4985 [] 2]
4986 ,thread))
4987 (t
4988 ;; Not sure how XEmacs handles these things, so let's keep the old code.
4989 (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207"
4990 (vector thread) 2))))
4945 4991
4946(defsubst gnus-article-sort-by-number (h1 h2) 4992(defsubst gnus-article-sort-by-number (h1 h2)
4947 "Sort articles by article number." 4993 "Sort articles by article number."
@@ -5972,7 +6018,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
5972 (min (car active)) 6018 (min (car active))
5973 (max (cdr active)) 6019 (max (cdr active))
5974 (types gnus-article-mark-lists) 6020 (types gnus-article-mark-lists)
5975 marks var articles article mark mark-type 6021 var articles article mark mark-type
5976 bgn end) 6022 bgn end)
5977 ;; Hack to avoid adjusting marks for imap. 6023 ;; Hack to avoid adjusting marks for imap.
5978 (when (eq (car (gnus-find-method-for-group (gnus-info-group info))) 6024 (when (eq (car (gnus-find-method-for-group (gnus-info-group info)))
@@ -6234,7 +6280,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
6234(defun gnus-mark-xrefs-as-read (from-newsgroup headers unreads) 6280(defun gnus-mark-xrefs-as-read (from-newsgroup headers unreads)
6235 "Look through all the headers and mark the Xrefs as read." 6281 "Look through all the headers and mark the Xrefs as read."
6236 (let ((virtual (gnus-virtual-group-p from-newsgroup)) 6282 (let ((virtual (gnus-virtual-group-p from-newsgroup))
6237 name info xref-hashtb idlist method nth4) 6283 name info xref-hashtb method nth4)
6238 (with-current-buffer gnus-group-buffer 6284 (with-current-buffer gnus-group-buffer
6239 (when (setq xref-hashtb 6285 (when (setq xref-hashtb
6240 (gnus-create-xref-hashtb from-newsgroup headers unreads)) 6286 (gnus-create-xref-hashtb from-newsgroup headers unreads))
@@ -7488,7 +7534,7 @@ The state which existed when entering the ephemeral is reset."
7488 (with-current-buffer buffer 7534 (with-current-buffer buffer
7489 (gnus-deaden-summary)))))) 7535 (gnus-deaden-summary))))))
7490 7536
7491(defun gnus-summary-wake-up-the-dead (&rest args) 7537(defun gnus-summary-wake-up-the-dead (&rest _)
7492 "Wake up the dead summary buffer." 7538 "Wake up the dead summary buffer."
7493 (interactive) 7539 (interactive)
7494 (gnus-dead-summary-mode -1) 7540 (gnus-dead-summary-mode -1)
@@ -7714,6 +7760,12 @@ Given a prefix, will force an `article' buffer configuration."
7714 (gnus-article-setup-buffer)) 7760 (gnus-article-setup-buffer))
7715 (gnus-set-global-variables) 7761 (gnus-set-global-variables)
7716 (with-current-buffer gnus-article-buffer 7762 (with-current-buffer gnus-article-buffer
7763 ;; The buffer may be non-empty and even narrowed, so go back to
7764 ;; a sane state.
7765 (widen)
7766 ;; We're going to erase the buffer anyway so do it now: it can save us from
7767 ;; uselessly performing multibyte-conversion of the current content.
7768 (let ((inhibit-read-only t)) (erase-buffer))
7717 (setq gnus-article-charset gnus-newsgroup-charset) 7769 (setq gnus-article-charset gnus-newsgroup-charset)
7718 (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets) 7770 (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets)
7719 (mm-enable-multibyte)) 7771 (mm-enable-multibyte))
@@ -7857,7 +7909,7 @@ If BACKWARD, the previous article is selected instead of the next."
7857 (gnus-summary-walk-group-buffer 7909 (gnus-summary-walk-group-buffer
7858 gnus-newsgroup-name cmd unread backward point)))))))) 7910 gnus-newsgroup-name cmd unread backward point))))))))
7859 7911
7860(defun gnus-summary-walk-group-buffer (from-group cmd unread backward start) 7912(defun gnus-summary-walk-group-buffer (_from-group cmd unread backward start)
7861 (let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1)) 7913 (let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1))
7862 (?\C-p (gnus-group-prev-unread-group 1)))) 7914 (?\C-p (gnus-group-prev-unread-group 1))))
7863 (cursor-in-echo-area t) 7915 (cursor-in-echo-area t)
@@ -8151,7 +8203,7 @@ score higher than the default score."
8151 "Select the first unread subject that has a score over the default score." 8203 "Select the first unread subject that has a score over the default score."
8152 (interactive) 8204 (interactive)
8153 (let ((data gnus-newsgroup-data) 8205 (let ((data gnus-newsgroup-data)
8154 article score) 8206 article)
8155 (while (and (setq article (gnus-data-number (car data))) 8207 (while (and (setq article (gnus-data-number (car data)))
8156 (or (gnus-data-read-p (car data)) 8208 (or (gnus-data-read-p (car data))
8157 (not (> (gnus-summary-article-score article) 8209 (not (> (gnus-summary-article-score article)
@@ -8564,7 +8616,7 @@ If UNREPLIED (the prefix), limit to unreplied articles."
8564 (gnus-summary-limit gnus-newsgroup-replied)) 8616 (gnus-summary-limit gnus-newsgroup-replied))
8565 (gnus-summary-position-point)) 8617 (gnus-summary-position-point))
8566 8618
8567(defun gnus-summary-limit-exclude-marks (marks &optional reverse) 8619(defun gnus-summary-limit-exclude-marks (marks &optional _reverse)
8568 "Exclude articles that are marked with MARKS (e.g. \"DK\"). 8620 "Exclude articles that are marked with MARKS (e.g. \"DK\").
8569If REVERSE, limit the summary buffer to articles that are marked 8621If REVERSE, limit the summary buffer to articles that are marked
8570with MARKS. MARKS can either be a string of marks or a list of marks. 8622with MARKS. MARKS can either be a string of marks or a list of marks.
@@ -8866,7 +8918,7 @@ fetch-old-headers verbiage, and so on."
8866 (push gnus-newsgroup-limit gnus-newsgroup-limits) 8918 (push gnus-newsgroup-limit gnus-newsgroup-limits)
8867 (setq gnus-newsgroup-limit nil) 8919 (setq gnus-newsgroup-limit nil)
8868 (maphash 8920 (maphash
8869 (lambda (id deps) 8921 (lambda (_id deps)
8870 (unless (car deps) 8922 (unless (car deps)
8871 ;; These threads have no parents -- they are roots. 8923 ;; These threads have no parents -- they are roots.
8872 (let ((nodes (cdr deps)) 8924 (let ((nodes (cdr deps))
@@ -9524,6 +9576,9 @@ fetched headers for, whether they are displayed or not."
9524 (func `(lambda (h) (,(intern (concat "mail-header-" header)) h))) 9576 (func `(lambda (h) (,(intern (concat "mail-header-" header)) h)))
9525 (case-fold-search t)) 9577 (case-fold-search t))
9526 (dolist (header gnus-newsgroup-headers) 9578 (dolist (header gnus-newsgroup-headers)
9579 ;; FIXME: when called from gnus-summary-limit-include-thread via
9580 ;; gnus-summary-limit-include-matching-articles, `regexp' is a decoded
9581 ;; string whereas the header isn't decoded.
9527 (when (string-match regexp (funcall func header)) 9582 (when (string-match regexp (funcall func header))
9528 (push (mail-header-number header) articles))) 9583 (push (mail-header-number header) articles)))
9529 (nreverse articles))) 9584 (nreverse articles)))
@@ -9538,7 +9593,7 @@ be taken into consideration. If NOT-CASE-FOLD, case won't be folded
9538in the comparisons. If NOT-MATCHING, return a list of all articles that 9593in the comparisons. If NOT-MATCHING, return a list of all articles that
9539not match REGEXP on HEADER." 9594not match REGEXP on HEADER."
9540 (let ((case-fold-search (not not-case-fold)) 9595 (let ((case-fold-search (not not-case-fold))
9541 articles d func) 9596 articles func)
9542 (if (consp header) 9597 (if (consp header)
9543 (if (eq (car header) 'extra) 9598 (if (eq (car header) 'extra)
9544 (setq func 9599 (setq func
@@ -9658,6 +9713,10 @@ to save in."
9658 (gnus-summary-remove-process-mark article)) 9713 (gnus-summary-remove-process-mark article))
9659 (ps-despool filename)) 9714 (ps-despool filename))
9660 9715
9716(defvar ps-right-header)
9717(defvar ps-left-header)
9718(defvar shr-ignore-cache)
9719
9661(defun gnus-print-buffer () 9720(defun gnus-print-buffer ()
9662 (let ((ps-left-header 9721 (let ((ps-left-header
9663 (list 9722 (list
@@ -9883,7 +9942,7 @@ prefix specifies how many places to rotate each letter forward."
9883 ;; Create buttons and stuff... 9942 ;; Create buttons and stuff...
9884 (gnus-treat-article nil)) 9943 (gnus-treat-article nil))
9885 9944
9886(defun gnus-summary-idna-message (&optional arg) 9945(defun gnus-summary-idna-message (&optional _arg)
9887 "Decode IDNA encoded domain names in the current articles. 9946 "Decode IDNA encoded domain names in the current articles.
9888IDNA encoded domain names looks like `xn--bar'. If a string 9947IDNA encoded domain names looks like `xn--bar'. If a string
9889remain unencoded after running this function, it is likely an 9948remain unencoded after running this function, it is likely an
@@ -9891,7 +9950,7 @@ invalid IDNA string (`xn--bar' is invalid).
9891 9950
9892You must have GNU Libidn (URL `https://www.gnu.org/software/libidn/') 9951You must have GNU Libidn (URL `https://www.gnu.org/software/libidn/')
9893installed for this command to work." 9952installed for this command to work."
9894 (interactive "P") 9953 (interactive)
9895 (gnus-summary-select-article) 9954 (gnus-summary-select-article)
9896 (let ((mail-header-separator "")) 9955 (let ((mail-header-separator ""))
9897 (gnus-eval-in-buffer-window gnus-article-buffer 9956 (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9903,9 +9962,9 @@ installed for this command to work."
9903 (replace-match (puny-decode-domain (match-string 1)))) 9962 (replace-match (puny-decode-domain (match-string 1))))
9904 (set-window-start (get-buffer-window (current-buffer)) start)))))) 9963 (set-window-start (get-buffer-window (current-buffer)) start))))))
9905 9964
9906(defun gnus-summary-morse-message (&optional arg) 9965(defun gnus-summary-morse-message (&optional _arg)
9907 "Morse decode the current article." 9966 "Morse decode the current article."
9908 (interactive "P") 9967 (interactive)
9909 (gnus-summary-select-article) 9968 (gnus-summary-select-article)
9910 (let ((mail-header-separator "")) 9969 (let ((mail-header-separator ""))
9911 (gnus-eval-in-buffer-window gnus-article-buffer 9970 (gnus-eval-in-buffer-window gnus-article-buffer
@@ -9963,11 +10022,11 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
9963 (cond ((and (eq action 'move) 10022 (cond ((and (eq action 'move)
9964 (not (gnus-check-backend-function 10023 (not (gnus-check-backend-function
9965 'request-move-article gnus-newsgroup-name))) 10024 'request-move-article gnus-newsgroup-name)))
9966 (error "The current group does not support article moving")) 10025 (user-error "The current group does not support article moving"))
9967 ((and (eq action 'crosspost) 10026 ((and (eq action 'crosspost)
9968 (not (gnus-check-backend-function 10027 (not (gnus-check-backend-function
9969 'request-replace-article gnus-newsgroup-name))) 10028 'request-replace-article gnus-newsgroup-name)))
9970 (error "The current group does not support article editing"))) 10029 (user-error "The current group does not support article editing")))
9971 (let ((articles (gnus-summary-work-articles n)) 10030 (let ((articles (gnus-summary-work-articles n))
9972 (prefix (if (gnus-check-backend-function 10031 (prefix (if (gnus-check-backend-function
9973 'request-move-article gnus-newsgroup-name) 10032 'request-move-article gnus-newsgroup-name)
@@ -9979,7 +10038,7 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
9979 (crosspost "Crosspost" "Crossposting"))) 10038 (crosspost "Crosspost" "Crossposting")))
9980 (copy-buf (save-excursion 10039 (copy-buf (save-excursion
9981 (nnheader-set-temp-buffer " *copy article*"))) 10040 (nnheader-set-temp-buffer " *copy article*")))
9982 art-group to-method new-xref to-groups 10041 art-group to-method new-xref article to-groups
9983 articles-to-update-marks encoded) 10042 articles-to-update-marks encoded)
9984 (unless (assq action names) 10043 (unless (assq action names)
9985 (error "Unknown action %s" action)) 10044 (error "Unknown action %s" action))
@@ -10029,7 +10088,9 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
10029 (or (car select-method) 10088 (or (car select-method)
10030 (gnus-group-decoded-name to-newsgroup)) 10089 (gnus-group-decoded-name to-newsgroup))
10031 articles) 10090 articles)
10032 (dolist (article articles) 10091 ;; This `while' is not equivalent to a `dolist' (bug#33653#134).
10092 (while articles
10093 (setq article (pop articles))
10033 ;; Set any marks that may have changed in the summary buffer. 10094 ;; Set any marks that may have changed in the summary buffer.
10034 (when gnus-preserve-marks 10095 (when gnus-preserve-marks
10035 (gnus-summary-push-marks-to-backend article)) 10096 (gnus-summary-push-marks-to-backend article))
@@ -10231,7 +10292,7 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
10231 to-newsgroup 10292 to-newsgroup
10232 select-method)) 10293 select-method))
10233 10294
10234 ;;;!!!Why is this necessary? 10295 ;;!!!Why is this necessary?
10235 (set-buffer gnus-summary-buffer) 10296 (set-buffer gnus-summary-buffer)
10236 10297
10237 (when (eq action 'move) 10298 (when (eq action 'move)
@@ -10597,7 +10658,7 @@ groups."
10597 (let ((mbl mml-buffer-list)) 10658 (let ((mbl mml-buffer-list))
10598 (setq mml-buffer-list nil) 10659 (setq mml-buffer-list nil)
10599 (let ((rfc2047-quote-decoded-words-containing-tspecials t)) 10660 (let ((rfc2047-quote-decoded-words-containing-tspecials t))
10600 (mime-to-mml ,'current-handles)) 10661 (mime-to-mml ',current-handles))
10601 (let ((mbl1 mml-buffer-list)) 10662 (let ((mbl1 mml-buffer-list))
10602 (setq mml-buffer-list mbl) 10663 (setq mml-buffer-list mbl)
10603 (set (make-local-variable 'mml-buffer-list) mbl1)) 10664 (set (make-local-variable 'mml-buffer-list) mbl1))
@@ -10885,8 +10946,8 @@ the actual number of articles unmarked is returned."
10885 (set var (cons article (symbol-value var))) 10946 (set var (cons article (symbol-value var)))
10886 (if (memq type '(processable cached replied forwarded recent saved)) 10947 (if (memq type '(processable cached replied forwarded recent saved))
10887 (gnus-summary-update-secondary-mark article) 10948 (gnus-summary-update-secondary-mark article)
10888 ;;; !!! This is bogus. We should find out what primary 10949 ;; !!! This is bogus. We should find out what primary
10889 ;;; !!! mark we want to set. 10950 ;; !!! mark we want to set.
10890 (gnus-summary-update-mark gnus-del-mark 'unread))))) 10951 (gnus-summary-update-mark gnus-del-mark 'unread)))))
10891 10952
10892(defun gnus-summary-mark-as-expirable (n) 10953(defun gnus-summary-mark-as-expirable (n)
@@ -12015,10 +12076,10 @@ Argument REVERSE means reverse order."
12015 (interactive "P") 12076 (interactive "P")
12016 (gnus-summary-sort 'marks reverse)) 12077 (gnus-summary-sort 'marks reverse))
12017 12078
12018(defun gnus-summary-sort-by-original (&optional reverse) 12079(defun gnus-summary-sort-by-original (&optional _reverse)
12019 "Sort the summary buffer using the default sorting method. 12080 "Sort the summary buffer using the default sorting method.
12020Argument REVERSE means reverse order." 12081Argument REVERSE means reverse order."
12021 (interactive "P") 12082 (interactive)
12022 (let* ((inhibit-read-only t) 12083 (let* ((inhibit-read-only t)
12023 (gnus-summary-prepare-hook nil)) 12084 (gnus-summary-prepare-hook nil))
12024 ;; We do the sorting by regenerating the threads. 12085 ;; We do the sorting by regenerating the threads.
@@ -12344,7 +12405,7 @@ save those articles instead."
12344 (string= to-newsgroup prefix)) 12405 (string= to-newsgroup prefix))
12345 (setq to-newsgroup default)) 12406 (setq to-newsgroup default))
12346 (unless to-newsgroup 12407 (unless to-newsgroup
12347 (error "No group name entered")) 12408 (user-error "No group name entered"))
12348 (setq encoded (encode-coding-string 12409 (setq encoded (encode-coding-string
12349 to-newsgroup 12410 to-newsgroup
12350 (gnus-group-name-charset to-method to-newsgroup))) 12411 (gnus-group-name-charset to-method to-newsgroup)))
@@ -12356,7 +12417,7 @@ save those articles instead."
12356 (gnus-activate-group encoded nil nil to-method) 12417 (gnus-activate-group encoded nil nil to-method)
12357 (gnus-subscribe-group encoded)) 12418 (gnus-subscribe-group encoded))
12358 (error "Couldn't create group %s" to-newsgroup))) 12419 (error "Couldn't create group %s" to-newsgroup)))
12359 (error "No such group: %s" to-newsgroup)) 12420 (user-error "No such group: %s" to-newsgroup))
12360 encoded))) 12421 encoded)))
12361 12422
12362(defvar gnus-summary-save-parts-counter) 12423(defvar gnus-summary-save-parts-counter)
@@ -12654,14 +12715,21 @@ If REVERSE, save parts that do not match TYPE."
12654 (c cond) 12715 (c cond)
12655 (list gnus-summary-highlight)) 12716 (list gnus-summary-highlight))
12656 (while list 12717 (while list
12657 (setcdr c (cons (list (caar list) (list 'quote (cdar list))) 12718 (setcdr c `((,(caar list) ',(cdar list))))
12658 nil))
12659 (setq c (cdr c) 12719 (setq c (cdr c)
12660 list (cdr list))) 12720 list (cdr list)))
12661 (gnus-byte-compile (list 'lambda nil cond)))))) 12721 (gnus-byte-compile
12722 `(lambda ()
12723 (with-no-warnings ;See docstring of gnus-summary-highlight.
12724 (defvar score) (defvar default) (defvar default-high)
12725 (defvar default-low) (defvar mark) (defvar uncached))
12726 ,cond))))))
12662 12727
12663(defun gnus-summary-highlight-line () 12728(defun gnus-summary-highlight-line ()
12664 "Highlight current line according to `gnus-summary-highlight'." 12729 "Highlight current line according to `gnus-summary-highlight'."
12730 (with-no-warnings ;See docstring of gnus-summary-highlight.
12731 (defvar score) (defvar default) (defvar default-high) (defvar default-low)
12732 (defvar mark) (defvar uncached))
12665 (let* ((beg (point-at-bol)) 12733 (let* ((beg (point-at-bol))
12666 (article (or (gnus-summary-article-number) gnus-current-article)) 12734 (article (or (gnus-summary-article-number) gnus-current-article))
12667 (score (or (cdr (assq article 12735 (score (or (cdr (assq article
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index 8ce094349f2..1e1d264b994 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -476,29 +476,32 @@ If MODE is not set, try to find mode automatically."
476 (mm-decode-string text charset)) 476 (mm-decode-string text charset))
477 (t 477 (t
478 text))) 478 text)))
479 (require 'font-lock) 479 (let ((font-lock-verbose nil) ; font-lock is a bit too verbose.
480 ;; I find font-lock a bit too verbose.
481 (let ((font-lock-verbose nil)
482 (font-lock-support-mode nil)
483 (enable-local-variables nil)) 480 (enable-local-variables nil))
484 ;; Disable support modes, e.g., jit-lock, lazy-lock, etc. 481 ;; We used to set font-lock-mode-hook to nil to avoid enabling
485 ;; Note: XEmacs people use `font-lock-mode-hook' to run those modes. 482 ;; support modes, but now that we use font-lock-ensure, support modes
483 ;; aren't a problem any more. So we could probably get rid of this
484 ;; setting now, but it seems harmless and potentially still useful.
486 (set (make-local-variable 'font-lock-mode-hook) nil) 485 (set (make-local-variable 'font-lock-mode-hook) nil)
487 (setq buffer-file-name (mm-handle-filename handle)) 486 (setq buffer-file-name (mm-handle-filename handle))
488 (with-demoted-errors 487 (with-demoted-errors
489 (if mode 488 (if mode
490 (save-window-excursion 489 (save-window-excursion
491 (switch-to-buffer (current-buffer)) 490 ;; According to Katsumi Yamaoka <yamaoka@jpl.org>, org-mode
492 (funcall mode)) 491 ;; requires the buffer to be temporarily displayed here, but
492 ;; I could not reproduce this problem. Furthermore, if
493 ;; there's such a problem, we should fix org-mode rather than
494 ;; use switch-to-buffer which can have undesirable
495 ;; side-effects!
496 ;;(switch-to-buffer (current-buffer))
497 (funcall mode))
493 (let ((auto-mode-alist 498 (let ((auto-mode-alist
494 (delq (rassq 'doc-view-mode-maybe auto-mode-alist) 499 (delq (rassq 'doc-view-mode-maybe auto-mode-alist)
495 (copy-sequence auto-mode-alist)))) 500 (copy-sequence auto-mode-alist))))
496 (set-auto-mode) 501 (set-auto-mode)
497 (setq mode major-mode))) 502 (setq mode major-mode)))
498 ;; The mode function might have already turned on font-lock.
499 ;; Do not fontify if the guess mode is fundamental. 503 ;; Do not fontify if the guess mode is fundamental.
500 (unless (or font-lock-mode 504 (unless (eq major-mode 'fundamental-mode)
501 (eq major-mode 'fundamental-mode))
502 (font-lock-ensure)))) 505 (font-lock-ensure))))
503 (setq text (buffer-string)) 506 (setq text (buffer-string))
504 (when (eq mode 'diff-mode) 507 (when (eq mode 'diff-mode)
@@ -508,7 +511,7 @@ If MODE is not set, try to find mode automatically."
508 ;; Set buffer unmodified to avoid confirmation when killing the 511 ;; Set buffer unmodified to avoid confirmation when killing the
509 ;; buffer. 512 ;; buffer.
510 (set-buffer-modified-p nil)) 513 (set-buffer-modified-p nil))
511 (let ((b (1- (point)))) 514 (let ((b (- (point) (save-restriction (widen) (point-min)))))
512 (mm-insert-inline handle text) 515 (mm-insert-inline handle text)
513 (dolist (ov ovs) 516 (dolist (ov ovs)
514 (move-overlay (nth 0 ov) (+ (nth 1 ov) b) 517 (move-overlay (nth 0 ov) (+ (nth 1 ov) b)
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index a95cdb4a4f8..b6dbbea74cc 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -663,7 +663,7 @@ nn*-request-list should have been called before calling this function."
663 (narrow-to-region (point) (point-at-eol)) 663 (narrow-to-region (point) (point-at-eol))
664 (setq group (read buffer)) 664 (setq group (read buffer))
665 (unless (stringp group) 665 (unless (stringp group)
666 (setq group (symbol-name group))) 666 (setq group (encode-coding-string (symbol-name group) 'latin-1)))
667 (if (and (numberp (setq max (read buffer))) 667 (if (and (numberp (setq max (read buffer)))
668 (numberp (setq min (read buffer)))) 668 (numberp (setq min (read buffer))))
669 (push (list group (cons min max)) 669 (push (list group (cons min max))
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 5770777ad4b..205e9e48034 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -259,7 +259,7 @@ non-nil.")
259 (t 259 (t
260 (nnheader-re-read-dir nnml-current-directory) 260 (nnheader-re-read-dir nnml-current-directory)
261 (nnmail-activate 'nnml) 261 (nnmail-activate 'nnml)
262 (let ((active (nth 1 (assoc group nnml-group-alist)))) 262 (let ((active (nth 1 (assoc-string group nnml-group-alist))))
263 (if (not active) 263 (if (not active)
264 (nnheader-report 'nnml "No such group: %s" decoded) 264 (nnheader-report 'nnml "No such group: %s" decoded)
265 (nnheader-report 'nnml "Selected group %s" decoded) 265 (nnheader-report 'nnml "Selected group %s" decoded)
@@ -295,7 +295,7 @@ non-nil.")
295 (nnheader-report 'nnml "%s is a file" 295 (nnheader-report 'nnml "%s is a file"
296 (directory-file-name (nnml-group-pathname group 296 (directory-file-name (nnml-group-pathname group
297 nil server)))) 297 nil server))))
298 ((assoc group nnml-group-alist) 298 ((assoc-string group nnml-group-alist)
299 t) 299 t)
300 (t 300 (t
301 (let (active) 301 (let (active)
@@ -379,7 +379,7 @@ non-nil.")
379 (nnml-nov-delete-article group number)) 379 (nnml-nov-delete-article group number))
380 (push number rest))) 380 (push number rest)))
381 (push number rest))) 381 (push number rest)))
382 (let ((active (nth 1 (assoc group nnml-group-alist)))) 382 (let ((active (nth 1 (assoc-string group nnml-group-alist))))
383 (when active 383 (when active
384 (setcar active (or (and active-articles 384 (setcar active (or (and active-articles
385 (apply 'min active-articles)) 385 (apply 'min active-articles))
@@ -520,7 +520,7 @@ non-nil.")
520 (nnheader-report 'nnml "No such directory: %s/" file)) 520 (nnheader-report 'nnml "No such directory: %s/" file))
521 ;; Remove the group from all structures. 521 ;; Remove the group from all structures.
522 (setq nnml-group-alist 522 (setq nnml-group-alist
523 (delq (assoc group nnml-group-alist) nnml-group-alist) 523 (delq (assoc-string group nnml-group-alist) nnml-group-alist)
524 nnml-current-group nil 524 nnml-current-group nil
525 nnml-current-directory nil) 525 nnml-current-directory nil)
526 ;; Save the active file. 526 ;; Save the active file.
@@ -549,7 +549,7 @@ non-nil.")
549 (when (<= (length (directory-files old-dir)) 2) 549 (when (<= (length (directory-files old-dir)) 2)
550 (ignore-errors (delete-directory old-dir))) 550 (ignore-errors (delete-directory old-dir)))
551 ;; That went ok, so we change the internal structures. 551 ;; That went ok, so we change the internal structures.
552 (let ((entry (assoc group nnml-group-alist))) 552 (let ((entry (assoc-string group nnml-group-alist)))
553 (when entry 553 (when entry
554 (setcar entry new-name)) 554 (setcar entry new-name))
555 (setq nnml-current-directory nil 555 (setq nnml-current-directory nil
@@ -597,7 +597,7 @@ non-nil.")
597 (when (setq path (nnml-article-to-file article)) 597 (when (setq path (nnml-article-to-file article))
598 (when (file-writable-p path) 598 (when (file-writable-p path)
599 (or (not nnmail-keep-last-article) 599 (or (not nnmail-keep-last-article)
600 (not (eq (cdr (nth 1 (assoc group nnml-group-alist))) 600 (not (eq (cdr (nth 1 (assoc-string group nnml-group-alist)))
601 article))))))) 601 article)))))))
602 602
603;; Find an article number in the current group given the Message-ID. 603;; Find an article number in the current group given the Message-ID.
@@ -742,7 +742,7 @@ article number. This function is called narrowed to an article."
742 "Compute the next article number in GROUP on SERVER." 742 "Compute the next article number in GROUP on SERVER."
743 (let* ((encoded (if nnmail-group-names-not-encoded-p 743 (let* ((encoded (if nnmail-group-names-not-encoded-p
744 (nnml-encoded-group-name group server))) 744 (nnml-encoded-group-name group server)))
745 (active (cadr (assoc (or encoded group) nnml-group-alist)))) 745 (active (cadr (assoc-string (or encoded group) nnml-group-alist))))
746 ;; The group wasn't known to nnml, so we just create an active 746 ;; The group wasn't known to nnml, so we just create an active
747 ;; entry for it. 747 ;; entry for it.
748 (unless active 748 (unless active
@@ -783,7 +783,7 @@ article number. This function is called narrowed to an article."
783 (cdr nnml-incremental-nov-buffer-alist))))) 783 (cdr nnml-incremental-nov-buffer-alist)))))
784 784
785(defun nnml-open-incremental-nov (group) 785(defun nnml-open-incremental-nov (group)
786 (or (cdr (assoc group nnml-incremental-nov-buffer-alist)) 786 (or (cdr (assoc-string group nnml-incremental-nov-buffer-alist))
787 (let ((buffer (nnml-get-nov-buffer group t))) 787 (let ((buffer (nnml-get-nov-buffer group t)))
788 (push (cons group buffer) nnml-incremental-nov-buffer-alist) 788 (push (cons group buffer) nnml-incremental-nov-buffer-alist)
789 buffer))) 789 buffer)))
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index 7f2accc2b66..0bfecb28e09 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -340,10 +340,10 @@ for decoding when the cdr that the data specify is not available.")
340 (let (elem) 340 (let (elem)
341 ;; There may be two or more entries in `nnrss-group-alist' since 341 ;; There may be two or more entries in `nnrss-group-alist' since
342 ;; this function didn't delete them formerly. 342 ;; this function didn't delete them formerly.
343 (while (setq elem (assoc group nnrss-group-alist)) 343 (while (setq elem (assoc-string group nnrss-group-alist))
344 (setq nnrss-group-alist (delq elem nnrss-group-alist)))) 344 (setq nnrss-group-alist (delq elem nnrss-group-alist))))
345 (setq nnrss-server-data 345 (setq nnrss-server-data
346 (delq (assoc group nnrss-server-data) nnrss-server-data)) 346 (delq (assoc-string group nnrss-server-data) nnrss-server-data))
347 (nnrss-save-server-data server) 347 (nnrss-save-server-data server)
348 (ignore-errors 348 (ignore-errors
349 (let ((file-name-coding-system nnmail-pathname-coding-system)) 349 (let ((file-name-coding-system nnmail-pathname-coding-system))
@@ -367,7 +367,7 @@ for decoding when the cdr that the data specify is not available.")
367 (with-current-buffer nntp-server-buffer 367 (with-current-buffer nntp-server-buffer
368 (erase-buffer) 368 (erase-buffer)
369 (dolist (group groups) 369 (dolist (group groups)
370 (let ((elem (assoc (gnus-group-decoded-name group) nnrss-server-data))) 370 (let ((elem (assoc-string (gnus-group-decoded-name group) nnrss-server-data)))
371 (insert (format "%S %s 1 y\n" group (or (cadr elem) 0))))) 371 (insert (format "%S %s 1 y\n" group (or (cadr elem) 0)))))
372 'active)) 372 'active))
373 373
@@ -539,7 +539,7 @@ which RSS 2.0 allows."
539 (if (hash-table-p nnrss-group-hashtb) 539 (if (hash-table-p nnrss-group-hashtb)
540 (clrhash nnrss-group-hashtb) 540 (clrhash nnrss-group-hashtb)
541 (setq nnrss-group-hashtb (make-hash-table :test 'equal))) 541 (setq nnrss-group-hashtb (make-hash-table :test 'equal)))
542 (let ((pair (assoc group nnrss-server-data))) 542 (let ((pair (assoc-string group nnrss-server-data)))
543 (setq nnrss-group-max (or (cadr pair) 0)) 543 (setq nnrss-group-max (or (cadr pair) 0))
544 (setq nnrss-group-min (+ nnrss-group-max 1))) 544 (setq nnrss-group-min (+ nnrss-group-max 1)))
545 (let ((file (nnrss-make-filename group server)) 545 (let ((file (nnrss-make-filename group server))
@@ -644,8 +644,8 @@ which RSS 2.0 allows."
644 (concat group ".xml")) 644 (concat group ".xml"))
645 nnrss-directory)))) 645 nnrss-directory))))
646 (setq xml (nnrss-fetch file t)) 646 (setq xml (nnrss-fetch file t))
647 (setq url (or (nth 2 (assoc group nnrss-server-data)) 647 (setq url (or (nth 2 (assoc-string group nnrss-server-data))
648 (cadr (assoc group nnrss-group-alist)))) 648 (cadr (assoc-string group nnrss-group-alist))))
649 (unless url 649 (unless url
650 (setq url 650 (setq url
651 (cdr 651 (cdr
@@ -653,7 +653,7 @@ which RSS 2.0 allows."
653 (nnrss-discover-feed 653 (nnrss-discover-feed
654 (read-string 654 (read-string
655 (format "URL to search for %s: " group) "http://"))))) 655 (format "URL to search for %s: " group) "http://")))))
656 (let ((pair (assoc group nnrss-server-data))) 656 (let ((pair (assoc-string group nnrss-server-data)))
657 (if pair 657 (if pair
658 (setcdr (cdr pair) (list url)) 658 (setcdr (cdr pair) (list url))
659 (push (list group nnrss-group-max url) nnrss-server-data))) 659 (push (list group nnrss-group-max url) nnrss-server-data)))
@@ -721,7 +721,7 @@ which RSS 2.0 allows."
721 (setq extra nil)) 721 (setq extra nil))
722 (when changed 722 (when changed
723 (nnrss-save-group-data group server) 723 (nnrss-save-group-data group server)
724 (let ((pair (assoc group nnrss-server-data))) 724 (let ((pair (assoc-string group nnrss-server-data)))
725 (if pair 725 (if pair
726 (setcar (cdr pair) nnrss-group-max) 726 (setcar (cdr pair) nnrss-group-max)
727 (push (list group nnrss-group-max) nnrss-server-data))) 727 (push (list group nnrss-group-max) nnrss-server-data)))
@@ -792,7 +792,7 @@ It is useful when `(setq nnrss-use-local t)'."
792 (insert "RSSDIR='" (expand-file-name nnrss-directory) "'\n") 792 (insert "RSSDIR='" (expand-file-name nnrss-directory) "'\n")
793 (dolist (elem nnrss-server-data) 793 (dolist (elem nnrss-server-data)
794 (let ((url (or (nth 2 elem) 794 (let ((url (or (nth 2 elem)
795 (cadr (assoc (car elem) nnrss-group-alist))))) 795 (cadr (assoc-string (car elem) nnrss-group-alist)))))
796 (insert "$WGET -q -O \"$RSSDIR\"/'" 796 (insert "$WGET -q -O \"$RSSDIR\"/'"
797 (nnrss-translate-file-chars (concat (car elem) ".xml")) 797 (nnrss-translate-file-chars (concat (car elem) ".xml"))
798 "' '" url "'\n")))) 798 "' '" url "'\n"))))
diff --git a/lisp/indent.el b/lisp/indent.el
index f3d3158faa0..bf87d6af760 100644
--- a/lisp/indent.el
+++ b/lisp/indent.el
@@ -600,8 +600,9 @@ considered.
600 600
601If the previous nonblank line has no indent points beyond the 601If the previous nonblank line has no indent points beyond the
602column point starts at, then `tab-to-tab-stop' is done, if both 602column point starts at, then `tab-to-tab-stop' is done, if both
603FIRST-ONLY and UNINDENTED-OK are nil, otherwise nothing is done 603FIRST-ONLY and UNINDENTED-OK are nil, otherwise nothing is done.
604in this case. 604If there isn't a previous nonblank line and UNINDENTED-OK is nil,
605call `tab-to-tab-stop'.
605 606
606See also `indent-relative-first-indent-point'." 607See also `indent-relative-first-indent-point'."
607 (interactive "P") 608 (interactive "P")
diff --git a/lisp/info.el b/lisp/info.el
index f2a064abb67..f3b413a2f9f 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -4768,7 +4768,7 @@ first line or header line, and for breadcrumb links.")
4768 ;; This is a serious problem for trying to handle multiple 4768 ;; This is a serious problem for trying to handle multiple
4769 ;; frame types at once. We want this text to be invisible 4769 ;; frame types at once. We want this text to be invisible
4770 ;; on frames that can display the font above. 4770 ;; on frames that can display the font above.
4771 (when (memq (framep (selected-frame)) '(x pc w32 ns)) 4771 (when (display-multi-font-p)
4772 (add-text-properties (1- (match-beginning 2)) (match-end 2) 4772 (add-text-properties (1- (match-beginning 2)) (match-end 2)
4773 '(invisible t front-sticky nil rear-nonsticky t)))))) 4773 '(invisible t front-sticky nil rear-nonsticky t))))))
4774 4774
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index bd05fcec698..3266b93b446 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -568,7 +568,7 @@ While this input method is active, the variable
568 (quail-delete-overlays) 568 (quail-delete-overlays)
569 (setq describe-current-input-method-function nil) 569 (setq describe-current-input-method-function nil)
570 (quail-hide-guidance) 570 (quail-hide-guidance)
571 (remove-hook 'post-command-hook 'quail-show-guidance t) 571 (remove-hook 'post-command-hook #'quail-show-guidance t)
572 (run-hooks 'quail-deactivate-hook)) 572 (run-hooks 'quail-deactivate-hook))
573 (kill-local-variable 'input-method-function)) 573 (kill-local-variable 'input-method-function))
574 ;; Let's activate Quail input method. 574 ;; Let's activate Quail input method.
@@ -579,19 +579,18 @@ While this input method is active, the variable
579 (setq name (car (car quail-package-alist))) 579 (setq name (car (car quail-package-alist)))
580 (error "No Quail package loaded")) 580 (error "No Quail package loaded"))
581 (quail-select-package name))) 581 (quail-select-package name)))
582 (setq deactivate-current-input-method-function 'quail-deactivate) 582 (setq deactivate-current-input-method-function #'quail-deactivate)
583 (setq describe-current-input-method-function 'quail-help) 583 (setq describe-current-input-method-function #'quail-help)
584 (quail-delete-overlays) 584 (quail-delete-overlays)
585 (setq quail-guidance-str "") 585 (setq quail-guidance-str "")
586 (quail-show-guidance) 586 (quail-show-guidance)
587 ;; If we are in minibuffer, turn off the current input method 587 ;; If we are in minibuffer, turn off the current input method
588 ;; before exiting. 588 ;; before exiting.
589 (when (eq (selected-window) (minibuffer-window)) 589 (when (eq (selected-window) (minibuffer-window))
590 (add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer) 590 (add-hook 'minibuffer-exit-hook #'quail-exit-from-minibuffer)
591 (add-hook 'post-command-hook 'quail-show-guidance nil t)) 591 (add-hook 'post-command-hook #'quail-show-guidance nil t))
592 (run-hooks 'quail-activate-hook) 592 (run-hooks 'quail-activate-hook)
593 (make-local-variable 'input-method-function) 593 (setq-local input-method-function #'quail-input-method)))
594 (setq input-method-function 'quail-input-method)))
595 594
596(define-obsolete-variable-alias 595(define-obsolete-variable-alias
597 'quail-inactivate-hook 596 'quail-inactivate-hook
@@ -1367,9 +1366,7 @@ If STR has `advice' text property, append the following special event:
1367 (let ((start (overlay-start overlay)) 1366 (let ((start (overlay-start overlay))
1368 (end (overlay-end overlay))) 1367 (end (overlay-end overlay)))
1369 (if (< start end) 1368 (if (< start end)
1370 (prog1 1369 (string-to-list (delete-and-extract-region start end)))))
1371 (string-to-list (buffer-substring start end))
1372 (delete-region start end)))))
1373 1370
1374(defsubst quail-delete-region () 1371(defsubst quail-delete-region ()
1375 "Delete the text in the current translation region of Quail." 1372 "Delete the text in the current translation region of Quail."
diff --git a/lisp/leim/quail/sami.el b/lisp/leim/quail/sami.el
index d4cf4ec96e8..7cfd0b7348c 100644
--- a/lisp/leim/quail/sami.el
+++ b/lisp/leim/quail/sami.el
@@ -1,6 +1,6 @@
1;;; sami.el --- Quail package for inputting Sámi -*-coding: utf-8;-*- 1;;; sami.el --- Quail package for inputting Sámi -*-coding: utf-8;-*-
2 2
3;; Copyright (C) 1998, 2001-2019 Free Software Foundation, Inc. 3;; Copyright (C) 2019 Free Software Foundation, Inc.
4 4
5;; Author: Wojciech S. Gac <wojciech.s.gac@gmail.com> 5;; Author: Wojciech S. Gac <wojciech.s.gac@gmail.com>
6;; Maintainer: Wojciech S. Gac <wojciech.s.gac@gmail.com>> 6;; Maintainer: Wojciech S. Gac <wojciech.s.gac@gmail.com>>
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 68960426b68..db9acbfc631 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -968,7 +968,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
968 (program (car command)) 968 (program (car command))
969 (args (cdr command)) 969 (args (cdr command))
970 (command 970 (command
971 (format "cd %s; %s" 971 (format "cd %s && exec %s"
972 (tramp-shell-quote-argument localname) 972 (tramp-shell-quote-argument localname)
973 (mapconcat #'tramp-shell-quote-argument 973 (mapconcat #'tramp-shell-quote-argument
974 (cons program args) " "))) 974 (cons program args) " ")))
@@ -1000,24 +1000,16 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
1000 ;; otherwise we might be interrupted by 1000 ;; otherwise we might be interrupted by
1001 ;; `verify-visited-file-modtime'. 1001 ;; `verify-visited-file-modtime'.
1002 (let ((buffer-undo-list t) 1002 (let ((buffer-undo-list t)
1003 (inhibit-read-only t) 1003 (inhibit-read-only t))
1004 (mark (point)))
1005 (clear-visited-file-modtime) 1004 (clear-visited-file-modtime)
1006 (narrow-to-region (point-max) (point-max)) 1005 (narrow-to-region (point-max) (point-max))
1007 ;; We call `tramp-adb-maybe-open-connection', in 1006 ;; We call `tramp-adb-maybe-open-connection', in
1008 ;; order to cleanup the prompt afterwards. 1007 ;; order to cleanup the prompt afterwards.
1009 (tramp-adb-maybe-open-connection v) 1008 (tramp-adb-maybe-open-connection v)
1010 (widen) 1009 (delete-region (point-min) (point-max))
1011 (delete-region mark (point-max))
1012 (narrow-to-region (point-max) (point-max))
1013 ;; Send the command. 1010 ;; Send the command.
1014 (let* ((p (tramp-get-connection-process v)) 1011 (let* ((p (tramp-get-connection-process v)))
1015 (prompt 1012 (tramp-adb-send-command v command nil t) ; nooutput
1016 (tramp-get-connection-property p "prompt" nil)))
1017 (tramp-set-connection-property
1018 p "prompt" (regexp-quote command))
1019 (tramp-adb-send-command v command)
1020 (tramp-set-connection-property p "prompt" prompt)
1021 ;; Stop process if indicated. 1013 ;; Stop process if indicated.
1022 (when stop 1014 (when stop
1023 (stop-process p)) 1015 (stop-process p))
@@ -1032,6 +1024,14 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
1032 (ignore-errors 1024 (ignore-errors
1033 (set-process-query-on-exit-flag p (null noquery)) 1025 (set-process-query-on-exit-flag p (null noquery))
1034 (set-marker (process-mark p) (point))) 1026 (set-marker (process-mark p) (point)))
1027 ;; Read initial output. Remove the first line,
1028 ;; which is the command echo.
1029 (while
1030 (progn
1031 (goto-char (point-min))
1032 (not (re-search-forward "[\n]" nil t)))
1033 (tramp-accept-process-output p 0))
1034 (delete-region (point-min) (point))
1035 ;; Return process. 1035 ;; Return process.
1036 p)))) 1036 p))))
1037 1037
@@ -1119,26 +1119,27 @@ This happens for Android >= 4.0."
1119 1119
1120;; Connection functions 1120;; Connection functions
1121 1121
1122(defun tramp-adb-send-command (vec command) 1122(defun tramp-adb-send-command (vec command &optional neveropen nooutput)
1123 "Send the COMMAND to connection VEC." 1123 "Send the COMMAND to connection VEC."
1124 (tramp-adb-maybe-open-connection vec) 1124 (unless neveropen (tramp-adb-maybe-open-connection vec))
1125 (tramp-message vec 6 "%s" command) 1125 (tramp-message vec 6 "%s" command)
1126 (tramp-send-string vec command) 1126 (tramp-send-string vec command)
1127 ;; FIXME: Race condition. 1127 (unless nooutput
1128 (tramp-adb-wait-for-output (tramp-get-connection-process vec)) 1128 ;; FIXME: Race condition.
1129 (with-current-buffer (tramp-get-connection-buffer vec) 1129 (tramp-adb-wait-for-output (tramp-get-connection-process vec))
1130 (save-excursion 1130 (with-current-buffer (tramp-get-connection-buffer vec)
1131 (goto-char (point-min)) 1131 (save-excursion
1132 ;; We can't use stty to disable echo of command. stty is said 1132 (goto-char (point-min))
1133 ;; to be added to toybox 0.7.6. busybox shall have it, but this 1133 ;; We can't use stty to disable echo of command. stty is said
1134 ;; isn't used any longer for Android. 1134 ;; to be added to toybox 0.7.6. busybox shall have it, but this
1135 (delete-matching-lines (regexp-quote command)) 1135 ;; isn't used any longer for Android.
1136 ;; When the local machine is W32, there are still trailing ^M. 1136 (delete-matching-lines (regexp-quote command))
1137 ;; There must be a better solution by setting the correct coding 1137 ;; When the local machine is W32, there are still trailing ^M.
1138 ;; system, but this requires changes in core Tramp. 1138 ;; There must be a better solution by setting the correct coding
1139 (goto-char (point-min)) 1139 ;; system, but this requires changes in core Tramp.
1140 (while (re-search-forward "\r+$" nil t) 1140 (goto-char (point-min))
1141 (replace-match "" nil nil))))) 1141 (while (re-search-forward "\r+$" nil t)
1142 (replace-match "" nil nil))))))
1142 1143
1143(defun tramp-adb-send-command-and-check (vec command) 1144(defun tramp-adb-send-command-and-check (vec command)
1144 "Run COMMAND and check its exit status. 1145 "Run COMMAND and check its exit status.
@@ -1245,6 +1246,9 @@ connection if a previous connection has died for some reason."
1245 (tramp-adb-wait-for-output p 30) 1246 (tramp-adb-wait-for-output p 30)
1246 (unless (process-live-p p) 1247 (unless (process-live-p p)
1247 (tramp-error vec 'file-error "Terminated!")) 1248 (tramp-error vec 'file-error "Terminated!"))
1249
1250 ;; Set sentinel and query flag. Initialize variables.
1251 (set-process-sentinel p #'tramp-process-sentinel)
1248 (process-put p 'vector vec) 1252 (process-put p 'vector vec)
1249 (process-put p 'adjust-window-size-function #'ignore) 1253 (process-put p 'adjust-window-size-function #'ignore)
1250 (set-process-query-on-exit-flag p nil) 1254 (set-process-query-on-exit-flag p nil)
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index 9e131b1a47d..ba4c26cdf2f 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -584,9 +584,7 @@ offered."
584 584
585(defun tramp-archive-handle-file-readable-p (filename) 585(defun tramp-archive-handle-file-readable-p (filename)
586 "Like `file-readable-p' for file archives." 586 "Like `file-readable-p' for file archives."
587 (with-parsed-tramp-file-name 587 (file-readable-p (tramp-archive-gvfs-file-name filename)))
588 (tramp-archive-gvfs-file-name filename) nil
589 (tramp-check-cached-permissions v ?r)))
590 588
591(defun tramp-archive-handle-file-system-info (filename) 589(defun tramp-archive-handle-file-system-info (filename)
592 "Like `file-system-info' for file archives." 590 "Like `file-system-info' for file archives."
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 2d8f42004a8..8fea82d97c4 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1136,7 +1136,8 @@ If FILE-SYSTEM is non-nil, return file system attributes."
1136 "Like `file-executable-p' for Tramp files." 1136 "Like `file-executable-p' for Tramp files."
1137 (with-parsed-tramp-file-name filename nil 1137 (with-parsed-tramp-file-name filename nil
1138 (with-tramp-file-property v localname "file-executable-p" 1138 (with-tramp-file-property v localname "file-executable-p"
1139 (tramp-check-cached-permissions v ?x)))) 1139 (and (file-exists-p filename)
1140 (tramp-check-cached-permissions v ?x)))))
1140 1141
1141(defun tramp-gvfs-handle-file-name-all-completions (filename directory) 1142(defun tramp-gvfs-handle-file-name-all-completions (filename directory)
1142 "Like `file-name-all-completions' for Tramp files." 1143 "Like `file-name-all-completions' for Tramp files."
@@ -1258,7 +1259,20 @@ file-notify events."
1258 "Like `file-readable-p' for Tramp files." 1259 "Like `file-readable-p' for Tramp files."
1259 (with-parsed-tramp-file-name filename nil 1260 (with-parsed-tramp-file-name filename nil
1260 (with-tramp-file-property v localname "file-readable-p" 1261 (with-tramp-file-property v localname "file-readable-p"
1261 (tramp-check-cached-permissions v ?r)))) 1262 (and (file-exists-p filename)
1263 (or (tramp-check-cached-permissions v ?r)
1264 ;; If the user is different from what we guess to be
1265 ;; the user, we don't know. Let's check, whether
1266 ;; access is restricted explicitly.
1267 (and (/= (tramp-gvfs-get-remote-uid v 'integer)
1268 (tramp-compat-file-attribute-user-id
1269 (file-attributes filename 'integer)))
1270 (not
1271 (string-equal
1272 "FALSE"
1273 (cdr (assoc
1274 "access::can-read"
1275 (tramp-gvfs-get-file-attributes filename)))))))))))
1262 1276
1263(defun tramp-gvfs-handle-file-system-info (filename) 1277(defun tramp-gvfs-handle-file-system-info (filename)
1264 "Like `file-system-info' for Tramp files." 1278 "Like `file-system-info' for Tramp files."
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index edd9af489e2..7d903c5769c 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2769,15 +2769,6 @@ the result will be a local, non-Tramp, file name."
2769 2769
2770;;; Remote commands: 2770;;; Remote commands:
2771 2771
2772(defun tramp-process-sentinel (proc event)
2773 "Flush file caches."
2774 (unless (process-live-p proc)
2775 (let ((vec (process-get proc 'vector)))
2776 (when vec
2777 (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event)
2778 (tramp-flush-connection-properties proc)
2779 (tramp-flush-directory-properties vec "")))))
2780
2781;; We use BUFFER also as connection buffer during setup. Because of 2772;; We use BUFFER also as connection buffer during setup. Because of
2782;; this, its original contents must be saved, and restored once 2773;; this, its original contents must be saved, and restored once
2783;; connection has been setup. 2774;; connection has been setup.
@@ -2912,8 +2903,7 @@ the result will be a local, non-Tramp, file name."
2912 ;; otherwise we might be interrupted by 2903 ;; otherwise we might be interrupted by
2913 ;; `verify-visited-file-modtime'. 2904 ;; `verify-visited-file-modtime'.
2914 (let ((buffer-undo-list t) 2905 (let ((buffer-undo-list t)
2915 (inhibit-read-only t) 2906 (inhibit-read-only t))
2916 (mark (point-max)))
2917 (clear-visited-file-modtime) 2907 (clear-visited-file-modtime)
2918 (narrow-to-region (point-max) (point-max)) 2908 (narrow-to-region (point-max) (point-max))
2919 ;; We call `tramp-maybe-open-connection', in 2909 ;; We call `tramp-maybe-open-connection', in
@@ -2926,9 +2916,7 @@ the result will be a local, non-Tramp, file name."
2926 (let ((pid (tramp-send-command-and-read v "echo $$"))) 2916 (let ((pid (tramp-send-command-and-read v "echo $$")))
2927 (process-put p 'remote-pid pid) 2917 (process-put p 'remote-pid pid)
2928 (tramp-set-connection-property p "remote-pid" pid)) 2918 (tramp-set-connection-property p "remote-pid" pid))
2929 (widen) 2919 (delete-region (point-min) (point-max))
2930 (delete-region mark (point-max))
2931 (narrow-to-region (point-max) (point-max))
2932 ;; Now do it. 2920 ;; Now do it.
2933 (if command 2921 (if command
2934 ;; Send the command. 2922 ;; Send the command.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 7206d8eb8a6..32963ac5432 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2801,14 +2801,14 @@ for all methods. Resulting data are derived from default settings."
2801 :port method :require '(:port) :max most-positive-fixnum)))) 2801 :port method :require '(:port) :max most-positive-fixnum))))
2802 2802
2803;; Generic function. 2803;; Generic function.
2804(defun tramp-parse-group (regexp match-level skip-regexp) 2804(defun tramp-parse-group (regexp match-level skip-chars)
2805 "Return a (user host) tuple allowed to access. 2805 "Return a (user host) tuple allowed to access.
2806User is always nil." 2806User is always nil."
2807 (let (result) 2807 (let (result)
2808 (when (re-search-forward regexp (point-at-eol) t) 2808 (when (re-search-forward regexp (point-at-eol) t)
2809 (setq result (list nil (match-string match-level)))) 2809 (setq result (list nil (match-string match-level))))
2810 (or 2810 (or
2811 (> (skip-chars-forward skip-regexp) 0) 2811 (> (skip-chars-forward skip-chars) 0)
2812 (forward-line 1)) 2812 (forward-line 1))
2813 result)) 2813 result))
2814 2814
@@ -2864,7 +2864,7 @@ User is always nil."
2864 (tramp-parse-group 2864 (tramp-parse-group
2865 (concat "\\(?:^[ \t]*Host\\)" "\\|" "\\(?:^.+\\)" 2865 (concat "\\(?:^[ \t]*Host\\)" "\\|" "\\(?:^.+\\)"
2866 "\\|" "\\(" tramp-host-regexp "\\)") 2866 "\\|" "\\(" tramp-host-regexp "\\)")
2867 1 "[ \t]+")) 2867 1 " \t"))
2868 2868
2869;; Generic function. 2869;; Generic function.
2870(defun tramp-parse-shostkeys-sknownhosts (dirname regexp) 2870(defun tramp-parse-shostkeys-sknownhosts (dirname regexp)
@@ -4212,6 +4212,19 @@ the remote host use line-endings as defined in the variable
4212 ;; Reenable the timers. 4212 ;; Reenable the timers.
4213 (with-timeout-unsuspend stimers)))) 4213 (with-timeout-unsuspend stimers))))
4214 4214
4215(defun tramp-process-sentinel (proc event)
4216 "Flush file caches and remove shell prompt."
4217 (unless (process-live-p proc)
4218 (let ((vec (process-get proc 'vector))
4219 (prompt (tramp-get-connection-property proc "prompt" nil)))
4220 (when vec
4221 (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event)
4222 (tramp-flush-connection-properties proc)
4223 (tramp-flush-directory-properties vec ""))
4224 (goto-char (point-max))
4225 (when (and prompt (re-search-backward (regexp-quote prompt) nil t))
4226 (delete-region (point) (point-max))))))
4227
4215(defun tramp-get-inode (vec) 4228(defun tramp-get-inode (vec)
4216 "Returns the virtual inode number. 4229 "Returns the virtual inode number.
4217If it doesn't exist, generate a new one." 4230If it doesn't exist, generate a new one."
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index bb371c5d7ab..9d919ccbbea 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -327,11 +327,11 @@ behavior for explicit filling, you might as well use \\[newline-and-indent]."
327(defcustom comment-empty-lines nil 327(defcustom comment-empty-lines nil
328 "If nil, `comment-region' does not comment out empty lines. 328 "If nil, `comment-region' does not comment out empty lines.
329If t, it always comments out empty lines. 329If t, it always comments out empty lines.
330If `eol' it only comments out empty lines if comments are 330If `eol', it only comments out empty lines if comments are
331terminated by the end of line (i.e. `comment-end' is empty)." 331terminated by the end of line (i.e., `comment-end' is empty)."
332 :type '(choice (const :tag "Never" nil) 332 :type '(choice (const :tag "Never" nil)
333 (const :tag "Always" t) 333 (const :tag "Always" t)
334 (const :tag "EOl-terminated" eol)) 334 (const :tag "EOL-terminated" eol))
335 :group 'comment) 335 :group 'comment)
336 336
337;;;; 337;;;;
diff --git a/lisp/printing.el b/lisp/printing.el
index 27856eb09fc..f2495ecda38 100644
--- a/lisp/printing.el
+++ b/lisp/printing.el
@@ -1,4 +1,4 @@
1;;; printing.el --- printing utilities 1;;; printing.el --- printing utilities -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2000-2001, 2003-2019 Free Software Foundation, Inc. 3;; Copyright (C) 2000-2001, 2003-2019 Free Software Foundation, Inc.
4 4
@@ -460,7 +460,7 @@ Please send all bug fixes and enhancements to
460;; subjects shows up at the printer. With major mode printing you don't need 460;; subjects shows up at the printer. With major mode printing you don't need
461;; to switch from gnus *Summary* buffer first. 461;; to switch from gnus *Summary* buffer first.
462;; 462;;
463;; Current global keyboard mapping for GNU Emacs is: 463;; Current global keyboard mapping is:
464;; 464;;
465;; (global-set-key [print] 'pr-ps-fast-fire) 465;; (global-set-key [print] 'pr-ps-fast-fire)
466;; (global-set-key [M-print] 'pr-ps-mode-using-ghostscript) 466;; (global-set-key [M-print] 'pr-ps-mode-using-ghostscript)
@@ -468,14 +468,6 @@ Please send all bug fixes and enhancements to
468;; (global-set-key [C-print] 'pr-txt-fast-fire) 468;; (global-set-key [C-print] 'pr-txt-fast-fire)
469;; (global-set-key [C-M-print] 'pr-txt-fast-fire) 469;; (global-set-key [C-M-print] 'pr-txt-fast-fire)
470;; 470;;
471;; And for XEmacs is:
472;;
473;; (global-set-key 'f22 'pr-ps-fast-fire)
474;; (global-set-key '(meta f22) 'pr-ps-mode-using-ghostscript)
475;; (global-set-key '(shift f22) 'pr-ps-mode-using-ghostscript)
476;; (global-set-key '(control f22) 'pr-txt-fast-fire)
477;; (global-set-key '(control meta f22) 'pr-txt-fast-fire)
478;;
479;; As a suggestion of global keyboard mapping for some `printing' commands: 471;; As a suggestion of global keyboard mapping for some `printing' commands:
480;; 472;;
481;; (global-set-key "\C-ci" 'pr-interface) 473;; (global-set-key "\C-ci" 'pr-interface)
@@ -493,7 +485,7 @@ Please send all bug fixes and enhancements to
493;; Below it's shown a brief description of `printing' options, please, see the 485;; Below it's shown a brief description of `printing' options, please, see the
494;; options declaration in the code for a long documentation. 486;; options declaration in the code for a long documentation.
495;; 487;;
496;; `pr-path-style' Specify which path style to use for external 488;; `pr-filename-style' Specify which filename style to use for external
497;; commands. 489;; commands.
498;; 490;;
499;; `pr-path-alist' Specify an alist for command paths. 491;; `pr-path-alist' Specify an alist for command paths.
@@ -999,7 +991,7 @@ Please send all bug fixes and enhancements to
999;; - automagic region detection. 991;; - automagic region detection.
1000;; - menu entry hiding. 992;; - menu entry hiding.
1001;; - fast fire PostScript printing command. 993;; - fast fire PostScript printing command.
1002;; - `pr-path-style' variable. 994;; - `pr-filename-style' variable.
1003;; 995;;
1004;; Thanks to Kim F. Storm <storm@filanet.dk> for beta-test and for suggestions: 996;; Thanks to Kim F. Storm <storm@filanet.dk> for beta-test and for suggestions:
1005;; - PostScript Print and PostScript Print Preview merge. 997;; - PostScript Print and PostScript Print Preview merge.
@@ -1023,7 +1015,7 @@ Please send all bug fixes and enhancements to
1023 1015
1024(require 'lpr) 1016(require 'lpr)
1025(require 'ps-print) 1017(require 'ps-print)
1026 1018(require 'easymenu)
1027 1019
1028(and (string< ps-print-version "6.6.4") 1020(and (string< ps-print-version "6.6.4")
1029 (error "`printing' requires `ps-print' package version 6.6.4 or later")) 1021 (error "`printing' requires `ps-print' package version 6.6.4 or later"))
@@ -1038,93 +1030,16 @@ Please send all bug fixes and enhancements to
1038;; To avoid compilation gripes 1030;; To avoid compilation gripes
1039 1031
1040 1032
1041;; Emacs has this since at least 21.1. 1033;; User Interface --- declared here to avoid compiler warnings
1042(when (featurep 'xemacs) 1034(define-obsolete-variable-alias 'pr-path-style 'pr-filename-style "27.1")
1043 (or (fboundp 'subst-char-in-string) ; hacked from subr.el 1035(defvar pr-filename-style)
1044 (defun subst-char-in-string (fromchar tochar string &optional inplace) 1036(defvar pr-auto-region)
1045 "Replace FROMCHAR with TOCHAR in STRING each time it occurs. 1037(defvar pr-menu-char-height)
1046Unless optional argument INPLACE is non-nil, return a new string." 1038(defvar pr-menu-char-width)
1047 (let ((i (length string)) 1039(defvar pr-menu-lock)
1048 (newstr (if inplace string (copy-sequence string)))) 1040(defvar pr-ps-printer-alist)
1049 (while (> (setq i (1- i)) 0) 1041(defvar pr-txt-printer-alist)
1050 (if (eq (aref newstr i) fromchar) 1042(defvar pr-ps-utility-alist)
1051 (aset newstr i tochar)))
1052 newstr))))
1053
1054
1055;; Emacs has this since at least 21.1, but the SUFFIX argument
1056;; (which this file uses) only since 22.1. So the fboundp test
1057;; wasn't even correct/adequate. Whatever, no-one is using
1058;; this file on older Emacs version, so it's irrelevant.
1059(when (featurep 'xemacs)
1060 (or (fboundp 'make-temp-file) ; hacked from subr.el
1061 (defun make-temp-file (prefix &optional dir-flag suffix)
1062 "Create a temporary file.
1063The returned file name (created by appending some random characters at the end
1064of PREFIX, and expanding against `temporary-file-directory' if necessary),
1065is guaranteed to point to a newly created empty file.
1066You can then use `write-region' to write new data into the file.
1067
1068If DIR-FLAG is non-nil, create a new empty directory instead of a file.
1069
1070If SUFFIX is non-nil, add that at the end of the file name."
1071 (let ((umask (default-file-modes))
1072 file)
1073 (unwind-protect
1074 (progn
1075 ;; Create temp files with strict access rights. It's easy to
1076 ;; loosen them later, whereas it's impossible to close the
1077 ;; time-window of loose permissions otherwise.
1078 (set-default-file-modes ?\700)
1079 (while (condition-case ()
1080 (progn
1081 (setq file
1082 (make-temp-name
1083 (expand-file-name prefix temporary-file-directory)))
1084 (if suffix
1085 (setq file (concat file suffix)))
1086 (if dir-flag
1087 (make-directory file)
1088 (write-region "" nil file nil 'silent nil 'excl))
1089 nil)
1090 (file-already-exists t))
1091 ;; the file was somehow created by someone else between
1092 ;; `make-temp-name' and `write-region', let's try again.
1093 nil)
1094 file)
1095 ;; Reset the umask.
1096 (set-default-file-modes umask))))))
1097
1098
1099(eval-when-compile
1100 ;; User Interface --- declared here to avoid compiler warnings
1101 (defvar pr-path-style)
1102 (defvar pr-auto-region)
1103 (defvar pr-menu-char-height)
1104 (defvar pr-menu-char-width)
1105 (defvar pr-menu-lock)
1106 (defvar pr-ps-printer-alist)
1107 (defvar pr-txt-printer-alist)
1108 (defvar pr-ps-utility-alist)
1109
1110
1111 ;; Internal fun alias to avoid compilation gripes
1112 (defalias 'pr-menu-lookup 'ignore)
1113 (defalias 'pr-menu-lock 'ignore)
1114 (defalias 'pr-menu-alist 'ignore)
1115 (defalias 'pr-even-or-odd-pages 'ignore)
1116 (defalias 'pr-menu-get-item 'ignore)
1117 (defalias 'pr-menu-set-item-name 'ignore)
1118 (defalias 'pr-menu-set-utility-title 'ignore)
1119 (defalias 'pr-menu-set-ps-title 'ignore)
1120 (defalias 'pr-menu-set-txt-title 'ignore)
1121 (defalias 'pr-region-active-p 'ignore)
1122 (defalias 'pr-do-update-menus 'ignore)
1123 (defalias 'pr-update-mode-line 'ignore)
1124 (defalias 'pr-read-string 'ignore)
1125 (defalias 'pr-set-keymap-parents 'ignore)
1126 (defalias 'pr-keep-region-active 'ignore))
1127
1128 1043
1129;; Internal Vars --- defined here to avoid compiler warnings 1044;; Internal Vars --- defined here to avoid compiler warnings
1130(defvar pr-menu-print-item "print" 1045(defvar pr-menu-print-item "print"
@@ -1151,480 +1066,206 @@ Used by `pr-menu-bind' and `pr-update-menus'.")
1151 1066
1152;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1067;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1153;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1068;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1154;; XEmacs Definitions 1069;; GNU Emacs Definitions
1155
1156
1157(cond
1158 ((featurep 'xemacs) ; XEmacs
1159 ;; XEmacs
1160 (defalias 'pr-set-keymap-parents 'set-keymap-parents)
1161 (defalias 'pr-set-keymap-name 'set-keymap-name)
1162
1163 ;; XEmacs
1164 (defun pr-read-string (prompt initial history default)
1165 (let ((str (read-string prompt initial)))
1166 (if (and str (not (string= str "")))
1167 str
1168 default)))
1169
1170 ;; XEmacs
1171 (defvar zmacs-region-stays nil)
1172
1173 ;; XEmacs
1174 (defun pr-keep-region-active ()
1175 (setq zmacs-region-stays t))
1176
1177 ;; XEmacs
1178 (defun pr-region-active-p ()
1179 (and pr-auto-region (not zmacs-region-stays) (ps-mark-active-p)))
1180
1181 ;; XEmacs
1182 (defun pr-menu-char-height ()
1183 (font-height (face-font 'default)))
1184
1185 ;; XEmacs
1186 (defun pr-menu-char-width ()
1187 (font-width (face-font 'default)))
1188
1189 ;; XEmacs
1190 (defmacro pr-xemacs-global-menubar (&rest body)
1191 `(save-excursion
1192 (let ((temp (get-buffer-create (make-temp-name " *Temp"))))
1193 ;; be sure to access global menubar
1194 (set-buffer temp)
1195 ,@body
1196 (kill-buffer temp))))
1197
1198 ;; XEmacs
1199 (defun pr-global-menubar (pr-menu-spec)
1200 ;; Menu binding
1201 (pr-xemacs-global-menubar
1202 (add-submenu nil (cons "Printing" pr-menu-spec) "Apps"))
1203 (setq pr-menu-print-item nil))
1204
1205 ;; XEmacs
1206 (defvar current-mouse-event nil)
1207 (defun pr-menu-position (entry index horizontal)
1208 (make-event
1209 'button-release
1210 (list 'button 1
1211 'x (- (event-x-pixel current-mouse-event) ; X
1212 (* horizontal pr-menu-char-width))
1213 'y (- (event-y-pixel current-mouse-event) ; Y
1214 (* (pr-menu-index entry index) pr-menu-char-height)))))
1215
1216 (defvar pr-menu-position nil)
1217 (defvar pr-menu-state nil)
1218
1219 ;; XEmacs
1220 (defvar current-menubar nil) ; to avoid compilation gripes
1221 (defun pr-menu-lookup (path)
1222 (car (find-menu-item current-menubar (cons "Printing" path))))
1223
1224 ;; XEmacs
1225 (defun pr-menu-lock (entry index horizontal state path)
1226 (when pr-menu-lock
1227 (or (and pr-menu-position (eq state pr-menu-state))
1228 (setq pr-menu-position (pr-menu-position entry index horizontal)
1229 pr-menu-state state))
1230 (let* ((menu (pr-menu-lookup path))
1231 (result (get-popup-menu-response menu pr-menu-position)))
1232 (and (misc-user-event-p result)
1233 (funcall (event-function result)
1234 (event-object result))))
1235 (setq pr-menu-position nil)))
1236
1237 ;; XEmacs
1238 (defalias 'pr-update-mode-line 'set-menubar-dirty-flag)
1239
1240 ;; XEmacs
1241 (defvar pr-ps-name-old "PostScript Printers")
1242 (defvar pr-txt-name-old "Text Printers")
1243 (defvar pr-ps-utility-old "PostScript Utility")
1244 (defvar pr-even-or-odd-old "Print All Pages")
1245
1246 ;; XEmacs
1247 (defun pr-do-update-menus (&optional force)
1248 (pr-menu-alist pr-ps-printer-alist
1249 'pr-ps-name
1250 'pr-menu-set-ps-title
1251 '("Printing")
1252 'pr-ps-printer-menu-modified
1253 force
1254 pr-ps-name-old
1255 'postscript 2)
1256 (pr-menu-alist pr-txt-printer-alist
1257 'pr-txt-name
1258 'pr-menu-set-txt-title
1259 '("Printing")
1260 'pr-txt-printer-menu-modified
1261 force
1262 pr-txt-name-old
1263 'text 2)
1264 (let ((save-var pr-ps-utility-menu-modified))
1265 (pr-menu-alist pr-ps-utility-alist
1266 'pr-ps-utility
1267 'pr-menu-set-utility-title
1268 '("Printing" "PostScript Print" "File")
1269 'save-var
1270 force
1271 pr-ps-utility-old
1272 nil 1))
1273 (pr-menu-alist pr-ps-utility-alist
1274 'pr-ps-utility
1275 'pr-menu-set-utility-title
1276 '("Printing" "PostScript Preview" "File")
1277 'pr-ps-utility-menu-modified
1278 force
1279 pr-ps-utility-old
1280 nil 1)
1281 (pr-even-or-odd-pages ps-even-or-odd-pages force))
1282
1283 ;; XEmacs
1284 (defun pr-menu-alist (alist var-sym fun menu-path modified-sym force name
1285 entry index)
1286 (when (and alist (or force (symbol-value modified-sym)))
1287 (pr-xemacs-global-menubar
1288 (add-submenu menu-path
1289 (pr-menu-create name alist var-sym
1290 fun entry index)))
1291 (funcall fun (symbol-value var-sym))
1292 (set modified-sym nil)))
1293
1294 ;; XEmacs
1295 (defun pr-relabel-menu-item (newname var-sym)
1296 (pr-xemacs-global-menubar
1297 (relabel-menu-item
1298 (list "Printing" (symbol-value var-sym))
1299 newname)
1300 (set var-sym newname)))
1301
1302 ;; XEmacs
1303 (defun pr-menu-set-ps-title (value &optional item entry index)
1304 (pr-relabel-menu-item (format "PostScript Printer: %s" value)
1305 'pr-ps-name-old)
1306 (pr-ps-set-printer value)
1307 (and index
1308 (pr-menu-lock entry index 12 'toggle nil)))
1309
1310 ;; XEmacs
1311 (defun pr-menu-set-txt-title (value &optional item entry index)
1312 (pr-relabel-menu-item (format "Text Printer: %s" value)
1313 'pr-txt-name-old)
1314 (pr-txt-set-printer value)
1315 (and index
1316 (pr-menu-lock entry index 12 'toggle nil)))
1317
1318 ;; XEmacs
1319 (defun pr-menu-set-utility-title (value &optional item entry index)
1320 (pr-xemacs-global-menubar
1321 (let ((newname (format "%s" value)))
1322 (relabel-menu-item
1323 (list "Printing" "PostScript Print" "File" pr-ps-utility-old)
1324 newname)
1325 (relabel-menu-item
1326 (list "Printing" "PostScript Preview" "File" pr-ps-utility-old)
1327 newname)
1328 (setq pr-ps-utility-old newname)))
1329 (pr-ps-set-utility value)
1330 (and index
1331 (pr-menu-lock entry index 5 nil '("PostScript Print" "File"))))
1332
1333 ;; XEmacs
1334 (defun pr-even-or-odd-pages (value &optional no-lock)
1335 (pr-relabel-menu-item (cdr (assq value pr-even-or-odd-alist))
1336 'pr-even-or-odd-old)
1337 (setq ps-even-or-odd-pages value)
1338 (or no-lock
1339 (pr-menu-lock 'postscript-options 8 12 'toggle nil)))
1340
1341 )
1342 (t ; GNU Emacs
1343 ;; Do nothing
1344 )) ; end cond featurep
1345 1070
1071(defun pr-keep-region-active ()
1072 (setq deactivate-mark nil))
1346 1073
1347 1074(defun pr-region-active-p ()
1348;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1075 (and pr-auto-region (use-region-p)))
1349;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1350;; GNU Emacs Definitions
1351 1076
1352(eval-and-compile 1077;; Menu binding
1353 (unless (featurep 'xemacs) 1078;; Replace existing "print" item by "Printing" item.
1354 (defvar pr-menu-bar nil 1079;; If you're changing this file, you'll load it a second,
1355 "Specify Printing menu-bar entry."))) 1080;; third... time, but "print" item exists only in the first load.
1356 1081
1357(cond 1082(defvar pr-menu-bar nil
1358 ((featurep 'xemacs) ; XEmacs 1083 "Specify Printing menu-bar entry.")
1359 ;; Do nothing 1084
1360 ) 1085(defun pr-global-menubar (menu-spec)
1361 (t ; GNU Emacs 1086 (let ((menu-file '("menu-bar" "file")))
1362 ;; GNU Emacs
1363 (defalias 'pr-set-keymap-parents 'set-keymap-parent)
1364 (defalias 'pr-set-keymap-name 'ignore)
1365 (defalias 'pr-read-string 'read-string)
1366
1367 ;; GNU Emacs
1368 (defvar deactivate-mark)
1369
1370 ;; GNU Emacs
1371 (defun pr-keep-region-active ()
1372 (setq deactivate-mark nil))
1373
1374 ;; GNU Emacs
1375 (defun pr-region-active-p ()
1376 (and pr-auto-region transient-mark-mode mark-active))
1377
1378 ;; GNU Emacs
1379 (defun pr-menu-char-height ()
1380 (frame-char-height))
1381
1382 ;; GNU Emacs
1383 (defun pr-menu-char-width ()
1384 (frame-char-width))
1385
1386 ;; GNU Emacs
1387 ;; Menu binding
1388 ;; Replace existing "print" item by "Printing" item.
1389 ;; If you're changing this file, you'll load it a second,
1390 ;; third... time, but "print" item exists only in the first load.
1391 (eval-when-compile
1392 (require 'easymenu)) ; to avoid compilation gripes
1393
1394 (declare-function easy-menu-add-item "easymenu"
1395 (map path item &optional before))
1396 (declare-function easy-menu-remove-item "easymenu" (map path name))
1397
1398 (eval-and-compile
1399 (defun pr-global-menubar (pr-menu-spec)
1400 (require 'easymenu)
1401 (let ((menu-file (if (= emacs-major-version 21)
1402 '("menu-bar" "files") ; GNU Emacs 21
1403 '("menu-bar" "file")))) ; GNU Emacs 22 or higher
1404 (cond
1405 (pr-menu-print-item
1406 (easy-menu-add-item global-map menu-file
1407 (easy-menu-create-menu "Print" pr-menu-spec)
1408 "print-buffer")
1409 (dolist (item '("print-buffer" "print-region"
1410 "ps-print-buffer-faces" "ps-print-region-faces"
1411 "ps-print-buffer" "ps-print-region"))
1412 (easy-menu-remove-item global-map menu-file item))
1413 (setq pr-menu-print-item nil
1414 pr-menu-bar (vector 'menu-bar
1415 (pr-get-symbol (nth 1 menu-file))
1416 (pr-get-symbol "Print"))))
1417 (t
1418 (easy-menu-add-item global-map menu-file
1419 (easy-menu-create-menu "Print" pr-menu-spec)))
1420 ))))
1421
1422 (eval-and-compile
1423 (cond 1087 (cond
1424 (lpr-windows-system 1088 (pr-menu-print-item
1425 ;; GNU Emacs for Windows 9x/NT 1089 (easy-menu-add-item global-map menu-file
1426 (defun pr-menu-position (entry index horizontal) 1090 (easy-menu-create-menu "Print" menu-spec)
1427 (let ((pos (cdr (mouse-pixel-position)))) 1091 "print-buffer")
1428 (list 1092 (dolist (item '("print-buffer" "print-region"
1429 (list (or (car pos) 0) ; X 1093 "ps-print-buffer-faces" "ps-print-region-faces"
1430 (- (or (cdr pos) 0) ; Y 1094 "ps-print-buffer" "ps-print-region"))
1431 (* (pr-menu-index entry index) pr-menu-char-height))) 1095 (easy-menu-remove-item global-map menu-file item))
1432 (selected-frame)))) ; frame 1096 (setq pr-menu-print-item nil
1433 ) 1097 pr-menu-bar (vector 'menu-bar
1098 (easy-menu-intern (nth 1 menu-file))
1099 (easy-menu-intern "Print"))))
1434 (t 1100 (t
1435 ;; GNU Emacs 1101 (easy-menu-add-item global-map menu-file
1436 (defun pr-menu-position (entry index horizontal) 1102 (easy-menu-create-menu "Print" menu-spec)))
1437 (let ((pos (cdr (mouse-pixel-position)))) 1103 )))
1438 (list 1104
1439 (list (- (or (car pos) 0) ; X 1105(defun pr-menu-position (entry index horizontal)
1440 (* horizontal pr-menu-char-width)) 1106 (let ((pos (cdr (mouse-pixel-position))))
1441 (- (or (cdr pos) 0) ; Y 1107 (list
1442 (* (pr-menu-index entry index) pr-menu-char-height))) 1108 (list (- (or (car pos) 0) ; X
1443 (selected-frame)))) ; frame 1109 (if lpr-windows-system
1444 ))) 1110 0 ;; GNU Emacs for Windows 9x/NT
1445 1111 (* horizontal pr-menu-char-width)))
1446 (defvar pr-menu-position nil) 1112 (- (or (cdr pos) 0) ; Y
1447 (defvar pr-menu-state nil) 1113 (* (pr-menu-index entry index) pr-menu-char-height)))
1448 1114 (selected-frame)))) ; frame
1449 ;; GNU Emacs 1115
1450 (defun pr-menu-lookup (path) 1116(defvar pr-menu-position nil)
1451 (lookup-key global-map 1117(defvar pr-menu-state nil)
1452 (if path 1118
1453 (vconcat pr-menu-bar 1119(defun pr-menu-lookup (path)
1454 (mapcar 'pr-get-symbol 1120 (lookup-key global-map
1455 (if (listp path) 1121 (if path
1456 path 1122 (vconcat pr-menu-bar
1457 (list path)))) 1123 (mapcar #'easy-menu-intern
1458 pr-menu-bar))) 1124 (if (listp path)
1459 1125 path
1460 ;; GNU Emacs 1126 (list path))))
1461 (defun pr-menu-lock (entry index horizontal state path) 1127 pr-menu-bar)))
1462 (when pr-menu-lock 1128
1463 (or (and pr-menu-position (eq state pr-menu-state)) 1129(defun pr-menu-lock (entry index horizontal state path)
1464 (setq pr-menu-position (pr-menu-position entry index horizontal) 1130 (when pr-menu-lock
1465 pr-menu-state state)) 1131 (or (and pr-menu-position (eq state pr-menu-state))
1466 (let* ((menu (pr-menu-lookup path)) 1132 (setq pr-menu-position (pr-menu-position entry index horizontal)
1467 (result (x-popup-menu pr-menu-position menu))) 1133 pr-menu-state state))
1468 (and result 1134 (let* ((menu (pr-menu-lookup path))
1469 (let ((command (lookup-key menu (vconcat result)))) 1135 (result (x-popup-menu pr-menu-position menu)))
1470 (if (fboundp command) 1136 (and result
1471 (funcall command) 1137 (let ((command (lookup-key menu (vconcat result))))
1472 (eval command))))) 1138 (if (fboundp command)
1473 (setq pr-menu-position nil))) 1139 (funcall command)
1474 1140 (eval command)))))
1475 ;; GNU Emacs 1141 (setq pr-menu-position nil)))
1476 (defalias 'pr-update-mode-line 'force-mode-line-update) 1142
1477 1143(defun pr-do-update-menus (&optional force)
1478 ;; GNU Emacs 1144 (pr-menu-alist pr-ps-printer-alist
1479 (defun pr-do-update-menus (&optional force) 1145 'pr-ps-name
1480 (pr-menu-alist pr-ps-printer-alist 1146 #'pr-menu-set-ps-title
1481 'pr-ps-name 1147 "PostScript Printers"
1482 'pr-menu-set-ps-title 1148 'pr-ps-printer-menu-modified
1483 "PostScript Printers" 1149 force
1484 'pr-ps-printer-menu-modified 1150 "PostScript Printers"
1485 force 1151 'postscript 2)
1486 "PostScript Printers" 1152 (pr-menu-alist pr-txt-printer-alist
1487 'postscript 2) 1153 'pr-txt-name
1488 (pr-menu-alist pr-txt-printer-alist 1154 #'pr-menu-set-txt-title
1489 'pr-txt-name 1155 "Text Printers"
1490 'pr-menu-set-txt-title 1156 'pr-txt-printer-menu-modified
1491 "Text Printers" 1157 force
1492 'pr-txt-printer-menu-modified 1158 "Text Printers"
1493 force 1159 'text 2)
1494 "Text Printers" 1160 (defvar pr--save-var)
1495 'text 2) 1161 (let ((pr--save-var pr-ps-utility-menu-modified))
1496 (let ((save-var pr-ps-utility-menu-modified))
1497 (pr-menu-alist pr-ps-utility-alist
1498 'pr-ps-utility
1499 'pr-menu-set-utility-title
1500 '("PostScript Print" "File" "PostScript Utility")
1501 'save-var
1502 force
1503 "PostScript Utility"
1504 nil 1))
1505 (pr-menu-alist pr-ps-utility-alist 1162 (pr-menu-alist pr-ps-utility-alist
1506 'pr-ps-utility 1163 'pr-ps-utility
1507 'pr-menu-set-utility-title 1164 #'pr-menu-set-utility-title
1508 '("PostScript Preview" "File" "PostScript Utility") 1165 '("PostScript Print" "File" "PostScript Utility")
1509 'pr-ps-utility-menu-modified 1166 'pr--save-var
1510 force 1167 force
1511 "PostScript Utility" 1168 "PostScript Utility"
1512 nil 1) 1169 nil 1))
1513 (pr-even-or-odd-pages ps-even-or-odd-pages force)) 1170 (pr-menu-alist pr-ps-utility-alist
1514 1171 'pr-ps-utility
1515 ;; GNU Emacs 1172 #'pr-menu-set-utility-title
1516 (defun pr-menu-get-item (name-list) 1173 '("PostScript Preview" "File" "PostScript Utility")
1517 ;; NAME-LIST is a string or a list of strings. 1174 'pr-ps-utility-menu-modified
1518 (or (listp name-list) 1175 force
1519 (setq name-list (list name-list))) 1176 "PostScript Utility"
1520 (and name-list 1177 nil 1)
1521 (let* ((reversed (reverse name-list)) 1178 (pr-even-or-odd-pages ps-even-or-odd-pages force))
1522 (name (pr-get-symbol (car reversed))) 1179
1523 (path (nreverse (cdr reversed))) 1180(defun pr-menu-get-item (name-list)
1524 (menu (lookup-key 1181 ;; NAME-LIST is a string or a list of strings.
1525 global-map 1182 (or (listp name-list)
1526 (vconcat pr-menu-bar 1183 (setq name-list (list name-list)))
1527 (mapcar 'pr-get-symbol path))))) 1184 (and name-list
1528 (assq name (nthcdr 2 menu))))) 1185 (let* ((reversed (reverse name-list))
1529 1186 (name (easy-menu-intern (car reversed)))
1530 ;; GNU Emacs 1187 (path (nreverse (cdr reversed)))
1531 (defvar pr-temp-menu nil) 1188 (menu (lookup-key
1532 1189 global-map
1533 ;; GNU Emacs 1190 (vconcat pr-menu-bar
1534 (defun pr-menu-alist (alist var-sym fun menu-path modified-sym force name 1191 (mapcar #'easy-menu-intern path)))))
1535 entry index) 1192 (assq name (nthcdr 2 menu)))))
1536 (when (and alist (or force (symbol-value modified-sym))) 1193
1537 (easy-menu-define pr-temp-menu nil "" 1194(defvar pr-temp-menu nil)
1538 (pr-menu-create name alist var-sym fun entry index)) 1195
1539 (let ((item (pr-menu-get-item menu-path))) 1196(defun pr-menu-alist (alist var-sym fun menu-path modified-sym force name
1540 (and item 1197 entry index)
1541 (let* ((binding (nthcdr 3 item)) 1198 (when (and alist (or force (symbol-value modified-sym)))
1542 (key-binding (cdr binding))) 1199 (easy-menu-define pr-temp-menu nil ""
1543 (setcar binding pr-temp-menu) 1200 (pr-menu-create name alist var-sym fun entry index))
1544 (and key-binding (listp (car key-binding)) 1201 (let ((item (pr-menu-get-item menu-path)))
1545 (setcdr binding (cdr key-binding))) ; skip KEY-BINDING 1202 (and item
1546 (funcall fun (symbol-value var-sym) item)))) 1203 (progn
1547 (set modified-sym nil))) 1204 (setf (nth 3 item) pr-temp-menu)
1548 1205 (funcall fun (symbol-value var-sym) item))))
1549 ;; GNU Emacs 1206 (set modified-sym nil)))
1550 (defun pr-menu-set-item-name (item name) 1207
1551 (and item 1208(defun pr-menu-set-item-name (item name)
1552 (setcar (nthcdr 2 item) name))) ; ITEM-NAME 1209 (and item
1553 1210 (setcar (nthcdr 2 item) name))) ; ITEM-NAME
1554 ;; GNU Emacs 1211
1555 (defun pr-menu-set-ps-title (value &optional item entry index) 1212(defun pr-menu-set-ps-title (value &optional item entry index)
1556 (pr-menu-set-item-name (or item 1213 (pr-menu-set-item-name (or item
1557 (pr-menu-get-item "PostScript Printers")) 1214 (pr-menu-get-item "PostScript Printers"))
1558 (format "PostScript Printer: %s" value)) 1215 (format "PostScript Printer: %s" value))
1559 (pr-ps-set-printer value) 1216 (pr-ps-set-printer value)
1560 (and index 1217 (and index
1561 (pr-menu-lock entry index 12 'toggle nil))) 1218 (pr-menu-lock entry index 12 'toggle nil)))
1562 1219
1563 ;; GNU Emacs 1220(defun pr-menu-set-txt-title (value &optional item entry index)
1564 (defun pr-menu-set-txt-title (value &optional item entry index) 1221 (pr-menu-set-item-name (or item
1565 (pr-menu-set-item-name (or item 1222 (pr-menu-get-item "Text Printers"))
1566 (pr-menu-get-item "Text Printers")) 1223 (format "Text Printer: %s" value))
1567 (format "Text Printer: %s" value)) 1224 (pr-txt-set-printer value)
1568 (pr-txt-set-printer value) 1225 (and index
1569 (and index 1226 (pr-menu-lock entry index 12 'toggle nil)))
1570 (pr-menu-lock entry index 12 'toggle nil))) 1227
1571 1228(defun pr-menu-set-utility-title (value &optional item entry index)
1572 ;; GNU Emacs 1229 (let ((name (symbol-name value)))
1573 (defun pr-menu-set-utility-title (value &optional item entry index) 1230 (if item
1574 (let ((name (symbol-name value))) 1231 (pr-menu-set-item-name item name)
1575 (if item 1232 (pr-menu-set-item-name
1576 (pr-menu-set-item-name item name) 1233 (pr-menu-get-item
1577 (pr-menu-set-item-name 1234 '("PostScript Print" "File" "PostScript Utility"))
1578 (pr-menu-get-item 1235 name)
1579 '("PostScript Print" "File" "PostScript Utility")) 1236 (pr-menu-set-item-name
1580 name) 1237 (pr-menu-get-item
1581 (pr-menu-set-item-name 1238 '("PostScript Preview" "File" "PostScript Utility"))
1582 (pr-menu-get-item 1239 name)))
1583 '("PostScript Preview" "File" "PostScript Utility")) 1240 (pr-ps-set-utility value)
1584 name))) 1241 (and index
1585 (pr-ps-set-utility value) 1242 (pr-menu-lock entry index 5 nil '("PostScript Print" "File"))))
1586 (and index 1243
1587 (pr-menu-lock entry index 5 nil '("PostScript Print" "File")))) 1244(defun pr-even-or-odd-pages (value &optional no-lock)
1588 1245 (pr-menu-set-item-name (pr-menu-get-item "Print All Pages")
1589 ;; GNU Emacs 1246 (cdr (assq value pr-even-or-odd-alist)))
1590 (defun pr-even-or-odd-pages (value &optional no-lock) 1247 (setq ps-even-or-odd-pages value)
1591 (pr-menu-set-item-name (pr-menu-get-item "Print All Pages") 1248 (or no-lock
1592 (cdr (assq value pr-even-or-odd-alist))) 1249 (pr-menu-lock 'postscript-options 8 12 'toggle nil)))
1593 (setq ps-even-or-odd-pages value)
1594 (or no-lock
1595 (pr-menu-lock 'postscript-options 8 12 'toggle nil)))
1596
1597 )) ; end cond featurep
1598
1599 1250
1600;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1251;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1601;; Internal Functions (I) 1252;; Internal Functions (I)
1602 1253
1603 1254
1604(defun pr-dosify-file-name (path) 1255(defun pr-dosify-file-name (filename)
1605 "Replace unix-style directory separator character with dos/windows one." 1256 "Replace unix-style directory separator character with dos/windows one."
1606 (interactive "sPath: ") 1257 (if (eq pr-filename-style 'windows)
1607 (if (eq pr-path-style 'windows) 1258 (subst-char-in-string ?/ ?\\ filename)
1608 (subst-char-in-string ?/ ?\\ path) 1259 filename))
1609 path))
1610
1611 1260
1612(defun pr-unixify-file-name (path) 1261(defun pr-standard-file-name (filename)
1613 "Replace dos/windows-style directory separator character with unix one."
1614 (interactive "sPath: ")
1615 (if (eq pr-path-style 'windows)
1616 (subst-char-in-string ?\\ ?/ path)
1617 path))
1618
1619
1620(defun pr-standard-file-name (path)
1621 "Ensure the proper directory separator depending on the OS. 1262 "Ensure the proper directory separator depending on the OS.
1622That is, if Emacs is running on DOS/Windows, ensure dos/windows-style directory 1263That is, if Emacs is running on DOS/Windows, ensure dos/windows-style directory
1623separator; otherwise, ensure unix-style directory separator." 1264separator; otherwise, ensure unix-style directory separator."
1265 ;; FIXME: Why not use pr-dosify-file-name?
1624 (if (or pr-cygwin-system lpr-windows-system) 1266 (if (or pr-cygwin-system lpr-windows-system)
1625 (subst-char-in-string ?/ ?\\ path) 1267 (subst-char-in-string ?/ ?\\ filename)
1626 (subst-char-in-string ?\\ ?/ path))) 1268 filename))
1627
1628 1269
1629;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1270;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1630;; Customization Functions 1271;; Customization Functions
@@ -1672,22 +1313,21 @@ separator; otherwise, ensure unix-style directory separator."
1672 :group 'postscript) 1313 :group 'postscript)
1673 1314
1674 1315
1675(defcustom pr-path-style 1316(defcustom pr-filename-style
1676 (if (and (not pr-cygwin-system) 1317 (if (and (not pr-cygwin-system)
1677 lpr-windows-system) 1318 lpr-windows-system)
1678 'windows 1319 'windows
1679 'unix) 1320 'unix)
1680 "Specify which path style to use for external commands. 1321 "Specify which filename style to use for external commands.
1681 1322
1682Valid values are: 1323Valid values are:
1683 1324
1684 windows Windows 9x/NT style (\\) 1325 windows Windows 9x/NT style (\\)
1685 1326
1686 unix Unix style (/)" 1327 unix Unix style (/)"
1687 :type '(choice :tag "Path style" 1328 :type '(choice :tag "Filename style"
1688 (const :tag "Windows 9x/NT Style (\\)" :value windows) 1329 (const :tag "Windows 9x/NT Style (\\)" :value windows)
1689 (const :tag "Unix Style (/)" :value unix)) 1330 (const :tag "Unix Style (/)" :value unix)))
1690 :group 'printing)
1691 1331
1692 1332
1693(defcustom pr-path-alist 1333(defcustom pr-path-alist
@@ -1708,13 +1348,13 @@ Where:
1708ENTRY It's a symbol, used to identify this entry. 1348ENTRY It's a symbol, used to identify this entry.
1709 There must exist at least one of the following entries: 1349 There must exist at least one of the following entries:
1710 1350
1711 unix this entry is used when Emacs is running on GNU or 1351 `unix' this entry is used when Emacs is running on GNU or
1712 Unix system. 1352 Unix system.
1713 1353
1714 cygwin this entry is used when Emacs is running on Windows 1354 `cygwin' this entry is used when Emacs is running on Windows
1715 95/98/NT/2000 with Cygwin. 1355 95/98/NT/2000 with Cygwin.
1716 1356
1717 windows this entry is used when Emacs is running on Windows 1357 `windows' this entry is used when Emacs is running on Windows
1718 95/98/NT/2000. 1358 95/98/NT/2000.
1719 1359
1720DIRECTORY It should be a string or a symbol. If it's a symbol, it should 1360DIRECTORY It should be a string or a symbol. If it's a symbol, it should
@@ -1764,8 +1404,7 @@ Examples:
1764 (choice :menu-tag "Directory" 1404 (choice :menu-tag "Directory"
1765 :tag "Directory" 1405 :tag "Directory"
1766 (string :value "") 1406 (string :value "")
1767 (symbol :value symbol))))) 1407 (symbol :value symbol))))))
1768 :group 'printing)
1769 1408
1770 1409
1771(defcustom pr-txt-name 'default 1410(defcustom pr-txt-name 'default
@@ -1778,8 +1417,7 @@ This variable should be modified by customization engine. If this variable is
1778modified by other means (for example, a lisp function), use `pr-update-menus' 1417modified by other means (for example, a lisp function), use `pr-update-menus'
1779function (see it for documentation) to update text printer menu." 1418function (see it for documentation) to update text printer menu."
1780 :type 'symbol 1419 :type 'symbol
1781 :set 'pr-txt-name-custom-set 1420 :set 'pr-txt-name-custom-set)
1782 :group 'printing)
1783 1421
1784 1422
1785(defcustom pr-txt-printer-alist 1423(defcustom pr-txt-printer-alist
@@ -1910,8 +1548,7 @@ Useful links:
1910 :tag "Printer Name" 1548 :tag "Printer Name"
1911 (const :tag "None" nil) 1549 (const :tag "None" nil)
1912 string))) 1550 string)))
1913 :set 'pr-alist-custom-set 1551 :set 'pr-alist-custom-set)
1914 :group 'printing)
1915 1552
1916 1553
1917(defcustom pr-ps-name 'default 1554(defcustom pr-ps-name 'default
@@ -1924,8 +1561,7 @@ This variable should be modified by customization engine. If this variable is
1924modified by other means (for example, a lisp function), use `pr-update-menus' 1561modified by other means (for example, a lisp function), use `pr-update-menus'
1925function (see it for documentation) to update PostScript printer menu." 1562function (see it for documentation) to update PostScript printer menu."
1926 :type 'symbol 1563 :type 'symbol
1927 :set 'pr-ps-name-custom-set 1564 :set 'pr-ps-name-custom-set)
1928 :group 'printing)
1929 1565
1930 1566
1931(defcustom pr-ps-printer-alist 1567(defcustom pr-ps-printer-alist
@@ -2196,33 +1832,21 @@ Useful links:
2196 (variable :tag "Other")) 1832 (variable :tag "Other"))
2197 (sexp :tag "Value"))) 1833 (sexp :tag "Value")))
2198 )) 1834 ))
2199 :set 'pr-alist-custom-set 1835 :set 'pr-alist-custom-set)
2200 :group 'printing) 1836
2201 1837
2202 1838(defcustom pr-temp-dir temporary-file-directory
2203(defcustom pr-temp-dir
2204 (pr-dosify-file-name
2205 (if (boundp 'temporary-file-directory)
2206 (symbol-value 'temporary-file-directory)
2207 ;; hacked from `temporary-file-directory' variable in files.el
2208 (file-name-as-directory
2209 (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP")
2210 (cond (lpr-windows-system "c:/temp")
2211 (t "/tmp")
2212 )))))
2213 "Specify a directory for temporary files during printing. 1839 "Specify a directory for temporary files during printing.
2214 1840
2215See also `pr-ps-temp-file' and `pr-file-modes'." 1841See also `pr-ps-temp-file' and `pr-file-modes'."
2216 :type '(directory :tag "Temporary Directory") 1842 :type '(directory :tag "Temporary Directory"))
2217 :group 'printing)
2218 1843
2219 1844
2220(defcustom pr-ps-temp-file "prspool-" 1845(defcustom pr-ps-temp-file "prspool-"
2221 "Specify PostScript temporary file name prefix. 1846 "Specify PostScript temporary file name prefix.
2222 1847
2223See also `pr-temp-dir' and `pr-file-modes'." 1848See also `pr-temp-dir' and `pr-file-modes'."
2224 :type '(file :tag "PostScript Temporary File Name") 1849 :type '(file :tag "PostScript Temporary File Name"))
2225 :group 'printing)
2226 1850
2227 1851
2228;; It uses 0600 as default instead of (default-file-modes). 1852;; It uses 0600 as default instead of (default-file-modes).
@@ -2234,8 +1858,7 @@ See also `pr-temp-dir' and `pr-file-modes'."
2234It should be an integer; only the low 9 bits are used. 1858It should be an integer; only the low 9 bits are used.
2235 1859
2236See also `pr-temp-dir' and `pr-ps-temp-file'." 1860See also `pr-temp-dir' and `pr-ps-temp-file'."
2237 :type '(integer :tag "File Permission Bits") 1861 :type '(integer :tag "File Permission Bits"))
2238 :group 'printing)
2239 1862
2240 1863
2241(defcustom pr-gv-command 1864(defcustom pr-gv-command
@@ -2275,8 +1898,7 @@ Useful links:
2275* MacGSView (Mac OS) 1898* MacGSView (Mac OS)
2276 `http://www.cs.wisc.edu/~ghost/macos/index.htm' 1899 `http://www.cs.wisc.edu/~ghost/macos/index.htm'
2277" 1900"
2278 :type '(string :tag "Ghostview Utility") 1901 :type '(string :tag "Ghostview Utility"))
2279 :group 'printing)
2280 1902
2281 1903
2282(defcustom pr-gs-command 1904(defcustom pr-gs-command
@@ -2301,8 +1923,7 @@ Useful links:
2301* Printer compatibility 1923* Printer compatibility
2302 `http://www.cs.wisc.edu/~ghost/doc/printer.htm' 1924 `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
2303" 1925"
2304 :type '(string :tag "Ghostscript Utility") 1926 :type '(string :tag "Ghostscript Utility"))
2305 :group 'printing)
2306 1927
2307 1928
2308(defcustom pr-gs-switches 1929(defcustom pr-gs-switches
@@ -2343,8 +1964,7 @@ Useful links:
2343* Printer compatibility 1964* Printer compatibility
2344 `http://www.cs.wisc.edu/~ghost/doc/printer.htm' 1965 `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
2345" 1966"
2346 :type '(repeat (string :tag "Ghostscript Switch")) 1967 :type '(repeat (string :tag "Ghostscript Switch")))
2347 :group 'printing)
2348 1968
2349 1969
2350(defcustom pr-gs-device 1970(defcustom pr-gs-device
@@ -2359,8 +1979,7 @@ A note on the gs switches:
2359 1979
2360See `pr-gs-switches' for documentation. 1980See `pr-gs-switches' for documentation.
2361See also `pr-ps-printer-alist'." 1981See also `pr-ps-printer-alist'."
2362 :type '(string :tag "Ghostscript Device") 1982 :type '(string :tag "Ghostscript Device"))
2363 :group 'printing)
2364 1983
2365 1984
2366(defcustom pr-gs-resolution 300 1985(defcustom pr-gs-resolution 300
@@ -2372,8 +1991,7 @@ A note on the gs switches:
2372 1991
2373See `pr-gs-switches' for documentation. 1992See `pr-gs-switches' for documentation.
2374See also `pr-ps-printer-alist'." 1993See also `pr-ps-printer-alist'."
2375 :type '(integer :tag "Ghostscript Resolution") 1994 :type '(integer :tag "Ghostscript Resolution"))
2376 :group 'printing)
2377 1995
2378 1996
2379(defcustom pr-print-using-ghostscript nil 1997(defcustom pr-print-using-ghostscript nil
@@ -2384,32 +2002,27 @@ ghostscript to print a PostScript file.
2384 2002
2385In GNU or Unix system, if ghostscript is set as a PostScript filter, this 2003In GNU or Unix system, if ghostscript is set as a PostScript filter, this
2386variable should be nil." 2004variable should be nil."
2387 :type 'boolean 2005 :type 'boolean)
2388 :group 'printing)
2389 2006
2390 2007
2391(defcustom pr-faces-p nil 2008(defcustom pr-faces-p nil
2392 "Non-nil means print with face attributes." 2009 "Non-nil means print with face attributes."
2393 :type 'boolean 2010 :type 'boolean)
2394 :group 'printing)
2395 2011
2396 2012
2397(defcustom pr-spool-p nil 2013(defcustom pr-spool-p nil
2398 "Non-nil means spool printing in a buffer." 2014 "Non-nil means spool printing in a buffer."
2399 :type 'boolean 2015 :type 'boolean)
2400 :group 'printing)
2401 2016
2402 2017
2403(defcustom pr-file-landscape nil 2018(defcustom pr-file-landscape nil
2404 "Non-nil means print PostScript file in landscape orientation." 2019 "Non-nil means print PostScript file in landscape orientation."
2405 :type 'boolean 2020 :type 'boolean)
2406 :group 'printing)
2407 2021
2408 2022
2409(defcustom pr-file-duplex nil 2023(defcustom pr-file-duplex nil
2410 "Non-nil means print PostScript file in duplex mode." 2024 "Non-nil means print PostScript file in duplex mode."
2411 :type 'boolean 2025 :type 'boolean)
2412 :group 'printing)
2413 2026
2414 2027
2415(defcustom pr-file-tumble nil 2028(defcustom pr-file-tumble nil
@@ -2419,8 +2032,7 @@ If tumble is off, produces a printing suitable for binding on the left or
2419right. 2032right.
2420If tumble is on, produces a printing suitable for binding at the top or 2033If tumble is on, produces a printing suitable for binding at the top or
2421bottom." 2034bottom."
2422 :type 'boolean 2035 :type 'boolean)
2423 :group 'printing)
2424 2036
2425 2037
2426(defcustom pr-auto-region t 2038(defcustom pr-auto-region t
@@ -2431,8 +2043,7 @@ Note that this will only work if you're using transient mark mode.
2431When this variable is non-nil, the `*-buffer*' commands will behave like 2043When this variable is non-nil, the `*-buffer*' commands will behave like
2432`*-region*' commands, that is, `*-buffer*' commands will print only the region 2044`*-region*' commands, that is, `*-buffer*' commands will print only the region
2433marked instead of all buffer." 2045marked instead of all buffer."
2434 :type 'boolean 2046 :type 'boolean)
2435 :group 'printing)
2436 2047
2437 2048
2438(defcustom pr-auto-mode t 2049(defcustom pr-auto-mode t
@@ -2442,8 +2053,7 @@ That is, if current major-mode is declared in `pr-mode-alist', the `*-buffer*'
2442and `*-region*' commands will behave like `*-mode*' commands; otherwise, 2053and `*-region*' commands will behave like `*-mode*' commands; otherwise,
2443`*-buffer*' commands will print the current buffer and `*-region*' commands 2054`*-buffer*' commands will print the current buffer and `*-region*' commands
2444will print the current region." 2055will print the current region."
2445 :type 'boolean 2056 :type 'boolean)
2446 :group 'printing)
2447 2057
2448 2058
2449(defcustom pr-mode-alist 2059(defcustom pr-mode-alist
@@ -2642,8 +2252,7 @@ DEFAULT It's a way to set default values when this entry is selected.
2642 (const :tag "inherits-from:" inherits-from:) 2252 (const :tag "inherits-from:" inherits-from:)
2643 (variable :tag "Other")) 2253 (variable :tag "Other"))
2644 (sexp :tag "Value"))) 2254 (sexp :tag "Value")))
2645 )) 2255 )))
2646 :group 'printing)
2647 2256
2648 2257
2649(defcustom pr-ps-utility 'mpage 2258(defcustom pr-ps-utility 'mpage
@@ -2659,8 +2268,7 @@ function (see it for documentation) to update PostScript utility menu.
2659NOTE: Don't forget to download and install the utilities declared on 2268NOTE: Don't forget to download and install the utilities declared on
2660 `pr-ps-utility-alist'." 2269 `pr-ps-utility-alist'."
2661 :type '(symbol :tag "PS File Utility") 2270 :type '(symbol :tag "PS File Utility")
2662 :set 'pr-ps-utility-custom-set 2271 :set 'pr-ps-utility-custom-set)
2663 :group 'printing)
2664 2272
2665 2273
2666(defcustom pr-ps-utility-alist 2274(defcustom pr-ps-utility-alist
@@ -2871,38 +2479,34 @@ Useful links:
2871 (variable :tag "Other")) 2479 (variable :tag "Other"))
2872 (sexp :tag "Value"))) 2480 (sexp :tag "Value")))
2873 )) 2481 ))
2874 :set 'pr-alist-custom-set 2482 :set 'pr-alist-custom-set)
2875 :group 'printing)
2876 2483
2877 2484
2878(defcustom pr-menu-lock t 2485(defcustom pr-menu-lock t
2879 "Non-nil means menu is locked while selecting toggle options. 2486 "Non-nil means menu is locked while selecting toggle options.
2880 2487
2881See also `pr-menu-char-height' and `pr-menu-char-width'." 2488See also `pr-menu-char-height' and `pr-menu-char-width'."
2882 :type 'boolean 2489 :type 'boolean)
2883 :group 'printing)
2884 2490
2885 2491
2886(defcustom pr-menu-char-height (pr-menu-char-height) 2492(defcustom pr-menu-char-height (frame-char-height)
2887 "Specify menu char height in pixels. 2493 "Specify menu char height in pixels.
2888 2494
2889This variable is used to guess which vertical position should be locked the 2495This variable is used to guess which vertical position should be locked the
2890menu, so don't forget to adjust it if menu position is not ok. 2496menu, so don't forget to adjust it if menu position is not ok.
2891 2497
2892See also `pr-menu-lock' and `pr-menu-char-width'." 2498See also `pr-menu-lock' and `pr-menu-char-width'."
2893 :type 'integer 2499 :type 'integer)
2894 :group 'printing)
2895 2500
2896 2501
2897(defcustom pr-menu-char-width (pr-menu-char-width) 2502(defcustom pr-menu-char-width (frame-char-width)
2898 "Specify menu char width in pixels. 2503 "Specify menu char width in pixels.
2899 2504
2900This variable is used to guess which horizontal position should be locked the 2505This variable is used to guess which horizontal position should be locked the
2901menu, so don't forget to adjust it if menu position is not ok. 2506menu, so don't forget to adjust it if menu position is not ok.
2902 2507
2903See also `pr-menu-lock' and `pr-menu-char-height'." 2508See also `pr-menu-lock' and `pr-menu-char-height'."
2904 :type 'integer 2509 :type 'integer)
2905 :group 'printing)
2906 2510
2907 2511
2908(defcustom pr-setting-database 2512(defcustom pr-setting-database
@@ -3017,8 +2621,7 @@ SETTING It's a cons like:
3017 (const :tag "Ghostscript Resolution" pr-gs-resolution) 2621 (const :tag "Ghostscript Resolution" pr-gs-resolution)
3018 (variable :tag "Other")) 2622 (variable :tag "Other"))
3019 (sexp :tag "Value"))) 2623 (sexp :tag "Value")))
3020 )) 2624 )))
3021 :group 'printing)
3022 2625
3023 2626
3024(defcustom pr-visible-entry-list 2627(defcustom pr-visible-entry-list
@@ -3070,8 +2673,7 @@ Any other value is ignored."
3070 (const postscript-options) 2673 (const postscript-options)
3071 (const postscript-process) 2674 (const postscript-process)
3072 (const printing) 2675 (const printing)
3073 (const help))) 2676 (const help))))
3074 :group 'printing)
3075 2677
3076 2678
3077(defcustom pr-delete-temp-file t 2679(defcustom pr-delete-temp-file t
@@ -3081,8 +2683,7 @@ Set `pr-delete-temp-file' to nil, if the following message (or a similar)
3081happens when printing: 2683happens when printing:
3082 2684
3083 Error: could not open \"c:\\temp\\prspool.ps\" for reading." 2685 Error: could not open \"c:\\temp\\prspool.ps\" for reading."
3084 :type 'boolean 2686 :type 'boolean)
3085 :group 'printing)
3086 2687
3087 2688
3088(defcustom pr-list-directory nil 2689(defcustom pr-list-directory nil
@@ -3094,16 +2695,14 @@ argument of functions below) are also printed (as dired-mode listings).
3094It's used by `pr-ps-directory-preview', `pr-ps-directory-using-ghostscript', 2695It's used by `pr-ps-directory-preview', `pr-ps-directory-using-ghostscript',
3095`pr-ps-directory-print', `pr-ps-directory-ps-print', `pr-printify-directory' 2696`pr-ps-directory-print', `pr-ps-directory-ps-print', `pr-printify-directory'
3096and `pr-txt-directory'." 2697and `pr-txt-directory'."
3097 :type 'boolean 2698 :type 'boolean)
3098 :group 'printing)
3099 2699
3100 2700
3101(defcustom pr-buffer-name "*Printing Interface*" 2701(defcustom pr-buffer-name "*Printing Interface*"
3102 "Specify the name of the buffer interface for printing package. 2702 "Specify the name of the buffer interface for printing package.
3103 2703
3104It's used by `pr-interface'." 2704It's used by `pr-interface'."
3105 :type 'string 2705 :type 'string)
3106 :group 'printing)
3107 2706
3108 2707
3109(defcustom pr-buffer-name-ignore 2708(defcustom pr-buffer-name-ignore
@@ -3115,16 +2714,14 @@ NOTE: Case is important for matching, that is, `case-fold-search' is always
3115 nil. 2714 nil.
3116 2715
3117It's used by `pr-interface'." 2716It's used by `pr-interface'."
3118 :type '(repeat (regexp :tag "Buffer Name Regexp")) 2717 :type '(repeat (regexp :tag "Buffer Name Regexp")))
3119 :group 'printing)
3120 2718
3121 2719
3122(defcustom pr-buffer-verbose t 2720(defcustom pr-buffer-verbose t
3123 "Non-nil means to be verbose when editing a field in interface buffer. 2721 "Non-nil means to be verbose when editing a field in interface buffer.
3124 2722
3125It's used by `pr-interface'." 2723It's used by `pr-interface'."
3126 :type 'boolean 2724 :type 'boolean)
3127 :group 'printing)
3128 2725
3129 2726
3130;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2727;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3167,15 +2764,6 @@ See `pr-ps-printer-alist'.")
3167 2764
3168 2765
3169;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2766;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3170;; Macros
3171
3172
3173(defmacro pr-save-file-modes (&rest body)
3174 "Execute BODY with file permissions temporarily set to `pr-file-modes'."
3175 (declare (obsolete with-file-modes "25.1"))
3176 `(with-file-modes pr-file-modes ,@body))
3177
3178;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3179;; Keys & Menus 2767;; Keys & Menus
3180 2768
3181 2769
@@ -3195,252 +2783,211 @@ See `pr-ps-printer-alist'.")
3195 (and pr-print-using-ghostscript (not pr-spool-p))) 2783 (and pr-print-using-ghostscript (not pr-spool-p)))
3196 2784
3197 2785
3198(defalias 'pr-get-symbol
3199 (if (featurep 'emacs) 'easy-menu-intern ; since 22.1
3200 (if (fboundp 'easy-menu-intern) ; hacked from easymenu.el
3201 'easy-menu-intern
3202 (lambda (s) (if (stringp s) (intern s) s)))))
3203
3204
3205(defconst pr-menu-spec 2786(defconst pr-menu-spec
3206 ;; Menu mapping: 2787 '(
3207 ;; unfortunately XEmacs doesn't support :active for submenus, 2788 ["Printing Interface" pr-interface
3208 ;; only for items. 2789 :help "Use buffer interface instead of menu interface"]
3209 ;; So, it uses :included instead of :active. 2790 "--"
3210 ;; Also, XEmacs doesn't support :help tag. 2791 ("PostScript Preview" :included (pr-visible-p 'postscript)
3211 (let ((pr-:active (if (featurep 'xemacs) 2792 :help "Preview PostScript instead of sending to printer"
3212 :included ; XEmacs 2793 ("Directory" :active (not pr-spool-p)
3213 :active)) ; GNU Emacs 2794 ["1-up" (pr-ps-directory-preview 1 nil nil t) t]
3214 (pr-:help (if (featurep 'xemacs) 2795 ["2-up" (pr-ps-directory-preview 2 nil nil t) t]
3215 'ignore ; XEmacs 2796 ["4-up" (pr-ps-directory-preview 4 nil nil t) t]
3216 #'(lambda (text) (list :help text))))) ; GNU Emacs 2797 ["Other..." (pr-ps-directory-preview nil nil nil t)
3217 `( 2798 :keys "\\[pr-ps-buffer-preview]"])
3218 ["Printing Interface" pr-interface 2799 ("Buffer" :active (not pr-spool-p)
3219 ,@(funcall 2800 ["1-up" (pr-ps-buffer-preview 1 t) t]
3220 pr-:help "Use buffer interface instead of menu interface")] 2801 ["2-up" (pr-ps-buffer-preview 2 t) t]
2802 ["4-up" (pr-ps-buffer-preview 4 t) t]
2803 ["Other..." (pr-ps-buffer-preview nil t)
2804 :keys "\\[pr-ps-buffer-preview]"])
2805 ("Region" :active (and (not pr-spool-p) (ps-mark-active-p))
2806 ["1-up" (pr-ps-region-preview 1 t) t]
2807 ["2-up" (pr-ps-region-preview 2 t) t]
2808 ["4-up" (pr-ps-region-preview 4 t) t]
2809 ["Other..." (pr-ps-region-preview nil t)
2810 :keys "\\[pr-ps-region-preview]"])
2811 ("Mode" :active (and (not pr-spool-p) (pr-mode-alist-p))
2812 ["1-up" (pr-ps-mode-preview 1 t) t]
2813 ["2-up" (pr-ps-mode-preview 2 t) t]
2814 ["4-up" (pr-ps-mode-preview 4 t) t]
2815 ["Other..." (pr-ps-mode-preview nil t)
2816 :keys "\\[pr-ps-mode-preview]"])
2817 ("File"
2818 ["No Preprocessing..." (call-interactively 'pr-ps-file-preview)
2819 :keys "\\[pr-ps-file-preview]"
2820 :help "Preview PostScript file"]
3221 "--" 2821 "--"
3222 ("PostScript Preview" :included (pr-visible-p 'postscript) 2822 ["PostScript Utility" pr-update-menus :active pr-ps-utility-alist
3223 ,@(funcall 2823 :help "Select PostScript utility"]
3224 pr-:help "Preview PostScript instead of sending to printer")
3225 ("Directory" ,pr-:active (not pr-spool-p)
3226 ["1-up" (pr-ps-directory-preview 1 nil nil t) t]
3227 ["2-up" (pr-ps-directory-preview 2 nil nil t) t]
3228 ["4-up" (pr-ps-directory-preview 4 nil nil t) t]
3229 ["Other..." (pr-ps-directory-preview nil nil nil t)
3230 :keys "\\[pr-ps-buffer-preview]"])
3231 ("Buffer" ,pr-:active (not pr-spool-p)
3232 ["1-up" (pr-ps-buffer-preview 1 t) t]
3233 ["2-up" (pr-ps-buffer-preview 2 t) t]
3234 ["4-up" (pr-ps-buffer-preview 4 t) t]
3235 ["Other..." (pr-ps-buffer-preview nil t)
3236 :keys "\\[pr-ps-buffer-preview]"])
3237 ("Region" ,pr-:active (and (not pr-spool-p) (ps-mark-active-p))
3238 ["1-up" (pr-ps-region-preview 1 t) t]
3239 ["2-up" (pr-ps-region-preview 2 t) t]
3240 ["4-up" (pr-ps-region-preview 4 t) t]
3241 ["Other..." (pr-ps-region-preview nil t)
3242 :keys "\\[pr-ps-region-preview]"])
3243 ("Mode" ,pr-:active (and (not pr-spool-p) (pr-mode-alist-p))
3244 ["1-up" (pr-ps-mode-preview 1 t) t]
3245 ["2-up" (pr-ps-mode-preview 2 t) t]
3246 ["4-up" (pr-ps-mode-preview 4 t) t]
3247 ["Other..." (pr-ps-mode-preview nil t)
3248 :keys "\\[pr-ps-mode-preview]"])
3249 ("File"
3250 ["No Preprocessing..." (call-interactively 'pr-ps-file-preview)
3251 :keys "\\[pr-ps-file-preview]"
3252 ,@(funcall
3253 pr-:help "Preview PostScript file")]
3254 "--"
3255 ["PostScript Utility" pr-update-menus :active pr-ps-utility-alist
3256 ,@(funcall
3257 pr-:help "Select PostScript utility")]
3258 "--"
3259 ["1-up..." (pr-ps-file-up-preview 1 t t) pr-ps-utility-alist]
3260 ["2-up..." (pr-ps-file-up-preview 2 t t) pr-ps-utility-alist]
3261 ["4-up..." (pr-ps-file-up-preview 4 t t) pr-ps-utility-alist]
3262 ["Other..." (pr-ps-file-up-preview nil t t)
3263 :keys "\\[pr-ps-file-up-preview]" :active pr-ps-utility-alist]
3264 "--"
3265 ["Landscape" pr-toggle-file-landscape-menu
3266 :style toggle :selected pr-file-landscape
3267 ,@(funcall
3268 pr-:help "Toggle landscape for PostScript file")
3269 :active pr-ps-utility-alist]
3270 ["Duplex" pr-toggle-file-duplex-menu
3271 :style toggle :selected pr-file-duplex
3272 ,@(funcall
3273 pr-:help "Toggle duplex for PostScript file")
3274 :active pr-ps-utility-alist]
3275 ["Tumble" pr-toggle-file-tumble-menu
3276 :style toggle :selected pr-file-tumble
3277 ,@(funcall
3278 pr-:help "Toggle tumble for PostScript file")
3279 :active (and pr-file-duplex pr-ps-utility-alist)])
3280 ["Despool..." (call-interactively 'pr-despool-preview)
3281 :active pr-spool-p :keys "\\[pr-despool-preview]"
3282 ,@(funcall
3283 pr-:help "Despool PostScript buffer to printer or file (C-u)")])
3284 ("PostScript Print" :included (pr-visible-p 'postscript)
3285 ,@(funcall
3286 pr-:help "Send PostScript to printer or file (C-u)")
3287 ("Directory"
3288 ["1-up" (pr-ps-directory-ps-print 1 nil nil t) t]
3289 ["2-up" (pr-ps-directory-ps-print 2 nil nil t) t]
3290 ["4-up" (pr-ps-directory-ps-print 4 nil nil t) t]
3291 ["Other..." (pr-ps-directory-ps-print nil nil nil t)
3292 :keys "\\[pr-ps-buffer-ps-print]"])
3293 ("Buffer"
3294 ["1-up" (pr-ps-buffer-ps-print 1 t) t]
3295 ["2-up" (pr-ps-buffer-ps-print 2 t) t]
3296 ["4-up" (pr-ps-buffer-ps-print 4 t) t]
3297 ["Other..." (pr-ps-buffer-ps-print nil t)
3298 :keys "\\[pr-ps-buffer-ps-print]"])
3299 ("Region" ,pr-:active (ps-mark-active-p)
3300 ["1-up" (pr-ps-region-ps-print 1 t) t]
3301 ["2-up" (pr-ps-region-ps-print 2 t) t]
3302 ["4-up" (pr-ps-region-ps-print 4 t) t]
3303 ["Other..." (pr-ps-region-ps-print nil t)
3304 :keys "\\[pr-ps-region-ps-print]"])
3305 ("Mode" ,pr-:active (pr-mode-alist-p)
3306 ["1-up" (pr-ps-mode-ps-print 1 t) t]
3307 ["2-up" (pr-ps-mode-ps-print 2 t) t]
3308 ["4-up" (pr-ps-mode-ps-print 4 t) t]
3309 ["Other..." (pr-ps-mode-ps-print nil t)
3310 :keys "\\[pr-ps-mode-ps-print]"])
3311 ("File"
3312 ["No Preprocessing..." (call-interactively 'pr-ps-file-ps-print)
3313 :keys "\\[pr-ps-file-ps-print]"
3314 ,@(funcall
3315 pr-:help "Send PostScript file to printer")]
3316 "--"
3317 ["PostScript Utility" pr-update-menus :active pr-ps-utility-alist
3318 ,@(funcall
3319 pr-:help "Select PostScript utility")]
3320 "--"
3321 ["1-up..." (pr-ps-file-up-ps-print 1 t t) pr-ps-utility-alist]
3322 ["2-up..." (pr-ps-file-up-ps-print 2 t t) pr-ps-utility-alist]
3323 ["4-up..." (pr-ps-file-up-ps-print 4 t t) pr-ps-utility-alist]
3324 ["Other..." (pr-ps-file-up-ps-print nil t t)
3325 :keys "\\[pr-ps-file-up-ps-print]" :active pr-ps-utility-alist]
3326 "--"
3327 ["Landscape" pr-toggle-file-landscape-menu
3328 :style toggle :selected pr-file-landscape
3329 ,@(funcall
3330 pr-:help "Toggle landscape for PostScript file")
3331 :active pr-ps-utility-alist]
3332 ["Duplex" pr-toggle-file-duplex-menu
3333 :style toggle :selected pr-file-duplex
3334 ,@(funcall
3335 pr-:help "Toggle duplex for PostScript file")
3336 :active pr-ps-utility-alist]
3337 ["Tumble" pr-toggle-file-tumble-menu
3338 :style toggle :selected pr-file-tumble
3339 ,@(funcall
3340 pr-:help "Toggle tumble for PostScript file")
3341 :active (and pr-file-duplex pr-ps-utility-alist)])
3342 ["Despool..." (call-interactively 'pr-despool-ps-print)
3343 :active pr-spool-p :keys "\\[pr-despool-ps-print]"
3344 ,@(funcall
3345 pr-:help "Despool PostScript buffer to printer or file (C-u)")])
3346 ["PostScript Printers" pr-update-menus
3347 :active pr-ps-printer-alist :included (pr-visible-p 'postscript)
3348 ,@(funcall
3349 pr-:help "Select PostScript printer")]
3350 "--" 2824 "--"
3351 ("Printify" :included (pr-visible-p 'text) 2825 ["1-up..." (pr-ps-file-up-preview 1 t t) pr-ps-utility-alist]
3352 ,@(funcall 2826 ["2-up..." (pr-ps-file-up-preview 2 t t) pr-ps-utility-alist]
3353 pr-:help 2827 ["4-up..." (pr-ps-file-up-preview 4 t t) pr-ps-utility-alist]
3354 "Replace non-printing chars with printable representations.") 2828 ["Other..." (pr-ps-file-up-preview nil t t)
3355 ["Directory" pr-printify-directory t] 2829 :keys "\\[pr-ps-file-up-preview]" :active pr-ps-utility-alist]
3356 ["Buffer" pr-printify-buffer t]
3357 ["Region" pr-printify-region (ps-mark-active-p)])
3358 ("Print" :included (pr-visible-p 'text)
3359 ,@(funcall
3360 pr-:help "Send text to printer")
3361 ["Directory" pr-txt-directory t]
3362 ["Buffer" pr-txt-buffer t]
3363 ["Region" pr-txt-region (ps-mark-active-p)]
3364 ["Mode" pr-txt-mode (pr-mode-alist-p)])
3365 ["Text Printers" pr-update-menus
3366 :active pr-txt-printer-alist :included (pr-visible-p 'text)
3367 ,@(funcall
3368 pr-:help "Select text printer")]
3369 "--" 2830 "--"
3370 ["Landscape" pr-toggle-landscape-menu 2831 ["Landscape" pr-toggle-file-landscape-menu
3371 :style toggle :selected ps-landscape-mode 2832 :style toggle :selected pr-file-landscape
3372 :included (pr-visible-p 'postscript-options)] 2833 :help "Toggle landscape for PostScript file"
3373 ["Print Header" pr-toggle-header-menu 2834 :active pr-ps-utility-alist]
3374 :style toggle :selected ps-print-header 2835 ["Duplex" pr-toggle-file-duplex-menu
3375 :included (pr-visible-p 'postscript-options)] 2836 :style toggle :selected pr-file-duplex
3376 ["Print Header Frame" pr-toggle-header-frame-menu 2837 :help "Toggle duplex for PostScript file"
3377 :style toggle :selected ps-print-header-frame :active ps-print-header 2838 :active pr-ps-utility-alist]
3378 :included (pr-visible-p 'postscript-options)] 2839 ["Tumble" pr-toggle-file-tumble-menu
3379 ["Line Number" pr-toggle-line-menu 2840 :style toggle :selected pr-file-tumble
3380 :style toggle :selected ps-line-number 2841 :help "Toggle tumble for PostScript file"
3381 :included (pr-visible-p 'postscript-options)] 2842 :active (and pr-file-duplex pr-ps-utility-alist)])
3382 ["Zebra Stripes" pr-toggle-zebra-menu 2843 ["Despool..." (call-interactively 'pr-despool-preview)
3383 :style toggle :selected ps-zebra-stripes 2844 :active pr-spool-p :keys "\\[pr-despool-preview]"
3384 :included (pr-visible-p 'postscript-options)] 2845 :help "Despool PostScript buffer to printer or file (C-u)"])
3385 ["Duplex" pr-toggle-duplex-menu 2846 ("PostScript Print" :included (pr-visible-p 'postscript)
3386 :style toggle :selected ps-spool-duplex 2847 :help "Send PostScript to printer or file (C-u)"
3387 :included (pr-visible-p 'postscript-options)] 2848 ("Directory"
3388 ["Tumble" pr-toggle-tumble-menu 2849 ["1-up" (pr-ps-directory-ps-print 1 nil nil t) t]
3389 :style toggle :selected ps-spool-tumble :active ps-spool-duplex 2850 ["2-up" (pr-ps-directory-ps-print 2 nil nil t) t]
3390 :included (pr-visible-p 'postscript-options)] 2851 ["4-up" (pr-ps-directory-ps-print 4 nil nil t) t]
3391 ["Upside-Down" pr-toggle-upside-down-menu 2852 ["Other..." (pr-ps-directory-ps-print nil nil nil t)
3392 :style toggle :selected ps-print-upside-down 2853 :keys "\\[pr-ps-buffer-ps-print]"])
3393 :included (pr-visible-p 'postscript-options)] 2854 ("Buffer"
3394 ("Print All Pages" :included (pr-visible-p 'postscript-options) 2855 ["1-up" (pr-ps-buffer-ps-print 1 t) t]
3395 ,@(funcall 2856 ["2-up" (pr-ps-buffer-ps-print 2 t) t]
3396 pr-:help "Select odd/even pages/sheets to print") 2857 ["4-up" (pr-ps-buffer-ps-print 4 t) t]
3397 ["All Pages" (pr-even-or-odd-pages nil) 2858 ["Other..." (pr-ps-buffer-ps-print nil t)
3398 :style radio :selected (eq ps-even-or-odd-pages nil)] 2859 :keys "\\[pr-ps-buffer-ps-print]"])
3399 ["Even Pages" (pr-even-or-odd-pages 'even-page) 2860 ("Region" :active (ps-mark-active-p)
3400 :style radio :selected (eq ps-even-or-odd-pages 'even-page)] 2861 ["1-up" (pr-ps-region-ps-print 1 t) t]
3401 ["Odd Pages" (pr-even-or-odd-pages 'odd-page) 2862 ["2-up" (pr-ps-region-ps-print 2 t) t]
3402 :style radio :selected (eq ps-even-or-odd-pages 'odd-page)] 2863 ["4-up" (pr-ps-region-ps-print 4 t) t]
3403 ["Even Sheets" (pr-even-or-odd-pages 'even-sheet) 2864 ["Other..." (pr-ps-region-ps-print nil t)
3404 :style radio :selected (eq ps-even-or-odd-pages 'even-sheet)] 2865 :keys "\\[pr-ps-region-ps-print]"])
3405 ["Odd Sheets" (pr-even-or-odd-pages 'odd-sheet) 2866 ("Mode" :active (pr-mode-alist-p)
3406 :style radio :selected (eq ps-even-or-odd-pages 'odd-sheet)]) 2867 ["1-up" (pr-ps-mode-ps-print 1 t) t]
2868 ["2-up" (pr-ps-mode-ps-print 2 t) t]
2869 ["4-up" (pr-ps-mode-ps-print 4 t) t]
2870 ["Other..." (pr-ps-mode-ps-print nil t)
2871 :keys "\\[pr-ps-mode-ps-print]"])
2872 ("File"
2873 ["No Preprocessing..." (call-interactively 'pr-ps-file-ps-print)
2874 :keys "\\[pr-ps-file-ps-print]"
2875 :help "Send PostScript file to printer"]
3407 "--" 2876 "--"
3408 ["Spool Buffer" pr-toggle-spool-menu 2877 ["PostScript Utility" pr-update-menus :active pr-ps-utility-alist
3409 :style toggle :selected pr-spool-p 2878 :help "Select PostScript utility"]
3410 :included (pr-visible-p 'postscript-process)
3411 ,@(funcall
3412 pr-:help "Toggle PostScript spooling")]
3413 ["Print with faces" pr-toggle-faces-menu
3414 :style toggle :selected pr-faces-p
3415 :included (pr-visible-p 'postscript-process)
3416 ,@(funcall
3417 pr-:help "Toggle PostScript printing with faces")]
3418 ["Print via Ghostscript" pr-toggle-ghostscript-menu
3419 :style toggle :selected pr-print-using-ghostscript
3420 :included (pr-visible-p 'postscript-process)
3421 ,@(funcall
3422 pr-:help "Toggle PostScript generation using ghostscript")]
3423 "--" 2879 "--"
3424 ["Auto Region" pr-toggle-region-menu 2880 ["1-up..." (pr-ps-file-up-ps-print 1 t t) pr-ps-utility-alist]
3425 :style toggle :selected pr-auto-region 2881 ["2-up..." (pr-ps-file-up-ps-print 2 t t) pr-ps-utility-alist]
3426 :included (pr-visible-p 'printing)] 2882 ["4-up..." (pr-ps-file-up-ps-print 4 t t) pr-ps-utility-alist]
3427 ["Auto Mode" pr-toggle-mode-menu 2883 ["Other..." (pr-ps-file-up-ps-print nil t t)
3428 :style toggle :selected pr-auto-mode 2884 :keys "\\[pr-ps-file-up-ps-print]" :active pr-ps-utility-alist]
3429 :included (pr-visible-p 'printing)]
3430 ["Menu Lock" pr-toggle-lock-menu
3431 :style toggle :selected pr-menu-lock
3432 :included (pr-visible-p 'printing)]
3433 "--" 2885 "--"
3434 ("Customize" :included (pr-visible-p 'help) 2886 ["Landscape" pr-toggle-file-landscape-menu
3435 ["printing" pr-customize t] 2887 :style toggle :selected pr-file-landscape
3436 ["ps-print" ps-print-customize t] 2888 :help "Toggle landscape for PostScript file"
3437 ["lpr" lpr-customize t]) 2889 :active pr-ps-utility-alist]
3438 ("Show Settings" :included (pr-visible-p 'help) 2890 ["Duplex" pr-toggle-file-duplex-menu
3439 ["printing" pr-show-pr-setup t] 2891 :style toggle :selected pr-file-duplex
3440 ["ps-print" pr-show-ps-setup t] 2892 :help "Toggle duplex for PostScript file"
3441 ["lpr" pr-show-lpr-setup t]) 2893 :active pr-ps-utility-alist]
3442 ["Help" pr-help :active t :included (pr-visible-p 'help)] 2894 ["Tumble" pr-toggle-file-tumble-menu
3443 ))) 2895 :style toggle :selected pr-file-tumble
2896 :help "Toggle tumble for PostScript file"
2897 :active (and pr-file-duplex pr-ps-utility-alist)])
2898 ["Despool..." (call-interactively 'pr-despool-ps-print)
2899 :active pr-spool-p :keys "\\[pr-despool-ps-print]"
2900 :help "Despool PostScript buffer to printer or file (C-u)"])
2901 ["PostScript Printers" pr-update-menus
2902 :active pr-ps-printer-alist :included (pr-visible-p 'postscript)
2903 :help "Select PostScript printer"]
2904 "--"
2905 ("Printify" :included (pr-visible-p 'text)
2906 :help
2907 "Replace non-printing chars with printable representations."
2908 ["Directory" pr-printify-directory t]
2909 ["Buffer" pr-printify-buffer t]
2910 ["Region" pr-printify-region (ps-mark-active-p)])
2911 ("Print" :included (pr-visible-p 'text)
2912 :help "Send text to printer"
2913 ["Directory" pr-txt-directory t]
2914 ["Buffer" pr-txt-buffer t]
2915 ["Region" pr-txt-region (ps-mark-active-p)]
2916 ["Mode" pr-txt-mode (pr-mode-alist-p)])
2917 ["Text Printers" pr-update-menus
2918 :active pr-txt-printer-alist :included (pr-visible-p 'text)
2919 :help "Select text printer"]
2920 "--"
2921 ["Landscape" pr-toggle-landscape-menu
2922 :style toggle :selected ps-landscape-mode
2923 :included (pr-visible-p 'postscript-options)]
2924 ["Print Header" pr-toggle-header-menu
2925 :style toggle :selected ps-print-header
2926 :included (pr-visible-p 'postscript-options)]
2927 ["Print Header Frame" pr-toggle-header-frame-menu
2928 :style toggle :selected ps-print-header-frame :active ps-print-header
2929 :included (pr-visible-p 'postscript-options)]
2930 ["Line Number" pr-toggle-line-menu
2931 :style toggle :selected ps-line-number
2932 :included (pr-visible-p 'postscript-options)]
2933 ["Zebra Stripes" pr-toggle-zebra-menu
2934 :style toggle :selected ps-zebra-stripes
2935 :included (pr-visible-p 'postscript-options)]
2936 ["Duplex" pr-toggle-duplex-menu
2937 :style toggle :selected ps-spool-duplex
2938 :included (pr-visible-p 'postscript-options)]
2939 ["Tumble" pr-toggle-tumble-menu
2940 :style toggle :selected ps-spool-tumble :active ps-spool-duplex
2941 :included (pr-visible-p 'postscript-options)]
2942 ["Upside-Down" pr-toggle-upside-down-menu
2943 :style toggle :selected ps-print-upside-down
2944 :included (pr-visible-p 'postscript-options)]
2945 ("Print All Pages" :included (pr-visible-p 'postscript-options)
2946 :help "Select odd/even pages/sheets to print"
2947 ["All Pages" (pr-even-or-odd-pages nil)
2948 :style radio :selected (eq ps-even-or-odd-pages nil)]
2949 ["Even Pages" (pr-even-or-odd-pages 'even-page)
2950 :style radio :selected (eq ps-even-or-odd-pages 'even-page)]
2951 ["Odd Pages" (pr-even-or-odd-pages 'odd-page)
2952 :style radio :selected (eq ps-even-or-odd-pages 'odd-page)]
2953 ["Even Sheets" (pr-even-or-odd-pages 'even-sheet)
2954 :style radio :selected (eq ps-even-or-odd-pages 'even-sheet)]
2955 ["Odd Sheets" (pr-even-or-odd-pages 'odd-sheet)
2956 :style radio :selected (eq ps-even-or-odd-pages 'odd-sheet)])
2957 "--"
2958 ["Spool Buffer" pr-toggle-spool-menu
2959 :style toggle :selected pr-spool-p
2960 :included (pr-visible-p 'postscript-process)
2961 :help "Toggle PostScript spooling"]
2962 ["Print with faces" pr-toggle-faces-menu
2963 :style toggle :selected pr-faces-p
2964 :included (pr-visible-p 'postscript-process)
2965 :help "Toggle PostScript printing with faces"]
2966 ["Print via Ghostscript" pr-toggle-ghostscript-menu
2967 :style toggle :selected pr-print-using-ghostscript
2968 :included (pr-visible-p 'postscript-process)
2969 :help "Toggle PostScript generation using ghostscript"]
2970 "--"
2971 ["Auto Region" pr-toggle-region-menu
2972 :style toggle :selected pr-auto-region
2973 :included (pr-visible-p 'printing)]
2974 ["Auto Mode" pr-toggle-mode-menu
2975 :style toggle :selected pr-auto-mode
2976 :included (pr-visible-p 'printing)]
2977 ["Menu Lock" pr-toggle-lock-menu
2978 :style toggle :selected pr-menu-lock
2979 :included (pr-visible-p 'printing)]
2980 "--"
2981 ("Customize" :included (pr-visible-p 'help)
2982 ["printing" pr-customize t]
2983 ["ps-print" ps-print-customize t]
2984 ["lpr" lpr-customize t])
2985 ("Show Settings" :included (pr-visible-p 'help)
2986 ["printing" pr-show-pr-setup t]
2987 ["ps-print" pr-show-ps-setup t]
2988 ["lpr" pr-show-lpr-setup t])
2989 ["Help" pr-help :active t :included (pr-visible-p 'help)]
2990 ))
3444 2991
3445 2992
3446(defun pr-menu-bind () 2993(defun pr-menu-bind ()
@@ -3453,19 +3000,17 @@ Calls `pr-update-menus' to adjust menus."
3453 3000
3454 3001
3455;; Key binding 3002;; Key binding
3456(let ((pr-print-key (if (featurep 'xemacs) 3003;; FIXME: These should be moved to a function so that just loading the file
3457 'f22 ; XEmacs 3004;; doesn't affect the global keymap!
3458 'print))) ; GNU Emacs 3005(global-set-key [print] 'pr-ps-fast-fire)
3459 (global-set-key `[,pr-print-key] 'pr-ps-fast-fire) 3006;; Well, M-print and S-print are used because on my keyboard S-print works
3460 ;; Well, M-print and S-print are used because in my keyboard S-print works 3007;; and M-print doesn't. But M-print can work on other keyboards.
3461 ;; and M-print doesn't. But M-print can work in other keyboard. 3008(global-set-key [(meta print)] 'pr-ps-mode-using-ghostscript)
3462 (global-set-key `[(meta ,pr-print-key)] 'pr-ps-mode-using-ghostscript) 3009(global-set-key [(shift print)] 'pr-ps-mode-using-ghostscript)
3463 (global-set-key `[(shift ,pr-print-key)] 'pr-ps-mode-using-ghostscript) 3010;; Well, C-print and C-M-print are used because in my keyboard C-M-print works
3464 ;; Well, C-print and C-M-print are used because in my keyboard C-M-print works 3011;; and C-print doesn't. But C-print can work in other keyboard.
3465 ;; and C-print doesn't. But C-print can work in other keyboard. 3012(global-set-key [(control print)] 'pr-txt-fast-fire)
3466 (global-set-key `[(control ,pr-print-key)] 'pr-txt-fast-fire) 3013(global-set-key [(control meta print)] 'pr-txt-fast-fire)
3467 (global-set-key `[(control meta ,pr-print-key)] 'pr-txt-fast-fire))
3468
3469 3014
3470;;; You can also use something like: 3015;;; You can also use something like:
3471;;;(global-set-key "\C-ci" 'pr-interface) 3016;;;(global-set-key "\C-ci" 'pr-interface)
@@ -3962,13 +3507,16 @@ file name.
3962 3507
3963See also documentation for `pr-list-directory'." 3508See also documentation for `pr-list-directory'."
3964 (interactive (pr-interactive-ps-dir-args (pr-prompt "PS preview dir"))) 3509 (interactive (pr-interactive-ps-dir-args (pr-prompt "PS preview dir")))
3965 (pr-set-ps-dir-args 'n-up 'dir 'file-regexp 'filename 3510 (defvar pr--n-up) (defvar pr--dir) (defvar pr--file-regexp)
3966 (pr-prompt "PS preview dir")) 3511 (defvar pr--filename)
3967 (setq filename (pr-ps-file filename)) 3512 (let ((pr--n-up n-up) (pr--dir dir) (pr--file-regexp file-regexp)
3968 (pr-ps-file-list n-up dir file-regexp filename) 3513 (pr--filename filename))
3969 (or pr-spool-p 3514 (pr-set-ps-dir-args 'pr--n-up 'pr--dir 'pr--file-regexp 'pr--filename
3970 (pr-ps-file-preview filename))) 3515 (pr-prompt "PS preview dir"))
3971 3516 (setq pr--filename (pr-ps-file pr--filename))
3517 (pr-ps-file-list pr--n-up pr--dir pr--file-regexp pr--filename)
3518 (or pr-spool-p
3519 (pr-ps-file-preview pr--filename))))
3972 3520
3973;;;###autoload 3521;;;###autoload
3974(defun pr-ps-directory-using-ghostscript (n-up dir file-regexp &optional filename) 3522(defun pr-ps-directory-using-ghostscript (n-up dir file-regexp &optional filename)
@@ -3988,12 +3536,16 @@ file name.
3988 3536
3989See also documentation for `pr-list-directory'." 3537See also documentation for `pr-list-directory'."
3990 (interactive (pr-interactive-ps-dir-args (pr-prompt "PS print dir GS"))) 3538 (interactive (pr-interactive-ps-dir-args (pr-prompt "PS print dir GS")))
3991 (pr-set-ps-dir-args 'n-up 'dir 'file-regexp 'filename 3539 (defvar pr--n-up) (defvar pr--dir) (defvar pr--file-regexp)
3992 (pr-prompt "PS print dir GS")) 3540 (defvar pr--filename)
3993 (let ((file (pr-ps-file filename))) 3541 (let ((pr--n-up n-up) (pr--dir dir) (pr--file-regexp file-regexp)
3994 (pr-ps-file-list n-up dir file-regexp file) 3542 (pr--filename filename))
3995 (pr-ps-file-using-ghostscript file) 3543 (pr-set-ps-dir-args 'pr--n-up 'pr--dir 'pr--file-regexp 'pr--filename
3996 (or filename (pr-delete-file file)))) 3544 (pr-prompt "PS print dir GS"))
3545 (let ((file (pr-ps-file pr--filename)))
3546 (pr-ps-file-list pr--n-up pr--dir pr--file-regexp file)
3547 (pr-ps-file-using-ghostscript file)
3548 (or pr--filename (pr-delete-file file)))))
3997 3549
3998 3550
3999;;;###autoload 3551;;;###autoload
@@ -4014,12 +3566,16 @@ file name.
4014 3566
4015See also documentation for `pr-list-directory'." 3567See also documentation for `pr-list-directory'."
4016 (interactive (pr-interactive-ps-dir-args (pr-prompt "PS print dir"))) 3568 (interactive (pr-interactive-ps-dir-args (pr-prompt "PS print dir")))
4017 (pr-set-ps-dir-args 'n-up 'dir 'file-regexp 'filename 3569 (defvar pr--n-up) (defvar pr--dir) (defvar pr--file-regexp)
4018 (pr-prompt "PS print dir")) 3570 (defvar pr--filename)
4019 (let ((file (pr-ps-file filename))) 3571 (let ((pr--n-up n-up) (pr--dir dir) (pr--file-regexp file-regexp)
4020 (pr-ps-file-list n-up dir file-regexp file) 3572 (pr--filename filename))
4021 (pr-ps-file-print file) 3573 (pr-set-ps-dir-args 'pr--n-up 'pr--dir 'pr--file-regexp 'pr--filename
4022 (or filename (pr-delete-file file)))) 3574 (pr-prompt "PS print dir"))
3575 (let ((file (pr-ps-file pr--filename)))
3576 (pr-ps-file-list pr--n-up pr--dir pr--file-regexp file)
3577 (pr-ps-file-print file)
3578 (or pr--filename (pr-delete-file file)))))
4023 3579
4024 3580
4025;;;###autoload 3581;;;###autoload
@@ -4043,11 +3599,16 @@ file name.
4043See also documentation for `pr-list-directory'." 3599See also documentation for `pr-list-directory'."
4044 (interactive (pr-interactive-ps-dir-args 3600 (interactive (pr-interactive-ps-dir-args
4045 (pr-prompt (pr-prompt-gs "PS print dir")))) 3601 (pr-prompt (pr-prompt-gs "PS print dir"))))
4046 (pr-set-ps-dir-args 'n-up 'dir 'file-regexp 'filename 3602 (defvar pr--n-up) (defvar pr--dir) (defvar pr--file-regexp)
4047 (pr-prompt (pr-prompt-gs "PS print dir"))) 3603 (defvar pr--filename)
4048 (if (pr-using-ghostscript-p) 3604 (let ((pr--n-up n-up) (pr--dir dir) (pr--file-regexp file-regexp)
4049 (pr-ps-directory-using-ghostscript n-up dir file-regexp filename) 3605 (pr--filename filename))
4050 (pr-ps-directory-print n-up dir file-regexp filename))) 3606 (pr-set-ps-dir-args 'pr--n-up 'pr--dir 'pr--file-regexp 'pr--filename
3607 (pr-prompt (pr-prompt-gs "PS print dir")))
3608 (funcall (if (pr-using-ghostscript-p)
3609 #'pr-ps-directory-using-ghostscript
3610 #'pr-ps-directory-print)
3611 pr--n-up pr--dir pr--file-regexp pr--filename)))
4051 3612
4052 3613
4053;;;###autoload 3614;;;###autoload
@@ -4191,11 +3752,13 @@ See also `pr-ps-buffer-ps-print'."
4191 3752
4192See also `pr-ps-buffer-preview'." 3753See also `pr-ps-buffer-preview'."
4193 (interactive (pr-interactive-n-up-file "PS preview mode")) 3754 (interactive (pr-interactive-n-up-file "PS preview mode"))
4194 (pr-set-n-up-and-filename 'n-up 'filename "PS preview mode") 3755 (defvar pr--n-up) (defvar pr--filename)
4195 (let ((file (pr-ps-file filename))) 3756 (let ((pr--n-up n-up) (pr--filename filename))
4196 (and (pr-ps-mode n-up file) 3757 (pr-set-n-up-and-filename 'pr--n-up 'pr--filename "PS preview mode")
4197 (not pr-spool-p) 3758 (let ((file (pr-ps-file pr--filename)))
4198 (pr-ps-file-preview file)))) 3759 (and (pr-ps-mode pr--n-up file)
3760 (not pr-spool-p)
3761 (pr-ps-file-preview file)))))
4199 3762
4200 3763
4201;;;###autoload 3764;;;###autoload
@@ -4204,12 +3767,14 @@ See also `pr-ps-buffer-preview'."
4204 3767
4205See also `pr-ps-buffer-using-ghostscript'." 3768See also `pr-ps-buffer-using-ghostscript'."
4206 (interactive (pr-interactive-n-up-file "PS print GS mode")) 3769 (interactive (pr-interactive-n-up-file "PS print GS mode"))
4207 (pr-set-n-up-and-filename 'n-up 'filename "PS print GS mode") 3770 (defvar pr--n-up) (defvar pr--filename)
4208 (let ((file (pr-ps-file filename))) 3771 (let ((pr--n-up n-up) (pr--filename filename))
4209 (when (and (pr-ps-mode n-up file) 3772 (pr-set-n-up-and-filename 'pr--n-up 'pr--filename "PS print GS mode")
4210 (not pr-spool-p)) 3773 (let ((file (pr-ps-file pr--filename)))
4211 (pr-ps-file-using-ghostscript file) 3774 (when (and (pr-ps-mode pr--n-up file)
4212 (or filename (pr-delete-file file))))) 3775 (not pr-spool-p))
3776 (pr-ps-file-using-ghostscript file)
3777 (or pr--filename (pr-delete-file file))))))
4213 3778
4214 3779
4215;;;###autoload 3780;;;###autoload
@@ -4218,8 +3783,10 @@ See also `pr-ps-buffer-using-ghostscript'."
4218 3783
4219See also `pr-ps-buffer-print'." 3784See also `pr-ps-buffer-print'."
4220 (interactive (pr-interactive-n-up-file "PS print mode")) 3785 (interactive (pr-interactive-n-up-file "PS print mode"))
4221 (pr-set-n-up-and-filename 'n-up 'filename "PS print mode") 3786 (defvar pr--n-up) (defvar pr--filename)
4222 (pr-ps-mode n-up filename)) 3787 (let ((pr--n-up n-up) (pr--filename filename))
3788 (pr-set-n-up-and-filename 'pr--n-up 'pr--filename "PS print mode")
3789 (pr-ps-mode pr--n-up pr--filename)))
4223 3790
4224 3791
4225;;;###autoload 3792;;;###autoload
@@ -4247,8 +3814,10 @@ prompts for FILE(name)-REGEXP.
4247 3814
4248See also documentation for `pr-list-directory'." 3815See also documentation for `pr-list-directory'."
4249 (interactive (pr-interactive-dir-args "Printify dir")) 3816 (interactive (pr-interactive-dir-args "Printify dir"))
4250 (pr-set-dir-args 'dir 'file-regexp "Printify dir") 3817 (defvar pr--dir) (defvar pr--file-regexp)
4251 (pr-file-list dir file-regexp 'pr-printify-buffer)) 3818 (let ((pr--dir dir) (pr--file-regexp file-regexp))
3819 (pr-set-dir-args 'pr--dir 'pr--file-regexp "Printify dir")
3820 (pr-file-list pr--dir pr--file-regexp 'pr-printify-buffer)))
4252 3821
4253 3822
4254;;;###autoload 3823;;;###autoload
@@ -4283,8 +3852,10 @@ prompts for FILE(name)-REGEXP.
4283 3852
4284See also documentation for `pr-list-directory'." 3853See also documentation for `pr-list-directory'."
4285 (interactive (pr-interactive-dir-args "Print dir")) 3854 (interactive (pr-interactive-dir-args "Print dir"))
4286 (pr-set-dir-args 'dir 'file-regexp "Print dir") 3855 (defvar pr--dir) (defvar pr--file-regexp)
4287 (pr-file-list dir file-regexp 'pr-txt-buffer)) 3856 (let ((pr--dir dir) (pr--file-regexp file-regexp))
3857 (pr-set-dir-args 'pr--dir 'pr--file-regexp "Print dir")
3858 (pr-file-list pr--dir pr--file-regexp 'pr-txt-buffer)))
4288 3859
4289 3860
4290;;;###autoload 3861;;;###autoload
@@ -4406,10 +3977,12 @@ image in a file with that name."
4406(defun pr-ps-file-up-preview (n-up ifilename &optional ofilename) 3977(defun pr-ps-file-up-preview (n-up ifilename &optional ofilename)
4407 "Preview PostScript file FILENAME." 3978 "Preview PostScript file FILENAME."
4408 (interactive (pr-interactive-n-up-inout "PS preview")) 3979 (interactive (pr-interactive-n-up-inout "PS preview"))
4409 (let ((outfile (pr-ps-utility-args 'n-up 'ifilename 'ofilename 3980 (defvar pr--n-up) (defvar pr--ifilename) (defvar pr--ofilename)
4410 "PS preview "))) 3981 (let ((pr--n-up n-up) (pr--ifilename ifilename) (pr--ofilename ofilename))
4411 (pr-ps-utility-process n-up ifilename outfile) 3982 (let ((outfile (pr-ps-utility-args 'pr--n-up 'pr--ifilename 'pr--ofilename
4412 (pr-ps-file-preview outfile))) 3983 "PS preview ")))
3984 (pr-ps-utility-process pr--n-up pr--ifilename outfile)
3985 (pr-ps-file-preview outfile))))
4413 3986
4414 3987
4415;;;###autoload 3988;;;###autoload
@@ -4417,15 +3990,18 @@ image in a file with that name."
4417 "Print PostScript file FILENAME using ghostscript." 3990 "Print PostScript file FILENAME using ghostscript."
4418 (interactive (list (pr-ps-infile-preprint "Print preview "))) 3991 (interactive (list (pr-ps-infile-preprint "Print preview ")))
4419 (and (stringp filename) (file-exists-p filename) 3992 (and (stringp filename) (file-exists-p filename)
4420 (let* ((file (pr-expand-file-name filename)) 3993 (let* ((file (expand-file-name filename))
4421 (tempfile (pr-dosify-file-name (make-temp-file file)))) 3994 (tempfile (make-temp-file file)))
4422 ;; gs use 3995 ;; gs use
4423 (pr-call-process pr-gs-command 3996 (pr-call-process pr-gs-command
4424 (format "-sDEVICE=%s" pr-gs-device) 3997 (format "-sDEVICE=%s" pr-gs-device)
4425 (format "-r%d" pr-gs-resolution) 3998 (format "-r%d" pr-gs-resolution)
4426 (pr-switches-string pr-gs-switches "pr-gs-switches") 3999 (pr-switches-string pr-gs-switches "pr-gs-switches")
4427 (format "-sOutputFile=\"%s\"" tempfile) 4000 (format "-sOutputFile=\"%s\""
4428 file 4001 ;; FIXME: Do we need to dosify here really?
4002 (pr-dosify-file-name tempfile))
4003 ;; FIXME: Do we need to dosify here really?
4004 (pr-dosify-file-name file)
4429 "-c quit") 4005 "-c quit")
4430 ;; printing 4006 ;; printing
4431 (pr-ps-file-print tempfile) 4007 (pr-ps-file-print tempfile)
@@ -4439,7 +4015,7 @@ image in a file with that name."
4439 (interactive (list (pr-ps-infile-preprint "Print "))) 4015 (interactive (list (pr-ps-infile-preprint "Print ")))
4440 (and (stringp filename) (file-exists-p filename) 4016 (and (stringp filename) (file-exists-p filename)
4441 ;; printing 4017 ;; printing
4442 (let ((file (pr-expand-file-name filename))) 4018 (let ((file (expand-file-name filename)))
4443 (if (string= pr-ps-command "") 4019 (if (string= pr-ps-command "")
4444 ;; default action 4020 ;; default action
4445 (let ((ps-spool-buffer (get-buffer-create ps-spool-buffer-name))) 4021 (let ((ps-spool-buffer (get-buffer-create ps-spool-buffer-name)))
@@ -4448,16 +4024,16 @@ image in a file with that name."
4448 (insert-file-contents-literally file)) 4024 (insert-file-contents-literally file))
4449 (pr-despool-print)) 4025 (pr-despool-print))
4450 ;; use `pr-ps-command' to print 4026 ;; use `pr-ps-command' to print
4451 (apply 'pr-call-process 4027 (apply #'pr-call-process
4452 pr-ps-command 4028 pr-ps-command
4453 (pr-switches-string pr-ps-switches "pr-ps-switches") 4029 (pr-switches-string pr-ps-switches "pr-ps-switches")
4454 (if (string-match "cp" pr-ps-command) 4030 (if (string-match "cp" pr-ps-command)
4455 ;; for "cp" (cmd in out) 4031 ;; for "cp" (cmd in out)
4456 (list file 4032 (list (pr-dosify-file-name file)
4457 (concat pr-ps-printer-switch pr-ps-printer)) 4033 (concat pr-ps-printer-switch pr-ps-printer))
4458 ;; else, for others (cmd out in) 4034 ;; else, for others (cmd out in)
4459 (list (concat pr-ps-printer-switch pr-ps-printer) 4035 (list (concat pr-ps-printer-switch pr-ps-printer)
4460 file))))))) 4036 (pr-dosify-file-name file))))))))
4461 4037
4462 4038
4463;;;###autoload 4039;;;###autoload
@@ -4492,14 +4068,16 @@ file name."
4492 (if pr-print-using-ghostscript 4068 (if pr-print-using-ghostscript
4493 "PS print GS" 4069 "PS print GS"
4494 "PS print"))) 4070 "PS print")))
4495 (let ((outfile (pr-ps-utility-args 'n-up 'ifilename 'ofilename 4071 (defvar pr--n-up) (defvar pr--ifilename) (defvar pr--ofilename)
4496 (if pr-print-using-ghostscript 4072 (let ((pr--n-up n-up) (pr--ifilename ifilename) (pr--ofilename ofilename))
4497 "PS print GS " 4073 (let ((outfile (pr-ps-utility-args 'pr--n-up 'pr--ifilename 'pr--ofilename
4498 "PS print ")))) 4074 (if pr-print-using-ghostscript
4499 (pr-ps-utility-process n-up ifilename outfile) 4075 "PS print GS "
4500 (unless ofilename 4076 "PS print "))))
4501 (pr-ps-file-ps-print outfile) 4077 (pr-ps-utility-process pr--n-up pr--ifilename outfile)
4502 (pr-delete-file outfile)))) 4078 (unless pr--ofilename
4079 (pr-ps-file-ps-print outfile)
4080 (pr-delete-file outfile)))))
4503 4081
4504 4082
4505;;;###autoload 4083;;;###autoload
@@ -5210,9 +4788,9 @@ If menu binding was not done, calls `pr-menu-bind'."
5210 (let ((sym (car elt))) 4788 (let ((sym (car elt)))
5211 (vector 4789 (vector
5212 (symbol-name sym) 4790 (symbol-name sym)
5213 (list fun (list 'quote sym) nil (list 'quote entry) index) 4791 `(,fun ',sym nil ',entry ',index)
5214 :style 'radio 4792 :style 'radio
5215 :selected (list 'eq var-sym (list 'quote sym))))) 4793 :selected `(eq ,var-sym ',sym))))
5216 alist))) 4794 alist)))
5217 4795
5218 4796
@@ -5224,7 +4802,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5224 value)) 4802 value))
5225 (setq pr-ps-utility value) 4803 (setq pr-ps-utility value)
5226 (pr-eval-alist (nthcdr 9 item))) 4804 (pr-eval-alist (nthcdr 9 item)))
5227 (pr-update-mode-line)) 4805 (force-mode-line-update))
5228 4806
5229 4807
5230(defun pr-ps-set-printer (value) 4808(defun pr-ps-set-printer (value)
@@ -5234,7 +4812,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5234 "Invalid PostScript printer name `%s' for variable `pr-ps-name'" 4812 "Invalid PostScript printer name `%s' for variable `pr-ps-name'"
5235 value)) 4813 value))
5236 (setq pr-ps-name value 4814 (setq pr-ps-name value
5237 pr-ps-command (pr-dosify-file-name (nth 0 ps)) 4815 pr-ps-command (nth 0 ps)
5238 pr-ps-switches (nth 1 ps) 4816 pr-ps-switches (nth 1 ps)
5239 pr-ps-printer-switch (nth 2 ps) 4817 pr-ps-printer-switch (nth 2 ps)
5240 pr-ps-printer (nth 3 ps)) 4818 pr-ps-printer (nth 3 ps))
@@ -5251,7 +4829,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5251 (t "-P") 4829 (t "-P")
5252 ))) 4830 )))
5253 (pr-eval-alist (nthcdr 4 ps))) 4831 (pr-eval-alist (nthcdr 4 ps)))
5254 (pr-update-mode-line)) 4832 (force-mode-line-update))
5255 4833
5256 4834
5257(defun pr-txt-set-printer (value) 4835(defun pr-txt-set-printer (value)
@@ -5260,7 +4838,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5260 (error "Invalid text printer name `%s' for variable `pr-txt-name'" 4838 (error "Invalid text printer name `%s' for variable `pr-txt-name'"
5261 value)) 4839 value))
5262 (setq pr-txt-name value 4840 (setq pr-txt-name value
5263 pr-txt-command (pr-dosify-file-name (nth 0 txt)) 4841 pr-txt-command (nth 0 txt)
5264 pr-txt-switches (nth 1 txt) 4842 pr-txt-switches (nth 1 txt)
5265 pr-txt-printer (nth 2 txt))) 4843 pr-txt-printer (nth 2 txt)))
5266 (or (stringp pr-txt-command) 4844 (or (stringp pr-txt-command)
@@ -5269,30 +4847,28 @@ If menu binding was not done, calls `pr-menu-bind'."
5269 (lpr-lp-system "lp") 4847 (lpr-lp-system "lp")
5270 (t "lpr") 4848 (t "lpr")
5271 ))) 4849 )))
5272 (pr-update-mode-line)) 4850 (force-mode-line-update))
5273 4851
5274 4852
5275(defun pr-eval-alist (alist) 4853(defun pr-eval-alist (alist)
5276 (mapcar #'(lambda (option) 4854 (dolist (option alist)
5277 (let ((var-sym (car option)) 4855 (let ((var-sym (car option))
5278 (value (cdr option))) 4856 (value (cdr option)))
5279 (if (eq var-sym 'inherits-from:) 4857 (if (eq var-sym 'inherits-from:)
5280 (pr-eval-setting-alist value 'global) 4858 (pr-eval-setting-alist value 'global)
5281 (set var-sym (eval value))))) 4859 (set var-sym (eval value))))))
5282 alist))
5283 4860
5284 4861
5285(defun pr-eval-local-alist (alist) 4862(defun pr-eval-local-alist (alist)
5286 (let (local-list) 4863 (let (local-list)
5287 (mapc #'(lambda (option) 4864 (dolist (option alist)
5288 (let ((var-sym (car option)) 4865 (let ((var-sym (car option))
5289 (value (cdr option))) 4866 (value (cdr option)))
5290 (setq local-list 4867 (setq local-list
5291 (if (eq var-sym 'inherits-from:) 4868 (if (eq var-sym 'inherits-from:)
5292 (nconc (pr-eval-setting-alist value) local-list) 4869 (nconc (pr-eval-setting-alist value) local-list)
5293 (set (make-local-variable var-sym) (eval value)) 4870 (set (make-local-variable var-sym) (eval value))
5294 (cons var-sym local-list))))) 4871 (cons var-sym local-list)))))
5295 alist)
5296 local-list)) 4872 local-list))
5297 4873
5298 4874
@@ -5338,7 +4914,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5338 4914
5339 4915
5340(defun pr-kill-local-variable (local-var-list) 4916(defun pr-kill-local-variable (local-var-list)
5341 (mapcar 'kill-local-variable local-var-list)) 4917 (mapcar #'kill-local-variable local-var-list))
5342 4918
5343 4919
5344;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4920;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -5526,10 +5102,6 @@ If menu binding was not done, calls `pr-menu-bind'."
5526 (delete-file file))) 5102 (delete-file file)))
5527 5103
5528 5104
5529(defun pr-expand-file-name (filename)
5530 (pr-dosify-file-name (expand-file-name filename)))
5531
5532
5533(defun pr-ps-outfile-preprint (&optional mess) 5105(defun pr-ps-outfile-preprint (&optional mess)
5534 (let* ((prompt (format "%soutput PostScript file name: " (or mess ""))) 5106 (let* ((prompt (format "%soutput PostScript file name: " (or mess "")))
5535 (res (read-file-name prompt default-directory "" nil))) 5107 (res (read-file-name prompt default-directory "" nil)))
@@ -5549,7 +5121,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5549 (format "File %s; PostScript file: " prompt) 5121 (format "File %s; PostScript file: " prompt)
5550 (file-name-directory res) nil nil 5122 (file-name-directory res) nil nil
5551 (file-name-nondirectory res)))) 5123 (file-name-nondirectory res))))
5552 (pr-expand-file-name res))) 5124 (expand-file-name res)))
5553 5125
5554 5126
5555(defun pr-ps-infile-preprint (&optional mess) 5127(defun pr-ps-infile-preprint (&optional mess)
@@ -5569,7 +5141,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5569 (format "File %s; PostScript file: " prompt) 5141 (format "File %s; PostScript file: " prompt)
5570 (file-name-directory res) nil nil 5142 (file-name-directory res) nil nil
5571 (file-name-nondirectory res)))) 5143 (file-name-nondirectory res))))
5572 (pr-expand-file-name res))) 5144 (expand-file-name res)))
5573 5145
5574 5146
5575(defun pr-ps-utility-args (n-up-sym infile-sym outfile-sym prompt) 5147(defun pr-ps-utility-args (n-up-sym infile-sym outfile-sym prompt)
@@ -5582,13 +5154,10 @@ If menu binding was not done, calls `pr-menu-bind'."
5582 (set infile-sym (pr-ps-infile-preprint prompt))) 5154 (set infile-sym (pr-ps-infile-preprint prompt)))
5583 (or (symbol-value infile-sym) 5155 (or (symbol-value infile-sym)
5584 (error "%s: input PostScript file name is missing" prompt)) 5156 (error "%s: input PostScript file name is missing" prompt))
5585 (set infile-sym (pr-dosify-file-name (symbol-value infile-sym)))
5586 ;; output file 5157 ;; output file
5587 (and (eq (symbol-value outfile-sym) t) 5158 (and (eq (symbol-value outfile-sym) t)
5588 (set outfile-sym (and current-prefix-arg 5159 (set outfile-sym (and current-prefix-arg
5589 (pr-ps-outfile-preprint prompt)))) 5160 (pr-ps-outfile-preprint prompt))))
5590 (and (symbol-value outfile-sym)
5591 (set outfile-sym (pr-dosify-file-name (symbol-value outfile-sym))))
5592 (pr-ps-file (symbol-value outfile-sym))) 5161 (pr-ps-file (symbol-value outfile-sym)))
5593 5162
5594 5163
@@ -5608,9 +5177,9 @@ If menu binding was not done, calls `pr-menu-bind'."
5608 (and pr-file-landscape (nth 4 item)) 5177 (and pr-file-landscape (nth 4 item))
5609 (and pr-file-duplex (nth 5 item)) 5178 (and pr-file-duplex (nth 5 item))
5610 (and pr-file-tumble (nth 6 item)) 5179 (and pr-file-tumble (nth 6 item))
5611 (pr-expand-file-name infile) 5180 (pr-dosify-file-name (expand-file-name infile))
5612 (nth 7 item) 5181 (nth 7 item)
5613 (pr-expand-file-name outfile))))) 5182 (pr-dosify-file-name (expand-file-name outfile))))))
5614 5183
5615 5184
5616(defun pr-remove-nil-from-list (lst) 5185(defun pr-remove-nil-from-list (lst)
@@ -5640,7 +5209,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5640 (with-file-modes pr-file-modes 5209 (with-file-modes pr-file-modes
5641 (setq status 5210 (setq status
5642 (condition-case data 5211 (condition-case data
5643 (apply 'call-process cmd nil buffer nil args) 5212 (apply #'call-process cmd nil buffer nil args)
5644 ((quit error) 5213 ((quit error)
5645 (error-message-string data))))) 5214 (error-message-string data)))))
5646 ;; *Printing Command Output* == show exit status 5215 ;; *Printing Command Output* == show exit status
@@ -5666,7 +5235,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5666 ;; If SWITCHES is nil, return nil. 5235 ;; If SWITCHES is nil, return nil.
5667 ;; Otherwise, return the list of string in a string. 5236 ;; Otherwise, return the list of string in a string.
5668 (and switches 5237 (and switches
5669 (mapconcat 'identity (pr-switches switches mess) " "))) 5238 (mapconcat #'identity (pr-switches switches mess) " ")))
5670 5239
5671 5240
5672(defun pr-switches (switches mess) 5241(defun pr-switches (switches mess)
@@ -5677,36 +5246,42 @@ If menu binding was not done, calls `pr-menu-bind'."
5677 5246
5678 5247
5679(defun pr-ps-preview (kind n-up filename mess) 5248(defun pr-ps-preview (kind n-up filename mess)
5680 (pr-set-n-up-and-filename 'n-up 'filename mess) 5249 (defvar pr--n-up) (defvar pr--filename)
5681 (let ((file (pr-ps-file filename))) 5250 (let ((pr--n-up n-up) (pr--filename filename))
5682 (pr-text2ps kind n-up file) 5251 (pr-set-n-up-and-filename 'pr--n-up 'pr--filename mess)
5683 (or pr-spool-p (pr-ps-file-preview file)))) 5252 (let ((file (pr-ps-file pr--filename)))
5253 (pr-text2ps kind pr--n-up file)
5254 (or pr-spool-p (pr-ps-file-preview file)))))
5684 5255
5685 5256
5686(defun pr-ps-using-ghostscript (kind n-up filename mess) 5257(defun pr-ps-using-ghostscript (kind n-up filename mess)
5687 (pr-set-n-up-and-filename 'n-up 'filename mess) 5258 (defvar pr--n-up) (defvar pr--filename)
5688 (let ((file (pr-ps-file filename))) 5259 (let ((pr--n-up n-up) (pr--filename filename))
5689 (pr-text2ps kind n-up file) 5260 (pr-set-n-up-and-filename 'pr--n-up 'pr--filename mess)
5690 (unless (or pr-spool-p filename) 5261 (let ((file (pr-ps-file pr--filename)))
5691 (pr-ps-file-using-ghostscript file) 5262 (pr-text2ps kind pr--n-up file)
5692 (pr-delete-file file)))) 5263 (unless (or pr-spool-p pr--filename)
5264 (pr-ps-file-using-ghostscript file)
5265 (pr-delete-file file)))))
5693 5266
5694 5267
5695(defun pr-ps-print (kind n-up filename mess) 5268(defun pr-ps-print (kind n-up filename mess)
5696 (pr-set-n-up-and-filename 'n-up 'filename mess) 5269 (defvar pr--n-up) (defvar pr--filename)
5697 (let ((file (pr-ps-file filename))) 5270 (let ((pr--n-up n-up) (pr--filename filename))
5698 (pr-text2ps kind n-up file) 5271 (pr-set-n-up-and-filename 'pr--n-up 'pr--filename mess)
5699 (unless (or pr-spool-p filename) 5272 (let ((file (pr-ps-file pr--filename)))
5700 (pr-ps-file-print file) 5273 (pr-text2ps kind pr--n-up file)
5701 (pr-delete-file file)))) 5274 (unless (or pr-spool-p pr--filename)
5275 (pr-ps-file-print file)
5276 (pr-delete-file file)))))
5702 5277
5703 5278
5704(defun pr-ps-file (&optional filename) 5279(defun pr-ps-file (&optional filename)
5705 (pr-dosify-file-name (or filename 5280 (or filename
5706 (make-temp-file 5281 (make-temp-file
5707 (convert-standard-filename 5282 (convert-standard-filename
5708 (expand-file-name pr-ps-temp-file pr-temp-dir)) 5283 (expand-file-name pr-ps-temp-file pr-temp-dir))
5709 nil ".ps")))) 5284 nil ".ps")))
5710 5285
5711 5286
5712(defun pr-interactive-n-up (mess) 5287(defun pr-interactive-n-up (mess)
@@ -5714,7 +5289,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5714 (save-match-data 5289 (save-match-data
5715 (let* ((fmt-prompt "%s[%s] N-up printing (default 1): ") 5290 (let* ((fmt-prompt "%s[%s] N-up printing (default 1): ")
5716 (prompt "") 5291 (prompt "")
5717 (str (pr-read-string (format fmt-prompt prompt mess) "1" nil "1")) 5292 (str (read-string (format fmt-prompt prompt mess) nil nil "1"))
5718 int) 5293 int)
5719 (while (if (string-match "^\\s *[0-9]+$" str) 5294 (while (if (string-match "^\\s *[0-9]+$" str)
5720 (setq int (string-to-number str) 5295 (setq int (string-to-number str)
@@ -5724,7 +5299,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5724 (setq prompt "Invalid integer syntax; ")) 5299 (setq prompt "Invalid integer syntax; "))
5725 (ding) 5300 (ding)
5726 (setq str 5301 (setq str
5727 (pr-read-string (format fmt-prompt prompt mess) str nil "1"))) 5302 (read-string (format fmt-prompt prompt mess) str nil "1")))
5728 int))) 5303 int)))
5729 5304
5730 5305
@@ -5749,7 +5324,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5749 5324
5750 5325
5751(defun pr-interactive-regexp (mess) 5326(defun pr-interactive-regexp (mess)
5752 (pr-read-string (format "[%s] File regexp to print: " mess) "" nil "")) 5327 (read-string (format "[%s] File regexp to print: " mess) nil nil ""))
5753 5328
5754 5329
5755(defun pr-interactive-dir-args (mess) 5330(defun pr-interactive-dir-args (mess)
@@ -5796,9 +5371,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5796 (and (not pr-spool-p) 5371 (and (not pr-spool-p)
5797 (eq (symbol-value filename-sym) t) 5372 (eq (symbol-value filename-sym) t)
5798 (set filename-sym (and current-prefix-arg 5373 (set filename-sym (and current-prefix-arg
5799 (ps-print-preprint current-prefix-arg)))) 5374 (ps-print-preprint current-prefix-arg)))))
5800 (and (symbol-value filename-sym)
5801 (set filename-sym (pr-dosify-file-name (symbol-value filename-sym)))))
5802 5375
5803 5376
5804(defun pr-set-n-up-and-filename (n-up-sym filename-sym mess) 5377(defun pr-set-n-up-and-filename (n-up-sym filename-sym mess)
@@ -5875,7 +5448,7 @@ If menu binding was not done, calls `pr-menu-bind'."
5875 5448
5876 5449
5877(defun pr-ps-file-list (n-up dir file-regexp filename) 5450(defun pr-ps-file-list (n-up dir file-regexp filename)
5878 (pr-delete-file-if-exists (setq filename (pr-expand-file-name filename))) 5451 (pr-delete-file-if-exists (setq filename (expand-file-name filename)))
5879 (let ((pr-spool-p t)) 5452 (let ((pr-spool-p t))
5880 (pr-file-list dir file-regexp 5453 (pr-file-list dir file-regexp
5881 #'(lambda () 5454 #'(lambda ()
@@ -5941,15 +5514,14 @@ If Emacs is running on Windows 95/98/NT/2000, tries to find COMMAND,
5941COMMAND.exe, COMMAND.bat and COMMAND.com in this order." 5514COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
5942 (if (string= command "") 5515 (if (string= command "")
5943 command 5516 command
5944 (pr-dosify-file-name 5517 (or (pr-find-command command)
5945 (or (pr-find-command command) 5518 (pr-path-command (cond (pr-cygwin-system 'cygwin)
5946 (pr-path-command (cond (pr-cygwin-system 'cygwin) 5519 (lpr-windows-system 'windows)
5947 (lpr-windows-system 'windows) 5520 (t 'unix))
5948 (t 'unix)) 5521 (file-name-nondirectory command)
5949 (file-name-nondirectory command) 5522 nil)
5950 nil) 5523 (error "Command not found: %s"
5951 (error "Command not found: %s" 5524 (file-name-nondirectory command)))))
5952 (file-name-nondirectory command))))))
5953 5525
5954 5526
5955(defun pr-path-command (symbol command sym-list) 5527(defun pr-path-command (symbol command sym-list)
@@ -6004,12 +5576,6 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
6004;; Printing Interface (inspired by ps-print-interface.el) 5576;; Printing Interface (inspired by ps-print-interface.el)
6005 5577
6006 5578
6007(eval-when-compile
6008 (require 'cus-edit)
6009 (require 'wid-edit)
6010 (require 'widget))
6011
6012
6013(defvar pr-i-window-configuration nil) 5579(defvar pr-i-window-configuration nil)
6014 5580
6015(defvar pr-i-buffer nil) 5581(defvar pr-i-buffer nil)
@@ -6027,20 +5593,13 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
6027(defvar pr-i-ps-send 'printer) 5593(defvar pr-i-ps-send 'printer)
6028 5594
6029 5595
6030(defvar pr-interface-map nil 5596(defvar pr-interface-map
6031 "Keymap for pr-interface.")
6032
6033(unless pr-interface-map
6034 (let ((map (make-sparse-keymap))) 5597 (let ((map (make-sparse-keymap)))
6035 (cond ((featurep 'xemacs) ; XEmacs 5598 (set-keymap-parent map widget-keymap)
6036 (pr-set-keymap-parents map (list widget-keymap))
6037 (pr-set-keymap-name map 'pr-interface-map))
6038 (t ; GNU Emacs
6039 (pr-set-keymap-parents map widget-keymap)))
6040 (define-key map "q" 'pr-interface-quit) 5599 (define-key map "q" 'pr-interface-quit)
6041 (define-key map "?" 'pr-interface-help) 5600 (define-key map "?" 'pr-interface-help)
6042 (setq pr-interface-map map))) 5601 map)
6043 5602 "Keymap for pr-interface.")
6044 5603
6045(defmacro pr-interface-save (&rest body) 5604(defmacro pr-interface-save (&rest body)
6046 `(with-current-buffer pr-i-buffer 5605 `(with-current-buffer pr-i-buffer
@@ -6111,15 +5670,13 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
6111 (setq found (string-match (car ignore) name) 5670 (setq found (string-match (car ignore) name)
6112 ignore (cdr ignore))) 5671 ignore (cdr ignore)))
6113 (or found 5672 (or found
6114 (setq choices 5673 (push (list 'choice-item
6115 (cons (list 'quote 5674 :format "%[%t%]"
6116 (list 'choice-item 5675 name)
6117 :format "%[%t%]" 5676 choices))))
6118 name))
6119 choices)))))
6120 (nreverse choices)) 5677 (nreverse choices))
6121 " Buffer : " nil 5678 " Buffer : " nil
6122 '(progn 5679 (lambda ()
6123 (pr-interface-save 5680 (pr-interface-save
6124 (setq pr-i-region (ps-mark-active-p) 5681 (setq pr-i-region (ps-mark-active-p)
6125 pr-i-mode (pr-mode-alist-p))) 5682 pr-i-mode (pr-mode-alist-p)))
@@ -6345,11 +5902,10 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
6345 (pr-insert-italic "\n\nSelect Pages : " 2 14) 5902 (pr-insert-italic "\n\nSelect Pages : " 2 14)
6346 (pr-insert-menu "Page Parity" 'ps-even-or-odd-pages 5903 (pr-insert-menu "Page Parity" 'ps-even-or-odd-pages
6347 (mapcar #'(lambda (alist) 5904 (mapcar #'(lambda (alist)
6348 (list 'quote 5905 (list 'choice-item
6349 (list 'choice-item 5906 :format "%[%t%]"
6350 :format "%[%t%]" 5907 :tag (cdr alist)
6351 :tag (cdr alist) 5908 :value (car alist)))
6352 :value (car alist))))
6353 pr-even-or-odd-alist))) 5909 pr-even-or-odd-alist)))
6354 5910
6355 5911
@@ -6605,8 +6161,8 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
6605 6161
6606(defun pr-insert-toggle (var-sym label) 6162(defun pr-insert-toggle (var-sym label)
6607 (widget-create 'checkbox 6163 (widget-create 'checkbox
6608 :notify `(lambda (&rest _ignore) 6164 :notify (lambda (&rest _ignore)
6609 (setq ,var-sym (not ,var-sym))) 6165 (set var-sym (not (symbol-value var-sym))))
6610 (symbol-value var-sym)) 6166 (symbol-value var-sym))
6611 (widget-insert label)) 6167 (widget-insert label))
6612 6168
@@ -6619,32 +6175,32 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
6619 (widget-insert separator))) 6175 (widget-insert separator)))
6620 6176
6621 6177
6622(defun pr-insert-menu (tag var-sym choices &optional before after &rest body) 6178(defun pr-insert-menu (tag var-sym choices &optional before after body)
6623 (and before (widget-insert before)) 6179 (and before (widget-insert before))
6624 (eval `(widget-create 'menu-choice 6180 (apply #'widget-create 'menu-choice
6625 :tag ,tag 6181 :tag tag
6626 :format "%v" 6182 :format "%v"
6627 :inline t 6183 :inline t
6628 :value ,var-sym 6184 :value (symbol-value var-sym)
6629 :notify (lambda (widget &rest _ignore) 6185 :notify (lambda (widget &rest _ignore)
6630 (setq ,var-sym (widget-value widget)) 6186 (set var-sym (widget-value widget))
6631 ,@body) 6187 (when body (funcall body)))
6632 :void '(choice-item :format "%[%t%]" 6188 :void '(choice-item :format "%[%t%]"
6633 :tag "Can not display value!") 6189 :tag "Can not display value!")
6634 ,@choices)) 6190 choices)
6635 (and after (widget-insert after))) 6191 (and after (widget-insert after)))
6636 6192
6637 6193
6638(defun pr-insert-radio-button (var-sym sym) 6194(defun pr-insert-radio-button (var-sym sym)
6639 (widget-insert "\n") 6195 (widget-insert "\n")
6640 (let ((wid-list (get var-sym 'pr-widget-list)) 6196 (let ((wid-list (get var-sym 'pr-widget-list))
6641 (wid (eval `(widget-create 6197 (wid (widget-create
6642 'radio-button 6198 'radio-button
6643 :format " %[%v%]" 6199 :format " %[%v%]"
6644 :value (eq ,var-sym (quote ,sym)) 6200 :value (eq (symbol-value var-sym) sym)
6645 :notify (lambda (&rest _ignore) 6201 :notify (lambda (&rest _ignore)
6646 (setq ,var-sym (quote ,sym)) 6202 (set var-sym sym)
6647 (pr-update-radio-button (quote ,var-sym))))))) 6203 (pr-update-radio-button var-sym)))))
6648 (put var-sym 'pr-widget-list (cons (cons wid sym) wid-list)))) 6204 (put var-sym 'pr-widget-list (cons (cons wid sym) wid-list))))
6649 6205
6650 6206
@@ -6666,20 +6222,18 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
6666 6222
6667 6223
6668(defun pr-choice-alist (alist) 6224(defun pr-choice-alist (alist)
6669 (let ((max (apply 'max (mapcar #'(lambda (alist) 6225 (let ((max (apply #'max (mapcar #'(lambda (alist)
6670 (length (symbol-name (car alist)))) 6226 (length (symbol-name (car alist))))
6671 alist)))) 6227 alist))))
6672 (mapcar #'(lambda (alist) 6228 (mapcar #'(lambda (alist)
6673 (let* ((sym (car alist)) 6229 (let* ((sym (car alist))
6674 (name (symbol-name sym))) 6230 (name (symbol-name sym)))
6675 (list 6231 (list
6676 'quote 6232 'choice-item
6677 (list 6233 :format "%[%t%]"
6678 'choice-item 6234 :tag (concat name
6679 :format "%[%t%]" 6235 (make-string (- max (length name)) ?_))
6680 :tag (concat name 6236 :value sym)))
6681 (make-string (- max (length name)) ?_))
6682 :value sym))))
6683 alist))) 6237 alist)))
6684 6238
6685 6239
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index 759db1f5686..813ecbe3847 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -1,4 +1,4 @@
1;; bug-reference.el --- buttonize bug references 1;; bug-reference.el --- buttonize bug references -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 2008-2019 Free Software Foundation, Inc. 3;; Copyright (C) 2008-2019 Free Software Foundation, Inc.
4 4
@@ -91,7 +91,7 @@ The second subexpression should match the bug reference (usually a number)."
91(bug-reference-set-overlay-properties) 91(bug-reference-set-overlay-properties)
92 92
93(defun bug-reference-unfontify (start end) 93(defun bug-reference-unfontify (start end)
94 "Remove bug reference overlays from region." 94 "Remove bug reference overlays from the region between START and END."
95 (dolist (o (overlays-in start end)) 95 (dolist (o (overlays-in start end))
96 (when (eq (overlay-get o 'category) 'bug-reference) 96 (when (eq (overlay-get o 'category) 'bug-reference)
97 (delete-overlay o)))) 97 (delete-overlay o))))
@@ -99,7 +99,7 @@ The second subexpression should match the bug reference (usually a number)."
99(defvar bug-reference-prog-mode) 99(defvar bug-reference-prog-mode)
100 100
101(defun bug-reference-fontify (start end) 101(defun bug-reference-fontify (start end)
102 "Apply bug reference overlays to region." 102 "Apply bug reference overlays to the region between START and END."
103 (save-excursion 103 (save-excursion
104 (let ((beg-line (progn (goto-char start) (line-beginning-position))) 104 (let ((beg-line (progn (goto-char start) (line-beginning-position)))
105 (end-line (progn (goto-char end) (line-end-position)))) 105 (end-line (progn (goto-char end) (line-end-position))))
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 5bfb0bf9018..1a0d9bdbb70 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -562,7 +562,7 @@ LINE, END-LINE, COL, and END-COL can also be functions of no argument
562that return the corresponding line or column number. They can assume REGEXP 562that return the corresponding line or column number. They can assume REGEXP
563has just been matched, and should correspondingly preserve this match data. 563has just been matched, and should correspondingly preserve this match data.
564 564
565f/usr/shaTYPE is 2 or nil for a real error or 1 for warning or 0 for info. 565TYPE is 2 or nil for a real error or 1 for warning or 0 for info.
566TYPE can also be of the form (WARNING . INFO). In that case this 566TYPE can also be of the form (WARNING . INFO). In that case this
567will be equivalent to 1 if the WARNING'th subexpression matched 567will be equivalent to 1 if the WARNING'th subexpression matched
568or else equivalent to 0 if the INFO'th subexpression matched. 568or else equivalent to 0 if the INFO'th subexpression matched.
@@ -2056,8 +2056,7 @@ by replacing the first word, e.g., `compilation-scroll-output' from
2056 (if (boundp 'byte-compile-bound-variables) 2056 (if (boundp 'byte-compile-bound-variables)
2057 (memq (cdr v) byte-compile-bound-variables))) 2057 (memq (cdr v) byte-compile-bound-variables)))
2058 `(set (make-local-variable ',(car v)) ,(cdr v)))) 2058 `(set (make-local-variable ',(car v)) ,(cdr v))))
2059 '(compilation-buffer-name-function 2059 '(compilation-directory-matcher
2060 compilation-directory-matcher
2061 compilation-error 2060 compilation-error
2062 compilation-error-regexp-alist 2061 compilation-error-regexp-alist
2063 compilation-error-regexp-alist-alist 2062 compilation-error-regexp-alist-alist
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index c0f47159c95..8c7a58fd8bd 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -959,8 +959,16 @@ substitution string. Note dynamic scoping of variables.")
959The pattern can include shell wildcards. As whitespace triggers 959The pattern can include shell wildcards. As whitespace triggers
960completion when entering a pattern, including it requires 960completion when entering a pattern, including it requires
961quoting, e.g. `\\[quoted-insert]<space>'." 961quoting, e.g. `\\[quoted-insert]<space>'."
962 (let* ((bn (or (buffer-file-name) 962 (let* ((grep-read-files-function (get major-mode 'grep-read-files))
963 (replace-regexp-in-string "<[0-9]+>\\'" "" (buffer-name)))) 963 (file-name-at-point
964 (run-hook-with-args-until-success 'file-name-at-point-functions))
965 (bn (if grep-read-files-function
966 (funcall grep-read-files-function)
967 (or (if (and (stringp file-name-at-point)
968 (not (file-directory-p file-name-at-point)))
969 file-name-at-point)
970 (buffer-file-name)
971 (replace-regexp-in-string "<[0-9]+>\\'" "" (buffer-name)))))
964 (fn (and bn 972 (fn (and bn
965 (stringp bn) 973 (stringp bn)
966 (file-name-nondirectory bn))) 974 (file-name-nondirectory bn)))
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 4d91da73340..a0adaa84eeb 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -50,7 +50,6 @@
50(require 'imenu) 50(require 'imenu)
51(require 'moz nil t) 51(require 'moz nil t)
52(require 'json) 52(require 'json)
53(require 'sgml-mode)
54(require 'prog-mode) 53(require 'prog-mode)
55 54
56(eval-when-compile 55(eval-when-compile
@@ -66,7 +65,7 @@
66 65
67;;; Constants 66;;; Constants
68 67
69(defconst js--name-start-re "[a-zA-Z_$]" 68(defconst js--name-start-re (concat "[[:alpha:]_$]")
70 "Regexp matching the start of a JavaScript identifier, without grouping.") 69 "Regexp matching the start of a JavaScript identifier, without grouping.")
71 70
72(defconst js--stmt-delim-chars "^;{}?:") 71(defconst js--stmt-delim-chars "^;{}?:")
@@ -572,6 +571,119 @@ then the \".\"s will be lined up:
572 :safe 'booleanp 571 :safe 'booleanp
573 :group 'js) 572 :group 'js)
574 573
574(defcustom js-jsx-detect-syntax t
575 "When non-nil, automatically detect whether JavaScript uses JSX.
576`js-jsx-syntax' (which see) may be made buffer-local and set to
577t. The detection strategy can be customized by adding elements
578to `js-jsx-regexps', which see."
579 :version "27.1"
580 :type 'boolean
581 :safe 'booleanp
582 :group 'js)
583
584(defcustom js-jsx-syntax nil
585 "When non-nil, parse JavaScript with consideration for JSX syntax.
586
587This enables proper font-locking and indentation of code using
588Facebook’s “JSX” syntax extension for JavaScript, for use with
589Facebook’s “React” library. Font-locking is like sgml-mode.
590Indentation is also like sgml-mode, although some indentation
591behavior may differ slightly to align more closely with the
592conventions of the React developer community.
593
594When `js-mode' is already enabled, you should call
595`js-jsx-enable' to set this variable.
596
597It is set to be buffer-local (and t) when in `js-jsx-mode'."
598 :version "27.1"
599 :type 'boolean
600 :safe 'booleanp
601 :group 'js)
602
603(defcustom js-jsx-align->-with-< t
604 "When non-nil, “>” will be indented to the opening “<” in JSX.
605
606When this is enabled, JSX indentation looks like this:
607
608 <element
609 attr=\"\"
610 >
611 </element>
612 <input
613 />
614
615When this is disabled, JSX indentation looks like this:
616
617 <element
618 attr=\"\"
619 >
620 </element>
621 <input
622 />"
623 :version "27.1"
624 :type 'boolean
625 :safe 'booleanp
626 :group 'js)
627
628(defcustom js-jsx-indent-level nil
629 "When non-nil, indent JSX by this value, instead of like JS.
630
631Let `js-indent-level' be 4. When this variable is also set to
632nil, JSX indentation looks like this (consistent):
633
634 return (
635 <element>
636 <element>
637 Hello World!
638 </element>
639 </element>
640 )
641
642Alternatively, when this variable is also set to 2, JSX
643indentation looks like this (different):
644
645 return (
646 <element>
647 <element>
648 Hello World!
649 </element>
650 </element>
651 )"
652 :version "27.1"
653 :type 'integer
654 :safe (lambda (x) (or (null x) (integerp x)))
655 :group 'js)
656;; This is how indentation behaved out-of-the-box until Emacs 27. JSX
657;; indentation was controlled with `sgml-basic-offset', which defaults
658;; to 2, whereas `js-indent-level' defaults to 4. Users who had the
659;; same values configured for both their HTML and JS indentation would
660;; luckily get consistent JSX indentation; most others were probably
661;; unhappy. I’d be surprised if anyone actually wants different
662;; indentation levels, but just in case, here’s a way back to that.
663
664(defcustom js-jsx-attribute-offset 0
665 "Specifies a delta for JSXAttribute indentation.
666
667Let `js-indent-level' be 2. When this variable is also set to 0,
668JSXAttribute indentation looks like this:
669
670 <element
671 attribute=\"value\">
672 </element>
673
674Alternatively, when this variable is also set to 2, JSXAttribute
675indentation looks like this:
676
677 <element
678 attribute=\"value\">
679 </element>
680
681This variable is like `sgml-attribute-offset'."
682 :version "27.1"
683 :type 'integer
684 :safe 'integerp
685 :group 'js)
686
575;;; KeyMap 687;;; KeyMap
576 688
577(defvar js-mode-map 689(defvar js-mode-map
@@ -1485,6 +1597,102 @@ point of view of font-lock. It applies highlighting directly with
1485 ;; Matcher always "fails" 1597 ;; Matcher always "fails"
1486 nil) 1598 nil)
1487 1599
1600;; It wouldn’t be sufficient to font-lock JSX with mere regexps, since
1601;; a JSXElement may be nested inside a JS expression within the
1602;; boundaries of a parent JSXOpeningElement, and such a hierarchy
1603;; ought to be fontified like JSX, JS, and JSX respectively:
1604;;
1605;; <div attr={void(<div></div>) && void(0)}></div>
1606;;
1607;; <div attr={ ← JSX
1608;; void( ← JS
1609;; <div></div> ← JSX
1610;; ) && void(0) ← JS
1611;; }></div> ← JSX
1612;;
1613;; `js-syntax-propertize' unambiguously identifies JSX syntax,
1614;; including when it’s nested.
1615;;
1616;; Using a matcher function for each relevant part, retrieve match
1617;; data recorded as syntax properties for fontification.
1618
1619(defconst js-jsx--font-lock-keywords
1620 `((js-jsx--match-tag-name 0 font-lock-function-name-face t)
1621 (js-jsx--match-attribute-name 0 font-lock-variable-name-face t)
1622 (js-jsx--match-text 0 'default t) ; “Undo” keyword fontification.
1623 (js-jsx--match-tag-beg)
1624 (js-jsx--match-tag-end)
1625 (js-jsx--match-expr))
1626 "JSX font lock faces and multiline text properties.")
1627
1628(defun js-jsx--match-tag-name (limit)
1629 "Match JSXBoundaryElement names, until LIMIT."
1630 (when js-jsx-syntax
1631 (let ((pos (next-single-char-property-change (point) 'js-jsx-tag-name nil limit))
1632 value)
1633 (when (and pos (> pos (point)))
1634 (goto-char pos)
1635 (or (and (setq value (get-text-property pos 'js-jsx-tag-name))
1636 (progn (set-match-data value) t))
1637 (js-jsx--match-tag-name limit))))))
1638
1639(defun js-jsx--match-attribute-name (limit)
1640 "Match JSXAttribute names, until LIMIT."
1641 (when js-jsx-syntax
1642 (let ((pos (next-single-char-property-change (point) 'js-jsx-attribute-name nil limit))
1643 value)
1644 (when (and pos (> pos (point)))
1645 (goto-char pos)
1646 (or (and (setq value (get-text-property pos 'js-jsx-attribute-name))
1647 (progn (set-match-data value) t))
1648 (js-jsx--match-attribute-name limit))))))
1649
1650(defun js-jsx--match-text (limit)
1651 "Match JSXText, until LIMIT."
1652 (when js-jsx-syntax
1653 (let ((pos (next-single-char-property-change (point) 'js-jsx-text nil limit))
1654 value)
1655 (when (and pos (> pos (point)))
1656 (goto-char pos)
1657 (or (and (setq value (get-text-property pos 'js-jsx-text))
1658 (progn (set-match-data value)
1659 (put-text-property (car value) (cadr value) 'font-lock-multiline t)
1660 t))
1661 (js-jsx--match-text limit))))))
1662
1663(defun js-jsx--match-tag-beg (limit)
1664 "Match JSXBoundaryElements from start, until LIMIT."
1665 (when js-jsx-syntax
1666 (let ((pos (next-single-char-property-change (point) 'js-jsx-tag-beg nil limit))
1667 value)
1668 (when (and pos (> pos (point)))
1669 (goto-char pos)
1670 (or (and (setq value (get-text-property pos 'js-jsx-tag-beg))
1671 (progn (put-text-property pos (cdr value) 'font-lock-multiline t) t))
1672 (js-jsx--match-tag-beg limit))))))
1673
1674(defun js-jsx--match-tag-end (limit)
1675 "Match JSXBoundaryElements from end, until LIMIT."
1676 (when js-jsx-syntax
1677 (let ((pos (next-single-char-property-change (point) 'js-jsx-tag-end nil limit))
1678 value)
1679 (when (and pos (> pos (point)))
1680 (goto-char pos)
1681 (or (and (setq value (get-text-property pos 'js-jsx-tag-end))
1682 (progn (put-text-property value pos 'font-lock-multiline t) t))
1683 (js-jsx--match-tag-end limit))))))
1684
1685(defun js-jsx--match-expr (limit)
1686 "Match JSXExpressionContainers, until LIMIT."
1687 (when js-jsx-syntax
1688 (let ((pos (next-single-char-property-change (point) 'js-jsx-expr nil limit))
1689 value)
1690 (when (and pos (> pos (point)))
1691 (goto-char pos)
1692 (or (and (setq value (get-text-property pos 'js-jsx-expr))
1693 (progn (put-text-property pos value 'font-lock-multiline t) t))
1694 (js-jsx--match-expr limit))))))
1695
1488(defconst js--font-lock-keywords-3 1696(defconst js--font-lock-keywords-3
1489 `( 1697 `(
1490 ;; This goes before keywords-2 so it gets used preferentially 1698 ;; This goes before keywords-2 so it gets used preferentially
@@ -1596,7 +1804,10 @@ point of view of font-lock. It applies highlighting directly with
1596 (forward-symbol -1) 1804 (forward-symbol -1)
1597 (end-of-line)) 1805 (end-of-line))
1598 '(end-of-line) 1806 '(end-of-line)
1599 '(0 font-lock-variable-name-face)))) 1807 '(0 font-lock-variable-name-face)))
1808
1809 ;; jsx (when enabled)
1810 ,@js-jsx--font-lock-keywords)
1600 "Level three font lock for `js-mode'.") 1811 "Level three font lock for `js-mode'.")
1601 1812
1602(defun js--inside-pitem-p (pitem) 1813(defun js--inside-pitem-p (pitem)
@@ -1722,9 +1933,414 @@ This performs fontification according to `js--class-styles'."
1722 'syntax-table (string-to-syntax "\"/")) 1933 'syntax-table (string-to-syntax "\"/"))
1723 (goto-char end))))) 1934 (goto-char end)))))
1724 1935
1936(defconst js--unary-keyword-re
1937 (js--regexp-opt-symbol '("await" "delete" "typeof" "void" "yield"))
1938 "Regexp matching unary operator keywords.")
1939
1940(defun js--unary-keyword-p (string)
1941 "Check if STRING is a unary operator keyword in JavaScript."
1942 (string-match-p js--unary-keyword-re string))
1943
1944;; Adding `syntax-multiline' text properties to JSX isn’t sufficient
1945;; to identify multiline JSX when first typing it. For instance, if
1946;; the user is typing a JSXOpeningElement for the first time…
1947;;
1948;; <div
1949;; ^ (point)
1950;;
1951;; …and the user inserts a line break after the tag name (before the
1952;; JSXOpeningElement starting on that line has been unambiguously
1953;; identified as such), then the `syntax-propertize' region won’t be
1954;; extended backwards to the start of the JSXOpeningElement:
1955;;
1956;; <div ← This line wasn’t JSX when last edited.
1957;; attr=""> ← Despite completing the JSX, the next
1958;; ^ `syntax-propertize' region wouldn’t magically
1959;; extend back a few lines.
1960;;
1961;; Therefore, to try and recover from this scenario, parse backward
1962;; from “>” to try and find the start of JSXBoundaryElements, and
1963;; extend the `syntax-propertize' region there.
1964
1965(defun js--syntax-propertize-extend-region (start end)
1966 "Extend the START-END region for propertization, if necessary.
1967For use by `syntax-propertize-extend-region-functions'."
1968 (if js-jsx-syntax (js-jsx--syntax-propertize-extend-region start end)))
1969
1970(defun js-jsx--syntax-propertize-extend-region (start end)
1971 "Extend the START-END region for propertization, if necessary.
1972If any “>” in the region appears to be the end of a tag starting
1973before the start of the region, extend region backwards to the
1974start of that tag so parsing may proceed from that point.
1975For use by `syntax-propertize-extend-region-functions'."
1976 (let (new-start
1977 forward-sexp-function ; Use the Lisp version.
1978 parse-sexp-lookup-properties) ; Fix backward-sexp error here.
1979 (catch 'stop
1980 (goto-char start)
1981 (while (re-search-forward ">" end t)
1982 (catch 'continue
1983 ;; Check if this is really a right shift bitwise operator
1984 ;; (“>>” or “>>>”).
1985 (unless (or (eq (char-before (1- (point))) ?>)
1986 (eq (char-after) ?>))
1987 (save-excursion
1988 (backward-char)
1989 (while (progn (if (= (point) (point-min)) (throw 'continue nil))
1990 (/= (char-before) ?<))
1991 (skip-chars-backward " \t\n")
1992 (if (= (point) (point-min)) (throw 'continue nil))
1993 (cond
1994 ((memq (char-before) '(?\" ?\' ?\` ?\}))
1995 (condition-case nil
1996 (backward-sexp)
1997 (scan-error (throw 'continue nil))))
1998 ((memq (char-before) '(?\/ ?\=)) (backward-char))
1999 ((looking-back js--dotted-name-re (line-beginning-position) t)
2000 (goto-char (match-beginning 0)))
2001 (t (throw 'continue nil))))
2002 (when (< (point) start)
2003 (setq new-start (1- (point)))
2004 (throw 'stop nil)))))))
2005 (if new-start (cons new-start end))))
2006
2007;; When applying syntax properties, since `js-syntax-propertize' uses
2008;; `syntax-propertize-rules' to parse JSXBoundaryElements iteratively
2009;; and statelessly, whenever we exit such an element, we need to
2010;; determine the JSX depth. If >0, then we know we to apply syntax
2011;; properties to JSXText up until the next JSXBoundaryElement occurs.
2012;; But if the JSX depth is 0, then—importantly—we know to NOT parse
2013;; the following code as JSXText, rather propertize it as regular JS
2014;; as long as warranted.
2015;;
2016;; Also, when indenting code, we need to know if the code we’re trying
2017;; to indent is on the 2nd or later line of multiline JSX, in which
2018;; case the code is indented according to XML-like JSX conventions.
2019;;
2020;; For the aforementioned reasons, we find ourselves needing to
2021;; determine whether point is enclosed in JSX or not; and, if so,
2022;; where the JSX is. The following functions provide that knowledge.
2023
2024(defconst js-jsx--tag-start-re
2025 (concat "\\(" js--dotted-name-re "\\)\\(?:"
2026 ;; Whitespace is only necessary if an attribute implies JSX.
2027 "\\(?:\\s-\\|\n\\)*[{/>]"
2028 "\\|"
2029 "\\(?:\\s-\\|\n\\)+" js--name-start-re
2030 "\\)")
2031 "Regexp unambiguously matching a JSXOpeningElement.")
2032
2033(defun js-jsx--matched-tag-type ()
2034 "Determine if the last “<” was a JSXBoundaryElement and its type.
2035Return `close' for a JSXClosingElement/JSXClosingFragment match,
2036return `self-closing' for some self-closing JSXOpeningElements,
2037else return `other'."
2038 (cond
2039 ((= (char-after) ?/) (forward-char) 'close) ; JSXClosingElement/JSXClosingFragment
2040 ((= (char-after) ?>) (forward-char) 'other) ; JSXOpeningFragment
2041 ((and (looking-at js-jsx--tag-start-re) ; JSXOpeningElement
2042 (not (js--unary-keyword-p (match-string 1))))
2043 (goto-char (match-end 0))
2044 (if (= (char-before) ?/) 'self-closing 'other))))
2045
2046(defconst js-jsx--self-closing-re "/\\s-*>"
2047 "Regexp matching the end of a self-closing JSXOpeningElement.")
2048
2049(defun js-jsx--matching-close-tag-pos ()
2050 "Return position of the closer of the opener before point.
2051Assuming a JSXOpeningElement or a JSXOpeningFragment is
2052immediately before point, find a matching JSXClosingElement or
2053JSXClosingFragment, skipping over any nested JSXElements to find
2054the match. Return nil if a match can’t be found."
2055 (let ((tag-stack 1) tag-pos type last-pos pos)
2056 (catch 'stop
2057 (while (and (re-search-forward "<\\s-*" nil t) (not (eobp)))
2058 (when (setq tag-pos (match-beginning 0)
2059 type (js-jsx--matched-tag-type))
2060 (when last-pos
2061 (setq pos (point))
2062 (goto-char last-pos)
2063 (while (re-search-forward js-jsx--self-closing-re pos 'move)
2064 (setq tag-stack (1- tag-stack))))
2065 (if (eq type 'close)
2066 (progn
2067 (setq tag-stack (1- tag-stack))
2068 (when (= tag-stack 0)
2069 (throw 'stop tag-pos)))
2070 ;; JSXOpeningElements that we know are self-closing aren’t
2071 ;; added to the stack at all (because point is already
2072 ;; past that syntax).
2073 (unless (eq type 'self-closing)
2074 (setq tag-stack (1+ tag-stack))))
2075 (setq last-pos (point)))))))
2076
2077(defun js-jsx--enclosing-tag-pos ()
2078 "Return beginning and end of a JSXElement about point.
2079Look backward for a JSXElement that both starts before point and
2080also ends at/after point. That may be either a self-closing
2081JSXElement or a JSXOpeningElement/JSXClosingElement pair."
2082 (let ((start (point)) tag-beg tag-beg-pos tag-end-pos close-tag-pos)
2083 (while
2084 (and
2085 (setq tag-beg (js--backward-text-property 'js-jsx-tag-beg))
2086 (progn
2087 (setq tag-beg-pos (point)
2088 tag-end-pos (cdr tag-beg))
2089 (not
2090 (or
2091 (and (eq (car tag-beg) 'self-closing)
2092 (< start tag-end-pos))
2093 (and (eq (car tag-beg) 'open)
2094 (or (< start tag-end-pos)
2095 (progn
2096 (unless
2097 ;; Try to read a cached close position,
2098 ;; but it might not be available yet.
2099 (setq close-tag-pos
2100 (get-text-property (point) 'js-jsx-close-tag-pos))
2101 (save-excursion
2102 (goto-char tag-end-pos)
2103 (setq close-tag-pos (js-jsx--matching-close-tag-pos)))
2104 (when close-tag-pos
2105 ;; Cache the close position to make future
2106 ;; searches faster.
2107 (put-text-property
2108 (point) (1+ (point))
2109 'js-jsx-close-tag-pos close-tag-pos)))
2110 ;; The JSXOpeningElement may be unclosed, else
2111 ;; the closure must occur at/after the start
2112 ;; point (otherwise, a miscellaneous previous
2113 ;; JSXOpeningElement has been found, so keep
2114 ;; looking backwards for an enclosing one).
2115 (or (not close-tag-pos) (<= start close-tag-pos)))))))))
2116 ;; Don’t return the last tag pos, as it wasn’t enclosing.
2117 (setq tag-beg nil close-tag-pos nil))
2118 (and tag-beg (list tag-beg-pos tag-end-pos close-tag-pos))))
2119
2120(defun js-jsx--at-enclosing-tag-child-p ()
2121 "Return t if point is at an enclosing tag’s child."
2122 (let ((pos (save-excursion (js-jsx--enclosing-tag-pos))))
2123 (and pos (>= (point) (nth 1 pos)))))
2124
2125;; We implement `syntax-propertize-function' logic fully parsing JSX
2126;; in order to provide very accurate JSX indentation, even in the most
2127;; complex cases (e.g. to indent JSX within a JS expression within a
2128;; JSXAttribute…), as over the years users have requested this. Since
2129;; we find so much information during this parse, we later use some of
2130;; the useful bits for font-locking, too.
2131;;
2132;; Some extra effort is devoted to ensuring that no code which could
2133;; possibly be valid JS is ever misinterpreted as partial JSX, since
2134;; that would be regressive.
2135;;
2136;; We first parse trying to find the minimum number of components
2137;; necessary to unambiguously identify a JSXBoundaryElement, even if
2138;; it is a partial one. If a complete one is parsed, we move on to
2139;; parse any JSXText. When that’s terminated, we unwind back to the
2140;; `syntax-propertize-rules' loop so the next JSXBoundaryElement can
2141;; be parsed, if any, be it an opening or closing one.
2142
2143(defun js-jsx--put-syntax-table (start end value)
2144 "Set syntax-table text property from START to END as VALUE.
2145Redundantly set the value to two properties, syntax-table and
2146js-jsx-syntax-table. Derivative modes that remove syntax-table
2147text properties may recover the value from the second property." ; i.e. js2-mode
2148 (add-text-properties start end (list 'syntax-table value
2149 'js-jsx-syntax-table value)))
2150
2151(defun js-jsx--text-range (beg end)
2152 "Identify JSXText within a “>/{/}/<” pair."
2153 (when (> (- end beg) 0)
2154 (save-excursion
2155 (goto-char beg)
2156 (while (and (skip-chars-forward " \t\n" end) (< (point) end))
2157 ;; Comments and string quotes don’t serve their usual
2158 ;; syntactic roles in JSXText; make them plain punctuation to
2159 ;; negate those roles.
2160 (when (or (= (char-after) ?/) ; comment
2161 (= (syntax-class (syntax-after (point))) 7)) ; string quote
2162 (js-jsx--put-syntax-table (point) (1+ (point)) '(1)))
2163 (forward-char)))
2164 ;; Mark JSXText so it can be font-locked as non-keywords.
2165 (put-text-property beg (1+ beg) 'js-jsx-text (list beg end (current-buffer)))
2166 ;; Ensure future propertization beginning from within the
2167 ;; JSXText determines JSXText context from earlier lines.
2168 (put-text-property beg end 'syntax-multiline t)))
2169
2170;; In order to respect the end boundary `syntax-propertize-function'
2171;; sets, care is taken in the following functions to abort parsing
2172;; whenever that boundary is reached.
2173
2174(defun js-jsx--syntax-propertize-tag-text (end)
2175 "Determine if JSXText is before END and propertize it.
2176Text within an open/close tag pair may be JSXText. Temporarily
2177interrupt JSXText by JSXExpressionContainers, and terminate
2178JSXText when another JSXBoundaryElement is encountered. Despite
2179terminations, all JSXText will be identified once all the
2180JSXBoundaryElements within an outermost JSXElement’s tree have
2181been propertized."
2182 (let ((text-beg (point))
2183 forward-sexp-function) ; Use Lisp version.
2184 (catch 'stop
2185 (while (re-search-forward "[{<]" end t)
2186 (js-jsx--text-range text-beg (1- (point)))
2187 (cond
2188 ((= (char-before) ?{)
2189 (let (expr-beg expr-end)
2190 (condition-case nil
2191 (save-excursion
2192 (backward-char)
2193 (setq expr-beg (point))
2194 (forward-sexp)
2195 (setq expr-end (point)))
2196 (scan-error nil))
2197 ;; Recursively propertize the JSXExpressionContainer’s
2198 ;; (possibly-incomplete) expression.
2199 (js-syntax-propertize (1+ expr-beg) (if expr-end (min (1- expr-end) end) end))
2200 ;; Ensure future propertization beginning from within the
2201 ;; (possibly-incomplete) expression can determine JSXText
2202 ;; context from earlier lines.
2203 (put-text-property expr-beg (1+ expr-beg) 'js-jsx-expr (or expr-end end)) ; font-lock
2204 (put-text-property expr-beg (if expr-end (min expr-end end) end) 'syntax-multiline t) ; syntax-propertize
2205 ;; Exit the JSXExpressionContainer if that’s possible,
2206 ;; else move to the end of the propertized area.
2207 (goto-char (if expr-end (min expr-end end) end))))
2208 ((= (char-before) ?<)
2209 (backward-char) ; Ensure the next tag can be propertized.
2210 (throw 'stop nil)))
2211 (setq text-beg (point))))))
2212
2213(defconst js-jsx--attribute-name-re (concat js--name-start-re
2214 "\\(?:\\s_\\|\\sw\\|-\\)*")
2215 "Like `js--name-re', but matches “-” as well.")
2216
2217(defun js-jsx--syntax-propertize-tag (end)
2218 "Determine if a JSXBoundaryElement is before END and propertize it.
2219Disambiguate JSX from inequality operators and arrow functions by
2220testing for syntax only valid as JSX."
2221 (let ((tag-beg (1- (point))) tag-end (type 'open)
2222 name-beg name-match-data expr-attribute-beg unambiguous
2223 forward-sexp-function) ; Use Lisp version.
2224 (catch 'stop
2225 (while (and (< (point) end)
2226 (progn (skip-chars-forward " \t\n" end)
2227 (< (point) end)))
2228 (cond
2229 ((= (char-after) ?>)
2230 ;; Make the closing “>” a close parenthesis.
2231 (js-jsx--put-syntax-table (point) (1+ (point)) '(5))
2232 (forward-char)
2233 (setq unambiguous t)
2234 (throw 'stop nil))
2235 ;; Handle a JSXSpreadChild (“<Foo {...bar}”) or a
2236 ;; JSXExpressionContainer as a JSXAttribute value
2237 ;; (“<Foo bar={…}”). Check this early in case continuing a
2238 ;; JSXAttribute parse.
2239 ((or (and name-beg (= (char-after) ?{))
2240 (setq expr-attribute-beg nil))
2241 (setq unambiguous t) ; JSXExpressionContainer post tag name ⇒ JSX
2242 (when expr-attribute-beg
2243 ;; Remember that this JSXExpressionContainer is part of a
2244 ;; JSXAttribute, as that can affect its expression’s
2245 ;; indentation.
2246 (put-text-property
2247 (point) (1+ (point)) 'js-jsx-expr-attribute expr-attribute-beg)
2248 (setq expr-attribute-beg nil))
2249 (let (expr-end)
2250 (condition-case nil
2251 (save-excursion
2252 (forward-sexp)
2253 (setq expr-end (point)))
2254 (scan-error nil))
2255 (forward-char)
2256 (if (>= (point) end) (throw 'stop nil))
2257 (skip-chars-forward " \t\n" end)
2258 (if (>= (point) end) (throw 'stop nil))
2259 (if (= (char-after) ?}) (forward-char) ; Shortcut to bail.
2260 ;; Recursively propertize the JSXExpressionContainer’s
2261 ;; expression.
2262 (js-syntax-propertize (point) (if expr-end (min (1- expr-end) end) end))
2263 ;; Exit the JSXExpressionContainer if that’s possible,
2264 ;; else move to the end of the propertized area.
2265 (goto-char (if expr-end (min expr-end end) end)))))
2266 ((= (char-after) ?/)
2267 ;; Assume a tag is an open tag until a slash is found, then
2268 ;; figure out what type it actually is.
2269 (if (eq type 'open) (setq type (if name-beg 'self-closing 'close)))
2270 (forward-char))
2271 ((and (not name-beg) (looking-at js--dotted-name-re))
2272 ;; Don’t match code like “if (i < await foo)”
2273 (if (js--unary-keyword-p (match-string 0)) (throw 'stop nil))
2274 ;; Save boundaries for later fontification after
2275 ;; unambiguously determining the code is JSX.
2276 (setq name-beg (match-beginning 0)
2277 name-match-data (match-data))
2278 (goto-char (match-end 0)))
2279 ((and name-beg (looking-at js-jsx--attribute-name-re))
2280 (setq unambiguous t) ; Non-unary name followed by 2nd name ⇒ JSX
2281 ;; Save JSXAttribute’s name’s match data for font-locking later.
2282 (put-text-property (match-beginning 0) (1+ (match-beginning 0))
2283 'js-jsx-attribute-name (match-data))
2284 (goto-char (match-end 0))
2285 (if (>= (point) end) (throw 'stop nil))
2286 (skip-chars-forward " \t\n" end)
2287 (if (>= (point) end) (throw 'stop nil))
2288 ;; “=” is optional for null-valued JSXAttributes.
2289 (when (= (char-after) ?=)
2290 (forward-char)
2291 (if (>= (point) end) (throw 'stop nil))
2292 (skip-chars-forward " \t\n" end)
2293 (if (>= (point) end) (throw 'stop nil))
2294 ;; Skip over strings (if possible). Any
2295 ;; JSXExpressionContainer here will be parsed in the
2296 ;; next iteration of the loop.
2297 (if (memq (char-after) '(?\" ?\' ?\`))
2298 (progn
2299 ;; Record the string’s position so derived modes
2300 ;; applying syntactic fontification atypically
2301 ;; (e.g. js2-mode) can recognize it as part of JSX.
2302 (put-text-property (point) (1+ (point)) 'js-jsx-string t)
2303 (condition-case nil
2304 (forward-sexp)
2305 (scan-error (throw 'stop nil))))
2306 ;; Save JSXAttribute’s beginning in case we find a
2307 ;; JSXExpressionContainer as the JSXAttribute’s value which
2308 ;; we should associate with the JSXAttribute.
2309 (setq expr-attribute-beg (match-beginning 0)))))
2310 ;; There is nothing more to check; this either isn’t JSX, or
2311 ;; the tag is incomplete.
2312 (t (throw 'stop nil)))))
2313 (when unambiguous
2314 ;; Save JSXBoundaryElement’s name’s match data for font-locking.
2315 (if name-beg (put-text-property name-beg (1+ name-beg) 'js-jsx-tag-name name-match-data))
2316 ;; Make the opening “<” an open parenthesis.
2317 (js-jsx--put-syntax-table tag-beg (1+ tag-beg) '(4))
2318 ;; Prevent “out of range” errors when typing at the end of a buffer.
2319 (setq tag-end (if (eobp) (1- (point)) (point)))
2320 ;; Mark beginning and end of tag for font-locking.
2321 (put-text-property tag-beg (1+ tag-beg) 'js-jsx-tag-beg (cons type tag-end))
2322 (put-text-property tag-end (1+ tag-end) 'js-jsx-tag-end tag-beg)
2323 ;; Use text properties to extend the syntax-propertize region
2324 ;; backward to the beginning of the JSXBoundaryElement in the
2325 ;; future. Typically the closing angle bracket could suggest
2326 ;; extending backward, but that would also involve more rigorous
2327 ;; parsing, and the closing angle bracket may not even exist yet
2328 ;; if the JSXBoundaryElement is still being typed.
2329 (put-text-property tag-beg (1+ tag-end) 'syntax-multiline t))
2330 (if (js-jsx--at-enclosing-tag-child-p) (js-jsx--syntax-propertize-tag-text end))))
2331
2332(defconst js-jsx--text-properties
2333 (list
2334 'js-jsx-tag-beg nil 'js-jsx-tag-end nil 'js-jsx-close-tag-pos nil
2335 'js-jsx-tag-name nil 'js-jsx-attribute-name nil 'js-jsx-string nil
2336 'js-jsx-text nil 'js-jsx-expr nil 'js-jsx-expr-attribute nil
2337 'js-jsx-syntax-table nil)
2338 "Plist of text properties added by `js-syntax-propertize'.")
2339
1725(defun js-syntax-propertize (start end) 2340(defun js-syntax-propertize (start end)
1726 ;; JavaScript allows immediate regular expression objects, written /.../. 2341 ;; JavaScript allows immediate regular expression objects, written /.../.
1727 (goto-char start) 2342 (goto-char start)
2343 (if js-jsx-syntax (remove-text-properties start end js-jsx--text-properties))
1728 (js-syntax-propertize-regexp end) 2344 (js-syntax-propertize-regexp end)
1729 (funcall 2345 (funcall
1730 (syntax-propertize-rules 2346 (syntax-propertize-rules
@@ -1748,7 +2364,8 @@ This performs fontification according to `js--class-styles'."
1748 (put-text-property (match-beginning 1) (match-end 1) 2364 (put-text-property (match-beginning 1) (match-end 1)
1749 'syntax-table (string-to-syntax "\"/")) 2365 'syntax-table (string-to-syntax "\"/"))
1750 (js-syntax-propertize-regexp end))))) 2366 (js-syntax-propertize-regexp end)))))
1751 ("\\`\\(#\\)!" (1 "< b"))) 2367 ("\\`\\(#\\)!" (1 "< b"))
2368 ("<" (0 (ignore (if js-jsx-syntax (js-jsx--syntax-propertize-tag end))))))
1752 (point) end)) 2369 (point) end))
1753 2370
1754(defconst js--prettify-symbols-alist 2371(defconst js--prettify-symbols-alist
@@ -1774,6 +2391,11 @@ This performs fontification according to `js--class-styles'."
1774 (js--regexp-opt-symbol '("in" "instanceof"))) 2391 (js--regexp-opt-symbol '("in" "instanceof")))
1775 "Regexp matching operators that affect indentation of continued expressions.") 2392 "Regexp matching operators that affect indentation of continued expressions.")
1776 2393
2394(defun js-jsx--looking-at-start-tag-p ()
2395 "Non-nil if a JSXOpeningElement immediately follows point."
2396 (let ((tag-beg (get-text-property (point) 'js-jsx-tag-beg)))
2397 (and tag-beg (memq (car tag-beg) '(open self-closing)))))
2398
1777(defun js--looking-at-operator-p () 2399(defun js--looking-at-operator-p ()
1778 "Return non-nil if point is on a JavaScript operator, other than a comma." 2400 "Return non-nil if point is on a JavaScript operator, other than a comma."
1779 (save-match-data 2401 (save-match-data
@@ -1796,7 +2418,9 @@ This performs fontification according to `js--class-styles'."
1796 (js--backward-syntactic-ws) 2418 (js--backward-syntactic-ws)
1797 ;; We might misindent some expressions that would 2419 ;; We might misindent some expressions that would
1798 ;; return NaN anyway. Shouldn't be a problem. 2420 ;; return NaN anyway. Shouldn't be a problem.
1799 (memq (char-before) '(?, ?} ?{)))))))) 2421 (memq (char-before) '(?, ?} ?{)))))
2422 ;; “<” isn’t necessarily an operator in JSX.
2423 (not (and js-jsx-syntax (js-jsx--looking-at-start-tag-p))))))
1800 2424
1801(defun js--find-newline-backward () 2425(defun js--find-newline-backward ()
1802 "Move backward to the nearest newline that is not in a block comment." 2426 "Move backward to the nearest newline that is not in a block comment."
@@ -1816,6 +2440,10 @@ This performs fontification according to `js--class-styles'."
1816 (setq result nil))) 2440 (setq result nil)))
1817 result)) 2441 result))
1818 2442
2443(defun js-jsx--looking-back-at-end-tag-p ()
2444 "Non-nil if a JSXClosingElement immediately precedes point."
2445 (get-text-property (point) 'js-jsx-tag-end))
2446
1819(defun js--continued-expression-p () 2447(defun js--continued-expression-p ()
1820 "Return non-nil if the current line continues an expression." 2448 "Return non-nil if the current line continues an expression."
1821 (save-excursion 2449 (save-excursion
@@ -1833,12 +2461,19 @@ This performs fontification according to `js--class-styles'."
1833 (and (js--find-newline-backward) 2461 (and (js--find-newline-backward)
1834 (progn 2462 (progn
1835 (skip-chars-backward " \t") 2463 (skip-chars-backward " \t")
1836 (or (bobp) (backward-char)) 2464 (and
1837 (and (> (point) (point-min)) 2465 ;; The “>” at the end of any JSXBoundaryElement isn’t
1838 (save-excursion (backward-char) (not (looking-at "[/*]/\\|=>"))) 2466 ;; part of a continued expression.
1839 (js--looking-at-operator-p) 2467 (not (and js-jsx-syntax (js-jsx--looking-back-at-end-tag-p)))
1840 (and (progn (backward-char) 2468 (progn
1841 (not (looking-at "\\+\\+\\|--\\|/[/*]")))))))))) 2469 (or (bobp) (backward-char))
2470 (and (> (point) (point-min))
2471 (save-excursion
2472 (backward-char)
2473 (not (looking-at "[/*]/\\|=>")))
2474 (js--looking-at-operator-p)
2475 (and (progn (backward-char)
2476 (not (looking-at "\\+\\+\\|--\\|/[/*]"))))))))))))
1842 2477
1843(defun js--skip-term-backward () 2478(defun js--skip-term-backward ()
1844 "Skip a term before point; return t if a term was skipped." 2479 "Skip a term before point; return t if a term was skipped."
@@ -2064,23 +2699,182 @@ indentation is aligned to that column."
2064 (when comma-p 2699 (when comma-p
2065 (goto-char (1+ declaration-keyword-end)))))))) 2700 (goto-char (1+ declaration-keyword-end))))))))
2066 2701
2067(defconst js--line-terminating-arrow-re "\\s-*=>\\s-*\\(/[/*]\\|$\\)" 2702(defconst js--line-terminating-arrow-re "=>\\s-*\\(/[/*]\\|$\\)"
2068 "Regexp matching the last \"=>\" (arrow) token on a line. 2703 "Regexp matching the last \"=>\" (arrow) token on a line.
2069Whitespace and comments around the arrow are ignored.") 2704Whitespace and comments around the arrow are ignored.")
2070 2705
2071(defun js--looking-at-broken-arrow-function-p () 2706(defun js--broken-arrow-terminates-line-p ()
2072 "Helper function for `js--proper-indentation'. 2707 "Helper function for `js--proper-indentation'.
2073Return t if point is at the start of a (possibly async) arrow 2708Return t if the last non-comment, non-whitespace token of the
2074function and the last non-comment, non-whitespace token of the 2709current line is the \"=>\" token (of an arrow function)."
2075current line is the \"=>\" token." 2710 (let ((from (point)))
2076 (when (looking-at "\\s-*async\\s-*") 2711 (end-of-line)
2077 (goto-char (match-end 0))) 2712 (re-search-backward js--line-terminating-arrow-re from t)))
2078 (cond 2713
2079 ((eq (char-after) ?\() 2714;; When indenting, we want to know if the line is…
2080 (forward-list) 2715;;
2081 (looking-at-p js--line-terminating-arrow-re)) 2716;; - within a multiline JSXElement, or
2082 (t (looking-at-p 2717;; - within a string in a JSXBoundaryElement, or
2083 (concat js--name-re js--line-terminating-arrow-re))))) 2718;; - within JSXText, or
2719;; - within a JSXAttribute’s multiline JSXExpressionContainer.
2720;;
2721;; In these cases, special XML-like indentation rules for JSX apply.
2722;; If JS is nested within JSX, then indentation calculations may be
2723;; combined, such that JS indentation is “relative” to the JSX’s.
2724;;
2725;; Therefore, functions below provide such contextual information, and
2726;; `js--proper-indentation' may call itself once recursively in order
2727;; to finish calculating that “relative” JS+JSX indentation.
2728
2729(defun js-jsx--context ()
2730 "Determine JSX context and move to enclosing JSX."
2731 (let ((pos (point))
2732 (parse-status (syntax-ppss))
2733 (enclosing-tag-pos (js-jsx--enclosing-tag-pos)))
2734 (when enclosing-tag-pos
2735 (if (< pos (nth 1 enclosing-tag-pos))
2736 (if (nth 3 parse-status)
2737 (list 'string (nth 8 parse-status))
2738 (list 'tag (nth 0 enclosing-tag-pos) (nth 1 enclosing-tag-pos)))
2739 (list 'text (nth 0 enclosing-tag-pos) (nth 2 enclosing-tag-pos))))))
2740
2741(defun js-jsx--contextual-indentation (line context)
2742 "Calculate indentation column for LINE from CONTEXT.
2743The column calculation is based off of `sgml-calculate-indent'."
2744 (pcase (nth 0 context)
2745
2746 ('string
2747 ;; Go back to previous non-empty line.
2748 (while (and (> (point) (nth 1 context))
2749 (zerop (forward-line -1))
2750 (looking-at "[ \t]*$")))
2751 (if (> (point) (nth 1 context))
2752 ;; Previous line is inside the string.
2753 (current-indentation)
2754 (goto-char (nth 1 context))
2755 (1+ (current-column))))
2756
2757 ('tag
2758 ;; Special JSX indentation rule: a “dangling” closing angle
2759 ;; bracket on its own line is indented at the same level as the
2760 ;; opening angle bracket of the JSXElement. Otherwise, indent
2761 ;; JSXAttribute space like SGML.
2762 (if (and
2763 js-jsx-align->-with-<
2764 (progn
2765 (goto-char (nth 2 context))
2766 (and (= line (line-number-at-pos))
2767 (looking-back "^\\s-*/?>" (line-beginning-position)))))
2768 (progn
2769 (goto-char (nth 1 context))
2770 (current-column))
2771 ;; Indent JSXAttribute space like SGML.
2772 (goto-char (nth 1 context))
2773 ;; Skip tag name:
2774 (skip-chars-forward " \t")
2775 (skip-chars-forward "^ \t\n")
2776 (skip-chars-forward " \t")
2777 (if (not (eolp))
2778 (current-column)
2779 ;; This is the first attribute: indent.
2780 (goto-char (+ (nth 1 context) js-jsx-attribute-offset))
2781 (+ (current-column) (or js-jsx-indent-level js-indent-level)))))
2782
2783 ('text
2784 ;; Indent to reflect nesting.
2785 (goto-char (nth 1 context))
2786 (+ (current-column)
2787 ;; The last line isn’t nested, but the rest are.
2788 (if (or (not (nth 2 context)) ; Unclosed.
2789 (< line (line-number-at-pos (nth 2 context))))
2790 (or js-jsx-indent-level js-indent-level)
2791 0)))
2792
2793 ))
2794
2795(defun js-jsx--enclosing-curly-pos ()
2796 "Return position of enclosing “{” in a “{/}” pair about point."
2797 (let ((parens (reverse (nth 9 (syntax-ppss)))) paren-pos curly-pos)
2798 (while
2799 (and
2800 (setq paren-pos (car parens))
2801 (not (when (= (char-after paren-pos) ?{)
2802 (setq curly-pos paren-pos)))
2803 (setq parens (cdr parens))))
2804 curly-pos))
2805
2806(defun js-jsx--goto-outermost-enclosing-curly (limit)
2807 "Set point to enclosing “{” at or closest after LIMIT."
2808 (let (pos)
2809 (while
2810 (and
2811 (setq pos (js-jsx--enclosing-curly-pos))
2812 (if (>= pos limit) (goto-char pos))
2813 (> pos limit)))))
2814
2815(defun js-jsx--expr-attribute-pos (start limit)
2816 "Look back from START to LIMIT for a JSXAttribute."
2817 (save-excursion
2818 (goto-char start) ; Skip the first curly.
2819 ;; Skip any remaining enclosing curlies until the JSXElement’s
2820 ;; beginning position; the last curly ought to be one of a
2821 ;; JSXExpressionContainer, which may refer to its JSXAttribute’s
2822 ;; beginning position (if it has one).
2823 (js-jsx--goto-outermost-enclosing-curly limit)
2824 (get-text-property (point) 'js-jsx-expr-attribute)))
2825
2826(defvar js-jsx--indent-col nil
2827 "Baseline column for JS indentation within JSX.")
2828
2829(defvar js-jsx--indent-attribute-line nil
2830 "Line relative to which indentation uses JSX as a baseline.")
2831
2832(defun js-jsx--expr-indentation (parse-status pos col)
2833 "Indent using PARSE-STATUS; relative to POS, use base COL.
2834To indent a JSXExpressionContainer’s expression, calculate the JS
2835indentation, using JSX indentation as the base column when
2836indenting relative to the beginning line of the
2837JSXExpressionContainer’s JSXAttribute (if any)."
2838 (let* ((js-jsx--indent-col col)
2839 (js-jsx--indent-attribute-line
2840 (if pos (line-number-at-pos pos))))
2841 (js--proper-indentation parse-status)))
2842
2843(defun js-jsx--indentation (parse-status)
2844 "Helper function for `js--proper-indentation'.
2845Return the proper indentation of the current line if it is part
2846of a JSXElement expression spanning multiple lines; otherwise,
2847return nil."
2848 (let ((current-line (line-number-at-pos))
2849 (curly-pos (js-jsx--enclosing-curly-pos))
2850 nth-context context expr-p beg-line col
2851 forward-sexp-function) ; Use the Lisp version.
2852 ;; Find the immediate context for indentation information, but
2853 ;; keep going to determine that point is at the N+1th line of
2854 ;; multiline JSX.
2855 (save-excursion
2856 (while
2857 (and
2858 (setq nth-context (js-jsx--context))
2859 (progn
2860 (unless context
2861 (setq context nth-context)
2862 (setq expr-p (and curly-pos (< (point) curly-pos))))
2863 (setq beg-line (line-number-at-pos))
2864 (and
2865 (= beg-line current-line)
2866 (or (not curly-pos) (> (point) curly-pos)))))))
2867 ;; When on the second or later line of JSX, indent as JSX,
2868 ;; possibly switching back to JS indentation within
2869 ;; JSXExpressionContainers, possibly using the JSX as a base
2870 ;; column while switching back to JS indentation.
2871 (when (and context (> current-line beg-line))
2872 (save-excursion
2873 (setq col (js-jsx--contextual-indentation current-line context)))
2874 (if expr-p
2875 (js-jsx--expr-indentation
2876 parse-status (js-jsx--expr-attribute-pos curly-pos (nth 1 context)) col)
2877 col))))
2084 2878
2085(defun js--proper-indentation (parse-status) 2879(defun js--proper-indentation (parse-status)
2086 "Return the proper indentation for the current line." 2880 "Return the proper indentation for the current line."
@@ -2089,6 +2883,8 @@ current line is the \"=>\" token."
2089 (cond ((nth 4 parse-status) ; inside comment 2883 (cond ((nth 4 parse-status) ; inside comment
2090 (js--get-c-offset 'c (nth 8 parse-status))) 2884 (js--get-c-offset 'c (nth 8 parse-status)))
2091 ((nth 3 parse-status) 0) ; inside string 2885 ((nth 3 parse-status) 0) ; inside string
2886 ((when (and js-jsx-syntax (not js-jsx--indent-col))
2887 (save-excursion (js-jsx--indentation parse-status))))
2092 ((eq (char-after) ?#) 0) 2888 ((eq (char-after) ?#) 0)
2093 ((save-excursion (js--beginning-of-macro)) 4) 2889 ((save-excursion (js--beginning-of-macro)) 4)
2094 ;; Indent array comprehension continuation lines specially. 2890 ;; Indent array comprehension continuation lines specially.
@@ -2113,7 +2909,7 @@ current line is the \"=>\" token."
2113 (goto-char (nth 1 parse-status)) ; go to the opening char 2909 (goto-char (nth 1 parse-status)) ; go to the opening char
2114 (if (or (not js-indent-align-list-continuation) 2910 (if (or (not js-indent-align-list-continuation)
2115 (looking-at "[({[]\\s-*\\(/[/*]\\|$\\)") 2911 (looking-at "[({[]\\s-*\\(/[/*]\\|$\\)")
2116 (save-excursion (forward-char) (js--looking-at-broken-arrow-function-p))) 2912 (save-excursion (forward-char) (js--broken-arrow-terminates-line-p)))
2117 (progn ; nothing following the opening paren/bracket 2913 (progn ; nothing following the opening paren/bracket
2118 (skip-syntax-backward " ") 2914 (skip-syntax-backward " ")
2119 (when (eq (char-before) ?\)) (backward-list)) 2915 (when (eq (char-before) ?\)) (backward-list))
@@ -2125,17 +2921,24 @@ current line is the \"=>\" token."
2125 (and switch-keyword-p 2921 (and switch-keyword-p
2126 in-switch-p))) 2922 in-switch-p)))
2127 (indent 2923 (indent
2128 (cond (same-indent-p 2924 (+
2129 (current-column)) 2925 (cond
2130 (continued-expr-p 2926 ((and js-jsx--indent-attribute-line
2131 (+ (current-column) (* 2 js-indent-level) 2927 (eq js-jsx--indent-attribute-line
2132 js-expr-indent-offset)) 2928 (line-number-at-pos)))
2133 (t 2929 js-jsx--indent-col)
2134 (+ (current-column) js-indent-level 2930 (t
2135 (pcase (char-after (nth 1 parse-status)) 2931 (current-column)))
2136 (?\( js-paren-indent-offset) 2932 (cond (same-indent-p 0)
2137 (?\[ js-square-indent-offset) 2933 (continued-expr-p
2138 (?\{ js-curly-indent-offset))))))) 2934 (+ (* 2 js-indent-level)
2935 js-expr-indent-offset))
2936 (t
2937 (+ js-indent-level
2938 (pcase (char-after (nth 1 parse-status))
2939 (?\( js-paren-indent-offset)
2940 (?\[ js-square-indent-offset)
2941 (?\{ js-curly-indent-offset))))))))
2139 (if in-switch-p 2942 (if in-switch-p
2140 (+ indent js-switch-indent-offset) 2943 (+ indent js-switch-indent-offset)
2141 indent))) 2944 indent)))
@@ -2151,193 +2954,6 @@ current line is the \"=>\" token."
2151 (+ js-indent-level js-expr-indent-offset)) 2954 (+ js-indent-level js-expr-indent-offset))
2152 (t (prog-first-column))))) 2955 (t (prog-first-column)))))
2153 2956
2154;;; JSX Indentation
2155
2156(defsubst js--jsx-find-before-tag ()
2157 "Find where JSX starts.
2158
2159Assume JSX appears in the following instances:
2160- Inside parentheses, when returned or as the first argument
2161 to a function, and after a newline
2162- When assigned to variables or object properties, but only
2163 on a single line
2164- As the N+1th argument to a function
2165
2166This is an optimized version of (re-search-backward \"[(,]\n\"
2167nil t), except set point to the end of the match. This logic
2168executes up to the number of lines in the file, so it should be
2169really fast to reduce that impact."
2170 (let (pos)
2171 (while (and (> (point) (point-min))
2172 (not (progn
2173 (end-of-line 0)
2174 (when (or (eq (char-before) 40) ; (
2175 (eq (char-before) 44)) ; ,
2176 (setq pos (1- (point))))))))
2177 pos))
2178
2179(defconst js--jsx-end-tag-re
2180 (concat "</" sgml-name-re ">\\|/>")
2181 "Find the end of a JSX element.")
2182
2183(defconst js--jsx-after-tag-re "[),]"
2184 "Find where JSX ends.
2185This complements the assumption of where JSX appears from
2186`js--jsx-before-tag-re', which see.")
2187
2188(defun js--jsx-indented-element-p ()
2189 "Determine if/how the current line should be indented as JSX.
2190
2191Return `first' for the first JSXElement on its own line.
2192Return `nth' for subsequent lines of the first JSXElement.
2193Return `expression' for an embedded JS expression.
2194Return `after' for anything after the last JSXElement.
2195Return nil for non-JSX lines.
2196
2197Currently, JSX indentation supports the following styles:
2198
2199- Single-line elements (indented like normal JS):
2200
2201 var element = <div></div>;
2202
2203- Multi-line elements (enclosed in parentheses):
2204
2205 function () {
2206 return (
2207 <div>
2208 <div></div>
2209 </div>
2210 );
2211 }
2212
2213- Function arguments:
2214
2215 React.render(
2216 <div></div>,
2217 document.querySelector('.root')
2218 );"
2219 (let ((current-pos (point))
2220 (current-line (line-number-at-pos))
2221 last-pos
2222 before-tag-pos before-tag-line
2223 tag-start-pos tag-start-line
2224 tag-end-pos tag-end-line
2225 after-tag-line
2226 parens paren type)
2227 (save-excursion
2228 (and
2229 ;; Determine if we're inside a jsx element
2230 (progn
2231 (end-of-line)
2232 (while (and (not tag-start-pos)
2233 (setq last-pos (js--jsx-find-before-tag)))
2234 (while (forward-comment 1))
2235 (when (= (char-after) 60) ; <
2236 (setq before-tag-pos last-pos
2237 tag-start-pos (point)))
2238 (goto-char last-pos))
2239 tag-start-pos)
2240 (progn
2241 (setq before-tag-line (line-number-at-pos before-tag-pos)
2242 tag-start-line (line-number-at-pos tag-start-pos))
2243 (and
2244 ;; A "before" line which also starts an element begins with js, so
2245 ;; indent it like js
2246 (> current-line before-tag-line)
2247 ;; Only indent the jsx lines like jsx
2248 (>= current-line tag-start-line)))
2249 (cond
2250 ;; Analyze bounds if there are any
2251 ((progn
2252 (while (and (not tag-end-pos)
2253 (setq last-pos (re-search-forward js--jsx-end-tag-re nil t)))
2254 (while (forward-comment 1))
2255 (when (looking-at js--jsx-after-tag-re)
2256 (setq tag-end-pos last-pos)))
2257 tag-end-pos)
2258 (setq tag-end-line (line-number-at-pos tag-end-pos)
2259 after-tag-line (line-number-at-pos after-tag-line))
2260 (or (and
2261 ;; Ensure we're actually within the bounds of the jsx
2262 (<= current-line tag-end-line)
2263 ;; An "after" line which does not end an element begins with
2264 ;; js, so indent it like js
2265 (<= current-line after-tag-line))
2266 (and
2267 ;; Handle another case where there could be e.g. comments after
2268 ;; the element
2269 (> current-line tag-end-line)
2270 (< current-line after-tag-line)
2271 (setq type 'after))))
2272 ;; They may not be any bounds (yet)
2273 (t))
2274 ;; Check if we're inside an embedded multi-line js expression
2275 (cond
2276 ((not type)
2277 (goto-char current-pos)
2278 (end-of-line)
2279 (setq parens (nth 9 (syntax-ppss)))
2280 (while (and parens (not type))
2281 (setq paren (car parens))
2282 (cond
2283 ((and (>= paren tag-start-pos)
2284 ;; Curly bracket indicates the start of an embedded expression
2285 (= (char-after paren) 123) ; {
2286 ;; The first line of the expression is indented like sgml
2287 (> current-line (line-number-at-pos paren))
2288 ;; Check if within a closing curly bracket (if any)
2289 ;; (exclusive, as the closing bracket is indented like sgml)
2290 (cond
2291 ((progn
2292 (goto-char paren)
2293 (ignore-errors (let (forward-sexp-function)
2294 (forward-sexp))))
2295 (< current-line (line-number-at-pos)))
2296 (t)))
2297 ;; Indicate this guy will be indented specially
2298 (setq type 'expression))
2299 (t (setq parens (cdr parens)))))
2300 t)
2301 (t))
2302 (cond
2303 (type)
2304 ;; Indent the first jsx thing like js so we can indent future jsx things
2305 ;; like sgml relative to the first thing
2306 ((= current-line tag-start-line) 'first)
2307 ('nth))))))
2308
2309(defmacro js--as-sgml (&rest body)
2310 "Execute BODY as if in sgml-mode."
2311 `(with-syntax-table sgml-mode-syntax-table
2312 (let (forward-sexp-function
2313 parse-sexp-lookup-properties)
2314 ,@body)))
2315
2316(defun js--expression-in-sgml-indent-line ()
2317 "Indent the current line as JavaScript or SGML (whichever is farther)."
2318 (let* (indent-col
2319 (savep (point))
2320 ;; Don't whine about errors/warnings when we're indenting.
2321 ;; This has to be set before calling parse-partial-sexp below.
2322 (inhibit-point-motion-hooks t)
2323 (parse-status (save-excursion
2324 (syntax-ppss (point-at-bol)))))
2325 ;; Don't touch multiline strings.
2326 (unless (nth 3 parse-status)
2327 (setq indent-col (save-excursion
2328 (back-to-indentation)
2329 (if (>= (point) savep) (setq savep nil))
2330 (js--as-sgml (sgml-calculate-indent))))
2331 (if (null indent-col)
2332 'noindent
2333 ;; Use whichever indentation column is greater, such that the sgml
2334 ;; column is effectively a minimum
2335 (setq indent-col (max (js--proper-indentation parse-status)
2336 (+ indent-col js-indent-level)))
2337 (if savep
2338 (save-excursion (indent-line-to indent-col))
2339 (indent-line-to indent-col))))))
2340
2341(defun js-indent-line () 2957(defun js-indent-line ()
2342 "Indent the current line as JavaScript." 2958 "Indent the current line as JavaScript."
2343 (interactive) 2959 (interactive)
@@ -2349,23 +2965,9 @@ Currently, JSX indentation supports the following styles:
2349 (when (> offset 0) (forward-char offset))))) 2965 (when (> offset 0) (forward-char offset)))))
2350 2966
2351(defun js-jsx-indent-line () 2967(defun js-jsx-indent-line ()
2352 "Indent the current line as JSX (with SGML offsets). 2968 "Indent the current line as JavaScript+JSX."
2353i.e., customize JSX element indentation with `sgml-basic-offset',
2354`sgml-attribute-offset' et al."
2355 (interactive) 2969 (interactive)
2356 (let ((indentation-type (js--jsx-indented-element-p))) 2970 (let ((js-jsx-syntax t)) (js-indent-line)))
2357 (cond
2358 ((eq indentation-type 'expression)
2359 (js--expression-in-sgml-indent-line))
2360 ((or (eq indentation-type 'first)
2361 (eq indentation-type 'after))
2362 ;; Don't treat this first thing as a continued expression (often a "<" or
2363 ;; ">" causes this misinterpretation)
2364 (cl-letf (((symbol-function #'js--continued-expression-p) 'ignore))
2365 (js-indent-line)))
2366 ((eq indentation-type 'nth)
2367 (js--as-sgml (sgml-indent-line)))
2368 (t (js-indent-line)))))
2369 2971
2370;;; Filling 2972;;; Filling
2371 2973
@@ -3856,6 +4458,77 @@ If one hasn't been set, or if it's stale, prompt for a new one."
3856 (when temp-name 4458 (when temp-name
3857 (delete-file temp-name)))))) 4459 (delete-file temp-name))))))
3858 4460
4461;;; Syntax extensions
4462
4463(defvar js-syntactic-mode-name t
4464 "If non-nil, print enabled syntaxes in the mode name.")
4465
4466(defun js--syntactic-mode-name-part ()
4467 "Return a string like “[JSX]” when `js-jsx-syntax' is enabled."
4468 (if js-syntactic-mode-name
4469 (let (syntaxes)
4470 (if js-jsx-syntax (push "JSX" syntaxes))
4471 (if syntaxes
4472 (concat "[" (mapconcat #'identity syntaxes ",") "]")
4473 ""))
4474 ""))
4475
4476(defun js-use-syntactic-mode-name ()
4477 "Print enabled syntaxes if `js-syntactic-mode-name' is t.
4478Modes deriving from `js-mode' should call this to ensure that
4479their `mode-name' updates to show enabled syntax extensions."
4480 (when (stringp mode-name)
4481 (setq mode-name `(,mode-name (:eval (js--syntactic-mode-name-part))))))
4482
4483(defun js-jsx-enable ()
4484 "Enable JSX in the current buffer."
4485 (interactive)
4486 (setq-local js-jsx-syntax t))
4487
4488;; To make discovering and using syntax extensions features easier for
4489;; users (who might not read the docs), try to safely and
4490;; automatically enable syntax extensions based on heuristics.
4491
4492(defvar js-jsx-regexps
4493 (list "\\_<\\(?:var\\|let\\|const\\|import\\)\\_>.*?React")
4494 "Regexps for detecting JSX in JavaScript buffers.
4495When `js-jsx-detect-syntax' is non-nil and any of these regexps
4496match text near the beginning of a JavaScript buffer,
4497`js-jsx-syntax' (which see) will be made buffer-local and set to
4498t.")
4499
4500(defun js-jsx--detect-and-enable (&optional arbitrarily)
4501 "Detect if JSX is likely to be used, and enable it if so.
4502Might make `js-jsx-syntax' buffer-local and set it to t. Matches
4503from the beginning of the buffer, unless optional arg ARBITRARILY
4504is non-nil. Return t after enabling, nil otherwise."
4505 (when (or (and (buffer-file-name)
4506 (string-match-p "\\.jsx\\'" (buffer-file-name)))
4507 (and js-jsx-detect-syntax
4508 (save-excursion
4509 (unless arbitrarily
4510 (goto-char (point-min)))
4511 (catch 'match
4512 (mapc
4513 (lambda (regexp)
4514 (if (re-search-forward regexp 4000 t) (throw 'match t)))
4515 js-jsx-regexps)
4516 nil))))
4517 (js-jsx-enable)
4518 t))
4519
4520(defun js-jsx--detect-after-change (beg end _len)
4521 "Detect if JSX is likely to be used after a change.
4522This function is intended for use in `after-change-functions'."
4523 (when (<= end 4000)
4524 (save-excursion
4525 (goto-char beg)
4526 (beginning-of-line)
4527 (save-restriction
4528 (narrow-to-region (point) end)
4529 (when (js-jsx--detect-and-enable 'arbitrarily)
4530 (remove-hook 'after-change-functions #'js-jsx--detect-after-change t))))))
4531
3859;;; Main Function 4532;;; Main Function
3860 4533
3861;;;###autoload 4534;;;###autoload
@@ -3871,6 +4544,10 @@ If one hasn't been set, or if it's stale, prompt for a new one."
3871 '(font-lock-syntactic-face-function 4544 '(font-lock-syntactic-face-function
3872 . js-font-lock-syntactic-face-function))) 4545 . js-font-lock-syntactic-face-function)))
3873 (setq-local syntax-propertize-function #'js-syntax-propertize) 4546 (setq-local syntax-propertize-function #'js-syntax-propertize)
4547 (add-hook 'syntax-propertize-extend-region-functions
4548 #'syntax-propertize-multiline 'append 'local)
4549 (add-hook 'syntax-propertize-extend-region-functions
4550 #'js--syntax-propertize-extend-region 'append 'local)
3874 (setq-local prettify-symbols-alist js--prettify-symbols-alist) 4551 (setq-local prettify-symbols-alist js--prettify-symbols-alist)
3875 4552
3876 (setq-local parse-sexp-ignore-comments t) 4553 (setq-local parse-sexp-ignore-comments t)
@@ -3878,6 +4555,7 @@ If one hasn't been set, or if it's stale, prompt for a new one."
3878 4555
3879 ;; Comments 4556 ;; Comments
3880 (setq-local comment-start "// ") 4557 (setq-local comment-start "// ")
4558 (setq-local comment-start-skip "\\(//+\\|/\\*+\\)\\s *")
3881 (setq-local comment-end "") 4559 (setq-local comment-end "")
3882 (setq-local fill-paragraph-function #'js-fill-paragraph) 4560 (setq-local fill-paragraph-function #'js-fill-paragraph)
3883 (setq-local normal-auto-fill-function #'js-do-auto-fill) 4561 (setq-local normal-auto-fill-function #'js-do-auto-fill)
@@ -3888,6 +4566,11 @@ If one hasn't been set, or if it's stale, prompt for a new one."
3888 ;; Frameworks 4566 ;; Frameworks
3889 (js--update-quick-match-re) 4567 (js--update-quick-match-re)
3890 4568
4569 ;; Syntax extensions
4570 (unless (js-jsx--detect-and-enable)
4571 (add-hook 'after-change-functions #'js-jsx--detect-after-change nil t))
4572 (js-use-syntactic-mode-name)
4573
3891 ;; Imenu 4574 ;; Imenu
3892 (setq imenu-case-fold-search nil) 4575 (setq imenu-case-fold-search nil)
3893 (setq imenu-create-index-function #'js--imenu-create-index) 4576 (setq imenu-create-index-function #'js--imenu-create-index)
@@ -3898,8 +4581,7 @@ If one hasn't been set, or if it's stale, prompt for a new one."
3898 c-paragraph-separate "$" 4581 c-paragraph-separate "$"
3899 c-block-comment-prefix "* " 4582 c-block-comment-prefix "* "
3900 c-line-comment-starter "//" 4583 c-line-comment-starter "//"
3901 c-comment-start-regexp "/[*/]\\|\\s!" 4584 c-comment-start-regexp "/[*/]\\|\\s!")
3902 comment-start-skip "\\(//+\\|/\\*+\\)\\s *")
3903 (setq-local comment-line-break-function #'c-indent-new-comment-line) 4585 (setq-local comment-line-break-function #'c-indent-new-comment-line)
3904 (setq-local c-block-comment-start-regexp "/\\*") 4586 (setq-local c-block-comment-start-regexp "/\\*")
3905 (setq-local comment-multi-line t) 4587 (setq-local comment-multi-line t)
@@ -3932,19 +4614,33 @@ If one hasn't been set, or if it's stale, prompt for a new one."
3932 ;;(syntax-propertize (point-max)) 4614 ;;(syntax-propertize (point-max))
3933 ) 4615 )
3934 4616
3935;;;###autoload 4617;; Since we made JSX support available and automatically-enabled in
3936(define-derived-mode js-jsx-mode js-mode "JSX" 4618;; the base `js-mode' (for ease of use), now `js-jsx-mode' simply
3937 "Major mode for editing JSX. 4619;; serves as one other interface to unconditionally enable JSX in
3938 4620;; buffers, mostly for backwards-compatibility.
3939To customize the indentation for this mode, set the SGML offset 4621;;
3940variables (`sgml-basic-offset', `sgml-attribute-offset' et al.) 4622;; Since it is probably more common for packages to integrate with
3941locally, like so: 4623;; `js-mode' than with `js-jsx-mode', it is therefore probably
4624;; slightly better for users to use one of the many other methods for
4625;; enabling JSX syntax. But using `js-jsx-mode' can’t be that bad
4626;; either, so we won’t bother users with an obsoletion warning.
3942 4627
3943 (defun set-jsx-indentation () 4628;;;###autoload
3944 (setq-local sgml-basic-offset js-indent-level)) 4629(define-derived-mode js-jsx-mode js-mode "JavaScript"
3945 (add-hook \\='js-jsx-mode-hook #\\='set-jsx-indentation)" 4630 "Major mode for editing JavaScript+JSX.
4631
4632Simply makes `js-jsx-syntax' buffer-local and sets it to t.
4633
4634`js-mode' may detect and enable support for JSX automatically if
4635it appears to be used in a JavaScript file. You could also
4636customize `js-jsx-regexps' to improve that detection; or, you
4637could set `js-jsx-syntax' to t in your init file, or in a
4638.dir-locals.el file, or using file variables; or, you could call
4639`js-jsx-enable' in `js-mode-hook'. You may be better served by
4640one of the aforementioned options instead of using this mode."
3946 :group 'js 4641 :group 'js
3947 (setq-local indent-line-function #'js-jsx-indent-line)) 4642 (js-jsx-enable)
4643 (js-use-syntactic-mode-name))
3948 4644
3949;;;###autoload (defalias 'javascript-mode 'js-mode) 4645;;;###autoload (defalias 'javascript-mode 'js-mode)
3950 4646
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 5d0d03d5029..b05f9a33e90 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -675,7 +675,7 @@ Which one will be chosen depends on the value of
675 675
676(defconst python-syntax-propertize-function 676(defconst python-syntax-propertize-function
677 (syntax-propertize-rules 677 (syntax-propertize-rules
678 ((python-rx string-delimiter) 678 ((rx (or "\"\"\"" "'''"))
679 (0 (ignore (python-syntax-stringify)))))) 679 (0 (ignore (python-syntax-stringify))))))
680 680
681(define-obsolete-variable-alias 'python--prettify-symbols-alist 681(define-obsolete-variable-alias 'python--prettify-symbols-alist
@@ -701,35 +701,27 @@ is used to limit the scan."
701 701
702(defun python-syntax-stringify () 702(defun python-syntax-stringify ()
703 "Put `syntax-table' property correctly on single/triple quotes." 703 "Put `syntax-table' property correctly on single/triple quotes."
704 (let* ((num-quotes (length (match-string-no-properties 1))) 704 (let* ((ppss (save-excursion (backward-char 3) (syntax-ppss)))
705 (ppss (prog2 705 (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))
706 (backward-char num-quotes) 706 (quote-starting-pos (- (point) 3))
707 (syntax-ppss) 707 (quote-ending-pos (point)))
708 (forward-char num-quotes))) 708 (cond ((or (nth 4 ppss) ;Inside a comment
709 (string-start (and (not (nth 4 ppss)) (nth 8 ppss))) 709 (and string-start
710 (quote-starting-pos (- (point) num-quotes)) 710 ;; Inside of a string quoted with different triple quotes.
711 (quote-ending-pos (point)) 711 (not (eql (char-after string-start)
712 (num-closing-quotes 712 (char-after quote-starting-pos)))))
713 (and string-start 713 ;; Do nothing.
714 (python-syntax-count-quotes
715 (char-before) string-start quote-starting-pos))))
716 (cond ((and string-start (= num-closing-quotes 0))
717 ;; This set of quotes doesn't match the string starting
718 ;; kind. Do nothing.
719 nil) 714 nil)
720 ((not string-start) 715 ((nth 5 ppss)
716 ;; The first quote is escaped, so it's not part of a triple quote!
717 (goto-char (1+ quote-starting-pos)))
718 ((null string-start)
721 ;; This set of quotes delimit the start of a string. 719 ;; This set of quotes delimit the start of a string.
722 (put-text-property quote-starting-pos (1+ quote-starting-pos) 720 (put-text-property quote-starting-pos (1+ quote-starting-pos)
723 'syntax-table (string-to-syntax "|"))) 721 'syntax-table (string-to-syntax "|")))
724 ((= num-quotes num-closing-quotes) 722 (t
725 ;; This set of quotes delimit the end of a string. 723 ;; This set of quotes delimit the end of a string.
726 (put-text-property (1- quote-ending-pos) quote-ending-pos 724 (put-text-property (1- quote-ending-pos) quote-ending-pos
727 'syntax-table (string-to-syntax "|")))
728 ((> num-quotes num-closing-quotes)
729 ;; This may only happen whenever a triple quote is closing
730 ;; a single quoted string. Add string delimiter syntax to
731 ;; all three quotes.
732 (put-text-property quote-starting-pos quote-ending-pos
733 'syntax-table (string-to-syntax "|")))))) 725 'syntax-table (string-to-syntax "|"))))))
734 726
735(defvar python-mode-syntax-table 727(defvar python-mode-syntax-table
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index dd3a6fa411e..853a3500ee1 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -2905,8 +2905,7 @@ STRING This is ignored for the purposes of calculating
2905 (setq align-point (point)))) 2905 (setq align-point (point))))
2906 (or (bobp) 2906 (or (bobp)
2907 (forward-char -1)) 2907 (forward-char -1))
2908 ;; FIXME: This charset looks too much like a regexp. --Stef 2908 (skip-chars-forward "*0-9?[]a-z")
2909 (skip-chars-forward "[a-z0-9]*?")
2910 ) 2909 )
2911 ((string-match "[])}]" x) 2910 ((string-match "[])}]" x)
2912 (setq x (sh-safe-forward-sexp -1)) 2911 (setq x (sh-safe-forward-sexp -1))
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index 7b9c3921fba..9226291ffbb 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -14263,13 +14263,13 @@ and the case items."
14263(defun verilog-sk-define-signal () 14263(defun verilog-sk-define-signal ()
14264 "Insert a definition of signal under point at top of module." 14264 "Insert a definition of signal under point at top of module."
14265 (interactive "*") 14265 (interactive "*")
14266 (let* ((sig-re "[a-zA-Z0-9_]*") 14266 (let* ((sig-chars "a-zA-Z0-9_")
14267 (v1 (buffer-substring 14267 (v1 (buffer-substring
14268 (save-excursion 14268 (save-excursion
14269 (skip-chars-backward sig-re) 14269 (skip-chars-backward sig-chars)
14270 (point)) 14270 (point))
14271 (save-excursion 14271 (save-excursion
14272 (skip-chars-forward sig-re) 14272 (skip-chars-forward sig-chars)
14273 (point))))) 14273 (point)))))
14274 (if (not (member v1 verilog-keywords)) 14274 (if (not (member v1 verilog-keywords))
14275 (save-excursion 14275 (save-excursion
diff --git a/lisp/replace.el b/lisp/replace.el
index 318a9fb0253..9d1b7bf747d 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2643,22 +2643,24 @@ characters."
2643 (setq def (lookup-key map key)) 2643 (setq def (lookup-key map key))
2644 ;; Restore the match data while we process the command. 2644 ;; Restore the match data while we process the command.
2645 (cond ((eq def 'help) 2645 (cond ((eq def 'help)
2646 (with-output-to-temp-buffer "*Help*" 2646 (let ((display-buffer-overriding-action
2647 (princ 2647 '(nil (inhibit-same-window . t))))
2648 (concat "Query replacing " 2648 (with-output-to-temp-buffer "*Help*"
2649 (if backward "backward " "") 2649 (princ
2650 (if delimited-flag 2650 (concat "Query replacing "
2651 (or (and (symbolp delimited-flag) 2651 (if backward "backward " "")
2652 (get delimited-flag 2652 (if delimited-flag
2653 'isearch-message-prefix)) 2653 (or (and (symbolp delimited-flag)
2654 "word ") "") 2654 (get delimited-flag
2655 (if regexp-flag "regexp " "") 2655 'isearch-message-prefix))
2656 from-string " with " 2656 "word ") "")
2657 next-replacement ".\n\n" 2657 (if regexp-flag "regexp " "")
2658 (substitute-command-keys 2658 from-string " with "
2659 query-replace-help))) 2659 next-replacement ".\n\n"
2660 (with-current-buffer standard-output 2660 (substitute-command-keys
2661 (help-mode)))) 2661 query-replace-help)))
2662 (with-current-buffer standard-output
2663 (help-mode)))))
2662 ((eq def 'exit) 2664 ((eq def 'exit)
2663 (setq keep-going nil) 2665 (setq keep-going nil)
2664 (setq done t)) 2666 (setq done t))
diff --git a/lisp/simple.el b/lisp/simple.el
index be84e48cf4a..37f92540dde 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -8221,6 +8221,9 @@ CHOICE - the string to insert in the buffer,
8221BUFFER - the buffer in which the choice should be inserted, 8221BUFFER - the buffer in which the choice should be inserted,
8222BASE-POSITION - where to insert the completion. 8222BASE-POSITION - where to insert the completion.
8223 8223
8224Functions should also accept and ignore a potential fourth
8225argument, passed for backwards compatibility.
8226
8224If a function in the list returns non-nil, that function is supposed 8227If a function in the list returns non-nil, that function is supposed
8225to have inserted the CHOICE in the BUFFER, and possibly exited 8228to have inserted the CHOICE in the BUFFER, and possibly exited
8226the minibuffer; no further functions will be called. 8229the minibuffer; no further functions will be called.
@@ -8705,7 +8708,7 @@ call `normal-erase-is-backspace-mode' (which see) instead."
8705 (and (not noninteractive) 8708 (and (not noninteractive)
8706 (or (memq system-type '(ms-dos windows-nt)) 8709 (or (memq system-type '(ms-dos windows-nt))
8707 (memq window-system '(w32 ns)) 8710 (memq window-system '(w32 ns))
8708 (and (memq window-system '(x)) 8711 (and (eq window-system 'x)
8709 (fboundp 'x-backspace-delete-keys-p) 8712 (fboundp 'x-backspace-delete-keys-p)
8710 (x-backspace-delete-keys-p)) 8713 (x-backspace-delete-keys-p))
8711 ;; If the terminal Emacs is running on has erase char 8714 ;; If the terminal Emacs is running on has erase char
@@ -8716,6 +8719,8 @@ call `normal-erase-is-backspace-mode' (which see) instead."
8716 normal-erase-is-backspace) 8719 normal-erase-is-backspace)
8717 1 0))))) 8720 1 0)))))
8718 8721
8722(declare-function display-symbol-keys-p "frame" (&optional display))
8723
8719(define-minor-mode normal-erase-is-backspace-mode 8724(define-minor-mode normal-erase-is-backspace-mode
8720 "Toggle the Erase and Delete mode of the Backspace and Delete keys. 8725 "Toggle the Erase and Delete mode of the Backspace and Delete keys.
8721 8726
@@ -8751,8 +8756,7 @@ See also `normal-erase-is-backspace'."
8751 (let ((enabled (eq 1 (terminal-parameter 8756 (let ((enabled (eq 1 (terminal-parameter
8752 nil 'normal-erase-is-backspace)))) 8757 nil 'normal-erase-is-backspace))))
8753 8758
8754 (cond ((or (memq window-system '(x w32 ns pc)) 8759 (cond ((display-symbol-keys-p)
8755 (memq system-type '(ms-dos windows-nt)))
8756 (let ((bindings 8760 (let ((bindings
8757 '(([M-delete] [M-backspace]) 8761 '(([M-delete] [M-backspace])
8758 ([C-M-delete] [C-M-backspace]) 8762 ([C-M-delete] [C-M-backspace])
diff --git a/lisp/subr.el b/lisp/subr.el
index 8d51474b0c9..bdf98979c49 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -138,7 +138,7 @@ This sets each VAR's default value to the corresponding VALUE.
138The VALUE for the Nth VAR can refer to the new default values 138The VALUE for the Nth VAR can refer to the new default values
139of previous VARs. 139of previous VARs.
140 140
141\(setq-default [VAR VALUE]...)" 141\(fn [VAR VALUE]...)"
142 (declare (debug setq)) 142 (declare (debug setq))
143 (let ((exps nil)) 143 (let ((exps nil))
144 (while args 144 (while args
@@ -779,9 +779,9 @@ Elements of ALIST that are not conses are ignored."
779 alist) 779 alist)
780 780
781(defun alist-get (key alist &optional default remove testfn) 781(defun alist-get (key alist &optional default remove testfn)
782 "Return the value associated with KEY in ALIST. 782 "Find the first element of ALIST whose `car' equals KEY and return its `cdr'.
783If KEY is not found in ALIST, return DEFAULT. 783If KEY is not found in ALIST, return DEFAULT.
784Use TESTFN to lookup in the alist if non-nil. Otherwise, use `assq'. 784Equality with KEY is tested by TESTFN, defaulting to `eq'.
785 785
786You can use `alist-get' in PLACE expressions. This will modify 786You can use `alist-get' in PLACE expressions. This will modify
787an existing association (more precisely, the first one if 787an existing association (more precisely, the first one if
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index dbde284da84..8940c7e09a6 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -116,7 +116,7 @@ You can always manually refine a hunk with `diff-refine-hunk'."
116 "If non-nil, diff hunk font-lock includes source language syntax highlighting. 116 "If non-nil, diff hunk font-lock includes source language syntax highlighting.
117This highlighting is the same as added by `font-lock-mode' 117This highlighting is the same as added by `font-lock-mode'
118when corresponding source files are visited normally. 118when corresponding source files are visited normally.
119Syntax highlighting is added over diff own highlighted changes. 119Syntax highlighting is added over diff-mode's own highlighted changes.
120 120
121If t, the default, highlight syntax only in Diff buffers created by Diff 121If t, the default, highlight syntax only in Diff buffers created by Diff
122commands that compare files or by VC commands that compare revisions. 122commands that compare files or by VC commands that compare revisions.
@@ -126,17 +126,17 @@ For diffs against the working-tree version of a file, the highlighting is
126based on the current file contents. File-based fontification tries to 126based on the current file contents. File-based fontification tries to
127infer fontification from the compared files. 127infer fontification from the compared files.
128 128
129If revision-based or file-based method fails, use hunk-based method to get 129If `hunk-only' fontification is based on hunk alone, without full source.
130fontification from hunk alone if the value is `hunk-also'.
131
132If `hunk-only', fontification is based on hunk alone, without full source.
133It tries to highlight hunks without enough context that sometimes might result 130It tries to highlight hunks without enough context that sometimes might result
134in wrong fontification. This is the fastest option, but less reliable." 131in wrong fontification. This is the fastest option, but less reliable.
132
133If `hunk-also', use reliable file-based syntax highlighting when available
134and hunk-based syntax highlighting otherwise as a fallback."
135 :version "27.1" 135 :version "27.1"
136 :type '(choice (const :tag "Don't highlight syntax" nil) 136 :type '(choice (const :tag "Don't highlight syntax" nil)
137 (const :tag "Hunk-based also" hunk-also)
138 (const :tag "Hunk-based only" hunk-only) 137 (const :tag "Hunk-based only" hunk-only)
139 (const :tag "Highlight syntax" t))) 138 (const :tag "Highlight syntax" t)
139 (const :tag "Allow hunk-based fallback" hunk-also)))
140 140
141(defvar diff-vc-backend nil 141(defvar diff-vc-backend nil
142 "The VC backend that created the current Diff buffer, if any.") 142 "The VC backend that created the current Diff buffer, if any.")
@@ -144,9 +144,8 @@ in wrong fontification. This is the fastest option, but less reliable."
144(defvar diff-vc-revisions nil 144(defvar diff-vc-revisions nil
145 "The VC revisions compared in the current Diff buffer, if any.") 145 "The VC revisions compared in the current Diff buffer, if any.")
146 146
147(defvar diff-default-directory nil 147(defvar-local diff-default-directory nil
148 "The default directory where the current Diff buffer was created.") 148 "The default directory where the current Diff buffer was created.")
149(make-variable-buffer-local 'diff-default-directory)
150 149
151(defvar diff-outline-regexp 150(defvar diff-outline-regexp
152 "\\([*+][*+][*+] [^0-9]\\|@@ ...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)") 151 "\\([*+][*+][*+] [^0-9]\\|@@ ...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)")
@@ -2423,7 +2422,9 @@ When OLD is non-nil, highlight the hunk from the old source."
2423 (let* ((hunk (buffer-substring-no-properties beg end)) 2422 (let* ((hunk (buffer-substring-no-properties beg end))
2424 ;; Trim a trailing newline to find hunk in diff-syntax-fontify-props 2423 ;; Trim a trailing newline to find hunk in diff-syntax-fontify-props
2425 ;; in diffs that have no newline at end of diff file. 2424 ;; in diffs that have no newline at end of diff file.
2426 (text (string-trim-right (or (with-demoted-errors (diff-hunk-text hunk (not old) nil)) ""))) 2425 (text (string-trim-right
2426 (or (with-demoted-errors (diff-hunk-text hunk (not old) nil))
2427 "")))
2427 (line (if (looking-at "\\(?:\\*\\{15\\}.*\n\\)?[-@* ]*\\([0-9,]+\\)\\([ acd+]+\\([0-9,]+\\)\\)?") 2428 (line (if (looking-at "\\(?:\\*\\{15\\}.*\n\\)?[-@* ]*\\([0-9,]+\\)\\([ acd+]+\\([0-9,]+\\)\\)?")
2428 (if old (match-string 1) 2429 (if old (match-string 1)
2429 (if (match-end 3) (match-string 3) (match-string 1))))) 2430 (if (match-end 3) (match-string 3) (match-string 1)))))
@@ -2432,83 +2433,106 @@ When OLD is non-nil, highlight the hunk from the old source."
2432 (list (string-to-number (match-string 1 line)) 2433 (list (string-to-number (match-string 1 line))
2433 (string-to-number (match-string 2 line))) 2434 (string-to-number (match-string 2 line)))
2434 (list (string-to-number line) 1)))) ; One-line diffs 2435 (list (string-to-number line) 1)))) ; One-line diffs
2435 props) 2436 (props
2436 (cond 2437 (or
2437 ((and diff-vc-backend (not (eq diff-font-lock-syntax 'hunk-only))) 2438 (when (and diff-vc-backend
2438 (let* ((file (diff-find-file-name old t)) 2439 (not (eq diff-font-lock-syntax 'hunk-only)))
2439 (revision (and file (if (not old) (nth 1 diff-vc-revisions) 2440 (let* ((file (diff-find-file-name old t))
2440 (or (nth 0 diff-vc-revisions) 2441 (revision (and file (if (not old) (nth 1 diff-vc-revisions)
2441 (vc-working-revision file)))))) 2442 (or (nth 0 diff-vc-revisions)
2442 (if file 2443 (vc-working-revision file))))))
2443 (if (not revision) 2444 (when file
2444 ;; Get properties from the current working revision 2445 (if (not revision)
2445 (when (and (not old) (file-exists-p file) (file-regular-p file)) 2446 ;; Get properties from the current working revision
2446 ;; Try to reuse an existing buffer 2447 (when (and (not old) (file-exists-p file)
2447 (if (get-file-buffer (expand-file-name file)) 2448 (file-regular-p file))
2448 (with-current-buffer (get-file-buffer (expand-file-name file)) 2449 (let ((buf (get-file-buffer (expand-file-name file))))
2449 (setq props (diff-syntax-fontify-props nil text line-nb))) 2450 ;; Try to reuse an existing buffer
2450 ;; Get properties from the file 2451 (if buf
2451 (with-temp-buffer 2452 (with-current-buffer buf
2452 (insert-file-contents file) 2453 (diff-syntax-fontify-props nil text line-nb))
2453 (setq props (diff-syntax-fontify-props file text line-nb))))) 2454 ;; Get properties from the file
2454 ;; Get properties from a cached revision 2455 (with-temp-buffer
2455 (let* ((buffer-name (format " *diff-syntax:%s.~%s~*" 2456 (insert-file-contents file)
2456 (expand-file-name file) revision)) 2457 (diff-syntax-fontify-props file text line-nb)))))
2457 (buffer (gethash buffer-name diff-syntax-fontify-revisions))) 2458 ;; Get properties from a cached revision
2458 (unless (and buffer (buffer-live-p buffer)) 2459 (let* ((buffer-name (format " *diff-syntax:%s.~%s~*"
2459 (let* ((vc-buffer (ignore-errors 2460 (expand-file-name file)
2460 (vc-find-revision-no-save 2461 revision))
2461 (expand-file-name file) revision 2462 (buffer (gethash buffer-name
2462 diff-vc-backend 2463 diff-syntax-fontify-revisions)))
2463 (get-buffer-create buffer-name))))) 2464 (unless (and buffer (buffer-live-p buffer))
2464 (when vc-buffer 2465 (let* ((vc-buffer (ignore-errors
2465 (setq buffer vc-buffer) 2466 (vc-find-revision-no-save
2466 (puthash buffer-name buffer diff-syntax-fontify-revisions)))) 2467 (expand-file-name file) revision
2467 (when buffer 2468 diff-vc-backend
2468 (with-current-buffer buffer 2469 (get-buffer-create buffer-name)))))
2469 (setq props (diff-syntax-fontify-props file text line-nb)))))) 2470 (when vc-buffer
2470 ;; If file is unavailable, get properties from the hunk alone 2471 (setq buffer vc-buffer)
2471 (setq file (car (diff-hunk-file-names old))) 2472 (puthash buffer-name buffer
2472 (with-temp-buffer 2473 diff-syntax-fontify-revisions))))
2473 (insert text) 2474 (when buffer
2474 (setq props (diff-syntax-fontify-props file text line-nb t)))))) 2475 (with-current-buffer buffer
2475 ((and diff-default-directory (not (eq diff-font-lock-syntax 'hunk-only))) 2476 (diff-syntax-fontify-props file text line-nb))))))))
2476 (let ((file (car (diff-hunk-file-names old)))) 2477 (let ((file (car (diff-hunk-file-names old))))
2477 (if (and file (file-exists-p file) (file-regular-p file)) 2478 (cond
2478 ;; Try to get full text from the file 2479 ((and file diff-default-directory
2479 (with-temp-buffer 2480 (not (eq diff-font-lock-syntax 'hunk-only))
2480 (insert-file-contents file) 2481 (not diff-vc-backend)
2481 (setq props (diff-syntax-fontify-props file text line-nb))) 2482 (file-readable-p file) (file-regular-p file))
2482 ;; Otherwise, get properties from the hunk alone 2483 ;; Try to get full text from the file.
2483 (with-temp-buffer 2484 (with-temp-buffer
2484 (insert text) 2485 (insert-file-contents file)
2485 (setq props (diff-syntax-fontify-props file text line-nb t)))))) 2486 (diff-syntax-fontify-props file text line-nb)))
2486 ((memq diff-font-lock-syntax '(hunk-also hunk-only)) 2487 ;; Otherwise, get properties from the hunk alone
2487 (let ((file (car (diff-hunk-file-names old)))) 2488 ((memq diff-font-lock-syntax '(hunk-also hunk-only))
2488 (with-temp-buffer 2489 (with-temp-buffer
2489 (insert text) 2490 (insert text)
2490 (setq props (diff-syntax-fontify-props file text line-nb t)))))) 2491 (diff-syntax-fontify-props file text line-nb t))))))))
2491 2492
2492 ;; Put properties over the hunk text 2493 ;; Put properties over the hunk text
2493 (goto-char beg) 2494 (goto-char beg)
2494 (when (and props (eq (diff-hunk-style) 'unified)) 2495 (when (and props (eq (diff-hunk-style) 'unified))
2495 (while (< (progn (forward-line 1) (point)) end) 2496 (while (< (progn (forward-line 1) (point)) end)
2496 (when (or (and (not old) (not (looking-at-p "[-<]"))) 2497 ;; Skip the "\ No newline at end of file" lines as well as the lines
2497 (and old (not (looking-at-p "[+>]")))) 2498 ;; corresponding to the "other" version.
2498 (unless (looking-at-p "\\\\") ; skip "\ No newline at end of file" 2499 (unless (looking-at-p (if old "[+>\\]" "[-<\\]"))
2499 (if (and old (not (looking-at-p "[-<]"))) 2500 (if (and old (not (looking-at-p "[-<]")))
2500 ;; Fontify context lines only from new source, 2501 ;; Fontify context lines only from new source,
2501 ;; don't refontify context lines from old source. 2502 ;; don't refontify context lines from old source.
2502 (pop props) 2503 (pop props)
2503 (let ((line-props (pop props)) 2504 (let ((line-props (pop props))
2504 (bol (1+ (point)))) 2505 (bol (1+ (point))))
2505 (dolist (prop line-props) 2506 (dolist (prop line-props)
2506 (let ((ol (make-overlay (+ bol (nth 0 prop)) 2507 ;; Ideally, we'd want to use text-properties as in:
2507 (+ bol (nth 1 prop)) 2508 ;;
2508 nil 'front-advance nil))) 2509 ;; (add-face-text-property
2509 (overlay-put ol 'diff-mode 'syntax) 2510 ;; (+ bol (nth 0 prop)) (+ bol (nth 1 prop))
2510 (overlay-put ol 'evaporate t) 2511 ;; (nth 2 prop) 'append)
2511 (overlay-put ol 'face (nth 2 prop)))))))))))) 2512 ;;
2513 ;; rather than overlays here, but they'd get removed by later
2514 ;; font-locking.
2515 ;; This is because we also apply faces outside of the
2516 ;; beg...end chunk currently font-locked and when font-lock
2517 ;; later comes to handle the rest of the hunk that we already
2518 ;; handled we don't (want to) redo it (we work at
2519 ;; hunk-granularity rather than font-lock's own chunk
2520 ;; granularity).
2521 ;; I see two ways to fix this:
2522 ;; - don't immediately apply the props that fall outside of
2523 ;; font-lock's chunk but stash them somewhere (e.g. in another
2524 ;; text property) and only later when font-lock comes back
2525 ;; move them to `face'.
2526 ;; - change the code so work at font-lock's chunk granularity
2527 ;; (this seems doable without too much extra overhead,
2528 ;; contrary to the refine highlighting, which inherently
2529 ;; works at a different granularity).
2530 (let ((ol (make-overlay (+ bol (nth 0 prop))
2531 (+ bol (nth 1 prop))
2532 nil 'front-advance nil)))
2533 (overlay-put ol 'diff-mode 'syntax)
2534 (overlay-put ol 'evaporate t)
2535 (overlay-put ol 'face (nth 2 prop)))))))))))
2512 2536
2513(defun diff-syntax-fontify-props (file text line-nb &optional hunk-only) 2537(defun diff-syntax-fontify-props (file text line-nb &optional hunk-only)
2514 "Get font-lock properties from the source code. 2538 "Get font-lock properties from the source code.
@@ -2516,21 +2540,23 @@ FILE is the name of the source file. If non-nil, it requests initialization
2516of the mode according to FILE. 2540of the mode according to FILE.
2517TEXT is the literal source text from hunk. 2541TEXT is the literal source text from hunk.
2518LINE-NB is a pair of numbers: start line number and the number of 2542LINE-NB is a pair of numbers: start line number and the number of
2519lines in the hunk. NO-INIT means no initialization is needed to set major 2543lines in the hunk.
2520mode. When HUNK-ONLY is non-nil, then don't verify the existence of the 2544When HUNK-ONLY is non-nil, then don't verify the existence of the
2521hunk text in the source file. Otherwise, don't highlight the hunk if the 2545hunk text in the source file. Otherwise, don't highlight the hunk if the
2522hunk text is not found in the source file." 2546hunk text is not found in the source file."
2523 (when file 2547 (when file
2524 ;; When initialization is requested, we should be in a brand new 2548 ;; When initialization is requested, we should be in a brand new
2525 ;; temp buffer. 2549 ;; temp buffer.
2526 (cl-assert (eq t buffer-undo-list))
2527 (cl-assert (not font-lock-mode))
2528 (cl-assert (null buffer-file-name)) 2550 (cl-assert (null buffer-file-name))
2529 (let ((enable-local-variables :safe) ;; to find `mode:' 2551 (let ((enable-local-variables :safe) ;; to find `mode:'
2530 (buffer-file-name file)) 2552 (buffer-file-name file))
2531 (set-auto-mode) 2553 (set-auto-mode)
2532 (when (and (memq 'generic-mode-find-file-hook find-file-hook) 2554 ;; FIXME: Is this really worth the trouble?
2533 (fboundp 'generic-mode-find-file-hook)) 2555 (when (and (fboundp 'generic-mode-find-file-hook)
2556 (memq #'generic-mode-find-file-hook
2557 ;; There's no point checking the buffer-local value,
2558 ;; we're in a fresh new buffer.
2559 (default-value 'find-file-hook)))
2534 (generic-mode-find-file-hook)))) 2560 (generic-mode-find-file-hook))))
2535 2561
2536 (let ((font-lock-defaults (or font-lock-defaults '(nil t))) 2562 (let ((font-lock-defaults (or font-lock-defaults '(nil t)))
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index 8bd1bbddb78..42710dd8dc9 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -350,7 +350,7 @@ The first subexpression is the actual text of the field.")
350(defun log-edit-goto-eoh () ;FIXME: Almost rfc822-goto-eoh! 350(defun log-edit-goto-eoh () ;FIXME: Almost rfc822-goto-eoh!
351 (goto-char (point-min)) 351 (goto-char (point-min))
352 (when (re-search-forward 352 (when (re-search-forward
353 "^\\([^[:alpha:]]\\|[[:alnum:]-]+[^[:alnum:]-:]\\)" nil 'move) 353 "^\\([^[:alpha:]]\\|[[:alnum:]-]+[^[:alnum:]-]\\)" nil 'move)
354 (goto-char (match-beginning 0)))) 354 (goto-char (match-beginning 0))))
355 355
356(defun log-edit--match-first-line (limit) 356(defun log-edit--match-first-line (limit)
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index e6f30c9f804..b992a8ebe09 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1806,7 +1806,12 @@ Return t if the buffer had changes, nil otherwise."
1806 1806
1807;;;###autoload 1807;;;###autoload
1808(defun vc-version-diff (_files rev1 rev2) 1808(defun vc-version-diff (_files rev1 rev2)
1809 "Report diffs between REV1 and REV2 revisions of the fileset." 1809 "Report diffs between revisions REV1 and REV2 in the repository history.
1810This compares two revisions of the current fileset.
1811If REV1 is nil, it defaults to the current revision, i.e. revision
1812of the last commit.
1813If REV2 is nil, it defaults to the work tree, i.e. the current
1814state of each file in the fileset."
1810 (interactive (vc-diff-build-argument-list-internal)) 1815 (interactive (vc-diff-build-argument-list-internal))
1811 ;; All that was just so we could do argument completion! 1816 ;; All that was just so we could do argument completion!
1812 (when (and (not rev1) rev2) 1817 (when (and (not rev1) rev2)
@@ -1891,8 +1896,14 @@ The merge base is a common ancestor between REV1 and REV2 revisions."
1891 1896
1892;;;###autoload 1897;;;###autoload
1893(defun vc-version-ediff (files rev1 rev2) 1898(defun vc-version-ediff (files rev1 rev2)
1894 "Show differences between revisions of the fileset in the 1899 "Show differences between REV1 and REV2 of FILES using ediff.
1895repository history using ediff." 1900This compares two revisions of the files in FILES. Currently,
1901only a single file's revisions can be compared, i.e. FILES can
1902specify only one file name.
1903If REV1 is nil, it defaults to the current revision, i.e. revision
1904of the last commit.
1905If REV2 is nil, it defaults to the work tree, i.e. the current
1906state of each file in FILES."
1896 (interactive (vc-diff-build-argument-list-internal)) 1907 (interactive (vc-diff-build-argument-list-internal))
1897 ;; All that was just so we could do argument completion! 1908 ;; All that was just so we could do argument completion!
1898 (when (and (not rev1) rev2) 1909 (when (and (not rev1) rev2)
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 52c0b5b74d2..b9f98cdc4c7 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -1163,8 +1163,9 @@ When not inside a field, signal an error."
1163 1163
1164(defun widget-at (&optional pos) 1164(defun widget-at (&optional pos)
1165 "The button or field at POS (default, point)." 1165 "The button or field at POS (default, point)."
1166 (or (get-char-property (or pos (point)) 'button) 1166 (let ((widget (or (get-char-property (or pos (point)) 'button)
1167 (widget-field-at pos))) 1167 (widget-field-at pos))))
1168 (and (widgetp widget) widget)))
1168 1169
1169;;;###autoload 1170;;;###autoload
1170(defun widget-setup () 1171(defun widget-setup ()
diff --git a/lisp/window.el b/lisp/window.el
index b769be06337..b4f5ac5cc44 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -9314,6 +9314,8 @@ is active. This function is run by `mouse-autoselect-window-timer'."
9314 ;; autoselection. 9314 ;; autoselection.
9315 (mouse-autoselect-window-start mouse-position window))))) 9315 (mouse-autoselect-window-start mouse-position window)))))
9316 9316
9317(declare-function display-multi-frame-p "frame" (&optional display))
9318
9317(defun handle-select-window (event) 9319(defun handle-select-window (event)
9318 "Handle select-window events." 9320 "Handle select-window events."
9319 (interactive "^e") 9321 (interactive "^e")
@@ -9351,7 +9353,7 @@ is active. This function is run by `mouse-autoselect-window-timer'."
9351 ;; we might get two windows with an active cursor. 9353 ;; we might get two windows with an active cursor.
9352 (select-window window) 9354 (select-window window)
9353 (cond 9355 (cond
9354 ((or (not (memq (window-system frame) '(x w32 ns))) 9356 ((or (not (display-multi-frame-p))
9355 (not focus-follows-mouse) 9357 (not focus-follows-mouse)
9356 ;; Focus FRAME if it's either a child frame or an ancestor 9358 ;; Focus FRAME if it's either a child frame or an ancestor
9357 ;; of the frame switched from. 9359 ;; of the frame switched from.
diff --git a/lisp/xml.el b/lisp/xml.el
index 2337952f064..b5b923f863e 100644
--- a/lisp/xml.el
+++ b/lisp/xml.el
@@ -718,10 +718,10 @@ This follows the rule [28] in the XML specifications."
718 (cond ((looking-at "PUBLIC\\s-+") 718 (cond ((looking-at "PUBLIC\\s-+")
719 (goto-char (match-end 0)) 719 (goto-char (match-end 0))
720 (unless (or (re-search-forward 720 (unless (or (re-search-forward
721 "\\=\"\\([[:space:][:alnum:]-'()+,./:=?;!*#@$_%]*\\)\"" 721 "\\=\"\\([[:space:][:alnum:]'()+,./:=?;!*#@$_%-]*\\)\""
722 nil t) 722 nil t)
723 (re-search-forward 723 (re-search-forward
724 "\\='\\([[:space:][:alnum:]-()+,./:=?;!*#@$_%]*\\)'" 724 "\\='\\([[:space:][:alnum:]()+,./:=?;!*#@$_%-]*\\)'"
725 nil t)) 725 nil t))
726 (error "XML: Missing Public ID")) 726 (error "XML: Missing Public ID"))
727 (let ((pubid (match-string-no-properties 1))) 727 (let ((pubid (match-string-no-properties 1)))