commit b8c43b594e4e8bf27b1b1c1693d48f07799a1aaf (HEAD, refs/remotes/origin/master) Author: Lars Ingebrigtsen Date: Wed Aug 4 10:35:53 2021 +0200 Add a new thing-at-point type: existing-filename * doc/lispref/text.texi (Buffer Contents): Mention it. * lisp/thingatpt.el (thing-at-point-file-at-point): New function. (existing-filename): Register it. diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index e18ba47282..9e0401fffb 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -315,10 +315,11 @@ word on the same line is acceptable. @defun thing-at-point thing &optional no-properties Return the @var{thing} around or next to point, as a string. -The argument @var{thing} is a symbol which specifies a kind of syntactic -entity. Possibilities include @code{symbol}, @code{list}, @code{sexp}, -@code{defun}, @code{filename}, @code{url}, @code{word}, @code{sentence}, -@code{whitespace}, @code{line}, @code{page}, and others. +The argument @var{thing} is a symbol which specifies a kind of +syntactic entity. Possibilities include @code{symbol}, @code{list}, +@code{sexp}, @code{defun}, @code{filename}, @code{existing-filename}, +@code{url}, @code{word}, @code{sentence}, @code{whitespace}, +@code{line}, @code{page}, and others. When the optional argument @var{no-properties} is non-@code{nil}, this function strips text properties from the return value. diff --git a/etc/NEWS b/etc/NEWS index 18cca8b4ab..f0fa686bc9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2639,6 +2639,11 @@ The semantics are as with 'walk-windows'. If non-nil, 'find-file-at-point' and friends will try to guess more expansively to identify a file name with spaces. ++++ +*** New 'thing-at-point' target: 'existing-filename'. +This is like 'filename', but is a full path, and is nil if the file +doesn't exist. + --- *** Two new commands for centering in 'doc-view-mode'. The new commands 'doc-view-center-page-horizontally' (bound to 'c h') diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el index 4c2470fbcb..5bbf1a85b3 100644 --- a/lisp/thingatpt.el +++ b/lisp/thingatpt.el @@ -73,8 +73,8 @@ provider functions are called with no parameters at the point in question. \"things\" include `symbol', `list', `sexp', `defun', `filename', -`url', `email', `uuid', `word', `sentence', `whitespace', `line', -and `page'.") +`existing-filename', `url', `email', `uuid', `word', `sentence', +`whitespace', `line', and `page'.") ;; Basic movement @@ -156,8 +156,8 @@ positions of the thing found." "Return the THING at point. THING should be a symbol specifying a type of syntactic entity. Possibilities include `symbol', `list', `sexp', `defun', -`filename', `url', `email', `uuid', `word', `sentence', `whitespace', -`line', `number', and `page'. +`filename', `existing-filename', `url', `email', `uuid', `word', +`sentence', `whitespace', `line', `number', and `page'. When the optional argument NO-PROPERTIES is non-nil, strip text properties from the return value. @@ -301,6 +301,17 @@ E.g.: (define-thing-chars filename thing-at-point-file-name-chars) +;; Files + +(defun thing-at-point-file-at-point (&optional _lax _bounds) + "Return the name of the existing file at point." + (when-let ((filename (thing-at-point 'filename))) + (setq filename (expand-file-name filename)) + (and (file-exists-p filename) + filename))) + +(put 'existing-filename 'thing-at-point 'thing-at-point-file-at-point) + ;; URIs (defvar thing-at-point-beginning-of-url-regexp nil commit b41f31d2b60269bd0e7addd1081f3738f91e76bc Author: Lars Ingebrigtsen Date: Wed Aug 4 10:03:12 2021 +0200 Make `M-j' work reliably if `comment-auto-fill-only-comments' is set * lisp/simple.el (default-indent-new-line): Force breaking the line when called interactively (bug#49849). (Perhaps the interactive command should be rebound and call this function instead...) diff --git a/lisp/simple.el b/lisp/simple.el index 5ec7fd80eb..3ad8634975 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8143,15 +8143,19 @@ is defined. The function should take a single optional argument, which is a flag indicating whether it should use soft newlines.") -(defun default-indent-new-line (&optional soft) +(defun default-indent-new-line (&optional soft force) "Break line at point and indent. If a comment syntax is defined, call `comment-line-break-function'. The inserted newline is marked hard if variable `use-hard-newlines' is true, unless optional argument SOFT is non-nil." - (interactive) + (interactive (list nil t)) (if comment-start - (funcall comment-line-break-function soft) + ;; Force breaking the line when called interactively. + (if force + (let ((comment-auto-fill-only-comments nil)) + (funcall comment-line-break-function soft)) + (funcall comment-line-break-function soft)) ;; Insert the newline before removing empty space so that markers ;; get preserved better. (if soft (insert-and-inherit ?\n) (newline 1)) commit 423a23ef7549ec425f26b537861c67e3ae78554c Author: Lars Ingebrigtsen Date: Wed Aug 4 09:38:45 2021 +0200 Improve `define-globalized-minor-mode' doc strings * lisp/emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Copy the description from easy-mmode--arg-docstring (bug#49843). diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index 3a00fdb454..8a2b3b4626 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -497,8 +497,11 @@ on if the hook has explicitly disabled it. ,(concat (format "Toggle %s in all buffers.\n" pretty-name) (internal--format-docstring-line "With prefix ARG, enable %s if ARG is positive; otherwise, \ -disable it. If called from Lisp, enable the mode if ARG is omitted or nil.\n\n" +disable it.\n\n" pretty-global-name) + "If called from Lisp, toggle the mode if ARG is `toggle'. +Enable the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number.\n\n" (internal--format-docstring-line "%s is enabled in all buffers where `%s' would do it.\n\n" pretty-name turn-on) commit 253b36bd40d1b342cdda09b0bee183788120f67e Author: dickmao Date: Tue Aug 3 12:02:48 2021 -0400 ffap ido accommodation Now that ffap-file-finder can be ido-find-file, the noninteractive portion of find-file-at-point cannot assume ffap-file-finder always takes an argument (ido-find-file does not). * lisp/ffap.el (find-file-at-point): Do not call ffap-file-finder. * test/lisp/ffap-tests.el (ffap-ido-mode): Test it. diff --git a/lisp/ffap.el b/lisp/ffap.el index b398d1c9f2..9be9c2906e 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1670,9 +1670,9 @@ See also the variables `ffap-dired-wildcards', `ffap-newfile-prompt', ((or (not ffap-newfile-prompt) (file-exists-p filename) (y-or-n-p "File does not exist, create buffer? ")) - (funcall ffap-file-finder - ;; expand-file-name fixes "~/~/.emacs" bug sent by CHUCKR. - (expand-file-name filename))) + (find-file + ;; expand-file-name fixes "~/~/.emacs" bug sent by CHUCKR. + (expand-file-name filename))) ;; User does not want to find a non-existent file: ((signal 'file-missing (list "Opening file buffer" "No such file or directory" diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el index 3ceb392d7f..4fb4c90e76 100644 --- a/test/lisp/ffap-tests.el +++ b/test/lisp/ffap-tests.el @@ -123,6 +123,21 @@ left alone when opening a URL in an external browser." (save-excursion (insert "type=")) (ffap-guess-file-name-at-point)))) +(ert-deftest ffap-ido-mode () + (require 'ido) + (with-temp-buffer + (let ((ido-mode t) + (read-filename-function read-file-name-function) + (read-buffer-function read-buffer-function)) + (ido-everywhere) + (let ((read-file-name-function (lambda (&rest args) + (expand-file-name + (nth 4 args) + (nth 1 args))))) + (save-excursion (insert "ffap-tests.el")) + (let (kill-buffer-query-functions) + (kill-buffer (call-interactively #'find-file-at-point))))))) + (provide 'ffap-tests) ;;; ffap-tests.el ends here commit b4f3e6cabafb3e04292a650874d977c692dbad22 Author: Miha Rihtaršič Date: Wed Aug 4 09:15:25 2021 +0200 Use `abort-minibuffers' in delsel * lisp/delsel.el (minibuffer-keyboard-quit): Use `abort-minibuffers' (bug#49821). Previously, C-g was bound to abort-recursive-edit, now it is bound to abort-minibuffers. However, after requiring delsel, it gets bound to minibuffer-keyboard-quit, which still uses abort-recursive-edit. Use the new function instead. diff --git a/lisp/delsel.el b/lisp/delsel.el index 3c99dd2344..93fdc6a886 100644 --- a/lisp/delsel.el +++ b/lisp/delsel.el @@ -300,7 +300,7 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer." (interactive) (if (and delete-selection-mode (region-active-p)) (setq deactivate-mark t) - (abort-recursive-edit))) + (abort-minibuffers))) (define-key minibuffer-local-map "\C-g" 'minibuffer-keyboard-quit) commit 51583a0f9f75950933a342a09ea3d317a528581e Author: martin rudalics Date: Wed Aug 4 08:48:18 2021 +0200 Add new user option 'read-minibuffer-restore-windows' * doc/lispref/minibuf.texi (Text from Minibuffer): Document it (bug#45072). * lisp/cus-start.el (standard): Add. * src/minibuf.c (syms_of_minibuf): New variable 'read-minibuffer-restore-windows'. diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index 196dd99076..d54c654562 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -469,6 +469,18 @@ If @var{default} is a non-@code{nil} list, the first element of the list is used in the prompt. @end defun +@defvar read-minibuffer-restore-windows +If this option is non-@code{nil} (the default), getting input from the +minibuffer will restore, on exit, the window configurations of the frame +where the minibuffer was entered from and, if it is different, the frame +that owns the minibuffer window. This means that if, for example, a +user splits a window while getting input from the minibuffer on the same +frame, that split will be undone when exiting the minibuffer. + +If this option is @code{nil}, no such restorations are done. Hence, the +window split mentioned above will persist after exiting the minibuffer. +@end defvar + @node Object from Minibuffer @section Reading Lisp Objects with the Minibuffer @cindex minibuffer input, reading lisp objects diff --git a/etc/NEWS b/etc/NEWS index 86aeea69ca..18cca8b4ab 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -178,6 +178,9 @@ behavior, which mixed these two, can be approximated by customizing 'minibuffer-follows-selected-frame' to a value which is neither nil nor t. ++++ +** New user option 'read-minibuffer-restore-windows'. + +++ ** New system for displaying documentation for groups of functions. This can either be used by saying 'M-x shortdoc-display-group' and diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 7df70d704e..27b98f2d80 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -431,6 +431,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of "21.1" :set minibuffer-prompt-properties--setter) (minibuffer-auto-raise minibuffer boolean) + (read-minibuffer-restore-windows boolean "28.1") ;; options property set at end (read-buffer-function minibuffer (choice (const nil) diff --git a/src/minibuf.c b/src/minibuf.c index 0f4349e70b..3ee0dca5e0 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -689,12 +689,15 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, call1 (Qpush_window_buffer_onto_prev, minibuf_window); record_unwind_protect_void (minibuffer_unwind); - record_unwind_protect (restore_window_configuration, - list3 (Fcurrent_window_configuration (Qnil), Qt, Qt)); + if (read_minibuffer_restore_windows) + record_unwind_protect (restore_window_configuration, + list3 (Fcurrent_window_configuration (Qnil), + Qt, Qt)); /* If the minibuffer window is on a different frame, save that frame's configuration too. */ - if (!EQ (mini_frame, selected_frame)) + if (read_minibuffer_restore_windows && + !EQ (mini_frame, selected_frame)) record_unwind_protect (restore_window_configuration, list3 (Fcurrent_window_configuration (mini_frame), Qnil, Qt)); @@ -2527,6 +2530,15 @@ for instance when running a headless Emacs server. Functions like instead. */); inhibit_interaction = 0; + DEFVAR_BOOL ("read-minibuffer-restore-windows", read_minibuffer_restore_windows, + doc: /* Non-nil means restore window configurations on exit from minibuffer. +If this is non-nil (the default), reading input with the minibuffer will +restore, on exit, the window configurations of the frame where the +minibuffer was entered from and, if it is different, the frame that owns +the associated minibuffer window. If this is nil, no such restorations +are done. */); + read_minibuffer_restore_windows = true; + defsubr (&Sactive_minibuffer_window); defsubr (&Sset_minibuffer_window); defsubr (&Sread_from_minibuffer); commit bee3e51550174047c73a1e942c16c8d45e2db1b8 Author: Lars Ingebrigtsen Date: Wed Aug 4 07:34:36 2021 +0200 Update outdated Gnus information * doc/misc/gnus.texi (History): Update information. diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index c46047ff77..c8d5a868ed 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -26860,9 +26860,10 @@ but at the common table.@* If you want to investigate the person responsible for this outrage, you can point your (feh!) web browser to -@uref{https://quimby.gnus.org/}. This is also the primary -distribution point for the new and spiffy versions of Gnus, and is -known as The Site That Destroys Newsrcs And Drives People Mad. +@uref{https://quimby.gnus.org/}. This used to be the primary +distribution point for the new and spiffy versions of Gnus, and was +known as The Site That Destroys Newsrcs And Drives People Mad, but +these days Gnus is developed in the Emacs repository. During the first extended alpha period of development, the new Gnus was called ``(ding) Gnus''. @dfn{(ding)} is, of course, short for commit b84986af52d4e9debace2850a5ec106f51e38e61 Author: Phil Sainty Date: Wed Aug 4 17:17:23 2021 +1200 ; * lisp/so-long.el: Bump version for the GNU ELPA build GNU ELPA released commit 359a8e4eda047b7dcb7e64faff7f8eaacf5d937c as version 1.1. diff --git a/lisp/so-long.el b/lisp/so-long.el index 829afd63ea..7bf15e85da 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -8,7 +8,7 @@ ;; Keywords: convenience ;; Created: 23 Dec 2015 ;; Package-Requires: ((emacs "24.4")) -;; Version: 1.1 +;; Version: 1.1.1 ;; This file is part of GNU Emacs. @@ -410,6 +410,7 @@ ;; * Change Log: ;; +;; 1.1.1 - Identical to 1.1, but fixing an incorrect GNU ELPA release. ;; 1.1 - Utilise `buffer-line-statistics' in Emacs 28+, with the new ;; `so-long-predicate' function `so-long-statistics-excessive-p'. ;; - Increase `so-long-threshold' from 250 to 10,000. commit 516affe1b3c1525d49fd7fd050a42d234470b4c6 Author: Lars Ingebrigtsen Date: Wed Aug 4 06:38:34 2021 +0200 Fix apparent typo in new cl-generic-tests.el test case diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el index 0093b04d1d..b48a48fb94 100644 --- a/test/lisp/emacs-lisp/cl-generic-tests.el +++ b/test/lisp/emacs-lisp/cl-generic-tests.el @@ -60,7 +60,7 @@ (defvar cl--generic-fooval 41) (cl-defmethod cl--generic-1 ((_x (eql (+ cl--generic-fooval 1))) _y) "forty-two") - (should (equal (cl--generic 42 nil) "forty-two"))) + (should (equal (cl--generic-1 42 nil) "forty-two"))) (cl-defstruct cl-generic-struct-parent a b) (cl-defstruct (cl-generic-struct-child1 (:include cl-generic-struct-parent)) c) commit b0d07396e8d970407a17388cdc207b9f3608f90e Author: Stefan Monnier Date: Tue Aug 3 19:02:11 2021 -0400 * lisp/emacs-lisp/cl-generic.el (cl-generic-generalizers): Don't emit warning Also remove "WARNING" annotations after confirming that he code was right. diff --git a/etc/NEWS b/etc/NEWS index fb6eddc754..86aeea69ca 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -813,7 +813,7 @@ It is now defined as a generalized variable that can be used with --- *** 'form' in '(eql form)' specializers in 'cl-defmethod' is now evaluated. This corresponds to the behaviour of defmethod in Common Lisp Object System. -A warning is issued when old style is used. +For compatibility, '(eql SYMBOL)' does not evaluate SYMBOL, for now. ** New minor mode 'cl-font-lock-built-in-mode' for 'lisp-mode'. The mode provides refined highlighting of built-in functions, types, diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 941e436ff7..db5a5a0c89 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -1161,7 +1161,12 @@ These match if the argument is `eql' to VAL." (let ((form (cadr specializer))) (puthash (if (or (not (symbolp form)) (macroexp-const-p form)) (eval form t) - (message "Quoting obsolete `eql' form: %S" specializer) + ;; FIXME: Compatibility with Emacs<28. For now emitting + ;; a warning would be annoying for third party packages + ;; which can't use the new form without breaking compatibility + ;; with older Emacsen, but in the future we should emit + ;; a warning. + ;; (message "Quoting obsolete `eql' form: %S" specializer) form) specializer cl--generic-eql-used)) (list cl--generic-eql-generalizer)) @@ -1274,11 +1279,6 @@ Used internally for the (major-mode MODE) context specializers." (cl-generic-define-context-rewriter major-mode (mode &rest modes) `(major-mode ,(if (consp mode) ;;E.g. could be (eql ...) - ;; WARNING: unsure whether this - ;; “could be (eql ...)” commentary (or code) - ;; should be adjusted - ;; following the (planned) changes to eql specializer. - ;; Bug #47327 (progn (cl-assert (null modes)) mode) `(derived-mode ,mode . ,modes)))) diff --git a/lisp/frame.el b/lisp/frame.el index 8c05ad2fe5..146fe278b3 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -36,11 +36,7 @@ as its argument.") (cl-generic-define-context-rewriter window-system (value) ;; If `value' is a `consp', it's probably an old-style specializer, ;; so just use it, and anyway `eql' isn't very useful on cons cells. - `(window-system ,(if (consp value) value - ;; WARNING: unsure whether this eql expression - ;; is actually an eql specializer. - ;; Bug #47327 - `(eql ',value)))) + `(window-system ,(if (consp value) value `(eql ',value)))) (cl-defmethod frame-creation-function (params &context (window-system nil)) ;; It's tempting to get rid of tty-create-frame-with-faces and turn it into commit 6535fd1fa9ac21238a168916249ac59677a6118e Author: akater Date: Tue Jul 20 01:25:01 2021 +0000 Evaluate eql specializers * lisp/emacs-lisp/cl-generic.el (cl-generic-generalizers): Evaluate forms that are eql specializers. Provide backward compatibility with a warning. * test/lisp/emacs-lisp/cl-generic-tests.el: Add a test. * lisp/emacs-lisp/bindat.el (bindat--type): Adhere to the new rule. * lisp/emacs-lisp/edebug.el (edebug--match-&-spec-op): Adhere to the new rule. * lisp/emacs-lisp/map.el (map-into): Adhere to the new rule. * lisp/emacs-lisp/radix-tree.el (map-into): Adhere to the new rule. * lisp/frame.el (cl-generic-define-context-rewriter): Adhere to the new rule. * lisp/gnus/gnus-search.el (gnus-search-transform-expression): Adhere to the new rule. * lisp/image/image-converter.el (image-converter--probe image-converter--convert): Adhere to the new rule. * lisp/mail/smtpmail.el (smtpmail-try-auth-method): Adhere to the new rule. * lisp/progmodes/elisp-mode.el (xref-backend-definitions) (xref-backend-apropos): Adhere to the new rule. * lisp/progmodes/etags.el (xref-backend-identifier-at-point) (xref-backend-identifier-completion-table) (xref-backend-identifier-completion-ignore-case) (xref-backend-definitions)(xref-backend-apropos): Adhere to the new rule. * test/lisp/emacs-lisp/checkdoc-tests.el (checkdoc-cl-defmethod-with-types-ok) (checkdoc-cl-defmethod-qualified-ok) (checkdoc-cl-defmethod-with-extra-qualifier-ok): Adhere to the new rule. * etc/NEWS: Describe the change. diff --git a/etc/NEWS b/etc/NEWS index 48dec0a2b3..fb6eddc754 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -810,6 +810,11 @@ work as before. It is now defined as a generalized variable that can be used with 'setf' to modify the value stored in a given class slot. +--- +*** 'form' in '(eql form)' specializers in 'cl-defmethod' is now evaluated. +This corresponds to the behaviour of defmethod in Common Lisp Object System. +A warning is issued when old style is used. + ** New minor mode 'cl-font-lock-built-in-mode' for 'lisp-mode'. The mode provides refined highlighting of built-in functions, types, and variables. diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 247fb91379..76c2e80fda 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -657,33 +657,33 @@ The port (if any) is omitted. IP can be a string, as well." OP can be one of: unpack', (pack VAL), or (length VAL) where VAL is the name of a variable that will hold the value we need to pack.") -(cl-defmethod bindat--type (op (_ (eql byte))) +(cl-defmethod bindat--type (op (_ (eql 'byte))) (bindat--pcase op ('unpack `(bindat--unpack-u8)) (`(length . ,_) `(cl-incf bindat-idx 1)) (`(pack . ,args) `(bindat--pack-u8 . ,args)))) -(cl-defmethod bindat--type (op (_ (eql uint)) n) +(cl-defmethod bindat--type (op (_ (eql 'uint)) n) (if (eq n 8) (bindat--type op 'byte) (bindat--pcase op ('unpack `(bindat--unpack-uint ,n)) (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8))) (`(pack . ,args) `(bindat--pack-uint ,n . ,args))))) -(cl-defmethod bindat--type (op (_ (eql uintr)) n) +(cl-defmethod bindat--type (op (_ (eql 'uintr)) n) (if (eq n 8) (bindat--type op 'byte) (bindat--pcase op ('unpack `(bindat--unpack-uintr ,n)) (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8))) (`(pack . ,args) `(bindat--pack-uintr ,n . ,args))))) -(cl-defmethod bindat--type (op (_ (eql str)) len) +(cl-defmethod bindat--type (op (_ (eql 'str)) len) (bindat--pcase op ('unpack `(bindat--unpack-str ,len)) (`(length . ,_) `(cl-incf bindat-idx ,len)) (`(pack . ,args) `(bindat--pack-str ,len . ,args)))) -(cl-defmethod bindat--type (op (_ (eql strz)) &optional len) +(cl-defmethod bindat--type (op (_ (eql 'strz)) &optional len) (bindat--pcase op ('unpack `(bindat--unpack-strz ,len)) (`(length ,val) @@ -701,25 +701,25 @@ is the name of a variable that will hold the value we need to pack.") (bindat--pack-str ,len . ,args) (bindat--pack-strz . ,args)))))) -(cl-defmethod bindat--type (op (_ (eql bits)) len) +(cl-defmethod bindat--type (op (_ (eql 'bits)) len) (bindat--pcase op ('unpack `(bindat--unpack-bits ,len)) (`(length . ,_) `(cl-incf bindat-idx ,len)) (`(pack . ,args) `(bindat--pack-bits ,len . ,args)))) -(cl-defmethod bindat--type (_op (_ (eql fill)) len) +(cl-defmethod bindat--type (_op (_ (eql 'fill)) len) `(progn (cl-incf bindat-idx ,len) nil)) -(cl-defmethod bindat--type (_op (_ (eql align)) len) +(cl-defmethod bindat--type (_op (_ (eql 'align)) len) `(progn (cl-callf bindat--align bindat-idx ,len) nil)) -(cl-defmethod bindat--type (op (_ (eql type)) exp) +(cl-defmethod bindat--type (op (_ (eql 'type)) exp) (bindat--pcase op ('unpack `(funcall (bindat--type-ue ,exp))) (`(length . ,args) `(funcall (bindat--type-le ,exp) . ,args)) (`(pack . ,args) `(funcall (bindat--type-pe ,exp) . ,args)))) -(cl-defmethod bindat--type (op (_ (eql vec)) count &rest type) +(cl-defmethod bindat--type (op (_ (eql 'vec)) count &rest type) (unless type (setq type '(byte))) (let ((fun (macroexpand-all (bindat--fun type) macroexpand-all-environment))) (bindat--pcase op @@ -743,10 +743,10 @@ is the name of a variable that will hold the value we need to pack.") `(dotimes (bindat--i ,count) (funcall ,fun (elt ,val bindat--i))))))) -(cl-defmethod bindat--type (op (_ (eql unit)) val) +(cl-defmethod bindat--type (op (_ (eql 'unit)) val) (pcase op ('unpack val) (_ nil))) -(cl-defmethod bindat--type (op (_ (eql struct)) &rest args) +(cl-defmethod bindat--type (op (_ (eql 'struct)) &rest args) (apply #'bindat--type op args)) (cl-defmethod bindat--type (op (_ (eql :pack-var)) var &rest fields) diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 544704be38..941e436ff7 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -1158,7 +1158,12 @@ These match if the argument is a cons cell whose car is `eql' to VAL." (cl-defmethod cl-generic-generalizers ((specializer (head eql))) "Support for (eql VAL) specializers. These match if the argument is `eql' to VAL." - (puthash (cadr specializer) specializer cl--generic-eql-used) + (let ((form (cadr specializer))) + (puthash (if (or (not (symbolp form)) (macroexp-const-p form)) + (eval form t) + (message "Quoting obsolete `eql' form: %S" specializer) + form) + specializer cl--generic-eql-used)) (list cl--generic-eql-generalizer)) (cl--generic-prefill-dispatchers 0 (eql nil)) @@ -1269,6 +1274,11 @@ Used internally for the (major-mode MODE) context specializers." (cl-generic-define-context-rewriter major-mode (mode &rest modes) `(major-mode ,(if (consp mode) ;;E.g. could be (eql ...) + ;; WARNING: unsure whether this + ;; “could be (eql ...)” commentary (or code) + ;; should be adjusted + ;; following the (planned) changes to eql specializer. + ;; Bug #47327 (progn (cl-assert (null modes)) mode) `(derived-mode ,mode . ,modes)))) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 2aec8197dc..7def9ff96a 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -1731,7 +1731,7 @@ contains a circular object." (defsubst edebug-match-body (cursor) (edebug-forms cursor)) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &optional)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&optional)) cursor specs) ;; Keep matching until one spec fails. (edebug-&optional-wrapper cursor specs #'edebug-&optional-wrapper)) @@ -1755,7 +1755,7 @@ contains a circular object." "Handle &foo spec operators. &foo spec operators operate on all the subsequent SPECS.") -(cl-defmethod edebug--match-&-spec-op ((_ (eql &rest)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&rest)) cursor specs) ;; Repeatedly use specs until failure. (let (edebug-best-error edebug-error-point) @@ -1768,7 +1768,7 @@ contains a circular object." (edebug-&optional-wrapper c (or s specs) rh))))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &or)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&or)) cursor specs) ;; Keep matching until one spec succeeds, and return its results. ;; If none match, fail. ;; This needs to be optimized since most specs spend time here. @@ -1792,7 +1792,7 @@ contains a circular object." (apply #'edebug-no-match cursor "Expected one of" original-specs)) )) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &interpose)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&interpose)) cursor specs) "Compute the specs for `&interpose SPEC FUN ARGS...'. Extracts the head of the data by matching it against SPEC, and then matches the rest by calling (FUN HEAD PF ARGS...) @@ -1817,7 +1817,7 @@ a sequence of elements." (append instrumented-head (edebug-match cursor newspecs))) ,@args)))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql ¬)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '¬)) cursor specs) ;; If any specs match, then fail (if (null (catch 'no-match (let ((edebug-gate nil)) @@ -1829,7 +1829,7 @@ a sequence of elements." ;; This means nothing matched, so it is OK. nil) ;; So, return nothing -(cl-defmethod edebug--match-&-spec-op ((_ (eql &key)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&key)) cursor specs) ;; Following specs must look like ( ) ... ;; where is the name of a keyword, and spec is its spec. ;; This really doesn't save much over the expanded form and takes time. @@ -1842,7 +1842,7 @@ a sequence of elements." (car (cdr pair)))) specs)))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &error)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&error)) cursor specs) ;; Signal an error, using the following string in the spec as argument. (let ((error-string (car specs)) (edebug-error-point (edebug-before-offset cursor))) @@ -1942,7 +1942,7 @@ a sequence of elements." (defun edebug-match-function (_cursor) (error "Use function-form instead of function in edebug spec")) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &define)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&define)) cursor specs) ;; Match a defining form. ;; Normally, &define is interpreted specially other places. ;; This should only be called inside of a spec list to match the remainder @@ -1958,7 +1958,7 @@ a sequence of elements." ;; Stop backtracking here (Bug#41988). (setq edebug-gate t))) -(cl-defmethod edebug--match-&-spec-op ((_ (eql &name)) cursor specs) +(cl-defmethod edebug--match-&-spec-op ((_ (eql '&name)) cursor specs) "Compute the name for `&name SPEC FUN` spec operator. The full syntax of that operator is: diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el index 5c76fb9eb9..c59342875d 100644 --- a/lisp/emacs-lisp/map.el +++ b/lisp/emacs-lisp/map.el @@ -407,15 +407,15 @@ See `map-into' for all supported values of TYPE." "Convert MAP into a map of TYPE.") ;; FIXME: I wish there was a way to avoid this η-redex! -(cl-defmethod map-into (map (_type (eql list))) +(cl-defmethod map-into (map (_type (eql 'list))) "Convert MAP into an alist." (map-pairs map)) -(cl-defmethod map-into (map (_type (eql alist))) +(cl-defmethod map-into (map (_type (eql 'alist))) "Convert MAP into an alist." (map-pairs map)) -(cl-defmethod map-into (map (_type (eql plist))) +(cl-defmethod map-into (map (_type (eql 'plist))) "Convert MAP into a plist." (let (plist) (map-do (lambda (k v) (setq plist `(,v ,k ,@plist))) map) @@ -510,7 +510,7 @@ KEYWORD-ARGS are forwarded to `make-hash-table'." map) ht)) -(cl-defmethod map-into (map (_type (eql hash-table))) +(cl-defmethod map-into (map (_type (eql 'hash-table))) "Convert MAP into a hash-table with keys compared with `equal'." (map--into-hash map (list :size (map-length map) :test #'equal))) diff --git a/lisp/emacs-lisp/radix-tree.el b/lisp/emacs-lisp/radix-tree.el index fb65975350..a529ed025d 100644 --- a/lisp/emacs-lisp/radix-tree.el +++ b/lisp/emacs-lisp/radix-tree.el @@ -240,7 +240,7 @@ PREFIX is only used internally." (declare-function map-apply "map" (function map)) (defun radix-tree-from-map (map) - ;; Aka (cl-defmethod map-into (map (type (eql radix-tree)))) ...) + ;; Aka (cl-defmethod map-into (map (type (eql 'radix-tree)))) ...) (require 'map) (let ((rt nil)) (map-apply (lambda (k v) (setq rt (radix-tree-insert rt k v))) map) diff --git a/lisp/frame.el b/lisp/frame.el index 9b3d120598..8c05ad2fe5 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -36,7 +36,11 @@ as its argument.") (cl-generic-define-context-rewriter window-system (value) ;; If `value' is a `consp', it's probably an old-style specializer, ;; so just use it, and anyway `eql' isn't very useful on cons cells. - `(window-system ,(if (consp value) value `(eql ,value)))) + `(window-system ,(if (consp value) value + ;; WARNING: unsure whether this eql expression + ;; is actually an eql specializer. + ;; Bug #47327 + `(eql ',value)))) (cl-defmethod frame-creation-function (params &context (window-system nil)) ;; It's tempting to get rid of tty-create-frame-with-faces and turn it into diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index 39bde837b3..53af2f6fe6 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -980,7 +980,7 @@ Responsible for handling and, or, and parenthetical expressions.") ;; Most search engines use implicit ANDs. (cl-defmethod gnus-search-transform-expression ((_ gnus-search-engine) - (_expr (eql and))) + (_expr (eql 'and))) nil) ;; Most search engines use explicit infixed ORs. diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el index e47f1f76e4..97bf1ac058 100644 --- a/lisp/image/image-converter.el +++ b/lisp/image/image-converter.el @@ -133,7 +133,7 @@ data is returned as a string." (list value) value))) -(cl-defmethod image-converter--probe ((type (eql graphicsmagick))) +(cl-defmethod image-converter--probe ((type (eql 'graphicsmagick))) "Check whether the system has GraphicsMagick installed." (with-temp-buffer (let ((command (image-converter--value type :command)) @@ -151,7 +151,7 @@ data is returned as a string." (push (downcase (match-string 1)) formats))) (nreverse formats))))) -(cl-defmethod image-converter--probe ((type (eql imagemagick))) +(cl-defmethod image-converter--probe ((type (eql 'imagemagick))) "Check whether the system has ImageMagick installed." (with-temp-buffer (let ((command (image-converter--value type :command)) @@ -171,7 +171,7 @@ data is returned as a string." (push (downcase (match-string 1)) formats))) (nreverse formats)))) -(cl-defmethod image-converter--probe ((type (eql ffmpeg))) +(cl-defmethod image-converter--probe ((type (eql 'ffmpeg))) "Check whether the system has ffmpeg installed." (with-temp-buffer (let ((command (image-converter--value type :command)) @@ -212,12 +212,12 @@ Only suffixes that map to `image-mode' are returned." 'image-mode) collect suffix)) -(cl-defmethod image-converter--convert ((type (eql graphicsmagick)) source +(cl-defmethod image-converter--convert ((type (eql 'graphicsmagick)) source image-format) "Convert using GraphicsMagick." (image-converter--convert-magick type source image-format)) -(cl-defmethod image-converter--convert ((type (eql imagemagick)) source +(cl-defmethod image-converter--convert ((type (eql 'imagemagick)) source image-format) "Convert using ImageMagick." (image-converter--convert-magick type source image-format)) @@ -249,7 +249,7 @@ Only suffixes that map to `image-mode' are returned." ;; error message. (buffer-string)))) -(cl-defmethod image-converter--convert ((type (eql ffmpeg)) source +(cl-defmethod image-converter--convert ((type (eql 'ffmpeg)) source image-format) "Convert using ffmpeg." (let ((command (image-converter--value type :command))) diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el index 133a2e1828..33bdd050bd 100644 --- a/lisp/mail/smtpmail.el +++ b/lisp/mail/smtpmail.el @@ -596,7 +596,7 @@ USER and PASSWORD should be non-nil." (error "Mechanism %S not implemented" mech)) (cl-defmethod smtpmail-try-auth-method - (process (_mech (eql cram-md5)) user password) + (process (_mech (eql 'cram-md5)) user password) (let ((ret (smtpmail-command-or-throw process "AUTH CRAM-MD5"))) (when (eq (car ret) 334) (let* ((challenge (substring (cadr ret) 4)) @@ -618,13 +618,13 @@ USER and PASSWORD should be non-nil." (smtpmail-command-or-throw process encoded))))) (cl-defmethod smtpmail-try-auth-method - (process (_mech (eql login)) user password) + (process (_mech (eql 'login)) user password) (smtpmail-command-or-throw process "AUTH LOGIN") (smtpmail-command-or-throw process (base64-encode-string user t)) (smtpmail-command-or-throw process (base64-encode-string password t))) (cl-defmethod smtpmail-try-auth-method - (process (_mech (eql plain)) user password) + (process (_mech (eql 'plain)) user password) ;; We used to send an empty initial request, and wait for an ;; empty response, and then send the password, but this ;; violate a SHOULD in RFC 2222 paragraph 5.1. Note that this diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 7ed2d3d08c..542f8ad0b1 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -696,7 +696,7 @@ Each function should return a list of xrefs, or nil; the first non-nil result supersedes the xrefs produced by `elisp--xref-find-definitions'.") -(cl-defmethod xref-backend-definitions ((_backend (eql elisp)) identifier) +(cl-defmethod xref-backend-definitions ((_backend (eql 'elisp)) identifier) (require 'find-func) ;; FIXME: use information in source near point to filter results: ;; (dvc-log-edit ...) - exclude 'feature @@ -875,7 +875,7 @@ non-nil result supersedes the xrefs produced by (declare-function xref-apropos-regexp "xref" (pattern)) -(cl-defmethod xref-backend-apropos ((_backend (eql elisp)) pattern) +(cl-defmethod xref-backend-apropos ((_backend (eql 'elisp)) pattern) (apply #'nconc (let ((regexp (xref-apropos-regexp pattern)) lst) @@ -893,7 +893,8 @@ non-nil result supersedes the xrefs produced by (facep sym))) 'strict)) -(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql elisp))) +(cl-defmethod xref-backend-identifier-completion-table ((_backend + (eql 'elisp))) elisp--xref-identifier-completion-table) (cl-defstruct (xref-elisp-location diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index f0180ceeec..ce1d8e5e62 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -2062,19 +2062,21 @@ file name, add `tag-partial-file-name-match-p' to the list value.") ;;;###autoload (defun etags--xref-backend () 'etags) -(cl-defmethod xref-backend-identifier-at-point ((_backend (eql etags))) +(cl-defmethod xref-backend-identifier-at-point ((_backend (eql 'etags))) (find-tag--default)) -(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql etags))) +(cl-defmethod xref-backend-identifier-completion-table ((_backend + (eql 'etags))) (tags-lazy-completion-table)) -(cl-defmethod xref-backend-identifier-completion-ignore-case ((_backend (eql etags))) +(cl-defmethod xref-backend-identifier-completion-ignore-case ((_backend + (eql 'etags))) (find-tag--completion-ignore-case)) -(cl-defmethod xref-backend-definitions ((_backend (eql etags)) symbol) +(cl-defmethod xref-backend-definitions ((_backend (eql 'etags)) symbol) (etags--xref-find-definitions symbol)) -(cl-defmethod xref-backend-apropos ((_backend (eql etags)) pattern) +(cl-defmethod xref-backend-apropos ((_backend (eql 'etags)) pattern) (etags--xref-find-definitions (xref-apropos-regexp pattern) t)) (defun etags--xref-find-definitions (pattern &optional regexp?) diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el b/test/lisp/emacs-lisp/checkdoc-tests.el index 7a7aa9fb3c..2a1d8b2763 100644 --- a/test/lisp/emacs-lisp/checkdoc-tests.el +++ b/test/lisp/emacs-lisp/checkdoc-tests.el @@ -49,27 +49,27 @@ (with-temp-buffer (emacs-lisp-mode) ;; this method matches if A is the symbol `smthg' and if b is a list: - (insert "(cl-defmethod foo ((a (eql smthg)) (b list)) \"Return A+B.\")") + (insert "(cl-defmethod foo ((a (eql 'smthg)) (b list)) \"Return A+B.\")") (checkdoc-defun))) (ert-deftest checkdoc-cl-defmethod-qualified-ok () "Checkdoc should be happy with a `cl-defmethod' using qualifiers." (with-temp-buffer (emacs-lisp-mode) - (insert "(cl-defmethod test :around ((a (eql smthg))) \"Return A.\")") + (insert "(cl-defmethod test :around ((a (eql 'smthg))) \"Return A.\")") (checkdoc-defun))) (ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-ok () "Checkdoc should be happy with a :extra qualified `cl-defmethod'." (with-temp-buffer (emacs-lisp-mode) - (insert "(cl-defmethod foo :extra \"foo\" ((a (eql smthg))) \"Return A.\")") + (insert "(cl-defmethod foo :extra \"foo\" ((a (eql 'smthg))) \"Return A.\")") (checkdoc-defun)) (with-temp-buffer (emacs-lisp-mode) (insert - "(cl-defmethod foo :extra \"foo\" :after ((a (eql smthg))) \"Return A.\")") + "(cl-defmethod foo :extra \"foo\" :after ((a (eql 'smthg))) \"Return A.\")") (checkdoc-defun))) (ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-and-nil-args-ok () diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el index 9312fb44a1..0093b04d1d 100644 --- a/test/lisp/emacs-lisp/cl-generic-tests.el +++ b/test/lisp/emacs-lisp/cl-generic-tests.el @@ -56,7 +56,11 @@ (should (equal (cl--generic-1 'a nil) '(a))) (should (equal (cl--generic-1 4 nil) '("quatre" 4))) (should (equal (cl--generic-1 5 nil) '("cinq" 5))) - (should (equal (cl--generic-1 6 nil) '("six" a)))) + (should (equal (cl--generic-1 6 nil) '("six" a))) + (defvar cl--generic-fooval 41) + (cl-defmethod cl--generic-1 ((_x (eql (+ cl--generic-fooval 1))) _y) + "forty-two") + (should (equal (cl--generic 42 nil) "forty-two"))) (cl-defstruct cl-generic-struct-parent a b) (cl-defstruct (cl-generic-struct-child1 (:include cl-generic-struct-parent)) c) commit 88577aed3a17109bb7b13871f185133641c25e73 Author: Lars Ingebrigtsen Date: Tue Aug 3 19:41:57 2021 +0200 file-name-concat is not error free * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns): Declare file-name-concat as side-effect free. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index ad0273dc15..96072ea1b5 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1348,6 +1348,7 @@ See Info node `(elisp) Integer Basics'." elt encode-char exp expt encode-time error-message-string fboundp fceiling featurep ffloor file-directory-p file-exists-p file-locked-p file-name-absolute-p + file-name-concat file-newer-than-file-p file-readable-p file-symlink-p file-writable-p float float-time floor format format-time-string frame-first-window frame-root-window frame-selected-window @@ -1405,7 +1406,6 @@ See Info node `(elisp) Integer Basics'." current-buffer current-global-map current-indentation current-local-map current-minor-mode-maps current-time eobp eolp eq equal eventp - file-name-concat fixnump floatp following-char framep get-largest-window get-lru-window hash-table-p commit 301ce625cb4b04c6a1662605d0221099b1de6359 Author: Lars Ingebrigtsen Date: Tue Aug 3 19:08:43 2021 +0200 Declare file-name-concat as side-effect free * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns): Declare file-name-concat as side-effect (and error) free. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 2232617e5e..ad0273dc15 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1405,6 +1405,7 @@ See Info node `(elisp) Integer Basics'." current-buffer current-global-map current-indentation current-local-map current-minor-mode-maps current-time eobp eolp eq equal eventp + file-name-concat fixnump floatp following-char framep get-largest-window get-lru-window hash-table-p commit 354c682421e14669ecc6638d9490a821106de578 Author: Mattias Engdegård Date: Tue Aug 3 15:55:55 2021 +0200 Remove ineffective expression in verilog-mode * lisp/progmodes/verilog-mode.el (verilog-set-auto-endcomments): Remove expression that now elicits a byte-compiler warning. diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el index 2b88120eb9..7c8ccea065 100644 --- a/lisp/progmodes/verilog-mode.el +++ b/lisp/progmodes/verilog-mode.el @@ -5112,7 +5112,6 @@ primitive or interface named NAME." (;- task/function/initial et cetera t - (match-end 0) (goto-char (match-end 0)) (setq there (point)) (setq err nil) commit 0809c9f6ef1e575a28b64c040834991588adf383 Author: Mattias Engdegård Date: Tue Aug 3 15:28:10 2021 +0200 Declare `match-beginning` and `match-end` as side-effect-free * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns): Add functions. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 142f206428..2232617e5e 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1362,6 +1362,7 @@ See Info node `(elisp) Integer Basics'." local-variable-if-set-p local-variable-p locale-info log log10 logand logb logcount logior lognot logxor lsh make-byte-code make-list make-string make-symbol mark marker-buffer max + match-beginning match-end member memq memql min minibuffer-selected-window minibuffer-window mod multibyte-char-to-unibyte next-window nth nthcdr number-to-string parse-colon-path plist-get plist-member commit 3a56d4eea93e2fe832021a0685e2d9fe5bbd034b Merge: b44abacc8c 59128bb804 Author: Phil Sainty Date: Tue Aug 3 23:42:35 2021 +1200 Merge branch 'scratch/so-long' commit 59128bb804bf029b5a7555cab573e177269e0478 Author: Phil Sainty Date: Sun Jan 17 01:25:13 2021 +1300 Make `global-so-long-mode' use `buffer-line-statistics' * lisp/so-long.el: (so-long-statistics-excessive-p): New predicate function using `buffer-line-statistics'. (so-long-predicate): Use `so-long-statistics-excessive-p' by default. * etc/NEWS: Describe changes. * test/lisp/so-long-tests/so-long-tests-helpers.el: * test/lisp/so-long-tests/so-long-tests.el: Update tests. Also improve the existing `so-long-tests-predicate' tests. diff --git a/etc/NEWS b/etc/NEWS index 6fc3d6ebbc..48dec0a2b3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2856,10 +2856,18 @@ personal key ring. ** So Long +--- +*** New 'so-long-predicate' function 'so-long-statistics-excessive-p' +efficiently detects the presence of a long line anywhere in the buffer +using 'buffer-line-statistics' (see above). This is now the default +predicate (replacing 'so-long-detected-long-line-p'). + --- *** 'so-long-threshold' and 'so-long-max-lines' have been raised to -10000 characters and 500 lines respectively, to reduce the likelihood -of false-positives when 'global-so-long-mode' is enabled. +10000 bytes and 500 lines respectively, to reduce the likelihood of +false-positives when 'global-so-long-mode' is enabled. The latter +value is now only used by the old predicate, as the new predicate +knows the longest line in the entire buffer. --- *** 'so-long-target-modes' now includes 'fundamental-mode' by default, diff --git a/lisp/so-long.el b/lisp/so-long.el index 5b7086d78f..829afd63ea 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -128,9 +128,9 @@ ;; Use M-x customize-group RET so-long RET ;; (or M-x so-long-customize RET) ;; -;; The user options `so-long-target-modes', `so-long-threshold', and -;; `so-long-max-lines' determine whether action will be taken automatically when -;; visiting a file, and `so-long-action' determines what will be done. +;; The user options `so-long-target-modes' and `so-long-threshold' determine +;; whether action will be taken automatically when visiting a file, and +;; `so-long-action' determines what will be done. ;; * Actions and menus ;; ------------------- @@ -306,8 +306,9 @@ ;; the criteria for calling `so-long' in any given mode (plus its derivatives) ;; by setting buffer-local values for the variables in question. This includes ;; `so-long-predicate' itself, as well as any variables used by the predicate -;; when determining the result. By default this means `so-long-max-lines', -;; `so-long-skip-leading-comments', and `so-long-threshold'. E.g.: +;; when determining the result. By default this means `so-long-threshold' and +;; possibly also `so-long-max-lines' and `so-long-skip-leading-comments' (these +;; latter two are not used by default starting from Emacs 28.1). E.g.: ;; ;; (add-hook 'js-mode-hook 'my-js-mode-hook) ;; @@ -409,7 +410,9 @@ ;; * Change Log: ;; -;; 1.1 - Increase `so-long-threshold' from 250 to 10,000. +;; 1.1 - Utilise `buffer-line-statistics' in Emacs 28+, with the new +;; `so-long-predicate' function `so-long-statistics-excessive-p'. +;; - Increase `so-long-threshold' from 250 to 10,000. ;; - Increase `so-long-max-lines' from 5 to 500. ;; - Include `fundamental-mode' in `so-long-target-modes'. ;; - New user option `so-long-mode-preserved-minor-modes'. @@ -475,8 +478,10 @@ (defconst so-long--latest-version "1.1") +(declare-function buffer-line-statistics "fns.c" t t) ;; Emacs 28+ (declare-function longlines-mode "longlines") (defvar longlines-mode) + (defvar so-long-enabled nil ;; This was initially a renaming of the old `so-long-mode-enabled' and ;; documented as "Set to nil to prevent `so-long' from being triggered @@ -519,13 +524,21 @@ (defcustom so-long-threshold 10000 "Maximum line length permitted before invoking `so-long-function'. -See `so-long-detected-long-line-p' for details." +Line length is counted in either bytes or characters, depending on +`so-long-predicate'. + +This is the only variable used to determine the presence of long lines if +the `so-long-predicate' function is `so-long-statistics-excessive-p'." :type 'integer :package-version '(so-long . "1.1")) (defcustom so-long-max-lines 500 "Number of non-blank, non-comment lines to test for excessive length. +This option normally has no effect in Emacs versions >= 28.1, as the default +`so-long-predicate' sees the entire buffer. Older versions of Emacs still make +use of this option. + If nil then all lines will be tested, until either a long line is detected, or the end of the buffer is reached. @@ -540,6 +553,10 @@ See `so-long-detected-long-line-p' for details." (defcustom so-long-skip-leading-comments t "Non-nil to ignore all leading comments and whitespace. +This option normally has no effect in Emacs versions >= 28.1, as the default +`so-long-predicate' sees the entire buffer. Older versions of Emacs still make +use of this option. + If the file begins with a shebang (#!), this option also causes that line to be ignored even if it doesn't match the buffer's comment syntax, to ensure that comments following the shebang will be ignored. @@ -594,7 +611,9 @@ the mentioned options might interfere with some intended processing." (function :tag "Custom function")) :package-version '(so-long . "1.0")) -(defcustom so-long-predicate 'so-long-detected-long-line-p +(defcustom so-long-predicate (if (fboundp 'buffer-line-statistics) + 'so-long-statistics-excessive-p + 'so-long-detected-long-line-p) "Function, called after `set-auto-mode' to decide whether action is needed. Only called if the major mode is a member of `so-long-target-modes'. @@ -602,10 +621,14 @@ Only called if the major mode is a member of `so-long-target-modes'. The specified function will be called with no arguments. If it returns non-nil then `so-long' will be invoked. -Defaults to `so-long-detected-long-line-p'." - :type '(radio (const so-long-detected-long-line-p) +Defaults to `so-long-statistics-excessive-p' starting from Emacs 28.1, or +`so-long-detected-long-line-p' in earlier versions. + +Note that `so-long-statistics-excessive-p' requires Emacs 28.1 or later." + :type '(radio (const so-long-statistics-excessive-p) + (const so-long-detected-long-line-p) (function :tag "Custom function")) - :package-version '(so-long . "1.0")) + :package-version '(so-long . "1.1")) ;; Silence byte-compiler warning. `so-long-action-alist' is defined below ;; as a user option; but the definition sequence required for its setter @@ -1153,12 +1176,23 @@ serves the same purpose.") ;; We change automatically to faster code ;; And then I won't feel so mad +(defun so-long-statistics-excessive-p () + "Non-nil if the buffer contains a line longer than `so-long-threshold' bytes. + +This uses `buffer-line-statistics' (available from Emacs 28.1) to establish the +longest line in the buffer (counted in bytes rather than characters). + +This is the default value of `so-long-predicate' in Emacs versions >= 28.1. +\(In earlier versions `so-long-detected-long-line-p' is used by default.)" + (> (cadr (buffer-line-statistics)) + so-long-threshold)) + (defun so-long-detected-long-line-p () "Determine whether the current buffer contains long lines. Following any initial comments and blank lines, the next N lines of the buffer -will be tested for excessive length (where \"excessive\" means above -`so-long-threshold', and N is `so-long-max-lines'). +will be tested for excessive length (where \"excessive\" means greater than +`so-long-threshold' characters, and N is `so-long-max-lines'). Returns non-nil if any such excessive-length line is detected. @@ -1166,7 +1200,9 @@ If `so-long-skip-leading-comments' is nil then the N lines will be counted starting from the first line of the buffer. In this instance you will likely want to increase `so-long-max-lines' to allow for possible comments. -This is the default value of `so-long-predicate'." +This is the default `so-long-predicate' function in Emacs versions < 28.1. +\(Starting from 28.1, the default and recommended predicate function is +`so-long-statistics-excessive-p', which is faster and sees the entire buffer.)" (let ((count 0) start) (save-excursion (goto-char (point-min)) diff --git a/test/lisp/so-long-tests/so-long-tests-helpers.el b/test/lisp/so-long-tests/so-long-tests-helpers.el index 822b2ce4df..dd2331e6e4 100644 --- a/test/lisp/so-long-tests/so-long-tests-helpers.el +++ b/test/lisp/so-long-tests/so-long-tests-helpers.el @@ -130,5 +130,12 @@ state against this remembered state." (push (cons mode (symbol-value mode)) so-long-tests-memory)))) +(defun so-long-tests-predicates () + "Return the list of testable predicate functions." + (if (fboundp 'buffer-line-statistics) + '(so-long-statistics-excessive-p + so-long-detected-long-line-p) + '(so-long-detected-long-line-p))) + (provide 'so-long-tests-helpers) ;;; so-long-tests-helpers.el ends here diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el index 291ec9a7ea..8e4597c946 100644 --- a/test/lisp/so-long-tests/so-long-tests.el +++ b/test/lisp/so-long-tests/so-long-tests.el @@ -57,101 +57,131 @@ (declare-function so-long-tests-assert-active "so-long-tests-helpers") (declare-function so-long-tests-assert-reverted "so-long-tests-helpers") (declare-function so-long-tests-assert-and-revert "so-long-tests-helpers") +(declare-function so-long-tests-predicates "so-long-tests-helpers") ;; Enable the automated behaviour for all tests. (global-so-long-mode 1) (ert-deftest so-long-tests-threshold-under () "Under line length threshold." - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - (insert (make-string (1- so-long-threshold) ?x)) - (normal-mode) - (should (eq major-mode 'emacs-lisp-mode)))) + (dolist (so-long-predicate (so-long-tests-predicates)) + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (insert (make-string (1- so-long-threshold) ?x)) + (normal-mode) + (should (eq major-mode 'emacs-lisp-mode))))) (ert-deftest so-long-tests-threshold-at () "At line length threshold." - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - (insert (make-string (1- so-long-threshold) ?x)) - (normal-mode) - (should (eq major-mode 'emacs-lisp-mode)))) + (dolist (so-long-predicate (so-long-tests-predicates)) + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (insert (make-string (1- so-long-threshold) ?x)) + (normal-mode) + (should (eq major-mode 'emacs-lisp-mode))))) (ert-deftest so-long-tests-threshold-over () "Over line length threshold." - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - (normal-mode) - (so-long-tests-remember) - (insert (make-string (1+ so-long-threshold) ?x)) - (normal-mode) - (so-long-tests-assert-and-revert 'so-long-mode))) + (dolist (so-long-predicate (so-long-tests-predicates)) + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (normal-mode) + (so-long-tests-remember) + (insert (make-string (1+ so-long-threshold) ?x)) + (normal-mode) + (so-long-tests-assert-and-revert 'so-long-mode)))) (ert-deftest so-long-tests-skip-comments () "Skip leading shebang, whitespace, and comments." - ;; Long comment, no newline. - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - (insert (make-string (1+ so-long-threshold) ?\;)) - (normal-mode) - (should (eq major-mode 'emacs-lisp-mode))) - ;; Long comment, with newline. - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - (insert (make-string (1+ so-long-threshold) ?\;)) - (insert "\n") - (normal-mode) - (should (eq major-mode 'emacs-lisp-mode))) - ;; Long comment, with short text following. - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - (insert (make-string (1+ so-long-threshold) ?\;)) - (insert "\n") - (insert (make-string so-long-threshold ?x)) - (normal-mode) - (should (eq major-mode 'emacs-lisp-mode))) - ;; Long comment, with long text following. - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - (insert (make-string (1+ so-long-threshold) ?\;)) - (insert "\n") - (insert (make-string (1+ so-long-threshold) ?x)) - (normal-mode) - (should (eq major-mode 'so-long-mode)))) + ;; Only for `so-long-detected-long-line-p' -- comments are not + ;; treated differently when using `so-long-statistics-excessive-p'. + (dolist (so-long-predicate (so-long-tests-predicates)) + ;; Long comment, no newline. + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (insert (make-string (1+ so-long-threshold) ?\;)) + (normal-mode) + (should (eq major-mode + (cond ((eq so-long-predicate #'so-long-detected-long-line-p) + 'emacs-lisp-mode) + ((eq so-long-predicate #'so-long-statistics-excessive-p) + 'so-long-mode))))) + ;; Long comment, with newline. + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (insert (make-string (1+ so-long-threshold) ?\;)) + (insert "\n") + (normal-mode) + (should (eq major-mode + (cond ((eq so-long-predicate #'so-long-detected-long-line-p) + 'emacs-lisp-mode) + ((eq so-long-predicate #'so-long-statistics-excessive-p) + 'so-long-mode))))) + ;; Long comment, with short text following. + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (insert (make-string (1+ so-long-threshold) ?\;)) + (insert "\n") + (insert (make-string so-long-threshold ?x)) + (normal-mode) + (should (eq major-mode + (cond ((eq so-long-predicate #'so-long-detected-long-line-p) + 'emacs-lisp-mode) + ((eq so-long-predicate #'so-long-statistics-excessive-p) + 'so-long-mode))))) + ;; Long comment, with long text following. + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (insert (make-string (1+ so-long-threshold) ?\;)) + (insert "\n") + (insert (make-string (1+ so-long-threshold) ?x)) + (normal-mode) + (should (eq major-mode 'so-long-mode))))) (ert-deftest so-long-tests-max-lines () "Give up after `so-long-max-lines'." - (with-temp-buffer - (display-buffer (current-buffer)) - (insert "#!emacs\n") - ;; Insert exactly `so-long-max-lines' non-comment lines, followed - ;; by a long line. - (dotimes (_ so-long-max-lines) - (insert "x\n")) - (insert (make-string (1+ so-long-threshold) ?x)) - (normal-mode) - (should (eq major-mode 'emacs-lisp-mode)) - ;; If `so-long-max-lines' is nil, don't give up the search. - (let ((so-long-max-lines nil)) - (normal-mode) - (should (eq major-mode 'so-long-mode))) - ;; If `so-long-skip-leading-comments' is nil, all lines are - ;; counted, and so the shebang line counts, which makes the - ;; long line one line further away. - (let ((so-long-skip-leading-comments nil) - (so-long-max-lines (1+ so-long-max-lines))) + ;; Only for `so-long-detected-long-line-p' -- the whole buffer is + ;; 'seen' when using `so-long-statistics-excessive-p'. + (dolist (so-long-predicate (so-long-tests-predicates)) + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + ;; Insert exactly `so-long-max-lines' non-comment lines, followed + ;; by a long line. + (dotimes (_ so-long-max-lines) + (insert "x\n")) + (insert (make-string (1+ so-long-threshold) ?x)) (normal-mode) - (should (eq major-mode 'emacs-lisp-mode)) - (let ((so-long-max-lines (1+ so-long-max-lines))) + (should (eq major-mode + (cond ((eq so-long-predicate #'so-long-detected-long-line-p) + 'emacs-lisp-mode) + ((eq so-long-predicate #'so-long-statistics-excessive-p) + 'so-long-mode)))) + ;; If `so-long-max-lines' is nil, don't give up the search. + (let ((so-long-max-lines nil)) (normal-mode) - (should (eq major-mode 'so-long-mode)))))) + (should (eq major-mode 'so-long-mode))) + ;; If `so-long-skip-leading-comments' is nil, all lines are + ;; counted, and so the shebang line counts, which makes the + ;; long line one line further away. + (let ((so-long-skip-leading-comments nil) + (so-long-max-lines (1+ so-long-max-lines))) + (normal-mode) + (should (eq major-mode + (cond ((eq so-long-predicate #'so-long-detected-long-line-p) + 'emacs-lisp-mode) + ((eq so-long-predicate #'so-long-statistics-excessive-p) + 'so-long-mode)))) + (let ((so-long-max-lines (1+ so-long-max-lines))) + (normal-mode) + (should (eq major-mode 'so-long-mode))))))) (ert-deftest so-long-tests-invisible-buffer-function () "Call `so-long-invisible-buffer-function' in invisible buffers." @@ -382,17 +412,21 @@ (ert-deftest so-long-tests-predicate () "Custom predicate function." ;; Test the `so-long-predicate' user option. + ;; Always true. Trigger when we normally wouldn't. (with-temp-buffer (display-buffer (current-buffer)) (insert "#!emacs\n") - ;; Always false. - (let ((so-long-predicate #'ignore)) - (normal-mode) - (should (eq major-mode 'emacs-lisp-mode))) - ;; Always true. (let ((so-long-predicate (lambda () t))) (normal-mode) - (should (eq major-mode 'so-long-mode))))) + (should (eq major-mode 'so-long-mode)))) + ;; Always false. Don't trigger when we normally would. + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (insert (make-string (1+ so-long-threshold) ?x)) + (let ((so-long-predicate #'ignore)) + (normal-mode) + (should (eq major-mode 'emacs-lisp-mode))))) (ert-deftest so-long-tests-file-local-action () "File-local action." commit 12cbe8e50977fdbd342b9767e4e8bbd7430d3231 Author: Phil Sainty Date: Fri Jul 30 13:46:00 2021 +1200 ; Revert "Make `so-long' restore `view-mode'" This reverts commit 3c2db0c541491fceb7081d5b54de5abec25e2f4b. A more general solution to bug#45084 has been implemented via new user options `so-long-mode-preserved-variables' and `so-long-mode-preserved-minor-modes'. See the previous commit (before this revert) for details. diff --git a/lisp/so-long.el b/lisp/so-long.el index a74a9200de..5b7086d78f 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -1758,8 +1758,7 @@ invoking the new action." (when so-long--active (so-long-revert)) ;; Invoke the new action. - (let ((so-long--calling t) - (view-mode-active view-mode)) + (let ((so-long--calling t)) (so-long--ensure-enabled) ;; ACTION takes precedence if supplied. (when action @@ -1788,10 +1787,7 @@ invoking the new action." ;; functions need to modify the buffer. We use `inhibit-read-only' to ;; side-step the issue (and likewise in `so-long-revert'). (let ((inhibit-read-only t)) - (run-hooks 'so-long-hook)) - ;; Restore `view-mode'. - (when view-mode-active - (view-mode))))) + (run-hooks 'so-long-hook))))) (defun so-long-revert () "Revert the active `so-long-action' and run `so-long-revert-hook'. commit 10bd4bc6ecf8c4e2b22e02872823212a94a72ecc Author: Phil Sainty Date: Sun Jan 10 15:02:58 2021 +1300 Support 'preserved' variables and minor modes in `so-long-mode' The default values support preserving the state of `view-mode' when switching to (and reverting from) `so-long-mode' (bug#45084). * lisp/so-long.el (so-long-mode-preserved-variables) (so-long-mode-preserved-minor-modes): New user options. (so-long-mode-maintain-preserved-variables) (so-long-mode-maintain-preserved-minor-modes): New functions. (so-long-remember-all, so-long-after-change-major-mode) (so-long-mode-revert): Use them. * etc/NEWS: Describe changes. * test/lisp/so-long-tests/so-long-tests-helpers.el: * test/lisp/so-long-tests/so-long-tests.el: Update tests. diff --git a/etc/NEWS b/etc/NEWS index 66d240016c..6fc3d6ebbc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2868,6 +2868,12 @@ not recognised. (This only has an effect if 'set-auto-mode' chooses 'fundamental-mode'; buffers which are simply in 'fundamental-mode' by default are unaffected.) +--- +*** New user options 'so-long-mode-preserved-minor-modes' and +'so-long-mode-preserved-variables' allow specified mode and variable +states to be maintained if 'so-long-mode' replaces the original major +mode. By default, these new options support 'view-mode'. + * New Modes and Packages in Emacs 28.1 diff --git a/lisp/so-long.el b/lisp/so-long.el index dafcfaa18c..a74a9200de 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -214,6 +214,24 @@ ;; performance or otherwise avoid undesirable behaviours. If `so-long-revert' ;; is called, then the original values are restored. +;; * Retaining minor modes and settings when switching to `so-long-mode' +;; --------------------------------------------------------------------- +;; A consequence of switching to a new major mode is that many buffer-local +;; minor modes and variables from the original major mode will be disabled. +;; For performance purposes this is a desirable trait of `so-long-mode', but +;; specified modes and variables can also be preserved across the major mode +;; transition by customizing the `so-long-mode-preserved-minor-modes' and +;; `so-long-mode-preserved-variables' user options. +;; +;; When `so-long-mode' is called, the states of any modes and variables +;; configured by these options are remembered in the original major mode, and +;; reinstated after switching to `so-long-mode'. Likewise, if `so-long-revert' +;; is used to switch back to the original major mode, these modes and variables +;; are again set to the same states. +;; +;; The default values for these options ensure that if `view-mode' was active +;; in the original mode, then it will also be active in `so-long-mode'. + ;; * Hooks ;; ------- ;; `so-long-hook' runs at the end of the `so-long' command, after the configured @@ -394,6 +412,8 @@ ;; 1.1 - Increase `so-long-threshold' from 250 to 10,000. ;; - Increase `so-long-max-lines' from 5 to 500. ;; - Include `fundamental-mode' in `so-long-target-modes'. +;; - New user option `so-long-mode-preserved-minor-modes'. +;; - New user option `so-long-mode-preserved-variables'. ;; 1.0 - Included in Emacs 27.1, and in GNU ELPA for prior versions of Emacs. ;; - New global mode `global-so-long-mode' to enable/disable the library. ;; - New user option `so-long-action'. @@ -859,6 +879,44 @@ intended to be edited manually." (which-func-mode boolean)) :package-version '(so-long . "1.0")) +(defcustom so-long-mode-preserved-minor-modes + '(view-mode) + "List of buffer-local minor modes to preserve in `so-long-mode'. + +These will be enabled or disabled after switching to `so-long-mode' (by calling +them with the numeric argument 1 or 0) in accordance with their state in the +buffer's original major mode. Unknown modes, and modes which are already in the +desired state, are ignored. + +This happens before `so-long-variable-overrides' and `so-long-minor-modes' +have been processed. + +By default this happens only if `so-long-action' is set to `so-long-mode'. +If `so-long-revert' is subsequently invoked, then the modes are again set +to their original state after the original major mode has been called. + +See also `so-long-mode-preserved-variables' (processed after this)." + :type '(repeat symbol) ;; not function, as may be unknown => mismatch. + :package-version '(so-long . "1.1")) + +(defcustom so-long-mode-preserved-variables + '(view-old-buffer-read-only) + "List of buffer-local variables to preserve in `so-long-mode'. + +The original value of each variable will be maintained after switching to +`so-long-mode'. Unknown variables are ignored. + +This happens before `so-long-variable-overrides' and `so-long-minor-modes' +have been processed. + +By default this happens only if `so-long-action' is set to `so-long-mode'. +If `so-long-revert' is subsequently invoked, then the variables are again +set to their original values after the original major mode has been called. + +See also `so-long-mode-preserved-minor-modes' (processed before this)." + :type '(repeat variable) + :package-version '(so-long . "1.1")) + (defcustom so-long-hook nil "List of functions to call after `so-long' is called. @@ -945,9 +1003,16 @@ If RESET is non-nil, remove any existing values before storing the new ones." (setq so-long-original-values nil)) (so-long-remember 'so-long-variable-overrides) (so-long-remember 'so-long-minor-modes) + (so-long-remember 'so-long-mode-preserved-variables) + (so-long-remember 'so-long-mode-preserved-minor-modes) (dolist (ovar so-long-variable-overrides) (so-long-remember (car ovar))) (dolist (mode so-long-minor-modes) + (when (and (boundp mode) mode) + (so-long-remember mode))) + (dolist (var so-long-mode-preserved-variables) + (so-long-remember var)) + (dolist (mode so-long-mode-preserved-minor-modes) (when (and (boundp mode) mode) (so-long-remember mode)))) @@ -1333,6 +1398,16 @@ This advice acts before `so-long-mode', with the previous mode still active." "Run by `so-long-mode' in `after-change-major-mode-hook'. Calls `so-long-disable-minor-modes' and `so-long-override-variables'." + ;; Check/set the state of 'preserved' variables and minor modes. + ;; (See also `so-long-mode-revert'.) + ;; The "modes before variables" sequence is important for the default + ;; preserved mode `view-mode' which remembers the `buffer-read-only' state + ;; (which is also permanent-local). That causes problems unless we restore + ;; the original value of `view-old-buffer-read-only' after; otherwise the + ;; sequence `view-mode' -> `so-long' -> `so-long-revert' -> `view-mode' + ;; results in `view-mode' being disabled but the buffer still read-only. + (so-long-mode-maintain-preserved-minor-modes) + (so-long-mode-maintain-preserved-variables) ;; Disable minor modes. (so-long-disable-minor-modes) ;; Override variables (again). We already did this in `so-long-mode' in @@ -1377,7 +1452,7 @@ The variables are set in accordance with what was remembered in `so-long'." ;; In the instance where `so-long-mode-revert' has just reverted the major ;; mode, note that `kill-all-local-variables' was already called by the ;; original mode function, and so these 'overridden' variables may now have - ;; global rather than buffer-local values. + ;; global rather than buffer-local values (if they are not permanent-local). (let* ((remembered (so-long-original variable :exists)) (originally-local (nth 2 remembered))) (if originally-local @@ -1393,6 +1468,24 @@ The variables are set in accordance with what was remembered in `so-long'." ;; the old value as a buffer-local value, so we keep it simple. (kill-local-variable variable)))) +(defun so-long-mode-maintain-preserved-variables () + "Set any 'preserved' variables. + +The variables are set in accordance with what was remembered in `so-long'." + (dolist (var (so-long-original 'so-long-mode-preserved-variables)) + (so-long-restore-variable var))) + +(defun so-long-mode-maintain-preserved-minor-modes () + "Enable or disable 'preserved' minor modes. + +The modes are set in accordance with what was remembered in `so-long'." + (dolist (mode (so-long-original 'so-long-mode-preserved-minor-modes)) + (when (boundp mode) + (let ((original (so-long-original mode)) + (current (symbol-value mode))) + (unless (equal current original) + (funcall mode (if original 1 0))))))) + (defun so-long-mode-revert () "Call the `major-mode' which was selected before `so-long-mode' replaced it. @@ -1420,6 +1513,10 @@ This is the `so-long-revert-function' for `so-long-mode'." ;; `kill-all-local-variables' was already called by the original mode ;; function, so we may be seeing global values. (so-long-restore-variables) + ;; Check/set the state of 'preserved' variables and minor modes. + ;; (Refer to `so-long-after-change-major-mode' regarding the sequence.) + (so-long-mode-maintain-preserved-minor-modes) + (so-long-mode-maintain-preserved-variables) ;; Restore the mode line construct. (unless (derived-mode-p 'so-long-mode) (setq so-long-mode-line-info (so-long-mode-line-info))))) diff --git a/test/lisp/so-long-tests/so-long-tests-helpers.el b/test/lisp/so-long-tests/so-long-tests-helpers.el index ab4d9c6c13..822b2ce4df 100644 --- a/test/lisp/so-long-tests/so-long-tests-helpers.el +++ b/test/lisp/so-long-tests/so-long-tests-helpers.el @@ -43,7 +43,8 @@ (cl-case action ('so-long-mode (should (eq major-mode 'so-long-mode)) - (so-long-tests-assert-overrides)) + (so-long-tests-assert-overrides) + (so-long-tests-assert-preserved)) ('so-long-minor-mode (should (eq so-long-minor-mode t)) (so-long-tests-assert-overrides)) @@ -62,7 +63,8 @@ (cl-case action ('so-long-mode (should-not (eq major-mode 'so-long-mode)) - (so-long-tests-assert-overrides-reverted)) + (so-long-tests-assert-overrides-reverted) + (so-long-tests-assert-preserved)) ('so-long-minor-mode (should-not (eq so-long-minor-mode t)) (so-long-tests-assert-overrides-reverted)) @@ -90,6 +92,17 @@ (when (boundp (car ovar)) (should (equal (symbol-value (car ovar)) (cdr ovar)))))) +(defun so-long-tests-assert-preserved () + "Assert that preserved modes and variables have their expected values." + (dolist (var so-long-mode-preserved-variables) + (when (boundp var) + (should (equal (symbol-value var) + (alist-get var so-long-tests-memory))))) + (dolist (mode so-long-mode-preserved-minor-modes) + (when (boundp mode) + (should (equal (symbol-value mode) + (alist-get mode so-long-tests-memory)))))) + (defun so-long-tests-remember () "Remember the original states of modes and variables. @@ -105,6 +118,14 @@ state against this remembered state." (push (cons (car ovar) (symbol-value (car ovar))) so-long-tests-memory))) (dolist (mode so-long-minor-modes) + (when (boundp mode) + (push (cons mode (symbol-value mode)) + so-long-tests-memory))) + (dolist (var so-long-mode-preserved-variables) + (when (boundp var) + (push (cons var (symbol-value var)) + so-long-tests-memory))) + (dolist (mode so-long-mode-preserved-minor-modes) (when (boundp mode) (push (cons mode (symbol-value mode)) so-long-tests-memory)))) diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el index 80f1c477cf..291ec9a7ea 100644 --- a/test/lisp/so-long-tests/so-long-tests.el +++ b/test/lisp/so-long-tests/so-long-tests.el @@ -327,6 +327,58 @@ (normal-mode) (should (eq major-mode 'so-long-mode))))) +(ert-deftest so-long-tests-preserved-variables-and-modes () + "Preserved variables and minor modes when using `so-long-mode'." + ;; Test the user options `so-long-mode-preserved-variables' and + ;; `so-long-mode-preserved-minor-modes'. The minor mode `view-mode' + ;; is 'preserved' by default (using both options). + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (normal-mode) + ;; We enable `view-mode' before triggering `so-long'. + (insert (make-string (1+ so-long-threshold) ?x)) + (view-mode 1) + (should (eq view-mode t)) + (should (eq buffer-read-only t)) + (so-long-tests-remember) + (let ((so-long-action 'so-long-mode) + (menu (so-long-menu))) + (so-long) + (so-long-tests-assert-active 'so-long-mode) + (should (eq view-mode t)) + (should (eq buffer-read-only t)) + ;; Revert. + (funcall (lookup-key menu [so-long-revert])) + (so-long-tests-assert-reverted 'so-long-mode) + (should (eq view-mode t)) + (should (eq buffer-read-only t)) + ;; Disable `view-mode'. Note that without the preserved + ;; variables, the conflict between how `view-mode' and `so-long' + ;; each deal with the buffer's original `buffer-read-only' value + ;; would lead to a situation whereby the buffer would still be + ;; read-only after `view-mode' had been disabled. + (view-mode 0) + (should (eq view-mode nil)) + (should (eq buffer-read-only nil)))) + ;; Without `view-mode'. + (with-temp-buffer + (display-buffer (current-buffer)) + (insert "#!emacs\n") + (normal-mode) + (insert (make-string (1+ so-long-threshold) ?x)) + (should (eq view-mode nil)) + (so-long-tests-remember) + (let ((so-long-action 'so-long-mode) + (menu (so-long-menu))) + (so-long) + (so-long-tests-assert-active 'so-long-mode) + (should (eq view-mode nil)) + ;; Revert. + (funcall (lookup-key menu [so-long-revert])) + (so-long-tests-assert-reverted 'so-long-mode) + (should (eq view-mode nil))))) + (ert-deftest so-long-tests-predicate () "Custom predicate function." ;; Test the `so-long-predicate' user option. commit 0ec67a295632f3c4ac92e0b6a0070f67dedac4eb Author: Phil Sainty Date: Sat Mar 20 21:48:18 2021 +1300 ; so-long-tests.el: Suppress expected warnings * test/lisp/so-long-tests/so-long-tests.el (so-long-tests-invisible-buffer-function): Suppress warning about obsolete function `run-window-configuration-change-hook', as we are using it intentionally (see the preceding code comments and URL for details). diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el index 56c20e63b5..80f1c477cf 100644 --- a/test/lisp/so-long-tests/so-long-tests.el +++ b/test/lisp/so-long-tests/so-long-tests.el @@ -195,7 +195,9 @@ ;; Emacs adds the framework necessary to make `redisplay' work ;; in batch mode. (unless (eq so-long--active t) - (run-window-configuration-change-hook)))) + (with-suppressed-warnings + ((obsolete run-window-configuration-change-hook)) + (run-window-configuration-change-hook))))) (so-long-tests-assert-and-revert 'so-long-mode)) ;; `so-long-invisible-buffer-function' is `nil'. (with-temp-buffer @@ -230,7 +232,9 @@ (redisplay) (when noninteractive (unless (eq so-long--active t) - (run-window-configuration-change-hook)))) + (with-suppressed-warnings + ((obsolete run-window-configuration-change-hook)) + (run-window-configuration-change-hook))))) (should (eq major-mode 'emacs-lisp-mode)))) (ert-deftest so-long-tests-actions () commit 748df220efdd46439578f252ee18091770c82af6 Author: Phil Sainty Date: Sun Jan 10 15:20:51 2021 +1300 ; * lisp/so-long.el: Minor bug fixes (so-long-disable-minor-modes): Don't call the mode function to disable the mode unless it was actually enabled. (so-long-restore-minor-modes, so-long-restore-variables): Use the remembered list values, which might be different to the defaults. Also comments, and spelling consistency changes for the so-long tests (a fixup for commit 83bc4ad369 which had only addressed so-long.el, and not the test files). diff --git a/lisp/so-long.el b/lisp/so-long.el index 8dd2d1a902..dafcfaa18c 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -1346,14 +1346,15 @@ Calls `so-long-disable-minor-modes' and `so-long-override-variables'." (defun so-long-disable-minor-modes () "Disable any active minor modes listed in `so-long-minor-modes'." (dolist (mode (so-long-original 'so-long-minor-modes)) - (when (and (boundp mode) mode) + (when (and (boundp mode) + (symbol-value mode)) (funcall mode 0)))) (defun so-long-restore-minor-modes () "Restore the minor modes which were disabled. The modes are enabled in accordance with what was remembered in `so-long'." - (dolist (mode so-long-minor-modes) + (dolist (mode (so-long-original 'so-long-minor-modes)) (when (and (so-long-original mode) (boundp mode) (not (symbol-value mode))) @@ -1368,7 +1369,7 @@ The modes are enabled in accordance with what was remembered in `so-long'." "Restore the remembered values for the overridden variables. The variables are set in accordance with what was remembered in `so-long'." - (dolist (ovar so-long-variable-overrides) + (dolist (ovar (so-long-original 'so-long-variable-overrides)) (so-long-restore-variable (car ovar)))) (defun so-long-restore-variable (variable) diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el index a6d8721ffc..56c20e63b5 100644 --- a/test/lisp/so-long-tests/so-long-tests.el +++ b/test/lisp/so-long-tests/so-long-tests.el @@ -58,7 +58,7 @@ (declare-function so-long-tests-assert-reverted "so-long-tests-helpers") (declare-function so-long-tests-assert-and-revert "so-long-tests-helpers") -;; Enable the automated behavior for all tests. +;; Enable the automated behaviour for all tests. (global-so-long-mode 1) (ert-deftest so-long-tests-threshold-under () @@ -180,7 +180,7 @@ ;; From Emacs 27 the `display-buffer' call is insufficient. ;; The various 'window change functions' are now invoked by the ;; redisplay, and redisplay does nothing at all in batch mode, - ;; so we cannot test under this revised behavior. Refer to: + ;; so we cannot test under this revised behaviour. Refer to: ;; https://lists.gnu.org/r/emacs-devel/2019-10/msg00971.html ;; For interactive (non-batch) test runs, calling `redisplay' ;; does do the trick; so do that first. @@ -405,7 +405,10 @@ (insert ,local-vars) (normal-mode) ;; Remember the `emacs-lisp-mode' state. The other cases - ;; will validate the 'reverted' state against this. + ;; will validate the 'reverted' state against this. (Note + ;; that we haven't displayed the buffer, and therefore only + ;; `so-long-invisible-buffer-function' has acted, so we are + ;; still remembering the 'before' state.) (so-long-tests-remember) (should (eq major-mode 'emacs-lisp-mode))) ;; Downgrade the action from major mode to minor mode. diff --git a/test/lisp/so-long-tests/spelling-tests.el b/test/lisp/so-long-tests/spelling-tests.el index 0be8555bdd..f778b64663 100644 --- a/test/lisp/so-long-tests/spelling-tests.el +++ b/test/lisp/so-long-tests/spelling-tests.el @@ -57,7 +57,7 @@ (unwind-protect (cl-letf (((symbol-function 'ispell-command-loop) (lambda (_miss _guess word _start _end) - (message "Unrecognized word: %s." word) + (message "Unrecognised word: %s." word) (throw 'mistake t)))) (catch 'mistake (find-library "so-long") commit 7828f69828fa4082771927993542a1f39abb0e61 Author: Phil Sainty Date: Sat Jul 4 01:44:32 2020 +1200 * lisp/so-long.el (so-long-minor-modes): Additional modes to disable diff --git a/lisp/so-long.el b/lisp/so-long.el index bcb670f654..8dd2d1a902 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -765,6 +765,7 @@ was established." display-line-numbers-mode flymake-mode flyspell-mode + glasses-mode goto-address-mode goto-address-prog-mode hi-lock-mode @@ -784,6 +785,8 @@ was established." hl-sexp-mode idle-highlight-mode rainbow-delimiters-mode + smartparens-mode + smartparens-strict-mode ) ;; It's not clear to me whether all of these would be problematic, but they ;; seemed like reasonable targets. Some are certainly excessive in smaller @@ -808,7 +811,7 @@ disabled modes are re-enabled by calling them with the numeric argument 1. Please submit bug reports to recommend additional modes for this list, whether they are in Emacs core, GNU ELPA, or elsewhere." :type '(repeat symbol) ;; not function, as may be unknown => mismatch. - :package-version '(so-long . "1.0")) + :package-version '(so-long . "1.1")) (defcustom so-long-variable-overrides '((bidi-inhibit-bpa . t) commit e8718522c22db801a7a89266cc5a9ee40c3fcbe0 Author: Phil Sainty Date: Sun Jan 10 14:43:16 2021 +1300 Make `global-so-long-mode' handle unrecognised file types * lisp/so-long.el (so-long-target-modes): Add `fundamental-mode' * etc/NEWS: Describe changes. This doesn't affect buffers which are simply in `fundamental-mode' by default. It only affects buffers for which `set-auto-mode' has been called (normally via `find-file') without establishing a different major mode. diff --git a/etc/NEWS b/etc/NEWS index 9f22d78159..66d240016c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2861,6 +2861,13 @@ personal key ring. 10000 characters and 500 lines respectively, to reduce the likelihood of false-positives when 'global-so-long-mode' is enabled. +--- +*** 'so-long-target-modes' now includes 'fundamental-mode' by default, +meaning that 'global-so-long-mode' will also process files which were +not recognised. (This only has an effect if 'set-auto-mode' chooses +'fundamental-mode'; buffers which are simply in 'fundamental-mode' by +default are unaffected.) + * New Modes and Packages in Emacs 28.1 diff --git a/lisp/so-long.el b/lisp/so-long.el index 58857deb47..bcb670f654 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -393,6 +393,7 @@ ;; ;; 1.1 - Increase `so-long-threshold' from 250 to 10,000. ;; - Increase `so-long-max-lines' from 5 to 500. +;; - Include `fundamental-mode' in `so-long-target-modes'. ;; 1.0 - Included in Emacs 27.1, and in GNU ELPA for prior versions of Emacs. ;; - New global mode `global-so-long-mode' to enable/disable the library. ;; - New user option `so-long-action'. @@ -528,7 +529,7 @@ See `so-long-detected-long-line-p' for details." :package-version '(so-long . "1.0")) (defcustom so-long-target-modes - '(prog-mode css-mode sgml-mode nxml-mode) + '(prog-mode css-mode sgml-mode nxml-mode fundamental-mode) "`so-long' affects only these modes and their derivatives. Our primary use-case is minified programming code, so `prog-mode' covers @@ -541,7 +542,7 @@ files would prevent Emacs from handling them correctly." ;; Use 'symbol', as 'function' may be unknown => mismatch. :type '(choice (repeat :tag "Specified modes" symbol) (const :tag "All modes" t)) - :package-version '(so-long . "1.0")) + :package-version '(so-long . "1.1")) (defcustom so-long-invisible-buffer-function #'so-long-deferred "Function called in place of `so-long' when the buffer is not displayed. commit 9df60d52d50b86639a82f22d7c0a07a81c3ba817 Author: Phil Sainty Date: Sun Jan 10 14:29:32 2021 +1300 Increase `so-long-threshold' and `so-long-max-lines' defaults * lisp/so-long.el (so-long-threshold, so-long-max-lines): Increase default values to reduce false-positives. * etc/NEWS: Describe changes. Lines shorter than 10,000 characters shouldn't generally be causing problems, so testing this explicitly will largely eliminate false-positives. We must also increase the maximum number of lines to check, because 'minified' code may still include newlines, and so there may be many lines shorter than the new threshold before we find a line which exceeds it. Previously we used a minimum-effort heuristic, testing a very small number of lines against a maximum length which, while not remotely long enough to cause problems, would nevertheless be uncommon in any normal file of programming code (and hence indicative that the file was likely to be minified code). Testing indicates that the performance penalty for the larger values should be negligible. diff --git a/etc/NEWS b/etc/NEWS index 95a2c87d05..9f22d78159 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2854,6 +2854,13 @@ GPG key servers can now be queried for keys with the 'M-x epa-search-keys' command. Keys can then be added to your personal key ring. +** So Long + +--- +*** 'so-long-threshold' and 'so-long-max-lines' have been raised to +10000 characters and 500 lines respectively, to reduce the likelihood +of false-positives when 'global-so-long-mode' is enabled. + * New Modes and Packages in Emacs 28.1 diff --git a/lisp/so-long.el b/lisp/so-long.el index bb996930b5..58857deb47 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -391,7 +391,8 @@ ;; * Change Log: ;; -;; 1.1 - ? +;; 1.1 - Increase `so-long-threshold' from 250 to 10,000. +;; - Increase `so-long-max-lines' from 5 to 500. ;; 1.0 - Included in Emacs 27.1, and in GNU ELPA for prior versions of Emacs. ;; - New global mode `global-so-long-mode' to enable/disable the library. ;; - New user option `so-long-action'. @@ -494,14 +495,14 @@ :prefix "so-long" :group 'convenience) -(defcustom so-long-threshold 250 +(defcustom so-long-threshold 10000 "Maximum line length permitted before invoking `so-long-function'. See `so-long-detected-long-line-p' for details." :type 'integer - :package-version '(so-long . "1.0")) + :package-version '(so-long . "1.1")) -(defcustom so-long-max-lines 5 +(defcustom so-long-max-lines 500 "Number of non-blank, non-comment lines to test for excessive length. If nil then all lines will be tested, until either a long line is detected, @@ -513,7 +514,7 @@ be counted. See `so-long-detected-long-line-p' for details." :type '(choice (integer :tag "Limit") (const :tag "Unlimited" nil)) - :package-version '(so-long . "1.0")) + :package-version '(so-long . "1.1")) (defcustom so-long-skip-leading-comments t "Non-nil to ignore all leading comments and whitespace. commit 359a8e4eda047b7dcb7e64faff7f8eaacf5d937c Author: Phil Sainty Date: Sun Jan 10 14:28:17 2021 +1300 ; * lisp/so-long.el: Bump to version 1.1 diff --git a/lisp/so-long.el b/lisp/so-long.el index 35a01894b4..bb996930b5 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -8,7 +8,7 @@ ;; Keywords: convenience ;; Created: 23 Dec 2015 ;; Package-Requires: ((emacs "24.4")) -;; Version: 1.0 +;; Version: 1.1 ;; This file is part of GNU Emacs. @@ -391,6 +391,7 @@ ;; * Change Log: ;; +;; 1.1 - ? ;; 1.0 - Included in Emacs 27.1, and in GNU ELPA for prior versions of Emacs. ;; - New global mode `global-so-long-mode' to enable/disable the library. ;; - New user option `so-long-action'. @@ -447,9 +448,10 @@ ;; (This eliminates the need for explicit :version keywords on the ;; custom definitions.) (add-to-list 'customize-package-emacs-version-alist - '(so-long ("1.0" . "27.1"))) + '(so-long ("1.0" . "27.1") + ("1.1" . "28.1"))) -(defconst so-long--latest-version "1.0") +(defconst so-long--latest-version "1.1") (declare-function longlines-mode "longlines") (defvar longlines-mode) commit 985a3bd3315e42032e970717d86c28b6f3392c43 Author: Phil Sainty Date: Mon Jan 11 01:58:26 2021 +1300 ; * lisp/so-long.el: Documentation diff --git a/lisp/so-long.el b/lisp/so-long.el index d765d3449c..35a01894b4 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -50,16 +50,17 @@ ;; performance further, as well as making the so-long activity more obvious to ;; the user. These kinds of minified files are typically not intended to be ;; edited, so not providing the usual editing mode in such cases will rarely be -;; an issue. However, you can reinstate the original state of the buffer by -;; calling `so-long-revert' (the key binding of which is advertised when the major -;; mode change occurs). If you prefer that the major mode not be changed, you -;; can customize the `so-long-minor-mode' action. +;; an issue; however you can restore the buffer to its original state by calling +;; `so-long-revert' (the key binding of which is advertised when the major mode +;; change occurs). If you prefer that the major mode not be changed in the +;; first place, there is a `so-long-minor-mode' action available, which you can +;; select by customizing the `so-long-action' user option. ;; ;; The user options `so-long-action' and `so-long-action-alist' determine what -;; actions `so-long' and `so-long-revert' will take. This allows you to configure -;; alternative actions (including custom actions). As well as -;; the major and minor mode actions provided by this library, `longlines-mode' -;; is also supported by default as an alternative action. +;; `so-long' and `so-long-revert' will do, enabling you to configure alternative +;; actions (including custom actions). As well as the major and minor mode +;; actions provided by this library, `longlines-mode' is also supported by +;; default as an alternative action. ;; ;; Note that while the measures taken can improve performance dramatically when ;; dealing with such files, this library does not have any effect on the @@ -152,7 +153,7 @@ ;; * Files with a file-local 'mode' ;; -------------------------------- ;; A file-local major mode is likely to be safe even if long lines are detected -;; (as the author of the file would otherwise be unlikely to have set that mode), +;; (the author of the file would otherwise be unlikely to have set that mode), ;; and so these files are treated as special cases. When a file-local 'mode' is ;; present, the function defined by the `so-long-file-local-mode-function' user ;; option is called. The default value will cause the `so-long-minor-mode' @@ -442,6 +443,9 @@ (require 'cl-lib) +;; Map each :package-version to the associated Emacs version. +;; (This eliminates the need for explicit :version keywords on the +;; custom definitions.) (add-to-list 'customize-package-emacs-version-alist '(so-long ("1.0" . "27.1"))) @@ -1191,7 +1195,8 @@ This minor mode is a standard `so-long-action' option." ;; Housekeeping. `so-long-minor-mode' might be invoked directly rather ;; than via `so-long', so replicate the necessary behaviours. The minor ;; mode also cares about whether `so-long' was already active, as we do - ;; not want to remember values which were potentially overridden already. + ;; not want to remember values which were (potentially) overridden + ;; already. (unless (or so-long--calling so-long--active) (so-long--ensure-enabled) (setq so-long--active t @@ -1896,7 +1901,7 @@ If it appears in `%s', you should remove it." (unless global-so-long-mode (global-so-long-mode 1))) (makunbound 'so-long-mode-enabled)) - ;; Update to version 1.N: + ;; Update to version 1.N from earlier versions: ;; (when (version< so-long-version "1.N") ...) ;; ;; All updates completed.