summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
authorJan D <jan.h.d@swipnet.se>2015-05-17 16:46:34 +0200
committerJan D <jan.h.d@swipnet.se>2015-05-17 16:46:34 +0200
commit6445ee0fb751ae2c1dfef900d44721b3d952812f (patch)
treed43006cb93d9ea7b00ea02aabcd5577c41ff827f /lisp/emacs-lisp
parentf92ac2e82ed199d6f25d2a59508e08addb1150ac (diff)
parentc9c4708ed47b18987940a71b98eb9873150d2b95 (diff)
downloademacs-6445ee0fb751ae2c1dfef900d44721b3d952812f.tar.gz
emacs-6445ee0fb751ae2c1dfef900d44721b3d952812f.tar.bz2
emacs-6445ee0fb751ae2c1dfef900d44721b3d952812f.zip
Merge branch 'master' into cairo
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/bytecomp.el80
-rw-r--r--lisp/emacs-lisp/chart.el4
-rw-r--r--lisp/emacs-lisp/check-declare.el7
-rw-r--r--lisp/emacs-lisp/cl-generic.el270
-rw-r--r--lisp/emacs-lisp/cl-lib.el7
-rw-r--r--lisp/emacs-lisp/cl-seq.el2
-rw-r--r--lisp/emacs-lisp/cl.el3
-rw-r--r--lisp/emacs-lisp/debug.el3
-rw-r--r--lisp/emacs-lisp/eieio-core.el24
-rw-r--r--lisp/emacs-lisp/eieio-custom.el14
-rw-r--r--lisp/emacs-lisp/eieio-opt.el3
-rw-r--r--lisp/emacs-lisp/eieio.el4
-rw-r--r--lisp/emacs-lisp/eldoc.el27
-rw-r--r--lisp/emacs-lisp/ert.el6
-rw-r--r--lisp/emacs-lisp/lisp.el15
-rw-r--r--lisp/emacs-lisp/package-x.el1
-rw-r--r--lisp/emacs-lisp/package.el274
-rw-r--r--lisp/emacs-lisp/pcase.el10
-rw-r--r--lisp/emacs-lisp/seq.el104
-rw-r--r--lisp/emacs-lisp/subr-x.el3
-rw-r--r--lisp/emacs-lisp/tabulated-list.el30
-rw-r--r--lisp/emacs-lisp/testcover.el27
22 files changed, 565 insertions, 353 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 51bbf8a2944..67744c69b14 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -979,17 +979,6 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
(lambda (x) (if (symbolp x) (list 'prin1-to-string x) x))
args))))))
-(defvar byte-compile--interactive nil
- "Determine if `byte-compile--message' uses the minibuffer.")
-
-(defun byte-compile--message (format &rest args)
- "Like `message', except sometimes don't print to minibuffer.
-If the variable `byte-compile--interactive' is nil, the message
-is not displayed on the minibuffer."
- (apply #'message format args)
- (unless byte-compile--interactive
- (message nil)))
-
;; Log something that isn't a warning.
(defun byte-compile-log-1 (string)
(with-current-buffer byte-compile-log-buffer
@@ -997,7 +986,7 @@ is not displayed on the minibuffer."
(goto-char (point-max))
(byte-compile-warning-prefix nil nil)
(cond (noninteractive
- (byte-compile--message " %s" string))
+ (message " %s" string))
(t
(insert (format "%s\n" string)))))))
@@ -1601,10 +1590,7 @@ extra args."
"Recompile every `.el' file in DIRECTORY that already has a `.elc' file.
Files in subdirectories of DIRECTORY are processed also."
(interactive "DByte force recompile (directory): ")
- (let ((byte-compile--interactive
- (or byte-compile--interactive
- (called-interactively-p 'any))))
- (byte-recompile-directory directory nil t)))
+ (byte-recompile-directory directory nil t))
;;;###autoload
(defun byte-recompile-directory (directory &optional arg force)
@@ -1634,9 +1620,6 @@ that already has a `.elc' file."
(compilation-mode))
(let ((directories (list default-directory))
(default-directory default-directory)
- (byte-compile--interactive
- (or byte-compile--interactive
- (called-interactively-p 'any)))
(skip-count 0)
(fail-count 0)
(file-count 0)
@@ -1645,7 +1628,7 @@ that already has a `.elc' file."
(displaying-byte-compile-warnings
(while directories
(setq directory (car directories))
- (byte-compile--message "Checking %s..." directory)
+ (message "Checking %s..." directory)
(dolist (file (directory-files directory))
(let ((source (expand-file-name file directory)))
(if (file-directory-p source)
@@ -1670,13 +1653,13 @@ that already has a `.elc' file."
(`t file-count)
(_ fail-count)))
(or noninteractive
- (byte-compile--message "Checking %s..." directory))
+ (message "Checking %s..." directory))
(if (not (eq last-dir directory))
(setq last-dir directory
dir-count (1+ dir-count)))
)))))
(setq directories (cdr directories))))
- (byte-compile--message "Done (Total of %d file%s compiled%s%s%s)"
+ (message "Done (Total of %d file%s compiled%s%s%s)"
file-count (if (= file-count 1) "" "s")
(if (> fail-count 0) (format ", %d failed" fail-count) "")
(if (> skip-count 0) (format ", %d skipped" skip-count) "")
@@ -1723,10 +1706,7 @@ If compilation is needed, this functions returns the result of
current-prefix-arg)))
(let ((dest (byte-compile-dest-file filename))
;; Expand now so we get the current buffer's defaults
- (filename (expand-file-name filename))
- (byte-compile--interactive
- (or byte-compile--interactive
- (called-interactively-p 'any))))
+ (filename (expand-file-name filename)))
(if (if (file-exists-p dest)
;; File was already compiled
;; Compile if forced to, or filename newer
@@ -1738,7 +1718,7 @@ If compilation is needed, this functions returns the result of
filename "? ")))))
(progn
(if (and noninteractive (not byte-compile-verbose))
- (byte-compile--message "Compiling %s..." filename))
+ (message "Compiling %s..." filename))
(byte-compile-file filename load))
(when load
(load (if (file-exists-p dest) dest filename)))
@@ -1782,9 +1762,6 @@ The value is non-nil if there were no errors, nil if errors."
(let ((byte-compile-current-file filename)
(byte-compile-current-group nil)
(set-auto-coding-for-load t)
- (byte-compile--interactive
- (or byte-compile--interactive
- (called-interactively-p 'any)))
target-file input-buffer output-buffer
byte-compile-dest-file)
(setq target-file (byte-compile-dest-file filename))
@@ -1840,14 +1817,14 @@ The value is non-nil if there were no errors, nil if errors."
;; (byte-compile-abbreviate-file filename)
;; (with-current-buffer input-buffer no-byte-compile))
(when (file-exists-p target-file)
- (byte-compile--message "%s deleted because of `no-byte-compile: %s'"
+ (message "%s deleted because of `no-byte-compile: %s'"
(byte-compile-abbreviate-file target-file)
(buffer-local-value 'no-byte-compile input-buffer))
(condition-case nil (delete-file target-file) (error nil)))
;; We successfully didn't compile this file.
'no-byte-compile)
(when byte-compile-verbose
- (byte-compile--message "Compiling %s..." filename))
+ (message "Compiling %s..." filename))
(setq byte-compiler-error-flag nil)
;; It is important that input-buffer not be current at this call,
;; so that the value of point set in input-buffer
@@ -1859,7 +1836,7 @@ The value is non-nil if there were no errors, nil if errors."
(if byte-compiler-error-flag
nil
(when byte-compile-verbose
- (byte-compile--message "Compiling %s...done" filename))
+ (message "Compiling %s...done" filename))
(kill-buffer input-buffer)
(with-current-buffer output-buffer
(goto-char (point-max))
@@ -1885,7 +1862,7 @@ The value is non-nil if there were no errors, nil if errors."
;; recompiled). Previously this was accomplished by
;; deleting target-file before writing it.
(rename-file tempfile target-file t)
- (or noninteractive (byte-compile--message "Wrote %s" target-file)))
+ (or noninteractive (message "Wrote %s" target-file)))
;; This is just to give a better error message than write-region
(signal 'file-error
(list "Opening output file"
@@ -1919,9 +1896,6 @@ With argument ARG, insert value in current buffer after the form."
(byte-compile-read-position (point))
(byte-compile-last-position byte-compile-read-position)
(byte-compile-last-warned-form 'nothing)
- (byte-compile--interactive
- (or byte-compile--interactive
- (called-interactively-p 'any)))
(value (eval
(let ((read-with-symbol-positions (current-buffer))
(read-symbol-positions-list nil))
@@ -1929,10 +1903,10 @@ With argument ARG, insert value in current buffer after the form."
(byte-compile-sexp (read (current-buffer)))))
lexical-binding)))
(cond (arg
- (byte-compile--message "Compiling from buffer... done.")
+ (message "Compiling from buffer... done.")
(prin1 value (current-buffer))
(insert "\n"))
- ((byte-compile--message "%s" (prin1-to-string value)))))))
+ ((message "%s" (prin1-to-string value)))))))
(defun byte-compile-from-buffer (inbuffer)
(let ((byte-compile-current-buffer inbuffer)
@@ -2436,7 +2410,7 @@ not to take responsibility for the actual compilation of the code."
(byte-compile-arglist-warn name arglist macro))
(if byte-compile-verbose
- (byte-compile--message "Compiling %s... (%s)"
+ (message "Compiling %s... (%s)"
(or byte-compile-current-file "") name))
(cond ((not (or macro (listp body)))
;; We do not know positively if the definition is a macro
@@ -2606,7 +2580,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
;; error to a simple message for the known case where signaling an error
;; causes problems.
((byte-code-function-p fun)
- (byte-compile--message "Function %s is already compiled"
+ (message "Function %s is already compiled"
(if (symbolp form) form "provided"))
fun)
(t
@@ -2946,11 +2920,17 @@ for symbols generated by the byte compiler itself."
;; Special macro-expander used during byte-compilation.
(defun byte-compile-macroexpand-declare-function (fn file &rest args)
- (push (cons fn
- (if (and (consp args) (listp (car args)))
- (list 'declared (car args))
- t)) ; Arglist not specified.
- byte-compile-function-environment)
+ (let ((gotargs (and (consp args) (listp (car args))))
+ (unresolved (assq fn byte-compile-unresolved-functions)))
+ (when unresolved ; function was called before declaration
+ (if (and gotargs (byte-compile-warning-enabled-p 'callargs))
+ (byte-compile-arglist-warn fn (car args) nil)
+ (setq byte-compile-unresolved-functions
+ (delq unresolved byte-compile-unresolved-functions))))
+ (push (cons fn (if gotargs
+ (list 'declared (car args))
+ t)) ; Arglist not specified.
+ byte-compile-function-environment))
;; We are stating that it _will_ be defined at runtime.
(setq byte-compile-noruntime-functions
(delq fn byte-compile-noruntime-functions))
@@ -4424,8 +4404,8 @@ binding slots have been popped."
name macro arglist body rest)
(when macro
(if (null fun)
- (byte-compile--message "Macro %s unrecognized, won't work in file" name)
- (byte-compile--message "Macro %s partly recognized, trying our luck" name)
+ (message "Macro %s unrecognized, won't work in file" name)
+ (message "Macro %s partly recognized, trying our luck" name)
(push (cons name (eval fun))
byte-compile-macro-environment)))
(byte-compile-keep-pending form))))
@@ -4551,11 +4531,11 @@ The call tree also lists those functions which are not known to be called
\(that is, to which no calls have been compiled\), and which cannot be
invoked interactively."
(interactive)
- (byte-compile--message "Generating call tree...")
+ (message "Generating call tree...")
(with-output-to-temp-buffer "*Call-Tree*"
(set-buffer "*Call-Tree*")
(erase-buffer)
- (byte-compile--message "Generating call tree... (sorting on %s)"
+ (message "Generating call tree... (sorting on %s)"
byte-compile-call-tree-sort)
(insert "Call tree for "
(cond ((null byte-compile-current-file) (or filename "???"))
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index 851b3bfc6fd..06601252a4c 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -280,7 +280,7 @@ START and END represent the boundary."
"Draw axis information based upon a range to be spread along the edge.
A is the chart to draw. DIR is the direction.
MARGIN, ZONE, START, and END specify restrictions in chart space."
- (call-next-method)
+ (cl-call-next-method)
;; We prefer about 5 spaces between each value
(let* ((i (car (oref a bounds)))
(e (cdr (oref a bounds)))
@@ -333,7 +333,7 @@ Automatically compensates for direction."
"Draw axis information based upon A range to be spread along the edge.
Optional argument DIR is the direction of the chart.
Optional arguments MARGIN, ZONE, START and END specify boundaries of the drawing."
- (call-next-method)
+ (cl-call-next-method)
;; We prefer about 5 spaces between each value
(let* ((i 0)
(s (oref a items))
diff --git a/lisp/emacs-lisp/check-declare.el b/lisp/emacs-lisp/check-declare.el
index 8fc299d7e93..7269b83b619 100644
--- a/lisp/emacs-lisp/check-declare.el
+++ b/lisp/emacs-lisp/check-declare.el
@@ -157,6 +157,7 @@ is a string giving details of the error."
(setq re (format (if cflag
"^[ \t]*\\(DEFUN\\)[ \t]*([ \t]*\"%s\""
"^[ \t]*(\\(fset[ \t]+'\\|\
+cl-def\\(?:generic\\|method\\)\\|\
def\\(?:un\\|subst\\|foo\\|method\\|class\\|\
ine-\\(?:derived\\|generic\\|\\(?:global\\(?:ized\\)?-\\)?minor\\)-mode\\|\
\\(?:ine-obsolete-function-\\)?alias[ \t]+'\\|\
@@ -200,8 +201,8 @@ ine-overloadable-function\\)\\)\
type)
'obsolete)
;; Can't easily check arguments in these cases.
- ((string-match "\\`\\(def\\(alias\\|\
-method\\|class\\)\\|fset\\)\\>" type)
+ ((string-match "\\`\\(def\\(alias\\|class\\)\\|\
+fset\\|\\(?:cl-\\)?defmethod\\)\\>" type)
t)
((looking-at "\\((\\|nil\\)")
(byte-compile-arglist-signature
@@ -284,6 +285,8 @@ TYPE is a string giving the nature of the error. Warning is displayed in
type)
nil check-declare-warning-buffer)))
+(declare-function compilation-forget-errors "compile" ())
+
(defun check-declare-files (&rest files)
"Check veracity of all `declare-function' statements in FILES.
Return a list of any errors found."
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index fb11a3e25a1..a2716ef87ee 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -54,6 +54,15 @@
;; - The standard method combination supports ":extra STRING" qualifiers
;; which simply allows adding more methods for the same
;; specializers&qualifiers.
+;; - Methods can dispatch on the context. For that, a method needs to specify
+;; context arguments, introduced by `&context' (which need to come right
+;; after the mandatory arguments and before anything like
+;; &optional/&rest/&key). Each context argument is given as (EXP SPECIALIZER)
+;; which means that EXP is taken as an expression which computes some context
+;; and this value is then used to dispatch.
+;; E.g. (foo &context (major-mode (eql c-mode))) is an arglist specifying
+;; that this method will only be applicable when `major-mode' has value
+;; `c-mode'.
;; Efficiency considerations: overall, I've made an effort to make this fairly
;; efficient for the expected case (e.g. no constant redefinition of methods).
@@ -222,17 +231,12 @@ BODY, if present, is used as the body of a default method.
,@(mapcar (lambda (method) `(cl-defmethod ,name ,@method))
(nreverse methods)))))
-(defun cl--generic-mandatory-args (args)
- (let ((res ()))
- (while (not (memq (car args) '(nil &rest &optional &key)))
- (push (pop args) res))
- (nreverse res)))
-
;;;###autoload
(defun cl-generic-define (name args options)
- (let ((generic (cl-generic-ensure-function name))
- (mandatory (cl--generic-mandatory-args args))
- (apo (assq :argument-precedence-order options)))
+ (pcase-let* ((generic (cl-generic-ensure-function name))
+ (`(,spec-args . ,_) (cl--generic-split-args args))
+ (mandatory (mapcar #'car spec-args))
+ (apo (assq :argument-precedence-order options)))
(setf (cl--generic-dispatches generic) nil)
(when apo
(dolist (arg (cdr apo))
@@ -259,52 +263,70 @@ This macro can only be used within the lexical scope of a cl-generic method."
(and (memq sexp vars) (not (memq sexp res)) (push sexp res))
res))
- (defun cl--generic-lambda (args body)
- "Make the lambda expression for a method with ARGS and BODY."
+ (defun cl--generic-split-args (args)
+ "Return (SPEC-ARGS . PLAIN-ARGS)."
(let ((plain-args ())
(specializers nil)
(mandatory t))
(dolist (arg args)
(push (pcase arg
((or '&optional '&rest '&key) (setq mandatory nil) arg)
- ((and `(,name . ,type) (guard mandatory))
+ ('&context
+ (unless mandatory
+ (error "&context not immediately after mandatory args"))
+ (setq mandatory 'context) nil)
+ ((let 'nil mandatory) arg)
+ ((let 'context mandatory)
+ (unless (consp arg)
+ (error "Invalid &context arg: %S" arg))
+ (push `((&context . ,(car arg)) . ,(cadr arg)) specializers)
+ nil)
+ (`(,name . ,type)
(push (cons name (car type)) specializers)
name)
- (_ arg))
+ (_
+ (push (cons arg t) specializers)
+ arg))
plain-args))
- (setq plain-args (nreverse plain-args))
- (let ((fun `(cl-function (lambda ,plain-args ,@body)))
- (macroenv (cons `(cl-generic-current-method-specializers
- . ,(lambda () specializers))
- macroexpand-all-environment)))
- (require 'cl-lib) ;Needed to expand `cl-flet' and `cl-function'.
- ;; First macroexpand away the cl-function stuff (e.g. &key and
- ;; destructuring args, `declare' and whatnot).
- (pcase (macroexpand fun macroenv)
- (`#'(lambda ,args . ,body)
- (let* ((parsed-body (macroexp-parse-body body))
- (cnm (make-symbol "cl--cnm"))
- (nmp (make-symbol "cl--nmp"))
- (nbody (macroexpand-all
- `(cl-flet ((cl-call-next-method ,cnm)
- (cl-next-method-p ,nmp))
- ,@(cdr parsed-body))
- macroenv))
- ;; FIXME: Rather than `grep' after the fact, the
- ;; macroexpansion should directly set some flag when cnm
- ;; is used.
- ;; FIXME: Also, optimize the case where call-next-method is
- ;; only called with explicit arguments.
- (uses-cnm (cl--generic-fgrep (list cnm nmp) nbody)))
- (cons (not (not uses-cnm))
- `#'(lambda (,@(if uses-cnm (list cnm)) ,@args)
- ,@(car parsed-body)
- ,(if (not (memq nmp uses-cnm))
- nbody
- `(let ((,nmp (lambda ()
- (cl--generic-isnot-nnm-p ,cnm))))
- ,nbody))))))
- (f (error "Unexpected macroexpansion result: %S" f)))))))
+ (cons (nreverse specializers)
+ (nreverse (delq nil plain-args)))))
+
+ (defun cl--generic-lambda (args body)
+ "Make the lambda expression for a method with ARGS and BODY."
+ (pcase-let* ((`(,spec-args . ,plain-args)
+ (cl--generic-split-args args))
+ (fun `(cl-function (lambda ,plain-args ,@body)))
+ (macroenv (cons `(cl-generic-current-method-specializers
+ . ,(lambda () spec-args))
+ macroexpand-all-environment)))
+ (require 'cl-lib) ;Needed to expand `cl-flet' and `cl-function'.
+ ;; First macroexpand away the cl-function stuff (e.g. &key and
+ ;; destructuring args, `declare' and whatnot).
+ (pcase (macroexpand fun macroenv)
+ (`#'(lambda ,args . ,body)
+ (let* ((parsed-body (macroexp-parse-body body))
+ (cnm (make-symbol "cl--cnm"))
+ (nmp (make-symbol "cl--nmp"))
+ (nbody (macroexpand-all
+ `(cl-flet ((cl-call-next-method ,cnm)
+ (cl-next-method-p ,nmp))
+ ,@(cdr parsed-body))
+ macroenv))
+ ;; FIXME: Rather than `grep' after the fact, the
+ ;; macroexpansion should directly set some flag when cnm
+ ;; is used.
+ ;; FIXME: Also, optimize the case where call-next-method is
+ ;; only called with explicit arguments.
+ (uses-cnm (cl--generic-fgrep (list cnm nmp) nbody)))
+ (cons (not (not uses-cnm))
+ `#'(lambda (,@(if uses-cnm (list cnm)) ,@args)
+ ,@(car parsed-body)
+ ,(if (not (memq nmp uses-cnm))
+ nbody
+ `(let ((,nmp (lambda ()
+ (cl--generic-isnot-nnm-p ,cnm))))
+ ,nbody))))))
+ (f (error "Unexpected macroexpansion result: %S" f))))))
;;;###autoload
@@ -375,21 +397,26 @@ which case this method will be invoked when the argument is `eql' to VAL.
;;;###autoload
(defun cl-generic-define-method (name qualifiers args uses-cnm function)
- (let* ((generic (cl-generic-ensure-function name))
- (mandatory (cl--generic-mandatory-args args))
- (specializers
- (mapcar (lambda (arg) (if (consp arg) (cadr arg) t)) mandatory))
- (method (cl--generic-make-method
- specializers qualifiers uses-cnm function))
- (mt (cl--generic-method-table generic))
- (me (cl--generic-member-method specializers qualifiers mt))
- (dispatches (cl--generic-dispatches generic))
- (i 0))
- (dolist (specializer specializers)
- (let* ((generalizers (cl-generic-generalizers specializer))
- (x (assq i dispatches)))
+ (pcase-let*
+ ((generic (cl-generic-ensure-function name))
+ (`(,spec-args . ,_) (cl--generic-split-args args))
+ (specializers (mapcar (lambda (spec-arg)
+ (if (eq '&context (car-safe (car spec-arg)))
+ spec-arg (cdr spec-arg)))
+ spec-args))
+ (method (cl--generic-make-method
+ specializers qualifiers uses-cnm function))
+ (mt (cl--generic-method-table generic))
+ (me (cl--generic-member-method specializers qualifiers mt))
+ (dispatches (cl--generic-dispatches generic))
+ (i 0))
+ (dolist (spec-arg spec-args)
+ (let* ((key (if (eq '&context (car-safe (car spec-arg)))
+ (car spec-arg) i))
+ (generalizers (cl-generic-generalizers (cdr spec-arg)))
+ (x (assoc key dispatches)))
(unless x
- (setq x (cons i (cl-generic-generalizers t)))
+ (setq x (cons key (cl-generic-generalizers t)))
(setf (cl--generic-dispatches generic)
(setq dispatches (cons x dispatches))))
(dolist (generalizer generalizers)
@@ -411,7 +438,16 @@ which case this method will be invoked when the argument is `eql' to VAL.
;; the generic function.
current-load-list)
;; For aliases, cl--generic-name gives us the actual name.
- (defalias (cl--generic-name generic) gfun))))
+ (funcall
+ (if purify-flag
+ ;; BEWARE! Don't purify this function definition, since that leads
+ ;; to memory corruption if the hash-tables it holds are modified
+ ;; (the GC doesn't trace those pointers).
+ #'fset
+ ;; But do use `defalias' in the normal case, so that it interacts
+ ;; properly with nadvice, e.g. for tracing/debug-on-entry.
+ #'defalias)
+ (cl--generic-name generic) gfun))))
(defmacro cl--generic-with-memoization (place &rest code)
(declare (indent 1) (debug t))
@@ -427,6 +463,7 @@ which case this method will be invoked when the argument is `eql' to VAL.
(defun cl--generic-get-dispatcher (dispatch)
(cl--generic-with-memoization
(gethash dispatch cl--generic-dispatchers)
+ ;; (message "cl--generic-get-dispatcher (%S)" dispatch)
(let* ((dispatch-arg (car dispatch))
(generalizers (cdr dispatch))
(lexical-binding t)
@@ -437,13 +474,14 @@ which case this method will be invoked when the argument is `eql' to VAL.
'arg))
generalizers))
(typescodes
- (mapcar (lambda (generalizer)
- `(funcall ',(cl--generic-generalizer-specializers-function
- generalizer)
- ,(funcall (cl--generic-generalizer-tagcode-function
- generalizer)
- 'arg)))
- generalizers))
+ (mapcar
+ (lambda (generalizer)
+ `(funcall ',(cl--generic-generalizer-specializers-function
+ generalizer)
+ ,(funcall (cl--generic-generalizer-tagcode-function
+ generalizer)
+ 'arg)))
+ generalizers))
(tag-exp
;; Minor optimization: since this tag-exp is
;; only used to lookup the method-cache, it
@@ -452,23 +490,30 @@ which case this method will be invoked when the argument is `eql' to VAL.
`(or ,@(if (macroexp-const-p (car (last tagcodes)))
(butlast tagcodes)
tagcodes)))
- (extraargs ()))
- (dotimes (_ dispatch-arg)
- (push (make-symbol "arg") extraargs))
+ (fixedargs '(arg))
+ (dispatch-idx dispatch-arg)
+ (bindings nil))
+ (when (eq '&context (car-safe dispatch-arg))
+ (setq bindings `((arg ,(cdr dispatch-arg))))
+ (setq fixedargs nil)
+ (setq dispatch-idx 0))
+ (dotimes (i dispatch-idx)
+ (push (make-symbol (format "arg%d" (- dispatch-idx i 1))) fixedargs))
;; FIXME: For generic functions with a single method (or with 2 methods,
;; one of which always matches), using a tagcode + hash-table is
;; overkill: better just use a `cl-typep' test.
(byte-compile
`(lambda (generic dispatches-left methods)
(let ((method-cache (make-hash-table :test #'eql)))
- (lambda (,@extraargs arg &rest args)
- (apply (cl--generic-with-memoization
- (gethash ,tag-exp method-cache)
- (cl--generic-cache-miss
- generic ',dispatch-arg dispatches-left methods
- ,(if (cdr typescodes)
- `(append ,@typescodes) (car typescodes))))
- ,@extraargs arg args))))))))
+ (lambda (,@fixedargs &rest args)
+ (let ,bindings
+ (apply (cl--generic-with-memoization
+ (gethash ,tag-exp method-cache)
+ (cl--generic-cache-miss
+ generic ',dispatch-arg dispatches-left methods
+ ,(if (cdr typescodes)
+ `(append ,@typescodes) (car typescodes))))
+ ,@fixedargs args)))))))))
(defun cl--generic-make-function (generic)
(cl--generic-make-next-function generic
@@ -593,8 +638,11 @@ FUN is the function that should be called when METHOD calls
dispatch-arg dispatches-left methods-left types)
(let ((methods '()))
(dolist (method methods-left)
- (let* ((specializer (or (nth dispatch-arg
- (cl--generic-method-specializers method))
+ (let* ((specializer (or (if (integerp dispatch-arg)
+ (nth dispatch-arg
+ (cl--generic-method-specializers method))
+ (cdr (assoc dispatch-arg
+ (cl--generic-method-specializers method))))
t))
(m (member specializer types)))
(when m
@@ -657,6 +705,25 @@ methods.")
(if (eq specializer t) (list cl--generic-t-generalizer)
(error "Unknown specializer %S" specializer)))
+(defmacro cl--generic-prefill-dispatchers (arg-or-context specializer)
+ (unless (integerp arg-or-context)
+ (setq arg-or-context `(&context . ,arg-or-context)))
+ (unless (fboundp 'cl--generic-get-dispatcher)
+ (require 'cl-generic))
+ (let ((fun (cl--generic-get-dispatcher
+ `(,arg-or-context ,@(cl-generic-generalizers specializer)
+ ,cl--generic-t-generalizer))))
+ ;; Recompute dispatch at run-time, since the generalizers may be slightly
+ ;; different (e.g. byte-compiled rather than interpreted).
+ ;; FIXME: There is a risk that the run-time generalizer is not equivalent
+ ;; to the compile-time one, in which case `fun' may not be correct
+ ;; any more!
+ `(let ((dispatch `(,',arg-or-context
+ ,@(cl-generic-generalizers ',specializer)
+ ,cl--generic-t-generalizer)))
+ ;; (message "Prefilling for %S with \n%S" dispatch ',fun)
+ (puthash dispatch ',fun cl--generic-dispatchers))))
+
(cl-defmethod cl-generic-combine-methods (generic methods)
"Standard support for :after, :before, :around, and `:extra NAME' qualifiers."
(cl--generic-standard-method-combination generic methods))
@@ -840,6 +907,8 @@ Can only be used from within the lexical body of a primary or around method."
(gethash (cadr specializer) cl--generic-head-used) specializer)
(list cl--generic-head-generalizer)))
+(cl--generic-prefill-dispatchers 0 (head eql))
+
;;; Support for (eql <val>) specializers.
(defvar cl--generic-eql-used (make-hash-table :test #'eql))
@@ -854,6 +923,9 @@ Can only be used from within the lexical body of a primary or around method."
(puthash (cadr specializer) specializer cl--generic-eql-used)
(list cl--generic-eql-generalizer))
+(cl--generic-prefill-dispatchers 0 (eql nil))
+(cl--generic-prefill-dispatchers window-system (eql nil))
+
;;; Support for cl-defstructs specializers.
(defun cl--generic-struct-tag (name)
@@ -910,6 +982,8 @@ Can only be used from within the lexical body of a primary or around method."
(list cl--generic-struct-generalizer))))
(cl-call-next-method)))
+(cl--generic-prefill-dispatchers 0 cl--generic-generalizer)
+
;;; Dispatch on "system types".
(defconst cl--generic-typeof-types
@@ -948,39 +1022,7 @@ Can only be used from within the lexical body of a primary or around method."
(list cl--generic-typeof-generalizer)))
(cl-call-next-method)))
-;;; Just for kicks: dispatch on major-mode
-;;
-;; Here's how you'd use it:
-;; (cl-defmethod foo ((x (major-mode text-mode)) y z) ...)
-;; And then
-;; (foo 'major-mode toto titi)
-;;
-;; FIXME: Better would be to do that via dispatch on an "implicit argument".
-;; E.g. (cl-defmethod foo (y z &context (major-mode text-mode)) ...)
-
-;; (defvar cl--generic-major-modes (make-hash-table :test #'eq))
-;;
-;; (add-function :before-until cl-generic-generalizer-function
-;; #'cl--generic-major-mode-tagcode)
-;; (defun cl--generic-major-mode-tagcode (type name)
-;; (if (eq 'major-mode (car-safe type))
-;; `(50 . (if (eq ,name 'major-mode)
-;; (cl--generic-with-memoization
-;; (gethash major-mode cl--generic-major-modes)
-;; `(cl--generic-major-mode . ,major-mode))))))
-;;
-;; (add-function :before-until cl-generic-tag-types-function
-;; #'cl--generic-major-mode-types)
-;; (defun cl--generic-major-mode-types (tag)
-;; (when (eq (car-safe tag) 'cl--generic-major-mode)
-;; (if (eq tag 'fundamental-mode) '(fundamental-mode t)
-;; (let ((types `((major-mode ,(cdr tag)))))
-;; (while (get (car types) 'derived-mode-parent)
-;; (push (list 'major-mode (get (car types) 'derived-mode-parent))
-;; types))
-;; (unless (eq 'fundamental-mode (car types))
-;; (push '(major-mode fundamental-mode) types))
-;; (nreverse types)))))
+(cl--generic-prefill-dispatchers 0 integer)
;; Local variables:
;; generated-autoload-file: "cl-loaddefs.el"
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index 6b43c126130..b6f3a793be6 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -731,9 +731,10 @@ If ALIST is non-nil, the new pairs are prepended to it."
;;; Miscellaneous.
(provide 'cl-lib)
-(or (load "cl-loaddefs" 'noerror 'quiet)
- ;; When bootstrapping, cl-loaddefs hasn't been built yet!
- (require 'cl-macs))
+(unless (load "cl-loaddefs" 'noerror 'quiet)
+ ;; When bootstrapping, cl-loaddefs hasn't been built yet!
+ (require 'cl-macs)
+ (require 'cl-seq))
;; Local variables:
;; byte-compile-dynamic: t
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el
index 5624accf66a..3aea67ad11b 100644
--- a/lisp/emacs-lisp/cl-seq.el
+++ b/lisp/emacs-lisp/cl-seq.el
@@ -1018,4 +1018,6 @@ Atoms are compared by `eql'; cons cells are compared recursively.
;; generated-autoload-file: "cl-loaddefs.el"
;; End:
+(provide 'cl-seq)
+
;;; cl-seq.el ends here
diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el
index 564a44457d8..c966ace3852 100644
--- a/lisp/emacs-lisp/cl.el
+++ b/lisp/emacs-lisp/cl.el
@@ -626,6 +626,8 @@ You can replace this form with `gv-define-setter'.
;; ...the rest, and build the 5-tuple))
(make-obsolete 'get-setf-method 'gv-letplace "24.3")
+(declare-function cl--arglist-args "cl-macs" (args))
+
(defmacro define-modify-macro (name arglist func &optional doc)
"Define a `setf'-like modify macro.
If NAME is called, it combines its PLACE argument with the other
@@ -639,6 +641,7 @@ You can replace this macro with `gv-letplace'."
symbolp &optional stringp)))
(if (memq '&key arglist)
(error "&key not allowed in define-modify-macro"))
+ (require 'cl-macs) ;For cl--arglist-args.
(let ((place (make-symbol "--cl-place--")))
`(cl-defmacro ,name (,place ,@arglist)
,doc
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index ce5c7863c3c..9d32ba241de 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -731,7 +731,8 @@ Complete list of commands:
(buffer-substring (line-beginning-position 0)
(line-end-position 0)))))
-(declare-function help-xref-interned "help-mode" (symbol))
+(declare-function help-xref-interned "help-mode"
+ (symbol &optional buffer frame))
(defun debug-help-follow (&optional pos)
"Follow cross-reference at POS, defaulting to point.
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index 59d834837b0..bf3f44206c4 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -88,7 +88,7 @@ Currently under control of this var:
(cl-defstruct (eieio--class
(:constructor nil)
- (:constructor eieio--class-make (name &aux (tag 'defclass)))
+ (:constructor eieio--class-make (name))
(:include cl--class)
(:copier nil))
children
@@ -277,12 +277,12 @@ See `defclass' for more information."
(setq eieio-hook nil)
(let* ((oldc (let ((c (eieio--class-v cname))) (if (eieio--class-p c) c)))
- (newc (if (and oldc (not (eieio--class-default-object-cache oldc)))
- ;; The oldc class is a stub setup by eieio-defclass-autoload.
- ;; Reuse it instead of creating a new one, so that existing
- ;; references stay valid.
- oldc
- (eieio--class-make cname)))
+ (newc (or oldc
+ ;; Reuse `oldc' instead of creating a new one, so that
+ ;; existing references stay valid. E.g. when
+ ;; reloading the file that does the `defclass', we don't
+ ;; want to create a new class object.
+ (eieio--class-make cname)))
(groups nil) ;; list of groups id'd from slots
(clearparent nil))
@@ -292,7 +292,13 @@ See `defclass' for more information."
;; method table breakage, particularly when the users is only
;; byte compiling an EIEIO file.
(if oldc
- (setf (eieio--class-children newc) (eieio--class-children oldc))
+ (progn
+ (cl-assert (eq newc oldc))
+ ;; Reset the fields.
+ (setf (eieio--class-parents newc) nil)
+ (setf (eieio--class-slots newc) nil)
+ (setf (eieio--class-initarg-tuples newc) nil)
+ (setf (eieio--class-class-slots newc) nil))
;; If the old class did not exist, but did exist in the autoload map,
;; then adopt those children. This is like the above, but deals with
;; autoloads nicely.
@@ -724,7 +730,7 @@ Argument FN is the function calling this verifier."
(cl-check-type slot symbol)
(cl-check-type obj (or eieio-object class))
(let* ((class (cond ((symbolp obj)
- (error "eieio-oref called on a class!")
+ (error "eieio-oref called on a class: %s" obj)
(let ((c (eieio--class-v obj)))
(if (eieio--class-p c) (eieio-class-un-autoload obj))
c))
diff --git a/lisp/emacs-lisp/eieio-custom.el b/lisp/emacs-lisp/eieio-custom.el
index 26fc452f7b1..31d0b85c55a 100644
--- a/lisp/emacs-lisp/eieio-custom.el
+++ b/lisp/emacs-lisp/eieio-custom.el
@@ -223,6 +223,7 @@ Optional argument IGNORE is an extraneous parameter."
;; Loop over all the slots, creating child widgets.
(dotimes (i (length slots))
(let* ((slot (aref slots i))
+ (sname (eieio-slot-descriptor-name slot))
(props (cl--slot-descriptor-props slot)))
;; Output this slot if it has a customize flag associated with it.
(when (and (alist-get :custom props)
@@ -261,13 +262,13 @@ Optional argument IGNORE is an extraneous parameter."
(or
(eieio--class-slot-initarg
(eieio--object-class obj)
- (car slots))
- (car slots)))))
+ sname)
+ sname))))
(capitalize
(if (string-match "^:" s)
(substring s (match-end 0))
s)))))
- :value (slot-value obj (car slots))
+ :value (slot-value obj sname)
:doc (or (alist-get :documentation props)
"Slot not Documented.")
:eieio-custom-visibility 'visible
@@ -297,6 +298,13 @@ Optional argument IGNORE is an extraneous parameter."
(let* ((slot (aref slots i))
(props (cl--slot-descriptor-props slot))
(cust (alist-get :custom props)))
+ ;;
+ ;; Shouldn't I be incremented unconditionally? Or
+ ;; better shouldn't we simply mapc on the slots vector
+ ;; avoiding use of this integer variable? PLN Sat May
+ ;; 2 07:35:45 2015
+ ;;
+ (setq i (+ i 1))
(if (and cust
(or eieio-custom-ignore-eieio-co
(not master-group)
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el
index 7f98730340d..02b89e043e4 100644
--- a/lisp/emacs-lisp/eieio-opt.el
+++ b/lisp/emacs-lisp/eieio-opt.el
@@ -74,6 +74,9 @@ Argument CH-PREFIX is another character prefix to display."
;;; CLASS COMPLETION / DOCUMENTATION
+;; Called via help-fns-describe-function-functions.
+(declare-function help-fns-short-filename "help-fns" (filename))
+
;;;###autoload
(defun eieio-help-class (class)
"Print help description for CLASS.
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index 111459509bc..f6ffa3d6c71 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -967,7 +967,7 @@ variable PRINT-FUNCTION. Optional argument NOESCAPE is passed to
;;; Start of automatically extracted autoloads.
-;;;### (autoloads nil "eieio-custom" "eieio-custom.el" "813d32fbf76d4248fc6b4dc97ebcd720")
+;;;### (autoloads nil "eieio-custom" "eieio-custom.el" "916f54b818479a77a02f3ecccda84a11")
;;; Generated autoloads from eieio-custom.el
(autoload 'customize-object "eieio-custom" "\
@@ -978,7 +978,7 @@ Optional argument GROUP is the sub-group of slots to display.
;;;***
-;;;### (autoloads nil "eieio-opt" "eieio-opt.el" "3005b815c6b30eccbf0642170b3f82a5")
+;;;### (autoloads nil "eieio-opt" "eieio-opt.el" "59cee62a4829ace9bb4a6526442d2b3c")
;;; Generated autoloads from eieio-opt.el
(autoload 'eieio-browse "eieio-opt" "\
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index d527d676d51..0091cdb8484 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -354,7 +354,32 @@ return any documentation.")
nil))
(eldoc-message (funcall eldoc-documentation-function)))))
-
+;; If the entire line cannot fit in the echo area, the symbol name may be
+;; truncated or eliminated entirely from the output to make room for the
+;; description.
+(defun eldoc-docstring-format-sym-doc (prefix doc &optional face)
+ (when (symbolp prefix)
+ (setq prefix (concat (propertize (symbol-name prefix) 'face face) ": ")))
+ (let* ((ea-multi eldoc-echo-area-use-multiline-p)
+ ;; Subtract 1 from window width since emacs will not write
+ ;; any chars to the last column, or in later versions, will
+ ;; cause a wraparound and resize of the echo area.
+ (ea-width (1- (window-width (minibuffer-window))))
+ (strip (- (+ (length prefix) (length doc)) ea-width)))
+ (cond ((or (<= strip 0)
+ (eq ea-multi t)
+ (and ea-multi (> (length doc) ea-width)))
+ (concat prefix doc))
+ ((> (length doc) ea-width)
+ (substring (format "%s" doc) 0 ea-width))
+ ((>= strip (string-match-p ":? *\\'" prefix))
+ doc)
+ (t
+ ;; Show the end of the partial symbol name, rather
+ ;; than the beginning, since the former is more likely
+ ;; to be unique given package namespace conventions.
+ (concat (substring prefix strip) doc)))))
+
;; When point is in a sexp, the function args are not reprinted in the echo
;; area after every possible interactive command because some of them print
;; their own messages in the echo area; the eldoc functions would instantly
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 4ffd8cd8558..b678e122c11 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -269,7 +269,7 @@ DATA is displayed to the user and should state the reason for skipping."
(defun ert--special-operator-p (thing)
"Return non-nil if THING is a symbol naming a special operator."
(and (symbolp thing)
- (let ((definition (indirect-function thing t)))
+ (let ((definition (indirect-function thing)))
(and (subrp definition)
(eql (cdr (subr-arity definition)) 'unevalled)))))
@@ -2537,7 +2537,7 @@ To be used in the ERT results buffer."
(add-to-list 'minor-mode-alist '(ert--current-run-stats
(:eval
(ert--tests-running-mode-line-indicator))))
-(add-to-list 'emacs-lisp-mode-hook 'ert--activate-font-lock-keywords)
+(add-hook 'emacs-lisp-mode-hook #'ert--activate-font-lock-keywords)
(defun ert--unload-function ()
"Unload function to undo the side-effects of loading ert.el."
@@ -2548,7 +2548,7 @@ To be used in the ERT results buffer."
nil)
(defvar ert-unload-hook '())
-(add-hook 'ert-unload-hook 'ert--unload-function)
+(add-hook 'ert-unload-hook #'ert--unload-function)
(provide 'ert)
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index 67d14872b3a..d401b316719 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -736,22 +736,19 @@ character."
)
(call-interactively 'minibuffer-complete)))
-(defun lisp-complete-symbol (&optional predicate)
+(defun lisp-complete-symbol (&optional _predicate)
"Perform completion on Lisp symbol preceding point.
Compare that symbol against the known Lisp symbols.
If no characters can be completed, display a list of possible completions.
Repeating the command at that point scrolls the list.
-When called from a program, optional arg PREDICATE is a predicate
-determining which symbols are considered, e.g. `commandp'.
-If PREDICATE is nil, the context determines which symbols are
-considered. If the symbol starts just after an open-parenthesis, only
-symbols with function definitions are considered. Otherwise, all
-symbols with function definitions, values or properties are
-considered."
+The context determines which symbols are considered. If the
+symbol starts just after an open-parenthesis, only symbols with
+function definitions are considered. Otherwise, all symbols with
+function definitions, values or properties are considered."
(declare (obsolete completion-at-point "24.4"))
(interactive)
- (let* ((data (lisp-completion-at-point predicate))
+ (let* ((data (lisp-completion-at-point))
(plist (nthcdr 3 data)))
(if (null data)
(minibuffer-message "Nothing to complete")
diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el
index 6955ce8f5a6..81d0b834722 100644
--- a/lisp/emacs-lisp/package-x.el
+++ b/lisp/emacs-lisp/package-x.el
@@ -156,6 +156,7 @@ DESCRIPTION is the text of the news item."
archive-url))
(declare-function lm-commentary "lisp-mnt" (&optional file))
+(defvar tar-data-buffer)
(defun package-upload-buffer-internal (pkg-desc extension &optional archive-url)
"Upload a package whose contents are in the current buffer.
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index f770acd557e..55fa962719d 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -185,7 +185,6 @@ and before `after-init-hook'. Activation is not done if
Even if the value is nil, you can type \\[package-initialize] to
activate the package system at any time."
:type 'boolean
- :group 'package
:version "24.1")
(defcustom package-load-list '(all)
@@ -203,7 +202,6 @@ If VERSION is a string, only that version is ever loaded.
If VERSION is nil, the package is not loaded (it is \"disabled\")."
:type '(repeat symbol)
:risky t
- :group 'package
:version "24.1")
(defcustom package-archives '(("gnu" . "http://elpa.gnu.org/packages/"))
@@ -222,7 +220,6 @@ a package can run arbitrary code."
:type '(alist :key-type (string :tag "Archive name")
:value-type (string :tag "URL or directory name"))
:risky t
- :group 'package
:version "24.1")
(defcustom package-menu-hide-low-priority 'archive
@@ -246,7 +243,6 @@ nil, so it can be toggled with \\<package-menu-mode-map> \\[package-menu-hide-ob
(const :tag "Hide per package-archive-priorities"
archive)
(const :tag "Hide per archive and version number" t))
- :group 'package
:version "25.1")
(defcustom package-archive-priorities nil
@@ -265,7 +261,6 @@ See also `package-menu-hide-low-priority'."
:type '(alist :key-type (string :tag "Archive name")
:value-type (integer :tag "Priority (default is 0)"))
:risky t
- :group 'package
:version "25.1")
(defcustom package-pinned-packages nil
@@ -289,7 +284,6 @@ the package will be unavailable."
;; via an entry (PACKAGE . NON-EXISTING). Which could be an issue
;; if PACKAGE has a known vulnerability that is fixed in newer versions.
:risky t
- :group 'package
:version "24.4")
(defcustom package-user-dir (locate-user-emacs-file "elpa")
@@ -299,7 +293,6 @@ Apart from this directory, Emacs also looks for system-wide
packages in `package-directory-list'."
:type 'directory
:risky t
- :group 'package
:version "24.1")
(defcustom package-directory-list
@@ -317,7 +310,6 @@ These directories contain packages intended for system-wide; in
contrast, `package-user-dir' contains packages for personal use."
:type '(repeat directory)
:risky t
- :group 'package
:version "24.1")
(defvar epg-gpg-program)
@@ -335,14 +327,12 @@ contents of the archive."
(const allow-unsigned :tag "Allow unsigned")
(const t :tag "Check always"))
:risky t
- :group 'package
:version "24.4")
(defcustom package-unsigned-archives nil
"List of archives where we do not check for package signatures."
:type '(repeat (string :tag "Archive name"))
:risky t
- :group 'package
:version "24.4")
(defcustom package-selected-packages nil
@@ -356,9 +346,15 @@ by running `package-user-selected-packages-install'.
To check if a package is contained in this list here, use
`package--user-selected-p', as it may populate the variable with
a sane initial value."
- :group 'package
:type '(repeat symbol))
+(defcustom package-menu-async t
+ "If non-nil, package-menu will use async operations when possible.
+This includes refreshing archive contents as well as installing
+packages."
+ :type 'boolean
+ :version "25.1")
+
;;; `package-desc' object definition
;; This is the struct used internally to represent packages.
@@ -897,7 +893,7 @@ untar into a directory named DIR; otherwise, signal an error."
;;(ignore-name (concat name "-pkg.el"))
(generated-autoload-file (expand-file-name auto-name pkg-dir))
;; Silence `autoload-generate-file-autoloads'.
- (noninteractive package--silence)
+ (noninteractive inhibit-message)
(backup-inhibited t)
(version-control 'never))
(package-autoload-ensure-default-file generated-autoload-file)
@@ -917,10 +913,13 @@ untar into a directory named DIR; otherwise, signal an error."
)
;;;; Compilation
+(defvar warning-minimum-level)
(defun package--compile (pkg-desc)
"Byte-compile installed package PKG-DESC."
- (package-activate-1 pkg-desc)
- (byte-recompile-directory (package-desc-dir pkg-desc) 0 t))
+ (let ((warning-minimum-level :error)
+ (save-silently inhibit-message))
+ (package-activate-1 pkg-desc)
+ (byte-recompile-directory (package-desc-dir pkg-desc) 0 t)))
;;;; Inferring package from current buffer
(defun package-read-from-string (str)
@@ -958,7 +957,7 @@ is wrapped around any parts requiring it."
deps))))
(declare-function lm-header "lisp-mnt" (header))
-(declare-function lm-homepage "lisp-mnt" ())
+(declare-function lm-homepage "lisp-mnt" (&optional file))
(defun package-buffer-info ()
"Return a `package-desc' describing the package in the current buffer.
@@ -1080,7 +1079,7 @@ The return result is a `package-desc'."
(declare-function epg-verify-string "epg" (context signature
&optional signed-text))
(declare-function epg-context-result-for "epg" (context name))
-(declare-function epg-signature-status "epg" (signature))
+(declare-function epg-signature-status "epg" (signature) t)
(declare-function epg-signature-to-string "epg" (signature))
(defun package--display-verify-error (context sig-file)
@@ -1137,7 +1136,8 @@ arguments see `package--with-work-buffer'."
(signal (cdar status) (cddr status)))
(goto-char (point-min))
(unless (search-forward "\n\n" nil 'noerror)
- (error "Invalid url response"))
+ (error "Invalid url response in buffer %s"
+ (current-buffer)))
(delete-region (point-min) (point))
,@body)
(kill-buffer (current-buffer)))
@@ -1346,6 +1346,9 @@ If successful, set `package-archive-contents'."
;; available on disk.
(defvar package--initialized nil)
+(defvar package--init-file-ensured nil
+ "Whether we know the init file has package-initialize.")
+
;;;###autoload
(defun package-initialize (&optional no-activate)
"Load Emacs Lisp packages, and activate them.
@@ -1355,7 +1358,11 @@ If `user-init-file' does not mention `(package-initialize)', add
it to the file."
(interactive)
(setq package-alist nil)
- (package--ensure-init-file)
+ (if (equal user-init-file load-file-name)
+ ;; If `package-initialize' is being called as part of loading
+ ;; the init file, it's obvious we don't need to ensure-init.
+ (setq package--init-file-ensured t)
+ (package--ensure-init-file))
(package-load-all-descriptors)
(package-read-all-archive-contents)
(unless no-activate
@@ -1378,16 +1385,6 @@ it to the file."
(declare-function epg-configuration "epg-config" ())
(declare-function epg-import-keys-from-file "epg" (context keys))
-(defvar package--silence nil)
-
-(defun package--message (format &rest args)
- "Like `message', except sometimes don't print to minibuffer.
-If the variable `package--silence' is non-nil, the message is not
-displayed on the minibuffer."
- (apply #'message format args)
- (when package--silence
- (message nil)))
-
;;;###autoload
(defun package-import-keyring (&optional file)
"Import keys from FILE."
@@ -1398,9 +1395,9 @@ displayed on the minibuffer."
(with-file-modes 448
(make-directory homedir t))
(setf (epg-context-home-directory context) homedir)
- (package--message "Importing %s..." (file-name-nondirectory file))
+ (message "Importing %s..." (file-name-nondirectory file))
(epg-import-keys-from-file context file)
- (package--message "Importing %s...done" (file-name-nondirectory file))))
+ (message "Importing %s...done" (file-name-nondirectory file))))
(defvar package--post-download-archives-hook nil
"Hook run after the archive contents are downloaded.
@@ -1466,9 +1463,9 @@ This populates `package-archive-contents'. If ASYNC is non-nil,
perform the downloads asynchronously."
;; The downloaded archive contents will be read as part of
;; `package--update-downloads-in-progress'.
- (setq package--downloads-in-progress
- (append package-archives
- package--downloads-in-progress))
+ (dolist (archive package-archives)
+ (cl-pushnew archive package--downloads-in-progress
+ :test #'equal))
(dolist (archive package-archives)
(condition-case-unless-debug nil
(package--download-one-archive
@@ -1492,14 +1489,14 @@ downloads in the background."
(make-directory package-user-dir t))
(let ((default-keyring (expand-file-name "package-keyring.gpg"
data-directory))
- (package--silence async))
+ (inhibit-message async))
(when (and package-check-signature (file-exists-p default-keyring))
(condition-case-unless-debug error
(progn
(epg-check-configuration (epg-configuration))
(package-import-keyring default-keyring))
- (error (message "Cannot import default keyring: %S" (cdr error)))))
- (package--download-and-read-archives async)))
+ (error (message "Cannot import default keyring: %S" (cdr error))))))
+ (package--download-and-read-archives async))
;;; Dependency Management
@@ -1541,7 +1538,7 @@ SEEN is used internally to detect infinite recursion."
;; we re-add it (along with its dependencies) at an earlier place
;; below (bug#16994).
(if (memq already seen) ;Avoid inf-loop on dependency cycles.
- (package--message "Dependency cycle going through %S"
+ (message "Dependency cycle going through %S"
(package-desc-full-name already))
(setq packages (delq already packages))
(setq already nil))
@@ -1607,7 +1604,7 @@ Used to populate `package-selected-packages'."
(defun package--save-selected-packages (value)
"Set and save `package-selected-packages' to VALUE."
- (let ((save-silently package--silence))
+ (let ((save-silently inhibit-message))
(customize-save-variable
'package-selected-packages
(setq package-selected-packages value))))
@@ -1728,7 +1725,8 @@ operation is done."
package-unsigned-archives))
;; If we don't care about the signature, unpack and we're
;; done.
- (progn (let ((save-silently async))
+ (progn (let ((save-silently async)
+ (inhibit-message async))
(package-unpack pkg-desc))
(funcall callback))
;; If we care, check it and *then* write the file.
@@ -1744,7 +1742,8 @@ operation is done."
(package-desc-name pkg-desc)))
;; Signature checked, unpack now.
(with-temp-buffer (insert content)
- (let ((save-silently async))
+ (let ((save-silently async)
+ (inhibit-message async))
(package-unpack pkg-desc)))
;; Here the package has been installed successfully, mark it as
;; signed if appropriate.
@@ -1804,9 +1803,15 @@ using `package-compute-transaction'."
(callback (funcall callback))))
(defun package--ensure-init-file ()
- "Ensure that the user's init file calls `package-initialize'."
+ "Ensure that the user's init file has `package-initialize'.
+`package-initialize' doesn't have to be called, as long as it is
+present somewhere in the file, even as a comment. If it is not,
+add a call to it along with some explanatory comments."
;; Don't mess with the init-file from "emacs -Q".
- (when user-init-file
+ (when (and (stringp user-init-file)
+ (not package--init-file-ensured)
+ (file-readable-p user-init-file)
+ (file-writable-p user-init-file))
(let* ((buffer (find-buffer-visiting user-init-file))
(contains-init
(if buffer
@@ -1816,6 +1821,7 @@ using `package-compute-transaction'."
(widen)
(goto-char (point-min))
(search-forward "(package-initialize)" nil 'noerror))))
+ ;; Don't visit the file if we don't have to.
(with-temp-buffer
(insert-file-contents user-init-file)
(goto-char (point-min))
@@ -1828,7 +1834,11 @@ using `package-compute-transaction'."
(save-restriction
(widen)
(goto-char (point-min))
+ (while (and (looking-at-p "[[:blank:]]*\\(;\\|$\\)")
+ (not (eobp)))
+ (forward-line 1))
(insert
+ "\n"
";; Added by Package.el. This must come before configurations of\n"
";; installed packages. Don't delete this line. If you don't want it,\n"
";; just comment it out by adding a semicolon to the start of the line.\n"
@@ -1839,7 +1849,8 @@ using `package-compute-transaction'."
(let ((file-precious-flag t))
(save-buffer))
(unless buffer
- (kill-buffer (current-buffer))))))))))
+ (kill-buffer (current-buffer)))))))))
+ (setq package--init-file-ensured t))
;;;###autoload
(defun package-install (pkg &optional dont-select async callback)
@@ -1885,7 +1896,8 @@ to install it but still mark it as selected."
(package-desc-reqs pkg)))
(package-compute-transaction () (list (list pkg))))))
(package-download-transaction transaction async callback)
- (package--message "`%s' is already installed" (package-desc-full-name pkg))))
+ (message "`%s' is already installed" (package-desc-full-name pkg))
+ (funcall callback)))
(defun package-strip-rcs-id (str)
"Strip RCS version ID from the version string STR.
@@ -1953,7 +1965,7 @@ The file can either be a tar file or an Emacs Lisp file."
(package-install-from-buffer)))
;;;###autoload
-(defun package-install-user-selected-packages ()
+(defun package-install-selected-packages ()
"Ensure packages in `package-selected-packages' are installed.
If some packages are not installed propose to install them."
(interactive)
@@ -2027,7 +2039,7 @@ If NOSAVE is non-nil, the package is not removed from
(delete pkg-desc pkgs)
(unless (cdr pkgs)
(setq package-alist (delq pkgs package-alist))))
- (package--message "Package `%s' deleted." (package-desc-full-name pkg-desc))))))
+ (message "Package `%s' deleted." (package-desc-full-name pkg-desc))))))
;;;###autoload
(defun package-reinstall (pkg)
@@ -2457,16 +2469,17 @@ of these dependencies, similar to the list returned by
((version-list-= version hv) "held")
((version-list-< version hv) "obsolete")
(t "disabled"))))
- ((package-built-in-p name version) "obsolete")
- ((package--incompatible-p pkg-desc) "incompat")
(dir ;One of the installed packages.
(cond
- ((not (file-exists-p (package-desc-dir pkg-desc))) "deleted")
+ ((not (file-exists-p dir)) "deleted")
+ ;; Not inside `package-user-dir'.
+ ((not (file-in-directory-p dir package-user-dir)) "external")
((eq pkg-desc (cadr (assq name package-alist)))
(if (not signed) "unsigned"
(if (package--user-selected-p name)
"installed" "dependency")))
(t "obsolete")))
+ ((package--incompatible-p pkg-desc) "incompat")
(t
(let* ((ins (cadr (assq name package-alist)))
(ins-v (if ins (package-desc-version ins))))
@@ -2497,29 +2510,43 @@ Installed obsolete packages are always displayed.")
(defun package--remove-hidden (pkg-list)
"Filter PKG-LIST according to `package-archive-priorities'.
-PKG-LIST must be a list of package-desc objects sorted by
-decreasing version number.
+PKG-LIST must be a list of package-desc objects, all with the
+same name, sorted by decreasing `package-desc-priority-version'.
Return a list of packages tied for the highest priority according
to their archives."
(when pkg-list
- ;; The first is a variable toggled with
- ;; `package-menu-hide-obsolete', the second is a static user
- ;; option that defines *what* we hide.
- (if (and package-menu--hide-obsolete
- package-menu-hide-low-priority)
- (let ((max-priority (package-desc-priority (car pkg-list)))
- (out (list (pop pkg-list))))
- (dolist (p pkg-list (nreverse out))
- (let ((priority (package-desc-priority p)))
- (cond
- ((> priority max-priority)
- (setq max-priority priority)
- (setq out (list p)))
- ;; This assumes pkg-list is sorted by version number.
- ((and (= priority max-priority)
- (eq package-menu-hide-low-priority 'archive))
- (push p out))))))
- pkg-list)))
+ ;; Variable toggled with `package-menu-hide-obsolete'.
+ (if (not package-menu--hide-obsolete)
+ pkg-list
+ (let ((installed (cadr (assq (package-desc-name (car pkg-list))
+ package-alist))))
+ (when installed
+ (setq pkg-list
+ (let ((ins-version (package-desc-version installed)))
+ (cl-remove-if (lambda (p) (version-list-< (package-desc-version p)
+ ins-version))
+ pkg-list))))
+ (let ((filtered-by-priority
+ (cond
+ ((not package-menu-hide-low-priority)
+ pkg-list)
+ ((eq package-menu-hide-low-priority 'archive)
+ (let* ((max-priority most-negative-fixnum)
+ (out))
+ (while pkg-list
+ (let ((p (pop pkg-list)))
+ (if (>= (package-desc-priority p) max-priority)
+ (push p out)
+ (setq pkg-list nil))))
+ (nreverse out)))
+ (pkg-list
+ (list (car pkg-list))))))
+ (if (not installed)
+ filtered-by-priority
+ (let ((ins-version (package-desc-version installed)))
+ (cl-remove-if (lambda (p) (version-list-= (package-desc-version p)
+ ins-version))
+ filtered-by-priority))))))))
(defun package-menu--refresh (&optional packages keywords)
"Re-populate the `tabulated-list-entries'.
@@ -2527,40 +2554,38 @@ PACKAGES should be nil or t, which means to display all known packages.
KEYWORDS should be nil or a list of keywords."
;; Construct list of (PKG-DESC . STATUS).
(unless packages (setq packages t))
- (let (info-list name)
+ (let (info-list)
;; Installed packages:
(dolist (elt package-alist)
- (setq name (car elt))
- (when (or (eq packages t) (memq name packages))
- (dolist (pkg (cdr elt))
- (when (package--has-keyword-p pkg keywords)
- (package--push pkg (package-desc-status pkg) info-list)))))
+ (let ((name (car elt)))
+ (when (or (eq packages t) (memq name packages))
+ (dolist (pkg (cdr elt))
+ (when (package--has-keyword-p pkg keywords)
+ (push pkg info-list))))))
;; Built-in packages:
(dolist (elt package--builtins)
- (setq name (car elt))
- (when (and (not (eq name 'emacs)) ; Hide the `emacs' package.
- (package--has-keyword-p (package--from-builtin elt) keywords)
- (or package-list-unversioned
- (package--bi-desc-version (cdr elt)))
- (or (eq packages t) (memq name packages)))
- (package--push (package--from-builtin elt) "built-in" info-list)))
+ (let ((pkg (package--from-builtin elt))
+ (name (car elt)))
+ (when (not (eq name 'emacs)) ; Hide the `emacs' package.
+ (when (and (package--has-keyword-p pkg keywords)
+ (or package-list-unversioned
+ (package--bi-desc-version (cdr elt)))
+ (or (eq packages t) (memq name packages)))
+ (push pkg info-list)))))
;; Available and disabled packages:
(dolist (elt package-archive-contents)
- (setq name (car elt))
- (when (or (eq packages t) (memq name packages))
- (dolist (pkg (package--remove-hidden (cdr elt)))
- ;; Hide available obsolete packages.
- (when (and (not (and package-menu--hide-obsolete
- (package-installed-p (package-desc-name pkg)
- (package-desc-version pkg))))
- (package--has-keyword-p pkg keywords))
- (package--push pkg (package-desc-status pkg) info-list)))))
+ (let ((name (car elt)))
+ (when (or (eq packages t) (memq name packages))
+ ;; Hide available-obsolete or low-priority packages.
+ (dolist (pkg (package--remove-hidden (cdr elt)))
+ (when (package--has-keyword-p pkg keywords)
+ (push pkg info-list))))))
;; Print the result.
(setq tabulated-list-entries
- (mapcar #'package-menu--print-info info-list))))
+ (mapcar #'package-menu--print-info-simple info-list))))
(defun package-all-keywords ()
"Collect all package keywords"
@@ -2642,10 +2667,18 @@ shown."
"Return a package entry suitable for `tabulated-list-entries'.
PKG has the form (PKG-DESC . STATUS).
Return (PKG-DESC [NAME VERSION STATUS DOC])."
- (let* ((pkg-desc (car pkg))
- (status (cdr pkg))
+ (package-menu--print-info-simple (car pkg)))
+(make-obsolete 'package-menu--print-info
+ 'package-menu--print-info-simple "25.1")
+
+(defun package-menu--print-info-simple (pkg)
+ "Return a package entry suitable for `tabulated-list-entries'.
+PKG is a package-desc object.
+Return (PKG-DESC [NAME VERSION STATUS DOC])."
+ (let* ((status (package-desc-status pkg))
(face (pcase status
(`"built-in" 'font-lock-builtin-face)
+ (`"external" 'font-lock-builtin-face)
(`"available" 'default)
(`"avail-obso" 'font-lock-comment-face)
(`"new" 'bold)
@@ -2656,21 +2689,23 @@ Return (PKG-DESC [NAME VERSION STATUS DOC])."
(`"unsigned" 'font-lock-warning-face)
(`"incompat" 'font-lock-comment-face)
(_ 'font-lock-warning-face)))) ; obsolete.
- (list pkg-desc
- `[,(list (symbol-name (package-desc-name pkg-desc))
- 'face 'link
- 'follow-link t
- 'package-desc pkg-desc
- 'action 'package-menu-describe-package)
+ (list pkg
+ `[(,(symbol-name (package-desc-name pkg))
+ face link
+ follow-link t
+ package-desc ,pkg
+ action package-menu-describe-package)
,(propertize (package-version-join
- (package-desc-version pkg-desc))
+ (package-desc-version pkg))
'font-lock-face face)
,(propertize status 'font-lock-face face)
,@(if (cdr package-archives)
- (list (propertize (or (package-desc-archive pkg-desc) "")
+ (list (propertize (or (package-desc-archive pkg) "")
'font-lock-face face)))
- ,(propertize (package-desc-summary pkg-desc)
- 'font-lock-face face)])))
+ ,(package-desc-summary pkg)])))
+
+(defvar package-menu--old-archive-contents nil
+ "`package-archive-contents' before the latest refresh.")
(defun package-menu-refresh ()
"Download the Emacs Lisp package archive.
@@ -2887,19 +2922,19 @@ asynchronously."
(package-install
pkg dont-mark async
(lambda () (package-menu--perform-transaction rest delete-list async))))
- ;; Once there are no more packages to install, proceed to
- ;; deletion.
- (let ((package--silence async))
+ (let ((inhibit-message async))
+ ;; Once there are no more packages to install, proceed to
+ ;; deletion.
(dolist (elt (package--sort-by-dependence delete-list))
(condition-case-unless-debug err
(package-delete elt)
- (error (message (cadr err)))))
- (when package-selected-packages
- (when-let ((removable (package--removable-packages)))
- (package--message "These %d packages are no longer needed, type `M-x package-autoremove' to remove them (%s)"
- (length removable)
- (mapconcat #'symbol-name removable ", ")))))
+ (error (message (cadr err))))))
(message "Transaction done")
+ (when package-selected-packages
+ (when-let ((removable (package--removable-packages)))
+ (message "These %d packages are no longer needed, type `M-x package-autoremove' to remove them (%s)"
+ (length removable)
+ (mapconcat #'symbol-name removable ", "))))
(package-menu--post-refresh)))
(defun package-menu-execute (&optional noquery)
@@ -2959,6 +2994,8 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
((string= sB "unsigned") nil)
((string= sA "held") t)
((string= sB "held") nil)
+ ((string= sA "external") t)
+ ((string= sB "external") nil)
((string= sA "built-in") t)
((string= sB "built-in") nil)
((string= sA "obsolete") t)
@@ -2982,9 +3019,6 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
(string< (or (package-desc-archive (car A)) "")
(or (package-desc-archive (car B)) "")))
-(defvar package-menu--old-archive-contents nil
- "`package-archive-contents' before the latest refresh.")
-
(defun package-menu--populate-new-package-list ()
"Decide which packages are new in `package-archives-contents'.
Store this list in `package-menu--new-package-list'."
@@ -3015,14 +3049,6 @@ after `package-menu--perform-transaction'."
(revert-buffer nil 'noconfirm))))
(package-menu--find-and-notify-upgrades))
-(defcustom package-menu-async t
- "If non-nil, package-menu will use async operations when possible.
-This includes refreshing archive contents as well as installing
-packages."
- :type 'boolean
- :version "25.1"
- :group 'package)
-
;;;###autoload
(defun list-packages (&optional no-fetch)
"Display a list of packages.
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 978c3f0dd30..5a81bb20e57 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -91,6 +91,10 @@
(def-edebug-spec pcase-MACRO pcase--edebug-match-macro)
+;; Only called from edebug.
+(declare-function get-edebug-spec "edebug" (symbol))
+(declare-function edebug-match "edebug" (cursor specs))
+
(defun pcase--edebug-match-macro (cursor)
(let (specs)
(mapatoms
@@ -158,12 +162,18 @@ Currently, the following patterns are provided this way:"
;; (puthash (car cases) `(,exp ,cases ,@expansion) pcase--memoize-2)
expansion))))
+(declare-function help-fns--signature "help-fns"
+ (function doc real-def real-function))
+
;; FIXME: Obviously, this will collide with nadvice's use of
;; function-documentation if we happen to advise `pcase'.
(put 'pcase 'function-documentation '(pcase--make-docstring))
(defun pcase--make-docstring ()
(let* ((main (documentation (symbol-function 'pcase) 'raw))
(ud (help-split-fundoc main 'pcase)))
+ ;; So that eg emacs -Q -l cl-lib --eval "(documentation 'pcase)" works,
+ ;; where cl-lib is anything using pcase-defmacro.
+ (require 'help-fns)
(with-temp-buffer
(insert (or (cdr ud) main))
(mapatoms
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 0050ff0a303..0aa0f095969 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -4,7 +4,7 @@
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Keywords: sequences
-;; Version: 1.4
+;; Version: 1.7
;; Package: seq
;; Maintainer: emacs-devel@gnu.org
@@ -63,9 +63,40 @@ Evaluate BODY with VAR bound to each element of SEQ, in turn.
(prog1 (seq-elt ,seq ,index)
(setq ,index (+ ,index 1)))
(pop ,index))))
- ,@body))
- ;; FIXME: Do we really want to support this?
- ,@(cddr spec))))
+ ,@body)))))
+
+(if (fboundp 'pcase-defmacro)
+ ;; Implementation of `seq-let' based on a `pcase'
+ ;; pattern. Requires Emacs>=25.1.
+ (progn
+ (pcase-defmacro seq (&rest args)
+ "pcase pattern matching sequence elements.
+Matches if the object is a sequence (list, string or vector), and
+binds each element of ARGS to the corresponding element of the
+sequence."
+ `(and (pred seq-p)
+ ,@(seq--make-pcase-bindings args)))
+
+ (defmacro seq-let (args seq &rest body)
+ "Bind the variables in ARGS to the elements of SEQ then evaluate BODY.
+
+ARGS can also include the `&rest' marker followed by a variable
+name to be bound to the rest of SEQ."
+ (declare (indent 2) (debug t))
+ `(pcase-let ((,(seq--make-pcase-patterns args) ,seq))
+ ,@body)))
+
+ ;; Implementation of `seq-let' compatible with Emacs<25.1.
+ (defmacro seq-let (args seq &rest body)
+ "Bind the variables in ARGS to the elements of SEQ then evaluate BODY.
+
+ARGS can also include the `&rest' marker followed by a variable
+name to be bound to the rest of SEQ."
+ (declare (indent 2) (debug t))
+ (let ((seq-var (make-symbol "seq")))
+ `(let* ((,seq-var ,seq)
+ ,@(seq--make-bindings args seq-var))
+ ,@body))))
(defun seq-drop (seq n)
"Return a subsequence of SEQ without its first N elements.
@@ -335,10 +366,70 @@ This is an optimization for lists in `seq-take-while'."
(setq n (+ 1 n)))
n))
+(defun seq--make-pcase-bindings (args)
+ "Return a list of bindings of the variables in ARGS to the elements of a sequence."
+ (let ((bindings '())
+ (index 0)
+ (rest-marker nil))
+ (seq-doseq (name args)
+ (unless rest-marker
+ (pcase name
+ (`&rest
+ (progn (push `(app (pcase--flip seq-drop ,index)
+ ,(seq--elt-safe args (1+ index)))
+ bindings)
+ (setq rest-marker t)))
+ (t
+ (push `(app (pcase--flip seq--elt-safe ,index) ,name) bindings))))
+ (setq index (1+ index)))
+ bindings))
+
+(defun seq--make-pcase-patterns (args)
+ "Return a list of `(seq ...)' pcase patterns from the argument list ARGS."
+ (cons 'seq
+ (seq-map (lambda (elt)
+ (if (seq-p elt)
+ (seq--make-pcase-patterns elt)
+ elt))
+ args)))
+
+;; Helper function for the Backward-compatible version of `seq-let'
+;; for Emacs<25.1.
+(defun seq--make-bindings (args seq &optional bindings)
+ "Return a list of bindings of the variables in ARGS to the elements of a sequence.
+if BINDINGS is non-nil, append new bindings to it, and return
+BINDINGS."
+ (let ((index 0)
+ (rest-marker nil))
+ (seq-doseq (name args)
+ (unless rest-marker
+ (pcase name
+ ((pred seq-p)
+ (setq bindings (seq--make-bindings (seq--elt-safe args index)
+ `(seq--elt-safe ,seq ,index)
+ bindings)))
+ (`&rest
+ (progn (push `(,(seq--elt-safe args (1+ index))
+ (seq-drop ,seq ,index))
+ bindings)
+ (setq rest-marker t)))
+ (t
+ (push `(,name (seq--elt-safe ,seq ,index)) bindings))))
+ (setq index (1+ index)))
+ bindings))
+
+(defun seq--elt-safe (seq n)
+ "Return element of SEQ at the index N.
+If no element is found, return nil."
+ (when (or (listp seq)
+ (and (sequencep seq)
+ (> (seq-length seq) n)))
+ (seq-elt seq n)))
+
(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-doseq\\>" "\\<seq-let\\>")))
(defalias 'seq-copy #'copy-sequence)
(defalias 'seq-elt #'elt)
@@ -346,11 +437,12 @@ This is an optimization for lists in `seq-take-while'."
(defalias 'seq-do #'mapc)
(defalias 'seq-each #'seq-do)
(defalias 'seq-map #'mapcar)
+(defalias 'seq-p #'sequencep)
(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-to-list 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords))
+ (add-hook 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords))
(provide 'seq)
;;; seq.el ends here
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 78a6dc98456..bd178faa4af 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -120,7 +120,8 @@ Argument BINDINGS is a list of tuples whose car is a symbol to be
bound and (optionally) used in THEN, and its cadr is a sexp to be
evalled to set symbol's value. In the special case you only want
to bind a single value, BINDINGS can just be a plain tuple."
- (declare (indent 2) (debug ((&rest (symbolp form)) form body)))
+ (declare (indent 2)
+ (debug ([&or (&rest (symbolp form)) (symbolp form)] form body)))
(when (and (<= (length bindings) 2)
(not (listp (car bindings))))
;; Adjust the single binding case
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index 15a0914cb17..5d10b55d14c 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -179,7 +179,9 @@ If ADVANCE is non-nil, move forward by one line afterwards."
table)
"The `glyphless-char-display' table in Tabulated List buffers.")
-(defvar tabulated-list--header-string nil)
+(defvar tabulated-list--header-string nil
+ "Holds the header if `tabulated-list-use-header-line' is nil.
+Populated by `tabulated-list-init-header'.")
(defvar tabulated-list--header-overlay nil)
(defun tabulated-list-init-header ()
@@ -243,15 +245,17 @@ If ADVANCE is non-nil, move forward by one line afterwards."
(setq-local tabulated-list--header-string cols))))
(defun tabulated-list-print-fake-header ()
- "Insert a fake Tabulated List \"header line\" at the start of the buffer."
- (goto-char (point-min))
- (let ((inhibit-read-only t))
- (insert tabulated-list--header-string "\n")
- (if tabulated-list--header-overlay
- (move-overlay tabulated-list--header-overlay (point-min) (point))
- (setq-local tabulated-list--header-overlay
- (make-overlay (point-min) (point))))
- (overlay-put tabulated-list--header-overlay 'face 'underline)))
+ "Insert a fake Tabulated List \"header line\" at the start of the buffer.
+Do nothing if `tabulated-list--header-string' is nil."
+ (when tabulated-list--header-string
+ (goto-char (point-min))
+ (let ((inhibit-read-only t))
+ (insert tabulated-list--header-string "\n")
+ (if tabulated-list--header-overlay
+ (move-overlay tabulated-list--header-overlay (point-min) (point))
+ (setq-local tabulated-list--header-overlay
+ (make-overlay (point-min) (point))))
+ (overlay-put tabulated-list--header-overlay 'face 'underline))))
(defun tabulated-list-revert (&rest ignored)
"The `revert-buffer-function' for `tabulated-list-mode'.
@@ -341,8 +345,10 @@ of column descriptors."
(dotimes (n ncols)
(setq x (tabulated-list-print-col n (aref cols n) x)))
(insert ?\n)
- (put-text-property beg (point) 'tabulated-list-id id)
- (put-text-property beg (point) 'tabulated-list-entry cols)))
+ ;; Ever so slightly faster than calling `put-text-property' twice.
+ (add-text-properties
+ beg (point)
+ `(tabulated-list-id ,id tabulated-list-entry ,cols))))
(defun tabulated-list-print-col (n col-desc x)
"Insert a specified Tabulated List entry at point.
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index a91704a11bf..110c63f777a 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -1,4 +1,4 @@
-;;;; testcover.el -- Visual code-coverage tool
+;;;; testcover.el -- Visual code-coverage tool -*- lexical-binding:t -*-
;; Copyright (C) 2002-2015 Free Software Foundation, Inc.
@@ -191,8 +191,9 @@ problems with type-ahead or post-command-hook, etc. If BYTE-COMPILE is
non-nil, byte-compiles each function after instrumenting."
(interactive "fStart covering file: ")
(let ((buf (find-file filename))
- (load-read-function 'testcover-read)
- (edebug-all-defs t))
+ (load-read-function load-read-function))
+ (add-function :around load-read-function
+ #'testcover--read)
(setq edebug-form-data nil
testcover-module-constants nil
testcover-module-1value-functions nil)
@@ -207,22 +208,26 @@ non-nil, byte-compiles each function after instrumenting."
(defun testcover-this-defun ()
"Start coverage on function under point."
(interactive)
- (let* ((edebug-all-defs t)
- (x (symbol-function (eval-defun nil))))
+ (let ((x (let ((edebug-all-defs t))
+ (symbol-function (eval-defun nil)))))
(testcover-reinstrument x)
x))
-(defun testcover-read (&optional stream)
+(defun testcover--read (orig &optional stream)
"Read a form using edebug, changing edebug callbacks to testcover callbacks."
- (let ((x (edebug-read stream)))
- (testcover-reinstrument x)
- x))
+ (or stream (setq stream standard-input))
+ (if (eq stream (current-buffer))
+ (let ((x (let ((edebug-all-defs t))
+ (edebug-read-and-maybe-wrap-form))))
+ (testcover-reinstrument x)
+ x)
+ (funcall (or orig #'read) stream)))
(defun testcover-reinstrument (form)
"Reinstruments FORM to use testcover instead of edebug. This
function modifies the list that FORM points to. Result is nil if
FORM should return multiple values, t if should always return same
-value, 'maybe if either is acceptable."
+value, `maybe' if either is acceptable."
(let ((fun (car-safe form))
id val)
(cond
@@ -495,7 +500,7 @@ eliminated by adding more test cases."
(len (length points))
(changed (buffer-modified-p))
(coverage (get def 'edebug-coverage))
- ov j item)
+ ov j)
(or (and def-mark points coverage)
(error "Missing edebug data for function %s" def))
(when (> len 0)