summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/backtrace.el3
-rw-r--r--lisp/emacs-lisp/benchmark.el3
-rw-r--r--lisp/emacs-lisp/byte-opt.el82
-rw-r--r--lisp/emacs-lisp/byte-run.el44
-rw-r--r--lisp/emacs-lisp/bytecomp.el46
-rw-r--r--lisp/emacs-lisp/cconv.el51
-rw-r--r--lisp/emacs-lisp/chart.el6
-rw-r--r--lisp/emacs-lisp/checkdoc.el11
-rw-r--r--lisp/emacs-lisp/cl-extra.el10
-rw-r--r--lisp/emacs-lisp/cl-generic.el32
-rw-r--r--lisp/emacs-lisp/cl-lib.el6
-rw-r--r--lisp/emacs-lisp/cl-macs.el300
-rw-r--r--lisp/emacs-lisp/cl-seq.el4
-rw-r--r--lisp/emacs-lisp/comp-cstr.el14
-rw-r--r--lisp/emacs-lisp/comp.el95
-rw-r--r--lisp/emacs-lisp/debug.el8
-rw-r--r--lisp/emacs-lisp/easy-mmode.el12
-rw-r--r--lisp/emacs-lisp/easymenu.el18
-rw-r--r--lisp/emacs-lisp/edebug.el26
-rw-r--r--lisp/emacs-lisp/eieio-core.el18
-rw-r--r--lisp/emacs-lisp/eieio-opt.el2
-rw-r--r--lisp/emacs-lisp/eieio.el20
-rw-r--r--lisp/emacs-lisp/elp.el2
-rw-r--r--lisp/emacs-lisp/ert-x.el57
-rw-r--r--lisp/emacs-lisp/generate-lisp-file.el14
-rw-r--r--lisp/emacs-lisp/gv.el126
-rw-r--r--lisp/emacs-lisp/icons.el10
-rw-r--r--lisp/emacs-lisp/lisp-mode.el100
-rw-r--r--lisp/emacs-lisp/loaddefs-gen.el18
-rw-r--r--lisp/emacs-lisp/macroexp.el12
-rw-r--r--lisp/emacs-lisp/nadvice.el47
-rw-r--r--lisp/emacs-lisp/oclosure.el15
-rw-r--r--lisp/emacs-lisp/package.el101
-rw-r--r--lisp/emacs-lisp/re-builder.el10
-rw-r--r--lisp/emacs-lisp/regexp-opt.el1
-rw-r--r--lisp/emacs-lisp/seq.el69
-rw-r--r--lisp/emacs-lisp/shortdoc.el84
-rw-r--r--lisp/emacs-lisp/subr-x.el1
-rw-r--r--lisp/emacs-lisp/tabulated-list.el16
-rw-r--r--lisp/emacs-lisp/testcover.el3
-rw-r--r--lisp/emacs-lisp/vtable.el3
41 files changed, 918 insertions, 582 deletions
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
index 4f98bf3f4f5..4ffe6f573c6 100644
--- a/lisp/emacs-lisp/backtrace.el
+++ b/lisp/emacs-lisp/backtrace.el
@@ -209,7 +209,6 @@ frames where the source code location is known.")
"v" #'backtrace-toggle-locals
"#" #'backtrace-toggle-print-circle
":" #'backtrace-toggle-print-gensym
- "s" #'backtrace-goto-source
"RET" #'backtrace-help-follow-symbol
"+" #'backtrace-multi-line
"-" #'backtrace-single-line
@@ -591,7 +590,7 @@ content of the sexp."
(begin (previous-single-property-change end 'backtrace-form
nil (point-min))))
(unless tag
- (when (or (= end (point-max)) (> end (point-at-eol)))
+ (when (or (= end (point-max)) (> end (line-end-position)))
(user-error "No form here to reformat"))
(goto-char end)
(setq pos end
diff --git a/lisp/emacs-lisp/benchmark.el b/lisp/emacs-lisp/benchmark.el
index 882b1d68c48..4bf61abe54c 100644
--- a/lisp/emacs-lisp/benchmark.el
+++ b/lisp/emacs-lisp/benchmark.el
@@ -31,6 +31,7 @@
;;; Code:
+(require 'cl-lib)
(eval-when-compile (require 'subr-x)) ;For `named-let'.
(defmacro benchmark-elapse (&rest forms)
@@ -70,7 +71,7 @@ number of repetitions actually used."
(defun benchmark--adaptive (func time)
"Measure the run time of FUNC, calling it enough times to last TIME seconds.
-Result is (REPETITIONS . DATA) where DATA is as returned by `branchmark-call'."
+Result is (REPETITIONS . DATA) where DATA is as returned by `benchmark-call'."
(named-let loop ((repetitions 1)
(data (let ((x (list 0))) (setcdr x x) x)))
;; (message "Running %d iteration" repetitions)
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index bbe8135f04a..5ef2d7fe827 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -728,17 +728,20 @@ for speeding up processing.")
(while (let ((head (car-safe form)))
(cond ((memq head '( progn inline save-excursion save-restriction
save-current-buffer))
- (setq form (car (last form)))
+ (setq form (car (last (cdr form))))
t)
- ((memq head '(let let* setq setcar setcdr))
+ ((memq head '(let let*))
(setq form (car (last (cddr form))))
t)
((memq head '( prog1 unwind-protect copy-sequence identity
reverse nreverse sort))
(setq form (nth 1 form))
t)
- ((eq head 'mapc)
+ ((memq head '(mapc setq setcar setcdr puthash set))
(setq form (nth 2 form))
+ t)
+ ((memq head '(aset put function-put))
+ (setq form (nth 3 form))
t))))
form)
@@ -753,22 +756,45 @@ for speeding up processing.")
((memq head
;; FIXME: Replace this list with a function property?
'( length safe-length cons lambda
- string make-string format concat
+ string unibyte-string make-string concat
+ format format-message
substring substring-no-properties string-replace
replace-regexp-in-string symbol-name make-symbol
+ compare-strings string-distance
mapconcat
vector make-vector vconcat make-record record
regexp-quote regexp-opt
buffer-string buffer-substring
buffer-substring-no-properties
- current-buffer buffer-size
- point point-min point-max
- following-char preceding-char max-char
- + - * / % 1+ 1- min max abs
- logand logior lorxor lognot ash
+ current-buffer buffer-size get-buffer-create
+ point point-min point-max buffer-end count-lines
+ following-char preceding-char get-byte max-char
+ region-beginning region-end
+ line-beginning-position line-end-position
+ pos-bol pos-eol
+ + - * / % 1+ 1- min max abs mod expt logb
+ logand logior logxor lognot ash logcount
+ floor ceiling round truncate
+ sqrt sin cos tan asin acos atan exp log copysign
+ ffloor fceiling fround ftruncate float
+ ldexp frexp
number-to-string string-to-number
- int-to-string char-to-string prin1-to-string
+ int-to-string char-to-string
+ prin1-to-string read-from-string
byte-to-string string-to-vector string-to-char
+ capitalize upcase downcase
+ propertize
+ string-as-multibyte string-as-unibyte
+ string-to-multibyte string-to-unibyte
+ string-make-multibyte string-make-unibyte
+ string-width char-width
+ make-hash-table hash-table-count
+ unibyte-char-to-multibyte multibyte-char-to-unibyte
+ sxhash sxhash-equal sxhash-eq sxhash-eql
+ sxhash-equal-including-properties
+ make-marker copy-marker point-marker mark-marker
+ set-marker
+ kbd key-description
always))
t)
((eq head 'if)
@@ -786,7 +812,7 @@ for speeding up processing.")
(defun byte-compile-nilconstp (form)
"Return non-nil if FORM always evaluates to a nil value."
(setq form (byte-opt--bool-value-form form))
- (or (not form) ; assume (quote nil) always being normalised to nil
+ (or (not form) ; assume (quote nil) always being normalized to nil
(and (consp form)
(let ((head (car form)))
;; FIXME: There are many other expressions that are statically nil.
@@ -1158,7 +1184,7 @@ See Info node `(elisp) Integer Basics'."
(if (equal new-args (cdr form))
;; Input is unchanged: keep original form, and don't represent
;; a nil result explicitly because that would lead to infinite
- ;; growth when the optimiser is iterated.
+ ;; growth when the optimizer is iterated.
(setq nil-result nil)
(setq form (cons (car form) new-args)))
@@ -1298,9 +1324,6 @@ See Info node `(elisp) Integer Basics'."
(list 'progn condition nil)))))
(defun byte-optimize-while (form)
- ;; FIXME: This check does not belong here, move!
- (when (< (length form) 2)
- (byte-compile-warn-x form "too few arguments for `while'"))
(let ((condition (nth 1 form)))
(if (byte-compile-nilconstp condition)
condition
@@ -1509,15 +1532,16 @@ See Info node `(elisp) Integer Basics'."
(put 'set 'byte-optimizer #'byte-optimize-set)
(defun byte-optimize-set (form)
- (let ((var (car-safe (cdr-safe form))))
- (cond
- ((and (eq (car-safe var) 'quote) (consp (cdr var)))
- `(setq ,(cadr var) ,@(cddr form)))
- ((and (eq (car-safe var) 'make-local-variable)
- (eq (car-safe (setq var (car-safe (cdr var)))) 'quote)
- (consp (cdr var)))
- `(progn ,(cadr form) (setq ,(cadr var) ,@(cddr form))))
- (t form))))
+ (pcase (cdr form)
+ ;; Make sure we only turn `set' into `setq' for dynamic variables.
+ (`((quote ,(and var (guard (and (symbolp var)
+ (not (macroexp--const-symbol-p var))
+ (not (assq var byte-optimize--lexvars))))))
+ ,newval)
+ `(setq ,var ,newval))
+ (`(,(and ml `(make-local-variable ,(and v `(quote ,_)))) ,newval)
+ `(progn ,ml (,(car form) ,v ,newval)))
+ (_ form)))
;; enumerating those functions which need not be called if the returned
;; value is not used. That is, something like
@@ -1570,7 +1594,7 @@ See Info node `(elisp) Integer Basics'."
keymap-parent
lax-plist-get ldexp
length length< length> length=
- line-beginning-position line-end-position
+ line-beginning-position line-end-position pos-bol pos-eol
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
@@ -1977,20 +2001,20 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
(setq keep-going t)
(setq tmp (aref byte-stack+-info (symbol-value (car lap0))))
(setq rest (cdr rest))
- (cond ((= tmp 1)
+ (cond ((eql tmp 1)
(byte-compile-log-lap
" %s discard\t-->\t<deleted>" lap0)
(setq lap (delq lap0 (delq lap1 lap))))
- ((= tmp 0)
+ ((eql tmp 0)
(byte-compile-log-lap
" %s discard\t-->\t<deleted> discard" lap0)
(setq lap (delq lap0 lap)))
- ((= tmp -1)
+ ((eql tmp -1)
(byte-compile-log-lap
" %s discard\t-->\tdiscard discard" lap0)
(setcar lap0 'byte-discard)
(setcdr lap0 0))
- ((error "Optimizer error: too much on the stack"))))
+ (t (error "Optimizer error: too much on the stack"))))
;;
;; goto*-X X: --> X:
;;
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 4a2860cd43d..9db84c31b88 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -112,44 +112,6 @@ So far, FUNCTION can only be a symbol, not a lambda expression."
(function-put 'defmacro 'doc-string-elt 3)
(function-put 'defmacro 'lisp-indent-function 2)
-;; `macro-declaration-function' are both obsolete (as marked at the end of this
-;; file) but used in many .elc files.
-
-;; We don't use #' here, because it's an obsolete function, and we
-;; can't use `with-suppressed-warnings' here due to how this file is
-;; used in the bootstrapping process.
-(defvar macro-declaration-function 'macro-declaration-function
- "Function to process declarations in a macro definition.
-The function will be called with two args MACRO and DECL.
-MACRO is the name of the macro being defined.
-DECL is a list `(declare ...)' containing the declarations.
-The value the function returns is not used.")
-
-(defalias 'macro-declaration-function
- #'(lambda (macro decl)
- "Process a declaration found in a macro definition.
-This is set as the value of the variable `macro-declaration-function'.
-MACRO is the name of the macro being defined.
-DECL is a list `(declare ...)' containing the declarations.
-The return value of this function is not used."
- ;; We can't use `dolist' or `cadr' yet for bootstrapping reasons.
- (let (d)
- ;; Ignore the first element of `decl' (it's always `declare').
- (while (setq decl (cdr decl))
- (setq d (car decl))
- (if (and (consp d)
- (listp (cdr d))
- (null (cdr (cdr d))))
- (cond ((eq (car d) 'indent)
- (put macro 'lisp-indent-function (car (cdr d))))
- ((eq (car d) 'debug)
- (put macro 'edebug-form-spec (car (cdr d))))
- ((eq (car d) 'doc-string)
- (put macro 'doc-string-elt (car (cdr d))))
- (t
- (message "Unknown declaration %s" d)))
- (message "Invalid declaration %s" d))))))
-
;; We define macro-declaration-alist here because it is needed to
;; handle declarations in macro definitions and this is the first file
;; loaded by loadup.el that uses declarations in macros. We specify
@@ -568,7 +530,6 @@ ACCESS-TYPE if non-nil should specify the kind of access that will trigger
(purecopy (list current-name access-type when)))
obsolete-name)
-
(defmacro define-obsolete-variable-alias ( obsolete-name current-name when
&optional docstring)
"Make OBSOLETE-NAME a variable alias for CURRENT-NAME and mark it obsolete.
@@ -772,9 +733,4 @@ type is. This defaults to \"INFO\"."
;; (file-format emacs19))"
;; nil)
-(make-obsolete-variable 'macro-declaration-function
- 'macro-declarations-alist "24.3")
-(make-obsolete 'macro-declaration-function
- 'macro-declarations-alist "24.3")
-
;;; byte-run.el ends here
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index a5bd2bca8a2..ec45f488971 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1235,7 +1235,8 @@ Order is by depth-first search."
(let (new-l new-c)
(save-excursion
(goto-char offset)
- (setq new-l (1+ (count-lines (point-min) (point-at-bol)))
+ (setq new-l (1+ (count-lines (point-min)
+ (line-beginning-position)))
new-c (1+ (current-column)))
(format "%d:%d:" new-l new-c))))
""))
@@ -1355,16 +1356,23 @@ FORMAT and ARGS are as in `byte-compile-warn'."
(let ((byte-compile-form-stack (cons arg byte-compile-form-stack)))
(apply #'byte-compile-warn format args)))
-(defun byte-compile-warn-obsolete (symbol)
- "Warn that SYMBOL (a variable or function) is obsolete."
+;;;###autoload
+(defun byte-compile-warn-obsolete (symbol type)
+ "Warn that SYMBOL (a variable, function or generalized variable) is obsolete.
+TYPE is a string that say which one of these three types it is."
(when (byte-compile-warning-enabled-p 'obsolete symbol)
- (let* ((funcp (get symbol 'byte-obsolete-info))
- (msg (macroexp--obsolete-warning
- symbol
- (or funcp (get symbol 'byte-obsolete-variable))
- (if funcp "function" "variable"))))
- (unless (and funcp (memq symbol byte-compile-not-obsolete-funcs))
- (byte-compile-warn-x symbol "%s" msg)))))
+ (byte-compile-warn-x
+ symbol "%s"
+ (macroexp--obsolete-warning
+ symbol
+ (pcase type
+ ("function"
+ (get symbol 'byte-obsolete-info))
+ ("variable"
+ (get symbol 'byte-obsolete-variable))
+ ("generalized variable"
+ (get symbol 'byte-obsolete-generalized-variable)))
+ type))))
(defun byte-compile-report-error (error-info &optional fill)
"Report Lisp error in compilation.
@@ -1461,15 +1469,17 @@ when printing the error message."
(defun byte-compile-arglist-signature-string (signature)
(cond ((null (cdr signature))
- (format "%d+" (car signature)))
+ (format "%d or more" (car signature)))
((= (car signature) (cdr signature))
(format "%d" (car signature)))
+ ((= (1+ (car signature)) (cdr signature))
+ (format "%d or %d" (car signature) (cdr signature)))
(t (format "%d-%d" (car signature) (cdr signature)))))
(defun byte-compile-function-warn (f nargs def)
(when (and (get f 'byte-obsolete-info)
- (byte-compile-warning-enabled-p 'obsolete f))
- (byte-compile-warn-obsolete f))
+ (not (memq f byte-compile-not-obsolete-funcs)))
+ (byte-compile-warn-obsolete f "function"))
;; Check to see if the function will be available at runtime
;; and/or remember its arity if it's unknown.
@@ -1697,12 +1707,12 @@ URLs."
(+ " " (or
;; Arguments.
(+ (or (syntax symbol)
- (any word "-/:[]&=().?^\\#'")))
+ (any word "-/:[]&=()<>.,?^\\#*'\"")))
;; Argument that is a list.
(seq "(" (* (not ")")) ")")))
")")))
""
- ;; Heuristic: We can't reliably do `subsititute-command-keys'
+ ;; Heuristic: We can't reliably do `substitute-command-keys'
;; substitutions, since the value of a keymap in general can't be
;; known at compile time. So instead, we assume that these
;; substitutions are of some length N.
@@ -3108,8 +3118,8 @@ lambda-expression."
;; Check that the bit after the `interactive' spec is
;; just a list of symbols (i.e., modes).
(unless (seq-every-p #'symbolp (cdr (cdr int)))
- (byte-compile-warn-x int "malformed interactive specc: %s"
- int))
+ (byte-compile-warn-x
+ int "malformed `interactive' specification: %s" int))
(setq command-modes (cdr (cdr int)))
;; If the interactive spec is a call to `list', don't
;; compile it, because `call-interactively' looks at the
@@ -3616,7 +3626,7 @@ lambda-expression."
('set (not (eq access-type 'reference)))
('get (eq access-type 'reference))
(_ t))))
- (byte-compile-warn-obsolete var))))
+ (byte-compile-warn-obsolete var "variable"))))
(defsubst byte-compile-dynamic-variable-op (base-op var)
(let ((tmp (assq var byte-compile-variables)))
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index 7f95fa94fa1..23d0f121948 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -137,6 +137,11 @@ is less than this number.")
;; Alist associating to each function body the list of its free variables.
)
+(defvar cconv--interactive-form-funs
+ ;; Table used to hold the functions we create internally for
+ ;; interactive forms.
+ (make-hash-table :test #'eq :weakness 'key))
+
;;;###autoload
(defun cconv-closure-convert (form)
"Main entry point for closure conversion.
@@ -503,9 +508,23 @@ places where they originally did not directly appear."
cond-forms)))
(`(function (lambda ,args . ,body) . ,_)
- (let ((docstring (if (eq :documentation (car-safe (car body)))
- (cconv-convert (cadr (pop body)) env extend))))
- (cconv--convert-function args body env form docstring)))
+ (let* ((docstring (if (eq :documentation (car-safe (car body)))
+ (cconv-convert (cadr (pop body)) env extend)))
+ (bf (if (stringp (car body)) (cdr body) body))
+ (if (when (eq 'interactive (car-safe (car bf)))
+ (gethash form cconv--interactive-form-funs)))
+ (cif (when if (cconv-convert if env extend)))
+ (_ (pcase cif
+ (`#'(lambda () ,form) (setf (cadr (car bf)) form) (setq cif nil))
+ ('nil nil)
+ ;; The interactive form needs special treatment, so the form
+ ;; inside the `interactive' won't be used any further.
+ (_ (setf (cadr (car bf)) nil))))
+ (cf (cconv--convert-function args body env form docstring)))
+ (if (not cif)
+ ;; Normal case, the interactive form needs no special treatment.
+ cf
+ `(cconv--interactive-helper ,cf ,cif))))
(`(internal-make-closure . ,_)
(byte-compile-report-error
@@ -589,12 +608,12 @@ places where they originally did not directly appear."
(cconv-convert arg env extend))
(cons fun args)))))))
- (`(interactive . ,forms)
- `(,(car form) . ,(mapcar (lambda (form)
- (cconv-convert form nil nil))
- forms)))
+ ;; The form (if any) is converted beforehand as part of the `lambda' case.
+ (`(interactive . ,_) form)
- (`(declare . ,_) form) ;The args don't contain code.
+ ;; `declare' should now be macro-expanded away (and if they're not, we're
+ ;; in trouble because they *can* contain code nowadays).
+ ;; (`(declare . ,_) form) ;The args don't contain code.
(`(oclosure--fix-type (ignore . ,vars) ,exp)
(dolist (var vars)
@@ -739,6 +758,13 @@ This function does not return anything but instead fills the
(`(function (lambda ,vrs . ,body-forms))
(when (eq :documentation (car-safe (car body-forms)))
(cconv-analyze-form (cadr (pop body-forms)) env))
+ (let ((bf (if (stringp (car body-forms)) (cdr body-forms) body-forms)))
+ (when (eq 'interactive (car-safe (car bf)))
+ (let ((if (cadr (car bf))))
+ (unless (macroexp-const-p if) ;Optimize this common case.
+ (let ((f `#'(lambda () ,if)))
+ (setf (gethash form cconv--interactive-form-funs) f)
+ (cconv-analyze-form f env))))))
(cconv--analyze-function vrs body-forms env form))
(`(setq ,var ,expr)
@@ -803,13 +829,8 @@ This function does not return anything but instead fills the
(cconv-analyze-form fun env)))
(dolist (form args) (cconv-analyze-form form env)))
- (`(interactive . ,forms)
- ;; These appear within the function body but they don't have access
- ;; to the function's arguments.
- ;; We could extend this to allow interactive specs to refer to
- ;; variables in the function's enclosing environment, but it doesn't
- ;; seem worth the trouble.
- (dolist (form forms) (cconv-analyze-form form nil)))
+ ;; The form (if any) is converted beforehand as part of the `lambda' case.
+ (`(interactive . ,_) nil)
;; `declare' should now be macro-expanded away (and if they're not, we're
;; in trouble because they *can* contain code nowadays).
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index ac6cbb53a56..9ff893b75b6 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -112,7 +112,7 @@ too much in text characters anyways.")
(set-face-foreground nf "black")
(if (and chart-face-use-pixmaps pl)
(condition-case nil
- (set-face-background-pixmap nf (car pl))
+ (set-face-stipple nf (car pl))
(error (message "Cannot set background pixmap %s" (car pl)))))
(push nf faces)
(setq cl (cdr cl)
@@ -526,9 +526,9 @@ cons cells of the form (NAME . NUM). See `sort' for more details."
(defun chart-zap-chars (n)
"Zap up to N chars without deleting EOLs."
(if (not (eobp))
- (if (< n (- (point-at-eol) (point)))
+ (if (< n (- (line-end-position) (point)))
(delete-char n)
- (delete-region (point) (point-at-eol)))))
+ (delete-region (point) (line-end-position)))))
(defun chart-display-label (label dir zone start end &optional face)
"Display LABEL in direction DIR in column/row ZONE between START and END.
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 04ead562f2f..3f9bc28e0b0 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -250,7 +250,7 @@ with these words enabled."
(defvar checkdoc-ispell-lisp-words
'("alist" "emacs" "etags" "keymap" "paren" "regexp" "sexp")
"List of words that are correct when spell-checking Lisp documentation.")
-;;;###autoload(put 'checkdoc-ispell-list-words 'safe-local-variable #'checkdoc-list-of-strings-p)
+;;;###autoload(put 'checkdoc-ispell-list-words 'safe-local-variable #'list-of-strings-p)
(defcustom checkdoc-max-keyref-before-warn nil
"If non-nil, number of \\\\=[command-to-keystroke] tokens allowed in a doc string.
@@ -281,8 +281,6 @@ Currently, all recognized keywords must be on `finder-known-keywords'."
:version "25.1"
:type 'boolean)
-(define-obsolete-variable-alias 'checkdoc-style-hooks
- 'checkdoc-style-functions "24.3")
(defvar checkdoc-style-functions nil
"Hook run after the standard style check is completed.
All functions must return nil or a string representing the error found.
@@ -292,8 +290,6 @@ Each hook is called with two parameters, (DEFUNINFO ENDPOINT).
DEFUNINFO is the return value of `checkdoc-defun-info'. ENDPOINT is the
location of end of the documentation string.")
-(define-obsolete-variable-alias 'checkdoc-comment-style-hooks
- 'checkdoc-comment-style-functions "24.3")
(defvar checkdoc-comment-style-functions nil
"Hook run after the standard comment style check is completed.
Must return nil if no errors are found, or a string describing the
@@ -324,7 +320,7 @@ These words are ignored when unquoted symbols are searched for.
This should be set in an Emacs Lisp file's local variables."
:type '(repeat (string :tag "Word"))
:version "28.1")
-;;;###autoload(put 'checkdoc-symbol-words 'safe-local-variable #'checkdoc-list-of-strings-p)
+;;;###autoload(put 'checkdoc-symbol-words 'safe-local-variable #'list-of-strings-p)
(defcustom checkdoc-column-zero-backslash-before-paren t
"Non-nil means to warn if there is no \"\\\" before \"(\" in column zero.
@@ -364,9 +360,9 @@ large number of libraries means it is impractical to fix all
of these warnings masse. In almost any other case, setting
this to anything but t is likely to be counter-productive.")
-;;;###autoload
(defun checkdoc-list-of-strings-p (obj)
"Return t when OBJ is a list of strings."
+ (declare (obsolete list-of-strings-p "29.1"))
;; this is a function so it might be shared by checkdoc-proper-noun-list
;; and/or checkdoc-ispell-lisp-words in the future
(and (listp obj)
@@ -2232,7 +2228,6 @@ nil."
(progn
(ispell-set-spellchecker-params) ; Initialize variables and dict alists.
(ispell-accept-buffer-local-defs) ; Use the correct dictionary.
- ;; This code copied in part from ispell.el Emacs 19.34
(dolist (w checkdoc-ispell-lisp-words)
(process-send-string ispell-process (concat "@" w "\n"))))
(error (setq checkdoc-spellcheck-documentation-flag nil)))))
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index 607810ee141..7c7f027d777 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -772,7 +772,7 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
(help-insert-xref-button
(help-fns-short-filename location)
'cl-type-definition type location 'define-type)
- (insert (substitute-command-keys "'")))
+ (insert (substitute-quotes "'")))
(insert ".\n")
;; Parents.
@@ -782,7 +782,7 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
(insert " Inherits from ")
(while (setq cur (pop pl))
(setq cur (cl--class-name cur))
- (insert (substitute-command-keys "`"))
+ (insert (substitute-quotes "`"))
(help-insert-xref-button (symbol-name cur)
'cl-help-type cur)
(insert (substitute-command-keys (if pl "', " "'"))))
@@ -796,7 +796,7 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
(when ch
(insert " Children ")
(while (setq cur (pop ch))
- (insert (substitute-command-keys "`"))
+ (insert (substitute-quotes "`"))
(help-insert-xref-button (symbol-name cur)
'cl-help-type cur)
(insert (substitute-command-keys (if ch "', " "'"))))
@@ -815,10 +815,10 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
(when generics
(insert (propertize "Specialized Methods:\n\n" 'face 'bold))
(dolist (generic generics)
- (insert (substitute-command-keys "`"))
+ (insert (substitute-quotes "`"))
(help-insert-xref-button (symbol-name generic)
'help-function generic)
- (insert (substitute-command-keys "'"))
+ (insert (substitute-quotes "'"))
(pcase-dolist (`(,qualifiers ,args ,doc)
(cl--generic-method-documentation generic type))
(insert (format " %s%S\n" qualifiers args)
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 0560ddda268..b3ade3b8943 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -94,11 +94,6 @@
;; This second one is closely related to what we do here (and that's
;; the name "generalizer" comes from).
-;; The autoloads.el mechanism which adds package--builtin-versions
-;; maintenance to loaddefs.el doesn't work for preloaded packages (such
-;; as this one), so we have to do it by hand!
-(push (purecopy '(cl-generic 1 0)) package--builtin-versions)
-
;; Note: For generic functions that dispatch on several arguments (i.e. those
;; which use the multiple-dispatch feature), we always use the same "tagcodes"
;; and the same set of arguments on which to dispatch. This works, but is
@@ -425,11 +420,13 @@ the specializer used will be the one returned by BODY."
;; only called with explicit arguments.
(uses-cnm (macroexp--fgrep `((,cnm) (,nmp)) nbody))
(Ī»-lift (mapcar #'car uses-cnm)))
- (if (not uses-cnm)
- (cons nil
- `#'(lambda (,@args)
- ,@(car parsed-body)
- ,nbody))
+ (cond
+ ((not uses-cnm)
+ (cons nil
+ `#'(lambda (,@args)
+ ,@(car parsed-body)
+ ,nbody)))
+ (lexical-binding
(cons 'curried
`#'(lambda (,nm) ;Called when constructing the effective method.
(let ((,nmp (if (cl--generic-isnot-nnm-p ,nm)
@@ -465,7 +462,20 @@ the specializer used will be the one returned by BODY."
;; A destructuring-bind would do the trick
;; as well when/if it's more efficient.
(apply (lambda (,@Ī»-lift ,@args) ,nbody)
- ,@Ī»-lift ,arglist)))))))))
+ ,@Ī»-lift ,arglist)))))))
+ (t
+ (cons t
+ `#'(lambda (,cnm ,@args)
+ ,@(car parsed-body)
+ ,(macroexp-warn-and-return
+ "cl-defmethod used without lexical-binding"
+ (if (not (assq nmp uses-cnm))
+ nbody
+ `(let ((,nmp (lambda ()
+ (cl--generic-isnot-nnm-p ,cnm))))
+ ,nbody))
+ 'lexical t)))))
+ ))
(f (error "Unexpected macroexpansion result: %S" f))))))
(put 'cl-defmethod 'function-documentation
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index a54fa21fa96..b83b44974d3 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -90,12 +90,6 @@
(defvar cl--optimize-safety 1)
;;;###autoload
-(define-obsolete-variable-alias
- ;; This alias is needed for compatibility with .elc files that use defstruct
- ;; and were compiled with Emacs<24.3.
- 'custom-print-functions 'cl-custom-print-functions "24.3")
-
-;;;###autoload
(defvar cl-custom-print-functions nil
"This is a list of functions that format user objects for printing.
Each function is called in turn with three arguments: the object, the
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 80ca43c902a..beafee1d631 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -775,14 +775,34 @@ compared by `eql'.
\(fn EXPR (KEYLIST BODY...)...)"
(declare (indent 1) (debug (form &rest (sexp body))))
(macroexp-let2 macroexp-copyable-p temp expr
- (let* ((head-list nil))
+ (let* ((head-list nil)
+ (has-otherwise nil))
`(cond
,@(mapcar
(lambda (c)
- (cons (cond ((memq (car c) '(t otherwise)) t)
+ (cons (cond (has-otherwise
+ (error "Misplaced t or `otherwise' clause"))
+ ((memq (car c) '(t otherwise))
+ (setq has-otherwise t)
+ t)
((eq (car c) 'cl--ecase-error-flag)
`(error "cl-ecase failed: %s, %s"
,temp ',(reverse head-list)))
+ ((null (car c))
+ (macroexp-warn-and-return
+ "Case nil will never match"
+ nil 'suspicious))
+ ((and (consp (car c)) (cdar c) (not (cddar c))
+ (memq (caar c) '(quote function)))
+ (macroexp-warn-and-return
+ (format-message
+ (concat "Case %s will match `%s'. If "
+ "that's intended, write %s "
+ "instead. Otherwise, don't "
+ "quote `%s'.")
+ (car c) (caar c) (list (cadar c) (caar c))
+ (cadar c))
+ `(cl-member ,temp ',(car c)) 'suspicious))
((listp (car c))
(setq head-list (append (car c) head-list))
`(cl-member ,temp ',(car c)))
@@ -2261,139 +2281,131 @@ This is like `cl-flet', but for macros instead of functions.
(eval `(function (lambda ,@res)) t))
macroexpand-all-environment))))))
-(defun cl--sm-macroexpand (orig-fun exp &optional env)
+(defun cl--sm-macroexpand (exp &optional env)
+ "Special macro expander used inside `cl-symbol-macrolet'."
+ ;; FIXME: Arguably, this should be the official definition of `macroexpand'.
+ (while (not (eq exp (setq exp (macroexpand-1 exp env)))))
+ exp)
+
+(defun cl--sm-macroexpand-1 (orig-fun exp &optional env)
"Special macro expander advice used inside `cl-symbol-macrolet'.
-This function extends `macroexpand' during macro expansion
+This function extends `macroexpand-1' during macro expansion
of `cl-symbol-macrolet' to additionally expand symbol macros."
- (let ((macroexpand-all-environment env)
+ (let ((exp (funcall orig-fun exp env))
(venv (alist-get :cl-symbol-macros env)))
- (while
- (progn
- (setq exp (funcall orig-fun exp env))
- (pcase exp
- ((pred symbolp)
- ;; Perform symbol-macro expansion.
- (let ((symval (assq exp venv)))
- (when symval
- (setq exp (cadr symval)))))
- (`(setq . ,args)
- ;; Convert setq to setf if required by symbol-macro expansion.
- (let ((convert nil)
- (rargs nil))
- (while args
- (let ((place (pop args)))
- ;; Here, we know `place' should be a symbol.
- (while
- (let ((symval (assq place venv)))
- (when symval
- (setq place (cadr symval))
- (if (symbolp place)
- t ;Repeat.
- (setq convert t)
- nil))))
- (push place rargs)
- (push (pop args) rargs)))
- (setq exp (cons (if convert 'setf 'setq)
- (nreverse rargs)))
- convert))
- ;; CL's symbol-macrolet used to treat re-bindings as candidates for
- ;; expansion (turning the let into a letf if needed), contrary to
- ;; Common-Lisp where such re-bindings hide the symbol-macro.
- ;; Not sure if there actually is code out there which depends
- ;; on this behavior (haven't found any yet).
- ;; Such code should explicitly use `cl-letf' instead, I think.
- ;;
- ;; (`(,(or `let `let*) . ,(or `(,bindings . ,body) pcase--dontcare))
- ;; (let ((letf nil) (found nil) (nbs ()))
- ;; (dolist (binding bindings)
- ;; (let* ((var (if (symbolp binding) binding (car binding)))
- ;; (sm (assq var venv)))
- ;; (push (if (not (cdr sm))
- ;; binding
- ;; (let ((nexp (cadr sm)))
- ;; (setq found t)
- ;; (unless (symbolp nexp) (setq letf t))
- ;; (cons nexp (cdr-safe binding))))
- ;; nbs)))
- ;; (when found
- ;; (setq exp `(,(if letf
- ;; (if (eq (car exp) 'let) 'cl-letf 'cl-letf*)
- ;; (car exp))
- ;; ,(nreverse nbs)
- ;; ,@body)))))
- ;;
- ;; We implement the Common-Lisp behavior, instead (see bug#26073):
- ;; The behavior of CL made sense in a dynamically scoped
- ;; language, but nowadays, lexical scoping semantics is more often
- ;; expected.
- (`(,(or 'let 'let*) . ,(or `(,bindings . ,body) pcase--dontcare))
- (let ((nbs ()) (found nil))
- (dolist (binding bindings)
- (let* ((var (if (symbolp binding) binding (car binding)))
- (val (and found (consp binding) (eq 'let* (car exp))
- (list (macroexpand-all (cadr binding)
- env)))))
- (push (if (assq var venv)
- ;; This binding should hide "its" surrounding
- ;; symbol-macro, but given the way macroexpand-all
- ;; works (i.e. the `env' we receive as input will
- ;; be (re)applied to the code we return), we can't
- ;; prevent application of `env' to the
- ;; sub-expressions, so we need to α-rename this
- ;; variable instead.
- (let ((nvar (make-symbol (symbol-name var))))
- (setq found t)
- (push (list var nvar) venv)
- (push (cons :cl-symbol-macros venv) env)
- (cons nvar (or val (cdr-safe binding))))
- (if val (cons var val) binding))
- nbs)))
- (when found
- (setq exp `(,(car exp)
- ,(nreverse nbs)
- ,@(macroexp-unprogn
- (macroexpand-all (macroexp-progn body)
- env)))))
- nil))
- ;; Do the same as for `let' but for variables introduced
- ;; via other means, such as `lambda' and `condition-case'.
- (`(function (lambda ,args . ,body))
- (let ((nargs ()) (found nil))
- (dolist (var args)
- (push (cond
- ((memq var '(&optional &rest)) var)
- ((assq var venv)
- (let ((nvar (make-symbol (symbol-name var))))
- (setq found t)
- (push (list var nvar) venv)
- (push (cons :cl-symbol-macros venv) env)
- nvar))
- (t var))
- nargs))
- (when found
- (setq exp `(function
- (lambda ,(nreverse nargs)
- . ,(mapcar (lambda (exp)
- (macroexpand-all exp env))
- body)))))
- nil))
- ((and `(condition-case ,var ,exp . ,clauses)
- (guard (assq var venv)))
- (let ((nvar (make-symbol (symbol-name var))))
- (push (list var nvar) venv)
- (push (cons :cl-symbol-macros venv) env)
- (setq exp
- `(condition-case ,nvar ,(macroexpand-all exp env)
- . ,(mapcar
- (lambda (clause)
- `(,(car clause)
- . ,(mapcar (lambda (exp)
- (macroexpand-all exp env))
- (cdr clause))))
- clauses)))
- nil))
- )))
- exp))
+ (pcase exp
+ ((pred symbolp)
+ ;; Try symbol-macro expansion.
+ (let ((symval (assq exp venv)))
+ (if symval (cadr symval) exp)))
+ (`(setq . ,args)
+ ;; Convert setq to setf if required by symbol-macro expansion.
+ (let ((convert nil))
+ (while args
+ (let* ((place (pop args))
+ ;; Here, we know `place' should be a symbol.
+ (symval (assq place venv)))
+ (pop args)
+ (when symval
+ (setq convert t))))
+ (if convert
+ (cons 'setf (cdr exp))
+ exp)))
+ ;; CL's symbol-macrolet used to treat re-bindings as candidates for
+ ;; expansion (turning the let into a letf if needed), contrary to
+ ;; Common-Lisp where such re-bindings hide the symbol-macro.
+ ;; Not sure if there actually is code out there which depends
+ ;; on this behavior (haven't found any yet).
+ ;; Such code should explicitly use `cl-letf' instead, I think.
+ ;;
+ ;; (`(,(or `let `let*) . ,(or `(,bindings . ,body) pcase--dontcare))
+ ;; (let ((letf nil) (found nil) (nbs ()))
+ ;; (dolist (binding bindings)
+ ;; (let* ((var (if (symbolp binding) binding (car binding)))
+ ;; (sm (assq var venv)))
+ ;; (push (if (not (cdr sm))
+ ;; binding
+ ;; (let ((nexp (cadr sm)))
+ ;; (setq found t)
+ ;; (unless (symbolp nexp) (setq letf t))
+ ;; (cons nexp (cdr-safe binding))))
+ ;; nbs)))
+ ;; (when found
+ ;; (setq exp `(,(if letf
+ ;; (if (eq (car exp) 'let) 'cl-letf 'cl-letf*)
+ ;; (car exp))
+ ;; ,(nreverse nbs)
+ ;; ,@body)))))
+ ;;
+ ;; We implement the Common-Lisp behavior, instead (see bug#26073):
+ ;; The behavior of CL made sense in a dynamically scoped
+ ;; language, but nowadays, lexical scoping semantics is more often
+ ;; expected.
+ (`(,(or 'let 'let*) . ,(or `(,bindings . ,body) pcase--dontcare))
+ (let ((nbs ()) (found nil))
+ (dolist (binding bindings)
+ (let* ((var (if (symbolp binding) binding (car binding)))
+ (val (and found (consp binding) (eq 'let* (car exp))
+ (list (macroexpand-all (cadr binding)
+ env)))))
+ (push (if (assq var venv)
+ ;; This binding should hide "its" surrounding
+ ;; symbol-macro, but given the way macroexpand-all
+ ;; works (i.e. the `env' we receive as input will
+ ;; be (re)applied to the code we return), we can't
+ ;; prevent application of `env' to the
+ ;; sub-expressions, so we need to α-rename this
+ ;; variable instead.
+ (let ((nvar (make-symbol (symbol-name var))))
+ (setq found t)
+ (push (list var nvar) venv)
+ (push (cons :cl-symbol-macros venv) env)
+ (cons nvar (or val (cdr-safe binding))))
+ (if val (cons var val) binding))
+ nbs)))
+ (if found
+ `(,(car exp)
+ ,(nreverse nbs)
+ ,@(macroexp-unprogn
+ (macroexpand-all (macroexp-progn body)
+ env)))
+ exp)))
+ ;; Do the same as for `let' but for variables introduced
+ ;; via other means, such as `lambda' and `condition-case'.
+ (`(function (lambda ,args . ,body))
+ (let ((nargs ()) (found nil))
+ (dolist (var args)
+ (push (cond
+ ((memq var '(&optional &rest)) var)
+ ((assq var venv)
+ (let ((nvar (make-symbol (symbol-name var))))
+ (setq found t)
+ (push (list var nvar) venv)
+ (push (cons :cl-symbol-macros venv) env)
+ nvar))
+ (t var))
+ nargs))
+ (if found
+ `(function
+ (lambda ,(nreverse nargs)
+ . ,(mapcar (lambda (exp)
+ (macroexpand-all exp env))
+ body)))
+ exp)))
+ ((and `(condition-case ,var ,exp . ,clauses)
+ (guard (assq var venv)))
+ (let ((nvar (make-symbol (symbol-name var))))
+ (push (list var nvar) venv)
+ (push (cons :cl-symbol-macros venv) env)
+ `(condition-case ,nvar ,(macroexpand-all exp env)
+ . ,(mapcar
+ (lambda (clause)
+ `(,(car clause)
+ . ,(mapcar (lambda (exp)
+ (macroexpand-all exp env))
+ (cdr clause))))
+ clauses))))
+ (_ exp))))
;;;###autoload
(defmacro cl-symbol-macrolet (bindings &rest body)
@@ -2412,7 +2424,8 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
(unwind-protect
(progn
(unless advised
- (advice-add 'macroexpand :around #'cl--sm-macroexpand))
+ (advice-add 'macroexpand :override #'cl--sm-macroexpand)
+ (advice-add 'macroexpand-1 :around #'cl--sm-macroexpand-1))
(let* ((venv (cdr (assq :cl-symbol-macros
macroexpand-all-environment)))
(expansion
@@ -2428,7 +2441,8 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
expansion nil nil rev-malformed-bindings))
expansion)))
(unless advised
- (advice-remove 'macroexpand #'cl--sm-macroexpand)))))
+ (advice-remove 'macroexpand #'cl--sm-macroexpand)
+ (advice-remove 'macroexpand-1 #'cl--sm-macroexpand-1)))))
;;;###autoload
(defmacro cl-with-gensyms (names &rest body)
@@ -2762,11 +2776,17 @@ Each PLACE may be a symbol, or any generalized variable allowed by `setf'.
(funcall setter vold)))
binds))))
(let* ((binding (car bindings))
- (place (macroexpand (car binding) macroexpand-all-environment)))
+ (place (car binding)))
(gv-letplace (getter setter) place
(macroexp-let2 nil vnew (cadr binding)
- (if (symbolp place)
+ (if (and (symbolp place)
+ ;; `place' could be some symbol-macro.
+ (eq place getter))
;; Special-case for simple variables.
+ ;; FIXME: We currently only use this special case when `place'
+ ;; is a simple var. Should we also use it when the
+ ;; macroexpansion of `place' is a simple var (i.e. when
+ ;; getter+setter is the same as that of a simple var)?
(cl--letf (cdr bindings)
(cons `(,getter ,(if (cdr binding) vnew getter))
simplebinds)
@@ -3105,7 +3125,7 @@ To see the documentation for a defined struct type, use
`(and ,pred-form t)))
forms)
(push `(eval-and-compile
- (put ',name 'cl-deftype-satisfies ',predicate))
+ (define-symbol-prop ',name 'cl-deftype-satisfies ',predicate))
forms))
(let ((pos 0) (descp descs))
(while descp
@@ -3570,7 +3590,7 @@ and then returning foo."
(cl-defun ,fname ,(if (memq '&whole args) (delq '&whole args)
(cons '_cl-whole-arg args))
,@body)
- (put ',func 'compiler-macro #',fname))))
+ (define-symbol-prop ',func 'compiler-macro #',fname))))
;;;###autoload
(defun cl-compiler-macroexpand (form)
@@ -3679,8 +3699,8 @@ macro that returns its `&whole' argument."
The type name can then be used in `cl-typecase', `cl-check-type', etc."
(declare (debug cl-defmacro) (doc-string 3) (indent 2))
`(cl-eval-when (compile load eval)
- (put ',name 'cl-deftype-handler
- (cl-function (lambda (&cl-defs ('*) ,@arglist) ,@body)))))
+ (define-symbol-prop ',name 'cl-deftype-handler
+ (cl-function (lambda (&cl-defs ('*) ,@arglist) ,@body)))))
(cl-deftype extended-char () '(and character (not base-char)))
;; Define fixnum so `cl-typep' recognize it and the type check emitted
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el
index 64ae05bf2a0..60e204eaf51 100644
--- a/lisp/emacs-lisp/cl-seq.el
+++ b/lisp/emacs-lisp/cl-seq.el
@@ -139,6 +139,10 @@ only case where FUNCTION is called with fewer than two arguments.
If SEQ contains exactly one element and no :INITIAL-VALUE is
specified, then return that element and FUNCTION is not called.
+If :FROM-END is non-nil, the reduction occurs from the back of
+the SEQ moving forward, and the order of arguments to the
+FUNCTION is also reversed.
+
\n(fn FUNCTION SEQ [KEYWORD VALUE]...)"
(cl--parsing-keywords (:from-end (:start 0) :end :initial-value :key) ()
(or (listp cl-seq) (setq cl-seq (append cl-seq nil)))
diff --git a/lisp/emacs-lisp/comp-cstr.el b/lisp/emacs-lisp/comp-cstr.el
index 6451e34c42f..8cff06a383a 100644
--- a/lisp/emacs-lisp/comp-cstr.el
+++ b/lisp/emacs-lisp/comp-cstr.el
@@ -37,16 +37,12 @@
(require 'cl-lib)
-(defconst comp--typeof-types (mapcar (lambda (x)
- (append x '(t)))
- cl--typeof-types)
+(defconst comp--typeof-builtin-types (mapcar (lambda (x)
+ (append x '(t)))
+ cl--typeof-types)
;; TODO can we just add t in `cl--typeof-types'?
"Like `cl--typeof-types' but with t as common supertype.")
-(defconst comp--all-builtin-types
- (append cl--all-builtin-types '(t))
- "Likewise like `cl--all-builtin-types' but with t as common supertype.")
-
(cl-defstruct (comp-cstr (:constructor comp-type-to-cstr
(type &aux
(null (eq type 'null))
@@ -234,7 +230,7 @@ Return them as multiple value."
(cl-loop
named outer
with found = nil
- for l in comp--typeof-types
+ for l in comp--typeof-builtin-types
do (cl-loop
for x in l
for i from (length l) downto 0
@@ -277,7 +273,7 @@ Return them as multiple value."
(cl-loop
with types = (apply #'append typesets)
with res = '()
- for lane in comp--typeof-types
+ for lane in comp--typeof-builtin-types
do (cl-loop
with last = nil
for x in lane
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 5ee10fcbca2..6656b7e57c1 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -178,14 +178,15 @@ and above."
:type '(repeat string)
:version "28.1")
-(defcustom native-comp-driver-options nil
+(defcustom native-comp-driver-options (when (eq system-type 'darwin)
+ '("-Wl,-w"))
"Options passed verbatim to the native compiler's back-end driver.
Note that not all options are meaningful; typically only the options
affecting the assembler and linker are likely to be useful.
Passing these options is only available in libgccjit version 9
and above."
- :type '(repeat string) ; FIXME is this right?
+ :type '(repeat string)
:version "28.1")
(defcustom comp-libgccjit-reproducer nil
@@ -304,7 +305,7 @@ Useful to hook into pass checkers.")
(bool-vector-subsetp (function (bool-vector bool-vector) boolean))
(boundp (function (symbol) boolean))
(buffer-end (function ((or number marker)) integer))
- (buffer-file-name (function (&optional buffer) string))
+ (buffer-file-name (function (&optional buffer) (or string null)))
(buffer-list (function (&optional frame) list))
(buffer-local-variables (function (&optional buffer) list))
(buffer-modified-p (function (&optional buffer) boolean))
@@ -321,8 +322,8 @@ Useful to hook into pass checkers.")
(cdr (function (list) t))
(cdr-safe (function (t) t))
(ceiling (function (number &optional number) integer))
- (char-after (function (&optional (or marker integer)) fixnum))
- (char-before (function (&optional (or marker integer)) fixnum))
+ (char-after (function (&optional (or marker integer)) (or fixnum null)))
+ (char-before (function (&optional (or marker integer)) (or fixnum null)))
(char-equal (function (integer integer) boolean))
(char-or-string-p (function (t) boolean))
(char-to-string (function (fixnum) string))
@@ -344,14 +345,21 @@ Useful to hook into pass checkers.")
(current-buffer (function () buffer))
(current-global-map (function () cons))
(current-indentation (function () integer))
- (current-local-map (function () cons))
- (current-minor-mode-maps (function () cons))
+ (current-local-map (function () (or cons null)))
+ (current-minor-mode-maps (function () (or cons null)))
(current-time (function () cons))
- (current-time-string (function (&optional string boolean) string))
- (current-time-zone (function (&optional string boolean) cons))
+ (current-time-string (function (&optional (or number list)
+ (or symbol string cons integer))
+ string))
+ (current-time-zone (function (&optional (or number list)
+ (or symbol string cons integer))
+ cons))
(custom-variable-p (function (symbol) boolean))
(decode-char (function (cons t) (or fixnum null)))
- (decode-time (function (&optional string symbol symbol) cons))
+ (decode-time (function (&optional (or number list)
+ (or symbol string cons integer)
+ symbol)
+ cons))
(default-boundp (function (symbol) boolean))
(default-value (function (symbol) t))
(degrees-to-radians (function (number) float))
@@ -383,12 +391,14 @@ Useful to hook into pass checkers.")
(file-writable-p (function (string) boolean))
(fixnump (function (t) boolean))
(float (function (number) float))
- (float-time (function (&optional cons) float))
+ (float-time (function (&optional (or number list)) float))
(floatp (function (t) boolean))
(floor (function (number &optional number) integer))
(following-char (function () fixnum))
(format (function (string &rest t) string))
- (format-time-string (function (string &optional cons symbol) string))
+ (format-time-string (function (string &optional (or number list)
+ (or symbol string cons integer))
+ string))
(frame-first-window (function ((or frame window)) window))
(frame-root-window (function (&optional (or frame window)) window))
(frame-selected-window (function (&optional (or frame window)) window))
@@ -400,8 +410,8 @@ Useful to hook into pass checkers.")
(get-buffer (function ((or buffer string)) (or buffer null)))
(get-buffer-window (function (&optional (or buffer string) (or symbol (integer 0 0))) (or null window)))
(get-file-buffer (function (string) (or null buffer)))
- (get-largest-window (function (&optional t t t) window))
- (get-lru-window (function (&optional t t t) window))
+ (get-largest-window (function (&optional t t t) (or window null)))
+ (get-lru-window (function (&optional t t t) (or window null)))
(getenv (function (string &optional frame) (or null string)))
(gethash (function (t hash-table &optional t) t))
(hash-table-count (function (hash-table) integer))
@@ -450,16 +460,16 @@ Useful to hook into pass checkers.")
(make-symbol (function (string) symbol))
(mark (function (&optional t) (or integer null)))
(mark-marker (function () marker))
- (marker-buffer (function (marker) buffer))
+ (marker-buffer (function (marker) (or buffer null)))
(markerp (function (t) boolean))
(max (function ((or number marker) &rest (or number marker)) number))
- (max-char (function () fixnum))
+ (max-char (function (&optional t) fixnum))
(member (function (t list) list))
(memory-limit (function () integer))
(memq (function (t list) list))
(memql (function (t list) list))
(min (function ((or number marker) &rest (or number marker)) number))
- (minibuffer-selected-window (function () window))
+ (minibuffer-selected-window (function () (or window null)))
(minibuffer-window (function (&optional frame) window))
(mod (function ((or number marker) (or number marker)) (or (integer 0 *) (float 0 *))))
(mouse-movement-p (function (t) boolean))
@@ -487,7 +497,7 @@ Useful to hook into pass checkers.")
(previous-window (function (&optional window t t) window))
(prin1-to-string (function (t &optional t t) string))
(processp (function (t) boolean))
- (proper-list-p (function (t) integer))
+ (proper-list-p (function (t) boolean))
(propertize (function (string &rest t) string))
(radians-to-degrees (function (number) float))
(rassoc (function (t list) list))
@@ -520,7 +530,7 @@ Useful to hook into pass checkers.")
(string-to-char (function (string) fixnum))
(string-to-multibyte (function (string) string))
(string-to-number (function (string &optional integer) number))
- (string-to-syntax (function (string) cons))
+ (string-to-syntax (function (string) (or cons null)))
(string< (function ((or string symbol) (or string symbol)) boolean))
(string= (function ((or string symbol) (or string symbol)) boolean))
(stringp (function (t) boolean))
@@ -542,7 +552,8 @@ Useful to hook into pass checkers.")
(this-command-keys-vector (function () vector))
(this-single-command-keys (function () vector))
(this-single-command-raw-keys (function () vector))
- (time-convert (function (t &optional (or boolean integer)) cons))
+ (time-convert (function ((or number list) &optional (or symbol integer))
+ (or cons number)))
(truncate (function (number &optional number) integer))
(type-of (function (t) symbol))
(unibyte-char-to-multibyte (function (fixnum) fixnum)) ;; byte is fixnum
@@ -3790,22 +3801,25 @@ Return the trampoline if found or nil otherwise."
(lexical-binding t))
(comp--native-compile
form nil
- (cl-loop
- for dir in (if native-compile-target-directory
- (list (expand-file-name comp-native-version-dir
- native-compile-target-directory))
- (comp-eln-load-path-eff))
- for f = (expand-file-name
- (comp-trampoline-filename subr-name)
- dir)
- unless (file-exists-p dir)
- do (ignore-errors
- (make-directory dir t)
- (cl-return f))
- when (file-writable-p f)
- do (cl-return f)
- finally (error "Cannot find suitable directory for output in \
-`native-comp-eln-load-path'")))))
+ ;; If we've disabled nativecomp, don't write the trampolines to
+ ;; the eln cache (but create them).
+ (and (not inhibit-automatic-native-compilation)
+ (cl-loop
+ for dir in (if native-compile-target-directory
+ (list (expand-file-name comp-native-version-dir
+ native-compile-target-directory))
+ (comp-eln-load-path-eff))
+ for f = (expand-file-name
+ (comp-trampoline-filename subr-name)
+ dir)
+ unless (file-exists-p dir)
+ do (ignore-errors
+ (make-directory dir t)
+ (cl-return f))
+ when (file-writable-p f)
+ do (cl-return f)
+ finally (error "Cannot find suitable directory for output in \
+`native-comp-eln-load-path'"))))))
;; Some entry point support code.
@@ -3925,8 +3939,11 @@ display a message."
when (or native-comp-always-compile
load ; Always compile when the compilation is
; commanded for late load.
- (file-newer-than-file-p
- source-file (comp-el-to-eln-filename source-file)))
+ ;; Skip compilation if `comp-el-to-eln-filename' fails
+ ;; to find a writable directory.
+ (with-demoted-errors "Async compilation :%S"
+ (file-newer-than-file-p
+ source-file (comp-el-to-eln-filename source-file))))
do (let* ((expr `((require 'comp)
(setq comp-async-compilation t)
(setq warning-fill-column most-positive-fixnum)
@@ -4031,7 +4048,6 @@ the deferred compilation mechanism."
(list "Not a function symbol or file" function-or-file)))
(catch 'no-native-compile
(let* ((print-symbols-bare t)
- (max-specpdl-size (max max-specpdl-size 5000))
(data function-or-file)
(comp-native-compiling t)
(byte-native-qualities nil)
@@ -4094,6 +4110,7 @@ the deferred compilation mechanism."
comp-ctxt
(comp-ctxt-output comp-ctxt)
(file-exists-p (comp-ctxt-output comp-ctxt)))
+ (message "Deleting %s" (comp-ctxt-output comp-ctxt))
(delete-file (comp-ctxt-output comp-ctxt)))))))
(defun native-compile-async-skip-p (file load selector)
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index 460057b3afd..f78d44cf98e 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -110,10 +110,6 @@ The value used here is passed to `quit-restore-window'."
(defvar debugger-previous-window-height nil
"The last recorded height of `debugger-previous-window'.")
-(defvar debugger-previous-backtrace nil
- "The contents of the previous backtrace (including text properties).
-This is to optimize `debugger-make-xrefs'.")
-
(defvar debugger-outer-match-data)
(defvar debugger-will-be-back nil
"Non-nil if we expect to get back in the debugger soon.")
@@ -836,6 +832,10 @@ To specify a nil argument interactively, exit with an empty minibuffer."
;;;###autoload
(defalias 'cancel-debug-watch #'cancel-debug-on-variable-change)
+(make-obsolete-variable 'debugger-previous-backtrace
+ "no longer used." "29.1")
+(defvar debugger-previous-backtrace nil)
+
(provide 'debug)
;;; debug.el ends here
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index c3a4e9fc7ab..7d54a84687b 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -417,7 +417,12 @@ No problems result if this variable is not bound.
`(defvar ,keymap-sym
(let ((m ,keymap))
(cond ((keymapp m) m)
- ((listp m) (easy-mmode-define-keymap m))
+ ;; FIXME: `easy-mmode-define-keymap' is obsolete,
+ ;; so this form should also be obsolete somehow.
+ ((listp m)
+ (with-suppressed-warnings ((obsolete
+ easy-mmode-define-keymap))
+ (easy-mmode-define-keymap m)))
(t (error "Invalid keymap %S" m))))
,(format "Keymap for `%s'." mode-name)))
@@ -679,6 +684,7 @@ Valid keywords and arguments are:
:group Ignored.
:suppress Non-nil to call `suppress-keymap' on keymap,
`nodigits' to suppress digits as prefix arguments."
+ (declare (obsolete define-keymap "29.1"))
(let (inherit dense suppress)
(while args
(let ((key (pop args))
@@ -719,9 +725,7 @@ The M, BS, and ARGS arguments are as per that function. DOC is
the constant's documentation.
This macro is deprecated; use `defvar-keymap' instead."
- ;; FIXME: Declare obsolete in favor of `defvar-keymap'. It is still
- ;; used for `gud-menu-map' and `gud-minor-mode-map', so fix that first.
- (declare (doc-string 3) (indent 1))
+ (declare (doc-string 3) (indent 1) (obsolete defvar-keymap "29.1"))
`(defconst ,m
(easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args))
,doc))
diff --git a/lisp/emacs-lisp/easymenu.el b/lisp/emacs-lisp/easymenu.el
index 43ce1872f9b..41e3a197af4 100644
--- a/lisp/emacs-lisp/easymenu.el
+++ b/lisp/emacs-lisp/easymenu.el
@@ -492,25 +492,11 @@ To implement dynamic menus, either call this from
`menu-bar-update-hook' or use a menu filter."
(easy-menu-add-item map path (easy-menu-create-menu name items) before))
-(defalias 'easy-menu-remove #'ignore
- "Remove MENU from the current menu bar.
-Contrary to XEmacs, this is a nop on Emacs since menus are automatically
-\(de)activated when the corresponding keymap is (de)activated.
-
-\(fn MENU)")
+(defalias 'easy-menu-remove #'ignore)
(make-obsolete 'easy-menu-remove "this was always a no-op in Emacs \
and can be safely removed." "28.1")
-(defalias 'easy-menu-add #'ignore
- "Add the menu to the menubar.
-On Emacs this is a nop, because menus are already automatically
-activated when the corresponding keymap is activated. On XEmacs
-this is needed to actually add the menu to the current menubar.
-
-You should call this once the menu and keybindings are set up
-completely and menu filter functions can be expected to work.
-
-\(fn MENU &optional MAP)")
+(defalias 'easy-menu-add #'ignore)
(make-obsolete 'easy-menu-add "this was always a no-op in Emacs \
and can be safely removed." "28.1")
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index dff16df0029..67704bdb51c 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -129,7 +129,7 @@ contains an infinite loop. When Edebug is instrumenting code
containing very large quoted lists, it may reach this limit and give
the error message \"Too deep - perhaps infinite loop in spec?\".
Make this limit larger to countermand that, but you may also need to
-increase `max-lisp-eval-depth' and `max-specpdl-size'."
+increase `max-lisp-eval-depth'."
:type 'integer
:version "26.1")
@@ -1107,8 +1107,7 @@ purpose by adding an entry to this alist, and setting
edebug-best-error
edebug-error-point
;; Do this once here instead of several times.
- (max-lisp-eval-depth (+ 800 max-lisp-eval-depth))
- (max-specpdl-size (+ 2000 max-specpdl-size)))
+ (max-lisp-eval-depth (+ 800 max-lisp-eval-depth)))
(let ((no-match
(catch 'no-match
(setq result (edebug-read-and-maybe-wrap-form1))
@@ -2317,7 +2316,6 @@ and run its entry function, and set up `edebug-before' and
;; but not inside an unwind-protect.
;; Doing it here also keeps it from growing too large.
(max-lisp-eval-depth (+ 100 max-lisp-eval-depth)) ; too much??
- (max-specpdl-size (+ 200 max-specpdl-size))
(debugger edebug-debugger) ; only while edebug is active.
(edebug-outside-debug-on-error debug-on-error)
@@ -2861,7 +2859,6 @@ See `edebug-behavior-alist' for implementations.")
(this-command this-command)
(current-prefix-arg nil)
- ;; More for Emacs 19
(last-input-event nil)
(last-command-event nil)
(last-event-frame nil)
@@ -3792,9 +3789,6 @@ limited by `edebug-print-length' or `edebug-print-level'."
;;; Edebug Minor Mode
-(define-obsolete-variable-alias 'gud-inhibit-global-bindings
- 'edebug-inhibit-emacs-lisp-mode-bindings "24.3")
-
(defvar edebug-inhibit-emacs-lisp-mode-bindings nil
"If non-nil, inhibit Edebug bindings on the C-x C-a key.
By default, loading the `edebug' library causes these bindings to
@@ -4183,6 +4177,7 @@ from Edebug instrumentation found in the backtrace."
(backtrace-mode)
(add-hook 'backtrace-goto-source-functions
#'edebug--backtrace-goto-source nil t))
+ (edebug-backtrace-mode)
(setq edebug-instrumented-backtrace-frames
(backtrace-get-frames 'edebug-debugger
:constructor #'edebug--make-frame)
@@ -4259,6 +4254,14 @@ Save DEF-NAME, BEFORE-INDEX and AFTER-INDEX in FRAME."
(setf (edebug--frame-before-index frame) before-index)
(setf (edebug--frame-after-index frame) after-index))
+(defvar-keymap edebug-backtrace-mode-map
+ "s" #'backtrace-goto-source)
+
+(define-minor-mode edebug-backtrace-mode
+ "Minor mode for showing backtraces from edebug."
+ :lighter nil
+ :interactive nil)
+
(defun edebug--backtrace-goto-source ()
(let* ((index (backtrace-get-index))
(frame (nth index backtrace-frames)))
@@ -4568,6 +4571,12 @@ With prefix argument, make it a temporary breakpoint."
(was-macro `(macro . ,unwrapped))
(t unwrapped))))))
+(defun edebug--strip-plist (symbol)
+ "Remove edebug related properties from plist for SYMBOL."
+ (dolist (prop '( edebug edebug-behavior edebug-coverage
+ edebug-freq-count ghost-edebug))
+ (cl-remprop symbol prop)))
+
(defun edebug-remove-instrumentation (functions)
"Remove Edebug instrumentation from FUNCTIONS.
Interactively, the user is prompted for the function to remove
@@ -4599,6 +4608,7 @@ instrumentation for, defaulting to all functions."
(dolist (symbol functions)
(when-let ((unwrapped
(edebug--unwrap*-symbol-function symbol)))
+ (edebug--strip-plist symbol)
(defalias symbol unwrapped)))
(message "Removed edebug instrumentation from %s"
(mapconcat #'symbol-name functions ", ")))
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index 5e7b5cbfb2f..65aa6aa6df7 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -249,16 +249,22 @@ use '%s or turn off `eieio-backward-compatibility' instead" cname)
(defun eieio-make-class-predicate (class)
(lambda (obj)
(:documentation
- (format "Return non-nil if OBJ is an object of type `%S'.\n\n(fn OBJ)"
- class))
+ (concat
+ (internal--format-docstring-line
+ "Return non-nil if OBJ is an object of type `%S'."
+ class)
+ "\n\n(fn OBJ)"))
(and (eieio-object-p obj)
(same-class-p obj class))))
(defun eieio-make-child-predicate (class)
(lambda (obj)
(:documentation
- (format "Return non-nil if OBJ is an object of type `%S' or a subclass.
-\n(fn OBJ)" class))
+ (concat
+ (internal--format-docstring-line
+ "Return non-nil if OBJ is an object of type `%S' or a subclass."
+ class)
+ "\n\n(fn OBJ)"))
(and (eieio-object-p obj)
(object-of-class-p obj class))))
@@ -353,8 +359,8 @@ See `defclass' for more information."
(defalias csym
(lambda (obj)
(:documentation
- (format
- "Test OBJ to see if it a list of objects which are a child of type %s"
+ (internal--format-docstring-line
+ "Test OBJ to see if it a list of objects which are a child of type `%s'."
cname))
(when (listp obj)
(let ((ans t)) ;; nil is valid
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el
index 5f67263f177..b599aabb7f7 100644
--- a/lisp/emacs-lisp/eieio-opt.el
+++ b/lisp/emacs-lisp/eieio-opt.el
@@ -153,7 +153,7 @@ are not abstract."
(help-insert-xref-button
(help-fns-short-filename location)
'cl-type-definition ctr location 'define-type)
- (insert (substitute-command-keys "'")))
+ (insert (substitute-quotes "'")))
(insert ".\nCreates an object of class " (symbol-name ctr) ".")
(goto-char (point-max))
(if (autoloadp def)
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index 984166b593a..8351d97b13d 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -136,6 +136,7 @@ and reference them using the function `class-option'."
(accessors ()))
;; Collect the accessors we need to define.
+ (setq slots (mapcar (lambda (x) (if (consp x) x (list x))) slots))
(pcase-dolist (`(,sname . ,soptions) slots)
(let* ((acces (plist-get soptions :accessor))
(initarg (plist-get soptions :initarg))
@@ -217,10 +218,11 @@ and reference them using the function `class-option'."
(when (and eieio-backward-compatibility (eq alloc :class))
;; FIXME: How could I declare this *method* as obsolete.
(push `(cl-defmethod ,acces ((this (subclass ,name)))
- ,(format
- "Retrieve the class slot `%S' from a class `%S'.
-This method is obsolete."
- sname name)
+ ,(concat
+ (internal--format-docstring-line
+ "Retrieve the class slot `%S' from a class `%S'."
+ sname name)
+ "\nThis method is obsolete.")
(if (slot-boundp this ',sname)
(eieio-oref-default this ',sname)))
accessors)))
@@ -229,16 +231,18 @@ This method is obsolete."
;; name whose purpose is to set the value of the slot.
(if writer
(push `(cl-defmethod ,writer ((this ,name) value)
- ,(format "Set the slot `%S' of an object of class `%S'."
- sname name)
+ ,(internal--format-docstring-line
+ "Set the slot `%S' of an object of class `%S'."
+ sname name)
(setf (slot-value this ',sname) value))
accessors))
;; If a reader is defined, then create a generic method
;; of that name whose purpose is to access this slot value.
(if reader
(push `(cl-defmethod ,reader ((this ,name))
- ,(format "Access the slot `%S' from object of class `%S'."
- sname name)
+ ,(internal--format-docstring-line
+ "Access the slot `%S' from object of class `%S'."
+ sname name)
(slot-value this ',sname))
accessors))
))
diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el
index 03c5b94e3b4..cbf38e7dd88 100644
--- a/lisp/emacs-lisp/elp.el
+++ b/lisp/emacs-lisp/elp.el
@@ -111,7 +111,7 @@
;; provide the functionality or interface that I wanted, so I wrote
;; this.
-;; Unlike previous profilers, elp uses Emacs 19's built-in function
+;; Unlike previous profilers, elp uses the built-in function
;; current-time to return interval times. This obviates the need for
;; both an external C program and Emacs processes to communicate with
;; such a program, and thus simplifies the package as a whole.
diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index 4436d0a4b16..a891f068a70 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -102,6 +102,43 @@ the name of the test and the result of NAME-FORM."
(indent 1))
`(ert--call-with-test-buffer ,name-form (lambda () ,@body)))
+(cl-defmacro ert-with-test-buffer-selected ((&key name)
+ &body body)
+ "Create a test buffer, switch to it, and run BODY.
+
+This extends `ert-with-test-buffer' by displaying the test
+buffer (whose name is derived from NAME) in a temporary window.
+The temporary window becomes the `selected-window' before BODY is
+evaluated. The modification hooks `before-change-functions' and
+`after-change-functions' are not inhibited during the evaluation
+of BODY, which makes it easier to use `execute-kbd-macro' to
+simulate user interaction. The window configuration is restored
+before returning, even if BODY exits nonlocally. The return
+value is the last form in BODY."
+ (declare (debug ((":name" form) def-body))
+ (indent 1))
+ (let ((ret (make-symbol "ert--with-test-buffer-selected-ret")))
+ `(save-window-excursion
+ (let (,ret)
+ (ert-with-test-buffer (:name ,name)
+ (with-current-buffer-window (current-buffer)
+ `(display-buffer-below-selected
+ (body-function
+ . ,(lambda (window)
+ (select-window window t)
+ ;; body-function is intended to initialize the
+ ;; contents of a temporary read-only buffer, so
+ ;; it is executed with some convenience
+ ;; changes. Undo those changes so that the
+ ;; test buffer behaves more like an ordinary
+ ;; buffer while the body executes.
+ (let ((inhibit-modification-hooks nil)
+ (inhibit-read-only nil)
+ (buffer-read-only nil))
+ (setq ,ret (progn ,@body))))))
+ nil))
+ ,ret))))
+
;;;###autoload
(defun ert-kill-all-test-buffers ()
"Kill all test buffers that are still live."
@@ -422,6 +459,10 @@ The following keyword arguments are supported:
:text STRING If non-nil, pass STRING to `make-temp-file' as
the TEXT argument.
+:buffer SYMBOL Open the temporary file using `find-file-noselect'
+ and bind SYMBOL to the buffer. Kill the buffer
+ after BODY exits normally or non-locally.
+
:coding CODING If non-nil, bind `coding-system-for-write' to CODING
when executing BODY. This is handy when STRING includes
non-ASCII characters or the temporary file must have a
@@ -430,14 +471,17 @@ The following keyword arguments are supported:
See also `ert-with-temp-directory'."
(declare (indent 1) (debug (symbolp body)))
(cl-check-type name symbol)
- (let (keyw prefix suffix directory text extra-keywords coding)
+ (let (keyw prefix suffix directory text extra-keywords buffer coding)
(while (keywordp (setq keyw (car body)))
(setq body (cdr body))
(pcase keyw
(:prefix (setq prefix (pop body)))
(:suffix (setq suffix (pop body)))
+ ;; This is only for internal use by `ert-with-temp-directory'
+ ;; and is therefore not documented.
(:directory (setq directory (pop body)))
(:text (setq text (pop body)))
+ (:buffer (setq buffer (pop body)))
(:coding (setq coding (pop body)))
(_ (push keyw extra-keywords) (pop body))))
(when extra-keywords
@@ -452,10 +496,17 @@ See also `ert-with-temp-directory'."
(make-temp-file ,prefix ,directory ,suffix ,text)))
(,name ,(if directory
`(file-name-as-directory ,temp-file)
- temp-file)))
+ temp-file))
+ ,@(when buffer
+ (list `(,buffer (find-file-literally ,temp-file)))))
(unwind-protect
(progn ,@body)
(ignore-errors
+ ,@(when buffer
+ (list `(with-current-buffer buf
+ (set-buffer-modified-p nil))
+ `(kill-buffer ,buffer))))
+ (ignore-errors
,(if directory
`(delete-directory ,temp-file :recursive)
`(delete-file ,temp-file))))))))
@@ -517,7 +568,7 @@ The same keyword arguments are supported as in
`("\\`mock\\'" nil ,(system-name)))
;; Emacs's Makefile sets $HOME to a nonexistent value. Needed
;; in batch mode only, therefore.
- (unless (and (null noninteractive) (file-directory-p "~/"))
+ (when (and noninteractive (not (file-directory-p "~/")))
(setenv "HOME" temporary-file-directory))
(format "/mock::%s" temporary-file-directory))))
"Temporary directory for remote file tests.")
diff --git a/lisp/emacs-lisp/generate-lisp-file.el b/lisp/emacs-lisp/generate-lisp-file.el
index 8896a3f7019..7b087a4ecbd 100644
--- a/lisp/emacs-lisp/generate-lisp-file.el
+++ b/lisp/emacs-lisp/generate-lisp-file.el
@@ -63,12 +63,12 @@ inserted."
(cl-defun generate-lisp-file-trailer (file &key version inhibit-provide
(coding 'utf-8-emacs-unix) autoloads
- compile provide)
+ compile provide inhibit-native-compile)
"Insert a standard trailer for FILE.
By default, this trailer inhibits version control, byte
compilation, updating autoloads, and uses a `utf-8-emacs-unix'
coding system. These can be inhibited by providing non-nil
-values to the VERSION, NO-PROVIDE, AUTOLOADS and COMPILE
+values to the VERSION, AUTOLOADS, COMPILE and NATIVE-COMPILE
keyword arguments.
CODING defaults to `utf-8-emacs-unix'. Use a nil value to
@@ -79,7 +79,11 @@ If PROVIDE is non-nil, use that in the `provide' statement
instead of using FILE as the basis.
If `standard-output' is bound to a buffer, insert in that buffer.
-If no, insert at point in the current buffer."
+If no, insert at point in the current buffer.
+
+If INHITBIT-NATIVE-COMPILE is non-nil, add a cookie to inhibit
+native compilation. (By default, a file will be native-compiled
+if it's also byte-compiled)."
(with-current-buffer (if (bufferp standard-output)
standard-output
(current-buffer))
@@ -96,9 +100,11 @@ If no, insert at point in the current buffer."
(unless version
(insert ";; version-control: never\n"))
(unless compile
- (insert ";; no-byte-" "compile: t\n")) ;; #$ is byte-compiled into nil.
+ (insert ";; no-byte-" "compile: t\n"))
(unless autoloads
(insert ";; no-update-autoloads: t\n"))
+ (when inhibit-native-compile
+ (insert ";; no-native-" "compile: t\n"))
(when coding
(insert (format ";; coding: %s\n"
(if (eq coding t)
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 54ddc7ac757..a96fa19a3ff 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -87,11 +87,18 @@ with a (not necessarily copyable) Elisp expression that returns the value to
set it to.
DO must return an Elisp expression."
(cond
- ((symbolp place) (funcall do place (lambda (v) `(setq ,place ,v))))
+ ((symbolp place)
+ (let ((me (macroexpand-1 place macroexpand-all-environment)))
+ (if (eq me place)
+ (funcall do place (lambda (v) `(setq ,place ,v)))
+ (gv-get me do))))
((not (consp place)) (signal 'gv-invalid-place (list place)))
(t
(let* ((head (car place))
(gf (function-get head 'gv-expander 'autoload)))
+ (when (and (symbolp head)
+ (get head 'byte-obsolete-generalized-variable))
+ (byte-compile-warn-obsolete head "generalized variable"))
(if gf (apply gf do (cdr place))
(let ((me (macroexpand-1 place
;; (append macroexpand-all-environment
@@ -166,6 +173,18 @@ arguments as NAME. DO is a function as defined in `gv-get'."
;; (`(expand ,expander) `(gv-define-expand ,name ,expander))
(_ (message "Unknown %s declaration %S" symbol handler) nil))))
+(defun make-obsolete-generalized-variable (obsolete-name current-name when)
+ "Make byte-compiler warn that generalized variable OBSOLETE-NAME is obsolete.
+The warning will say that CURRENT-NAME should be used instead.
+
+If CURRENT-NAME is a string, that is the `use instead' message.
+
+WHEN should be a string indicating when the variable was first
+made obsolete, for example a date or a release number."
+ (put obsolete-name 'byte-obsolete-generalized-variable
+ (purecopy (list current-name when)))
+ obsolete-name)
+
;; Additions for `declare'. We specify the values as named aliases so
;; that `describe-variable' prints something useful; cf. Bug#40491.
@@ -392,6 +411,7 @@ The return value is the last VAL in the list.
(gv-define-setter buffer-local-value (val var buf)
(macroexp-let2 nil v val
`(with-current-buffer ,buf (set (make-local-variable ,var) ,v))))
+(make-obsolete-generalized-variable 'buffer-local-value nil "29.1")
(gv-define-expander alist-get
(lambda (do key alist &optional default remove testfn)
@@ -516,13 +536,15 @@ The return value is the last VAL in the list.
(funcall do `(error . ,args)
(lambda (v) `(progn ,v (error . ,args))))))
-(defmacro gv-synthetic-place (getter setter)
+(defun gv-synthetic-place (getter setter)
"Special place described by its setter and getter.
GETTER and SETTER (typically obtained via `gv-letplace') get and
-set that place. I.e. This macro allows you to do the \"reverse\" of what
-`gv-letplace' does.
-This macro only makes sense when used in a place."
- (declare (gv-expander funcall))
+set that place. I.e. this function allows you to do the
+\"reverse\" of what `gv-letplace' does.
+
+This function is only useful when used in conjunction with
+generalized variables in place forms."
+ (declare (gv-expander funcall) (compiler-macro (lambda (_) getter)))
(ignore setter)
getter)
@@ -618,71 +640,160 @@ REF must have been previously obtained with `gv-ref'."
;; Some Emacs-related place types.
(gv-define-simple-setter buffer-file-name set-visited-file-name t)
+(make-obsolete-generalized-variable
+ 'buffer-file-name 'set-visited-file-name "29.1")
+
(gv-define-setter buffer-modified-p (flag &optional buf)
(macroexp-let2 nil buffer `(or ,buf (current-buffer))
`(with-current-buffer ,buffer
(set-buffer-modified-p ,flag))))
+(make-obsolete-generalized-variable
+ 'buffer-modified-p 'set-buffer-modified-p "29.1")
+
(gv-define-simple-setter buffer-name rename-buffer t)
+(make-obsolete-generalized-variable 'buffer-name 'rename-buffer "29.1")
+
(gv-define-setter buffer-string (store)
`(insert (prog1 ,store (erase-buffer))))
+(make-obsolete-generalized-variable 'buffer-string nil "29.1")
+
(gv-define-simple-setter buffer-substring cl--set-buffer-substring)
+(make-obsolete-generalized-variable 'buffer-substring nil "29.1")
+
(gv-define-simple-setter current-buffer set-buffer)
+(make-obsolete-generalized-variable 'current-buffer 'set-buffer "29.1")
+
(gv-define-simple-setter current-column move-to-column t)
+(make-obsolete-generalized-variable 'current-column 'move-to-column "29.1")
+
(gv-define-simple-setter current-global-map use-global-map t)
+(make-obsolete-generalized-variable 'current-global-map 'use-global-map "29.1")
+
(gv-define-setter current-input-mode (store)
`(progn (apply #'set-input-mode ,store) ,store))
+(make-obsolete-generalized-variable 'current-input-mode nil "29.1")
+
(gv-define-simple-setter current-local-map use-local-map t)
+(make-obsolete-generalized-variable 'current-local-map 'use-local-map "29.1")
+
(gv-define-simple-setter current-window-configuration
set-window-configuration t)
+(make-obsolete-generalized-variable
+ 'current-window-configuration 'set-window-configuration "29.1")
+
(gv-define-simple-setter default-file-modes set-default-file-modes t)
+(make-obsolete-generalized-variable
+ 'default-file-modes 'set-default-file-modes "29.1")
+
(gv-define-simple-setter documentation-property put)
+(make-obsolete-generalized-variable 'documentation-property 'put "29.1")
+
(gv-define-setter face-background (x f &optional s)
`(set-face-background ,f ,x ,s))
(gv-define-setter face-background-pixmap (x f &optional s)
- `(set-face-background-pixmap ,f ,x ,s))
+ `(set-face-stipple ,f ,x ,s))
+(make-obsolete-generalized-variable 'face-background-pixmap 'face-stipple "29.1")
+(gv-define-setter face-stipple (x f &optional s)
+ `(set-face-stipple ,f ,x ,s))
(gv-define-setter face-font (x f &optional s) `(set-face-font ,f ,x ,s))
(gv-define-setter face-foreground (x f &optional s)
`(set-face-foreground ,f ,x ,s))
(gv-define-setter face-underline-p (x f &optional s)
`(set-face-underline ,f ,x ,s))
(gv-define-simple-setter file-modes set-file-modes t)
+
(gv-define-setter frame-height (x &optional frame)
`(set-frame-height (or ,frame (selected-frame)) ,x))
+(make-obsolete-generalized-variable 'frame-height 'set-frame-height "29.1")
+
(gv-define-simple-setter frame-parameters modify-frame-parameters t)
(gv-define-simple-setter frame-visible-p cl--set-frame-visible-p)
+(make-obsolete-generalized-variable 'frame-visible-p nil "29.1")
+
(gv-define-setter frame-width (x &optional frame)
`(set-frame-width (or ,frame (selected-frame)) ,x))
+(make-obsolete-generalized-variable 'frame-width 'set-frame-width "29.1")
+
(gv-define-simple-setter getenv setenv t)
(gv-define-simple-setter get-register set-register)
+
(gv-define-simple-setter global-key-binding global-set-key)
+(make-obsolete-generalized-variable 'global-key-binding 'global-set-key "29.1")
+
(gv-define-simple-setter local-key-binding local-set-key)
+(make-obsolete-generalized-variable 'local-key-binding 'local-set-key "29.1")
+
(gv-define-simple-setter mark set-mark t)
+(make-obsolete-generalized-variable 'mark 'set-mark "29.1")
+
(gv-define-simple-setter mark-marker set-mark t)
+(make-obsolete-generalized-variable 'mark-marker 'set-mark "29.1")
+
(gv-define-simple-setter marker-position set-marker t)
+(make-obsolete-generalized-variable 'marker-position 'set-marker "29.1")
+
(gv-define-setter mouse-position (store scr)
`(set-mouse-position ,scr (car ,store) (cadr ,store)
(cddr ,store)))
+(make-obsolete-generalized-variable 'mouse-position 'set-mouse-position "29.1")
+
(gv-define-simple-setter point goto-char)
+(make-obsolete-generalized-variable 'point 'goto-char "29.1")
+
(gv-define-simple-setter point-marker goto-char t)
+(make-obsolete-generalized-variable 'point-marker 'goto-char "29.1")
+
(gv-define-setter point-max (store)
`(progn (narrow-to-region (point-min) ,store) ,store))
+(make-obsolete-generalized-variable 'point-max 'narrow-to-region "29.1")
+
(gv-define-setter point-min (store)
`(progn (narrow-to-region ,store (point-max)) ,store))
+(make-obsolete-generalized-variable 'point-min 'narrow-to-region "29.1")
+
(gv-define-setter read-mouse-position (store scr)
`(set-mouse-position ,scr (car ,store) (cdr ,store)))
+(make-obsolete-generalized-variable
+ 'read-mouse-position 'set-mouse-position "29.1")
+
(gv-define-simple-setter screen-height set-screen-height t)
+(make-obsolete-generalized-variable 'screen-height 'set-screen-height "29.1")
+
(gv-define-simple-setter screen-width set-screen-width t)
+(make-obsolete-generalized-variable 'screen-width 'set-screen-width "29.1")
+
(gv-define-simple-setter selected-window select-window)
+(make-obsolete-generalized-variable 'selected-window 'select-window "29.1")
+
(gv-define-simple-setter selected-screen select-screen)
+(make-obsolete-generalized-variable 'selected-screen 'select-screen "29.1")
+
(gv-define-simple-setter selected-frame select-frame)
+(make-obsolete-generalized-variable 'selected-frame 'select-frame "29.1")
+
(gv-define-simple-setter standard-case-table set-standard-case-table)
+(make-obsolete-generalized-variable
+ 'standard-case-table 'set-standard-case-table "29.1")
+
(gv-define-simple-setter syntax-table set-syntax-table)
+(make-obsolete-generalized-variable 'syntax-table 'set-syntax-table "29.1")
+
(gv-define-simple-setter visited-file-modtime set-visited-file-modtime t)
+(make-obsolete-generalized-variable
+ 'visited-file-modtime 'set-visited-file-modtime "29.1")
+
(gv-define-setter window-height (store)
`(progn (enlarge-window (- ,store (window-height))) ,store))
+(make-obsolete-generalized-variable 'window-height 'enlarge-window "29.1")
+
(gv-define-setter window-width (store)
`(progn (enlarge-window (- ,store (window-width)) t) ,store))
+(make-obsolete-generalized-variable 'window-width 'enlarge-window "29.1")
+
(gv-define-simple-setter x-get-secondary-selection x-own-secondary-selection t)
+(make-obsolete-generalized-variable
+ 'x-get-secondary-selection 'x-own-secondary-selection "29.1")
+
;; More complex setf-methods.
@@ -701,6 +812,7 @@ REF must have been previously obtained with `gv-ref'."
`(cond
(,v ,(funcall setter val))
((eq ,getter ,val) ,(funcall setter `(not ,val))))))))))
+(make-obsolete-generalized-variable 'eq nil "29.1")
(gv-define-expander substring
(lambda (do place from &optional to)
diff --git a/lisp/emacs-lisp/icons.el b/lisp/emacs-lisp/icons.el
index 277b285c2ef..a08ac7463ce 100644
--- a/lisp/emacs-lisp/icons.el
+++ b/lisp/emacs-lisp/icons.el
@@ -189,8 +189,10 @@ present if the icon is represented by an image."
(cl-defmethod icons--create ((_type (eql 'image)) icon keywords)
(let ((file (if (file-name-absolute-p icon)
icon
- (image-search-load-path icon))))
+ (and (fboundp 'image-search-load-path)
+ (image-search-load-path icon)))))
(and (display-images-p)
+ (fboundp 'image-supported-file-p)
(image-supported-file-p file)
(propertize
" " 'display
@@ -200,7 +202,11 @@ present if the icon is represented by an image."
:height (if (eq height 'line)
(window-default-line-height)
height)
- :scale 1)
+ :scale 1
+ :rotation (or (plist-get keywords :rotation) 0)
+ :ascent (if (plist-member keywords :ascent)
+ (plist-get keywords :ascent)
+ 'center))
(create-image file))))))
(cl-defmethod icons--create ((_type (eql 'emoji)) icon _keywords)
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index c56a9660e7c..7e39a77aed5 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -325,6 +325,20 @@ This will generate compile-time constants from BINDINGS."
(throw 'matched t)))
(throw 'matched nil)))))
+(defun lisp-mode--search-key (char bound)
+ (catch 'found
+ (while (re-search-forward
+ (concat "\\_<" char (rx lisp-mode-symbol) "\\_>")
+ bound t)
+ (when (or (< (match-beginning 0) (+ (point-min) 2))
+ ;; A quoted white space before the &/: means that this
+ ;; is not the start of a :keyword or an &option.
+ (not (eql (char-after (- (match-beginning 0) 2))
+ ?\\))
+ (not (memq (char-after (- (match-beginning 0) 1))
+ '(?\s ?\n ?\t))))
+ (throw 'found t)))))
+
(let-when-compile
((lisp-fdefs '("defmacro" "defun"))
(lisp-vdefs '("defvar"))
@@ -496,11 +510,11 @@ This will generate compile-time constants from BINDINGS."
(,(rx "\\\\=")
(0 font-lock-builtin-face prepend))
;; Constant values.
- (,(concat "\\_<:" (rx lisp-mode-symbol) "\\_>")
+ (,(lambda (bound) (lisp-mode--search-key ":" bound))
(0 font-lock-builtin-face))
;; ELisp and CLisp `&' keywords as types.
- (,(concat "\\_<&" (rx lisp-mode-symbol) "\\_>")
- . font-lock-type-face)
+ (,(lambda (bound) (lisp-mode--search-key "&" bound))
+ (0 font-lock-builtin-face))
;; ELisp regexp grouping constructs
(,(lambda (bound)
(catch 'found
@@ -549,11 +563,12 @@ This will generate compile-time constants from BINDINGS."
;; must come before keywords below to have effect
(,(concat "#:" (rx lisp-mode-symbol) "") 0 font-lock-builtin-face)
;; Constant values.
- (,(concat "\\_<:" (rx lisp-mode-symbol) "\\_>")
+ (,(lambda (bound) (lisp-mode--search-key ":" bound))
(0 font-lock-builtin-face))
;; ELisp and CLisp `&' keywords as types.
- (,(concat "\\_<&" (rx lisp-mode-symbol) "\\_>")
- . font-lock-type-face)
+ (,(lambda (bound) (lisp-mode--search-key "&" bound))
+ (0 font-lock-builtin-face))
+ ;; ELisp regexp grouping constructs
;; This is too general -- rms.
;; A user complained that he has functions whose names start with `do'
;; and that they get the wrong color.
@@ -728,67 +743,30 @@ font-lock keywords will not be case sensitive."
len))))
(defun lisp-current-defun-name ()
- "Return the name of the defun at point.
-If there is no defun at point, return the first symbol from the
-top-level form. If there is no top-level form, return nil.
-
-(\"defun\" here means \"form that defines something\", and is
-decided heuristically.)"
+ "Return the name of the defun at point, or nil."
(save-excursion
- (let ((location (point))
- name)
+ (let ((location (point)))
;; If we are now precisely at the beginning of a defun, make sure
;; beginning-of-defun finds that one rather than the previous one.
- (unless (eobp)
- (forward-char 1))
+ (or (eobp) (forward-char 1))
(beginning-of-defun)
;; Make sure we are really inside the defun found, not after it.
- (when (and (looking-at "(")
- (progn
- (end-of-defun)
- (< location (point)))
- (progn
- (forward-sexp -1)
- (>= location (point))))
- (when (looking-at "(")
- (forward-char 1))
- ;; Read the defining construct name, typically "defun" or
+ (when (and (looking-at "\\s(")
+ (progn (end-of-defun)
+ (< location (point)))
+ (progn (forward-sexp -1)
+ (>= location (point))))
+ (if (looking-at "\\s(")
+ (forward-char 1))
+ ;; Skip the defining construct name, typically "defun" or
;; "defvar".
- (let ((symbol (ignore-errors (read (current-buffer)))))
- (when (and symbol (not (symbolp symbol)))
- (setq symbol nil))
- ;; If there's an edebug spec, use that to determine what the
- ;; name is.
- (when symbol
- (let ((spec (or (get symbol 'edebug-form-spec)
- (and (eq (get symbol 'lisp-indent-function) 'defun)
- (get 'defun 'edebug-form-spec)))))
- (save-excursion
- (when (and (eq (car-safe spec) '&define)
- (memq 'name spec))
- (pop spec)
- (while (and spec (not name))
- (let ((candidate (ignore-errors (read (current-buffer)))))
- (when (eq (pop spec) 'name)
- (when (and (consp candidate)
- (symbolp (car (delete 'quote candidate))))
- (setq candidate (car (delete 'quote candidate))))
- (setq name candidate
- spec nil))))))))
- ;; We didn't have an edebug spec (or couldn't find the
- ;; name). If the symbol starts with \"def\", then it's
- ;; likely that the next symbol is the name.
- (when (and (not name)
- (string-match-p "\\(\\`\\|-\\)def" (symbol-name symbol)))
- (when-let ((candidate (ignore-errors (read (current-buffer)))))
- (cond
- ((symbolp candidate)
- (setq name candidate))
- ((and (consp candidate)
- (symbolp (car (delete 'quote candidate))))
- (setq name (car (delete 'quote candidate)))))))
- (when-let ((result (or name symbol)))
- (and (symbolp result) (symbol-name result))))))))
+ (forward-sexp 1)
+ ;; The second element is usually a symbol being defined. If it
+ ;; is not, use the first symbol in it.
+ (skip-chars-forward " \t\n'(")
+ (buffer-substring-no-properties (point)
+ (progn (forward-sexp 1)
+ (point)))))))
(defvar-keymap lisp-mode-shared-map
:doc "Keymap for commands shared by all sorts of Lisp modes."
diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el
index 8413373e5d4..964d23c770e 100644
--- a/lisp/emacs-lisp/loaddefs-gen.el
+++ b/lisp/emacs-lisp/loaddefs-gen.el
@@ -287,10 +287,14 @@ expression, in which case we want to handle forms differently."
;; In Emacs this is normally handled separately by cus-dep.el, but for
;; third party packages, it can be convenient to explicitly autoload
;; a group.
- (let ((groupname (nth 1 form)))
+ (let ((groupname (nth 1 form))
+ (parent (eval (plist-get form :group) t)))
`(let ((loads (get ',groupname 'custom-loads)))
(if (member ',file loads) nil
- (put ',groupname 'custom-loads (cons ',file loads))))))
+ (put ',groupname 'custom-loads (cons ',file loads))
+ ,@(when parent
+ `((put ',parent 'custom-loads
+ (cons ',groupname (get ',parent 'custom-loads)))))))))
;; When processing a macro expansion, any expression
;; before a :autoload-end should be included. These are typically (put
@@ -504,6 +508,7 @@ If COMPILE, don't include a \"don't compile\" cookie."
(generate-lisp-file-trailer
file :provide (and (stringp feature) feature)
:compile compile
+ :inhibit-native-compile t
:inhibit-provide (not feature))
(buffer-string))))
@@ -511,7 +516,7 @@ If COMPILE, don't include a \"don't compile\" cookie."
(defun loaddefs-generate (dir output-file &optional excluded-files
extra-data include-package-version
generate-full)
- "Generate loaddefs files for Lisp files in the directories DIRS.
+ "Generate loaddefs files for Lisp files in one or more directories given by DIR.
DIR can be either a single directory or a list of directories.
The autoloads will be written to OUTPUT-FILE. If any Lisp file
@@ -519,7 +524,7 @@ binds `generated-autoload-file' as a file-local variable, write
its autoloads into the specified file instead.
The function does NOT recursively descend into subdirectories of the
-directory or directories specified by DIRS.
+directories specified by DIR.
Optional argument EXCLUDED-FILES, if non-nil, should be a list of
files, such as preloaded files, whose autoloads should not be written
@@ -627,7 +632,7 @@ instead of just updating them with the new/changed autoloads."
;; It's a new file; put the data at the end.
(progn
(goto-char (point-max))
- (search-backward "\f\n"))
+ (search-backward "\f\n" nil t))
;; Delete the old version of the section.
(delete-region (match-beginning 0)
(and (search-forward "\n\f\n;;;")
@@ -645,7 +650,8 @@ instead of just updating them with the new/changed autoloads."
(unless (equal (buffer-hash) hash)
(write-region (point-min) (point-max) loaddefs-file nil 'silent)
(byte-compile-info
- (file-relative-name loaddefs-file lisp-directory) t "GEN"))))))))
+ (file-relative-name loaddefs-file (car (ensure-list dir)))
+ t "GEN"))))))))
(defun loaddefs-generate--print-form (def)
"Print DEF in a format that makes sense for version control."
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index 5ae9d8368f0..f4df40249de 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -110,7 +110,8 @@ each clause."
(let ((symbols-with-pos-enabled t))
(apply handler form (cdr form)))
(error
- (message "Compiler-macro error for %S: Handler: %S\n%S" (car form) handler err)
+ (message "Warning: Optimization failure for %S: Handler: %S\n%S"
+ (car form) handler err)
form)))
(defun macroexp--funcall-if-compiled (_form)
@@ -187,13 +188,15 @@ It should normally be a symbol with position and it defaults to FORM."
msg))
form)))
-(defun macroexp--obsolete-warning (fun obsolescence-data type)
+(defun macroexp--obsolete-warning (fun obsolescence-data type &optional key)
(let ((instead (car obsolescence-data))
(asof (nth 2 obsolescence-data)))
(format-message
"`%s' is an obsolete %s%s%s" fun type
(if asof (concat " (as of " asof ")") "")
(cond ((stringp instead) (concat "; " (substitute-command-keys instead)))
+ ((and instead key)
+ (format-message "; use `%s' (%s) instead." instead key))
(instead (format-message "; use `%s' instead." instead))
(t ".")))))
@@ -369,6 +372,11 @@ Assumes the caller has bound `macroexpand-all-environment'."
(macroexp--all-forms body))
(cdr form))
form)))
+ (`(while)
+ (macroexp-warn-and-return
+ "missing `while' condition"
+ `(signal 'wrong-number-of-arguments '(while 0))
+ nil 'compile-only form))
(`(setq ,(and var (pred symbolp)
(pred (not booleanp)) (pred (not keywordp)))
,expr)
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index a9a20ab5abf..429052bfdf3 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -4,6 +4,7 @@
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: extensions, lisp, tools
+;; Version: 1.0
;; This file is part of GNU Emacs.
@@ -37,11 +38,6 @@
;;; Code:
-;; The autoloads.el mechanism which adds package--builtin-versions
-;; maintenance to loaddefs.el doesn't work for preloaded packages (such
-;; as this one), so we have to do it by hand!
-(push (purecopy '(nadvice 1 0)) package--builtin-versions)
-
(oclosure-define (advice
(:predicate advice--p)
(:copier advice--cons (cdr))
@@ -108,19 +104,26 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.")
(format "%s\n%s" name doc)
(format "%s" name))
(or doc "No documentation")))))
- "\n")))
+ "\n"
+ (and
+ (eq how :override)
+ (concat
+ (format-message
+ "\nThis is an :override advice, which means that `%s' isn't\n" function)
+ "run at all, and the documentation below may be irrelevant.\n")))))
(defun advice--make-docstring (function)
"Build the raw docstring for FUNCTION, presumably advised."
(let* ((flist (indirect-function function))
(docfun nil)
(macrop (eq 'macro (car-safe flist)))
- (docstring nil))
+ (before nil)
+ (after nil))
(when macrop
(setq flist (cdr flist)))
(if (and (autoloadp flist)
(get function 'advice--pending))
- (setq docstring
+ (setq after
(advice--make-single-doc (get function 'advice--pending)
function macrop))
(while (advice--p flist)
@@ -130,9 +133,13 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.")
;; object instead! So here we try to undo the damage.
(when (integerp (aref flist 4))
(setq docfun flist))
- (setq docstring (concat docstring (advice--make-single-doc
- flist function macrop))
- flist (advice--cdr flist))))
+ (let ((doc-bit (advice--make-single-doc flist function macrop)))
+ ;; We want :overrides to go to the front, because they mean
+ ;; that the doc string may be irrelevant.
+ (if (eq (advice--how flist) :override)
+ (setq before (concat before doc-bit))
+ (setq after (concat after doc-bit))))
+ (setq flist (advice--cdr flist))))
(unless docfun
(setq docfun flist))
(let* ((origdoc (unless (eq function docfun) ;Avoid inf-loops.
@@ -145,12 +152,18 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.")
(if (stringp arglist) t
(help--make-usage-docstring function arglist)))
(setq origdoc (cdr usage)) (car usage)))
- (help-add-fundoc-usage (concat origdoc
- (if (string-suffix-p "\n" origdoc)
- "\n"
- "\n\n")
- docstring)
- usage))))
+ (help-add-fundoc-usage
+ (with-temp-buffer
+ (when before
+ (insert before)
+ (ensure-empty-lines 1))
+ (when origdoc
+ (insert origdoc))
+ (when after
+ (ensure-empty-lines 1)
+ (insert after))
+ (buffer-string))
+ usage))))
(defun advice-eval-interactive-spec (spec)
"Evaluate the interactive spec SPEC."
diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el
index 9775e8cc656..c77ac151d77 100644
--- a/lisp/emacs-lisp/oclosure.el
+++ b/lisp/emacs-lisp/oclosure.el
@@ -557,6 +557,21 @@ This has 2 uses:
(oclosure-define (save-some-buffers-function
(:predicate save-some-buffers-function--p)))
+;; This OClosure type is used internally by `cconv.el' to handle
+;; the case where we need to build a closure whose `interactive' spec
+;; captures variables from the context.
+;; It arguably belongs with `cconv.el' but is needed at runtime,
+;; so we placed it here.
+(oclosure-define (cconv--interactive-helper) fun if)
+(defun cconv--interactive-helper (fun if)
+ "Add interactive \"form\" IF to FUN.
+Returns a new command that otherwise behaves like FUN.
+IF should actually not be a form but a function of no arguments."
+ (oclosure-lambda (cconv--interactive-helper (fun fun) (if if))
+ (&rest args)
+ (apply (if (called-interactively-p 'any)
+ #'funcall-interactively #'funcall)
+ fun args)))
(provide 'oclosure)
;;; oclosure.el ends here
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index e0fb4b05723..b0659cd585f 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -346,21 +346,28 @@ default directory."
(defcustom package-check-signature 'allow-unsigned
"Non-nil means to check package signatures when installing.
-More specifically the value can be:
-- nil: package signatures are ignored.
-- `allow-unsigned': install a package even if it is unsigned, but
- if it is signed, we have the key for it, and OpenGPG is
- installed, verify the signature.
-- t: accept a package only if it comes with at least one verified signature.
-- `all': same as t, except when the package has several signatures,
- in which case we verify all the signatures.
This also applies to the \"archive-contents\" file that lists the
-contents of the archive."
+contents of the archive.
+
+The value can be one of:
+
+ t Accept a package only if it comes with at least
+ one verified signature.
+
+ `all' Same as t, but verify all signatures if there
+ are more than one.
+
+ `allow-unsigned' Install a package even if it is unsigned,
+ but verify the signature if possible (that
+ is, if it is signed, we have the key for it,
+ and GnuPG is installed).
+
+ nil Package signatures are ignored."
:type '(choice (const :value nil :tag "Never")
(const :value allow-unsigned :tag "Allow unsigned")
(const :value t :tag "Check always")
- (const :value all :tag "Check all signatures"))
+ (const :value all :tag "Check always (all signatures)"))
:risky t
:version "27.1")
@@ -2236,8 +2243,8 @@ to install it but still mark it as selected."
(assq (car elt) package-archive-contents)))
(and available
(version-list-<
- (package-desc-priority-version (cadr elt))
- (package-desc-priority-version (cadr available))))))
+ (package-desc-version (cadr elt))
+ (package-desc-version (cadr available))))))
package-alist)))
;;;###autoload
@@ -2483,10 +2490,14 @@ If NOSAVE is non-nil, the package is not removed from
"Reinstall package PKG.
PKG should be either a symbol, the package name, or a `package-desc'
object."
- (interactive (list (intern (completing-read
- "Reinstall package: "
- (mapcar #'symbol-name
- (mapcar #'car package-alist))))))
+ (interactive
+ (progn
+ (package--archives-initialize)
+ (list (intern (completing-read
+ "Reinstall package: "
+ (mapcar #'symbol-name
+ (mapcar #'car package-alist)))))))
+ (package--archives-initialize)
(package-delete
(if (package-desc-p pkg) pkg (cadr (assq pkg package-alist)))
'force 'nosave)
@@ -2698,7 +2709,7 @@ Helper function for `describe-package'."
"',\n shadowing a ")
(propertize "built-in package"
'font-lock-face 'package-status-built-in))
- (insert (substitute-command-keys "'")))
+ (insert (substitute-quotes "'")))
(if signed
(insert ".")
(insert " (unsigned)."))
@@ -3773,30 +3784,34 @@ objects removed."
`((delete . ,del) (install . ,ins) (upgrade . ,upg))))
(defun package-menu--perform-transaction (install-list delete-list)
- "Install packages in INSTALL-LIST and delete DELETE-LIST."
- (if install-list
- (let ((status-format (format ":Installing %%d/%d"
- (length install-list)))
- (i 0)
- (package-menu--transaction-status))
- (dolist (pkg install-list)
- (setq package-menu--transaction-status
- (format status-format (cl-incf i)))
- (force-mode-line-update)
- (redisplay 'force)
- ;; Don't mark as selected, `package-menu-execute' already
- ;; does that.
- (package-install pkg 'dont-select))))
- (let ((package-menu--transaction-status ":Deleting"))
- (force-mode-line-update)
- (redisplay 'force)
- (dolist (elt (package--sort-by-dependence delete-list))
- (condition-case-unless-debug err
- (let ((inhibit-message (or inhibit-message package-menu-async)))
- (package-delete elt nil 'nosave))
- (error (message "Error trying to delete `%s': %S"
- (package-desc-full-name elt)
- err))))))
+ "Install packages in INSTALL-LIST and delete DELETE-LIST.
+Return nil if there were no errors; non-nil otherwise."
+ (let ((errors nil))
+ (if install-list
+ (let ((status-format (format ":Installing %%d/%d"
+ (length install-list)))
+ (i 0)
+ (package-menu--transaction-status))
+ (dolist (pkg install-list)
+ (setq package-menu--transaction-status
+ (format status-format (cl-incf i)))
+ (force-mode-line-update)
+ (redisplay 'force)
+ ;; Don't mark as selected, `package-menu-execute' already
+ ;; does that.
+ (package-install pkg 'dont-select))))
+ (let ((package-menu--transaction-status ":Deleting"))
+ (force-mode-line-update)
+ (redisplay 'force)
+ (dolist (elt (package--sort-by-dependence delete-list))
+ (condition-case-unless-debug err
+ (let ((inhibit-message (or inhibit-message package-menu-async)))
+ (package-delete elt nil 'nosave))
+ (error
+ (push (package-desc-full-name elt) errors)
+ (message "Error trying to delete `%s': %S"
+ (package-desc-full-name elt) err)))))
+ errors))
(defun package--update-selected-packages (add remove)
"Update the `package-selected-packages' list according to ADD and REMOVE.
@@ -3869,8 +3884,8 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
(message "Operation %s started" message-template)
;; Packages being upgraded are not marked as selected.
(package--update-selected-packages .install .delete)
- (package-menu--perform-transaction install-list delete-list)
- (when package-selected-packages
+ (unless (package-menu--perform-transaction install-list delete-list)
+ ;; If there weren't errors, output data.
(if-let* ((removable (package--removable-packages)))
(message "Operation finished. Packages that are no longer needed: %d. Type `%s' to remove them"
(length removable)
diff --git a/lisp/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el
index 46b429ce6fe..897c35b5b19 100644
--- a/lisp/emacs-lisp/re-builder.el
+++ b/lisp/emacs-lisp/re-builder.el
@@ -369,7 +369,8 @@ provided in the Commentary section of this library."
(get-buffer-create reb-buffer)
`((display-buffer-in-direction)
(direction . ,dir)
- (dedicated . t))))))
+ (dedicated . t)
+ (window-height . fit-window-to-buffer))))))
(font-lock-mode 1)
(reb-initialize-buffer)))
@@ -497,7 +498,8 @@ Optional argument SYNTAX must be specified if called non-interactively."
(setq reb-re-syntax syntax)
(when buffer
(with-current-buffer buffer
- (reb-initialize-buffer))))
+ (reb-initialize-buffer))
+ (message "Switched syntax to `%s'" reb-re-syntax)))
(error "Invalid syntax: %s" syntax)))
@@ -737,8 +739,7 @@ If SUBEXP is non-nil mark only the corresponding sub-expressions."
(let ((face (get-text-property (1- (point)) 'face)))
(when (or (and (listp face)
(memq 'font-lock-string-face face))
- (eq 'font-lock-string-face face)
- t)
+ (eq 'font-lock-string-face face))
(throw 'found t))))))))
(defface reb-regexp-grouping-backslash
@@ -819,7 +820,6 @@ If SUBEXP is non-nil mark only the corresponding sub-expressions."
(defun reb-restart-font-lock ()
"Restart `font-lock-mode' to fit current regexp format."
- (message "reb-restart-font-lock re-re-syntax=%s" reb-re-syntax)
(with-current-buffer (get-buffer reb-buffer)
(let ((font-lock-is-on font-lock-mode))
(font-lock-mode -1)
diff --git a/lisp/emacs-lisp/regexp-opt.el b/lisp/emacs-lisp/regexp-opt.el
index cae5dd00d1d..4d5a39458d2 100644
--- a/lisp/emacs-lisp/regexp-opt.el
+++ b/lisp/emacs-lisp/regexp-opt.el
@@ -133,7 +133,6 @@ usually more efficient than that of a simplified version:
(save-match-data
;; Recurse on the sorted list.
(let* ((max-lisp-eval-depth 10000)
- (max-specpdl-size 10000)
(completion-ignore-case nil)
(completion-regexp-list nil)
(open (cond ((stringp paren) paren) (paren "\\(")))
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index b6f0f66e5b1..82ade0ac0c3 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -347,6 +347,20 @@ list."
sequence))
;;;###autoload
+(cl-defgeneric seq-remove-at-position (sequence n)
+ "Return a copy of SEQUENCE where the element at N got removed.
+
+N is the (zero-based) index of the element that should not be in
+the result.
+
+The result is a sequence of the same type as SEQUENCE."
+ (seq-concatenate
+ (let ((type (type-of sequence)))
+ (if (eq type 'cons) 'list type))
+ (seq-subseq sequence 0 n)
+ (seq-subseq sequence (1+ n))))
+
+;;;###autoload
(cl-defgeneric seq-reduce (function sequence initial-value)
"Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE.
@@ -409,7 +423,7 @@ found or not."
(cl-defgeneric seq-contains (sequence elt &optional testfn)
"Return the first element in SEQUENCE that is equal to ELT.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
+Equality is defined by the function TESTFN, which defaults to `equal'."
(declare (obsolete seq-contains-p "27.1"))
(seq-some (lambda (e)
(when (funcall (or testfn #'equal) elt e)
@@ -418,7 +432,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
(cl-defgeneric seq-contains-p (sequence elt &optional testfn)
"Return non-nil if SEQUENCE contains an element equal to ELT.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
+Equality is defined by the function TESTFN, which defaults to `equal'."
(catch 'seq--break
(seq-doseq (e sequence)
(let ((r (funcall (or testfn #'equal) e elt)))
@@ -429,14 +443,14 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
(cl-defgeneric seq-set-equal-p (sequence1 sequence2 &optional testfn)
"Return non-nil if SEQUENCE1 and SEQUENCE2 contain the same elements.
This does not depend on the order of the elements.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
+Equality is defined by the function TESTFN, which defaults to `equal'."
(and (seq-every-p (lambda (item1) (seq-contains-p sequence2 item1 testfn)) sequence1)
(seq-every-p (lambda (item2) (seq-contains-p sequence1 item2 testfn)) sequence2)))
;;;###autoload
(cl-defgeneric seq-position (sequence elt &optional testfn)
- "Return the index of the first element in SEQUENCE that is equal to ELT.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
+ "Return the (zero-based) index of the first element in SEQUENCE equal to ELT.
+Equality is defined by the function TESTFN, which defaults to `equal'."
(let ((index 0))
(catch 'seq--break
(seq-doseq (e sequence)
@@ -446,6 +460,23 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
nil)))
;;;###autoload
+(cl-defgeneric seq-positions (sequence elt &optional testfn)
+ "Return indices for which (TESTFN (seq-elt SEQUENCE index) ELT) is non-nil.
+
+TESTFN is a two-argument function which is passed each element of
+SEQUENCE as first argument and ELT as second. TESTFN defaults to
+`equal'.
+
+The result is a list of (zero-based) indices."
+ (let ((result '()))
+ (seq-do-indexed
+ (lambda (e index)
+ (when (funcall (or testfn #'equal) e elt)
+ (push index result)))
+ sequence)
+ (nreverse result)))
+
+;;;###autoload
(cl-defgeneric seq-uniq (sequence &optional testfn)
"Return a list of the elements of SEQUENCE with duplicates removed.
TESTFN is used to compare elements, or `equal' if TESTFN is nil."
@@ -502,7 +533,7 @@ negative integer or 0, nil is returned."
;;;###autoload
(cl-defgeneric seq-union (sequence1 sequence2 &optional testfn)
"Return a list of all elements that appear in either SEQUENCE1 or SEQUENCE2.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
+Equality is defined by the function TESTFN, which defaults to `equal'."
(let* ((accum (lambda (acc elt)
(if (seq-contains-p acc elt testfn)
acc
@@ -514,7 +545,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
;;;###autoload
(cl-defgeneric seq-intersection (sequence1 sequence2 &optional testfn)
"Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
+Equality is defined by the function TESTFN, which defaults to `equal'."
(seq-reduce (lambda (acc elt)
(if (seq-contains-p sequence2 elt testfn)
(cons elt acc)
@@ -524,7 +555,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if nil."
(cl-defgeneric seq-difference (sequence1 sequence2 &optional testfn)
"Return a list of the elements that appear in SEQUENCE1 but not in SEQUENCE2.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
+Equality is defined by the function TESTFN, which defaults to `equal'."
(seq-reduce (lambda (acc elt)
(if (seq-contains-p sequence2 elt testfn)
acc
@@ -618,13 +649,7 @@ Signal an error if SEQUENCE is empty."
(cl-defmethod seq-take ((list list) n)
"Optimized implementation of `seq-take' for lists."
- (if (eval-when-compile (fboundp 'take))
- (take n list)
- (let ((result '()))
- (while (and list (> n 0))
- (setq n (1- n))
- (push (pop list) result))
- (nreverse result))))
+ (take n list))
(cl-defmethod seq-drop-while (pred (list list))
"Optimized implementation of `seq-drop-while' for lists."
@@ -655,16 +680,6 @@ Signal an error if SEQUENCE is empty."
sequence
(concat sequence)))
-(defun seq--activate-font-lock-keywords ()
- "Activate font-lock keywords for some symbols defined in seq."
- (font-lock-add-keywords 'emacs-lisp-mode
- '("\\<seq-doseq\\>" "\\<seq-let\\>")))
-
-(unless (fboundp 'elisp--font-lock-flush-elisp-buffers)
- ;; In Emacs≄25, (via elisp--font-lock-flush-elisp-buffers and a few others)
- ;; we automatically highlight macros.
- (add-hook 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords))
-
(defun seq-split (sequence length)
"Split SEQUENCE into a list of sub-sequences of at most LENGTH.
All the sub-sequences will be of LENGTH, except the last one,
@@ -680,5 +695,9 @@ which may be shorter."
result))
(nreverse result)))
+(defun seq-keep (function sequence)
+ "Apply FUNCTION to SEQUENCE and return all non-nil results."
+ (delq nil (seq-map function sequence)))
+
(provide 'seq)
;;; seq.el ends here
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index d187af9ac83..4cfd658e10d 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -22,6 +22,15 @@
;;; Commentary:
+;; This package lists functions based on various groupings.
+;;
+;; For instance, `string-trim' and `mapconcat' are `string' functions,
+;; so `M-x shortdoc RET string RET' will give an overview of functions
+;; that operate on strings.
+;;
+;; The documentation groups are created with the
+;; `define-short-documentation-group' macro.
+
;;; Code:
(require 'seq)
@@ -355,13 +364,11 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
(abbreviate-file-name
:no-eval (abbreviate-file-name "/home/some-user")
:eg-result "~some-user")
- (file-parent-directory
- :eval (file-parent-directory "/foo/bar")
- :eval (file-parent-directory "~")
- :eval (file-parent-directory "/tmp/")
- :eval (file-parent-directory "foo/bar")
- :eval (file-parent-directory "foo")
- :eval (file-parent-directory "/"))
+ (file-name-parent-directory
+ :eval (file-name-parent-directory "/foo/bar")
+ :eval (file-name-parent-directory "/foo/")
+ :eval (file-name-parent-directory "foo/bar")
+ :eval (file-name-parent-directory "foo"))
"Quoted File Names"
(file-name-quote
:args (name)
@@ -846,6 +853,10 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
:eval (seq-find #'numberp '(a b 3 4 f 6)))
(seq-position
:eval (seq-position '(a b c) 'c))
+ (seq-positions
+ :eval (seq-positions '(a b c a d) 'a)
+ :eval (seq-positions '(a b c a d) 'z)
+ :eval (seq-positions '(11 5 7 12 9 15) 10 #'>=))
(seq-length
:eval (seq-length "abcde"))
(seq-max
@@ -888,6 +899,9 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
:eval (seq-filter #'numberp '(a b 3 4 f 6)))
(seq-remove
:eval (seq-remove #'numberp '(1 2 c d 5)))
+ (seq-remove-at-position
+ :eval (seq-remove-at-position '(a b c d e) 3)
+ :eval (seq-remove-at-position [a b c d e] 0))
(seq-group-by
:eval (seq-group-by #'cl-plusp '(-1 2 3 -4 -5 6)))
(seq-union
@@ -941,12 +955,24 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
:eval (point-min))
(point-max
:eval (point-max))
+ (pos-bol
+ :eval (pos-bol))
+ (pos-eol
+ :eval (pos-eol))
+ (bolp
+ :eval (bolp))
+ (eolp
+ :eval (eolp))
(line-beginning-position
:eval (line-beginning-position))
(line-end-position
:eval (line-end-position))
(buffer-size
:eval (buffer-size))
+ (bobp
+ :eval (bobp))
+ (eobp
+ :eval (eobp))
"Moving Around"
(goto-char
:no-eval (goto-char (point-max))
@@ -972,8 +998,13 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
(following-char
:no-eval (following-char)
:eg-result 67)
+ (preceding-char
+ :no-eval (preceding-char)
+ :eg-result 38)
(char-after
:eval (char-after 45))
+ (char-before
+ :eval (char-before 13))
(get-byte
:no-eval (get-byte 45)
:eg-result-string "#xff")
@@ -982,6 +1013,8 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
:no-value (delete-region (point-min) (point-max)))
(erase-buffer
:no-value (erase-buffer))
+ (delete-line
+ :no-value (delete-line))
(insert
:no-value (insert "This string will be inserted in the buffer\n"))
(subst-char-in-region
@@ -1488,8 +1521,11 @@ Example:
:doc "Keymap for `shortdoc-mode'."
"n" #'shortdoc-next
"p" #'shortdoc-previous
+ "N" #'shortdoc-next-section
+ "P" #'shortdoc-previous-section
"C-c C-n" #'shortdoc-next-section
- "C-c C-p" #'shortdoc-previous-section)
+ "C-c C-p" #'shortdoc-previous-section
+ "w" #'shortdoc-copy-function-as-kill)
(define-derived-mode shortdoc-mode special-mode "shortdoc"
"Mode for shortdoc."
@@ -1502,35 +1538,49 @@ Example:
(funcall
(if reverse 'text-property-search-backward
'text-property-search-forward)
- sym nil t t)
+ sym nil t)
(setq arg (1- arg))))
(defun shortdoc-next (&optional arg)
- "Move cursor to the next function.
-With ARG, do it that many times."
+ "Move point to the next function.
+With prefix numeric argument ARG, do it that many times."
(interactive "p" shortdoc-mode)
(shortdoc--goto-section arg 'shortdoc-function))
(defun shortdoc-previous (&optional arg)
- "Move cursor to the previous function.
-With ARG, do it that many times."
+ "Move point to the previous function.
+With prefix numeric argument ARG, do it that many times."
(interactive "p" shortdoc-mode)
(shortdoc--goto-section arg 'shortdoc-function t)
(backward-char 1))
(defun shortdoc-next-section (&optional arg)
- "Move cursor to the next section.
-With ARG, do it that many times."
+ "Move point to the next section.
+With prefix numeric argument ARG, do it that many times."
(interactive "p" shortdoc-mode)
(shortdoc--goto-section arg 'shortdoc-section))
(defun shortdoc-previous-section (&optional arg)
- "Move cursor to the previous section.
-With ARG, do it that many times."
+ "Move point to the previous section.
+With prefix numeric argument ARG, do it that many times."
(interactive "p" shortdoc-mode)
(shortdoc--goto-section arg 'shortdoc-section t)
(forward-line -2))
+(defun shortdoc-copy-function-as-kill ()
+ "Copy name of the function near point into the kill ring."
+ (interactive)
+ (save-excursion
+ (goto-char (pos-bol))
+ (when-let* ((re (rx bol "(" (group (+ (not (in " "))))))
+ (string
+ (and (or (looking-at re)
+ (re-search-backward re nil t))
+ (match-string 1))))
+ (set-text-properties 0 (length string) nil string)
+ (kill-new string)
+ (message string))))
+
(provide 'shortdoc)
;;; shortdoc.el ends here
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index bd7c3c82f97..6e4d88b4df3 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -97,6 +97,7 @@ threading."
(maphash (lambda (_ v) (push v values)) hash-table)
values))
+;;;###autoload
(defsubst string-join (strings &optional separator)
"Join all STRINGS using SEPARATOR.
Optional argument SEPARATOR must be a string, a vector, or a list of
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index 9868d8c4ec0..c01f3fd4fec 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -465,7 +465,7 @@ changing `tabulated-list-sort-key'."
(let* ((elt (car entries))
(tabulated-list--near-rows
(list
- (or (tabulated-list-get-entry (point-at-bol 0)) (cadr elt))
+ (or (tabulated-list-get-entry (pos-bol 0)) (cadr elt))
(cadr elt)
(or (cadr (cadr entries)) (cadr elt))))
(id (car elt)))
@@ -519,7 +519,7 @@ of column descriptors."
(insert (make-string x ?\s)))
(let ((tabulated-list--near-rows ; Bind it if not bound yet (Bug#25506).
(or (bound-and-true-p tabulated-list--near-rows)
- (list (or (tabulated-list-get-entry (point-at-bol 0))
+ (list (or (tabulated-list-get-entry (pos-bol 0))
cols)
cols))))
(dotimes (n ncols)
@@ -611,7 +611,7 @@ This function only changes the buffer contents; it does not alter
(cols (tabulated-list-get-entry))
(inhibit-read-only t))
(when cols
- (delete-region (line-beginning-position) (1+ (line-end-position)))
+ (delete-region (pos-bol) (1+ (pos-eol)))
(list id cols))))
(defun tabulated-list-set-col (col desc &optional change-entry-data)
@@ -625,8 +625,8 @@ by setting the appropriate slot of the vector originally used to
print this entry. If `tabulated-list-entries' has a list value,
this is the vector stored within it."
(let* ((opoint (point))
- (eol (line-end-position))
- (pos (line-beginning-position))
+ (eol (pos-eol))
+ (pos (pos-bol))
(id (tabulated-list-get-id pos))
(entry (tabulated-list-get-entry pos))
(prop 'tabulated-list-column-name)
@@ -651,9 +651,9 @@ this is the vector stored within it."
(goto-char pos)
(let ((tabulated-list--near-rows
(list
- (tabulated-list-get-entry (point-at-bol 0))
+ (tabulated-list-get-entry (pos-bol 0))
entry
- (or (tabulated-list-get-entry (point-at-bol 2)) entry))))
+ (or (tabulated-list-get-entry (pos-bol 2)) entry))))
(tabulated-list-print-col col desc (current-column)))
(if change-entry-data
(aset entry col desc))
@@ -785,7 +785,7 @@ If ARG is provided, move that many columns."
(let ((prev (or (previous-single-property-change
(point) 'tabulated-list-column-name)
1)))
- (unless (< prev (line-beginning-position))
+ (unless (< prev (pos-bol))
(goto-char prev)))))
;;; The mode definition:
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index cd2e388ce42..760063d1f9d 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -637,8 +637,7 @@ argument is maybe, return maybe. Return 1value only if both arguments
are 1value."
(cl-case val
(testcover-1value result)
- (maybe (and result 'maybe))
- (nil nil)))
+ (maybe (and result 'maybe))))
(defun testcover-analyze-coverage-compose (forms func)
"Analyze a list of FORMS for code coverage using FUNC.
diff --git a/lisp/emacs-lisp/vtable.el b/lisp/emacs-lisp/vtable.el
index 61265c97c28..9bdf90bf1d6 100644
--- a/lisp/emacs-lisp/vtable.el
+++ b/lisp/emacs-lisp/vtable.el
@@ -770,7 +770,8 @@ If NEXT, do the next column."
((string-match "\\([0-9.]+\\)px" spec)
(string-to-number (match-string 1 spec)))
((string-match "\\([0-9.]+\\)%" spec)
- (* (string-to-number (match-string 1 spec)) (window-width nil t)))
+ (/ (* (string-to-number (match-string 1 spec)) (window-width nil t))
+ 100))
(t
(error "Invalid spec: %s" spec))))