diff options
author | Jan D <jan.h.d@swipnet.se> | 2015-05-17 16:46:34 +0200 |
---|---|---|
committer | Jan D <jan.h.d@swipnet.se> | 2015-05-17 16:46:34 +0200 |
commit | 6445ee0fb751ae2c1dfef900d44721b3d952812f (patch) | |
tree | d43006cb93d9ea7b00ea02aabcd5577c41ff827f /lisp/emacs-lisp | |
parent | f92ac2e82ed199d6f25d2a59508e08addb1150ac (diff) | |
parent | c9c4708ed47b18987940a71b98eb9873150d2b95 (diff) | |
download | emacs-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.el | 80 | ||||
-rw-r--r-- | lisp/emacs-lisp/chart.el | 4 | ||||
-rw-r--r-- | lisp/emacs-lisp/check-declare.el | 7 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl-generic.el | 270 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl-lib.el | 7 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl-seq.el | 2 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl.el | 3 | ||||
-rw-r--r-- | lisp/emacs-lisp/debug.el | 3 | ||||
-rw-r--r-- | lisp/emacs-lisp/eieio-core.el | 24 | ||||
-rw-r--r-- | lisp/emacs-lisp/eieio-custom.el | 14 | ||||
-rw-r--r-- | lisp/emacs-lisp/eieio-opt.el | 3 | ||||
-rw-r--r-- | lisp/emacs-lisp/eieio.el | 4 | ||||
-rw-r--r-- | lisp/emacs-lisp/eldoc.el | 27 | ||||
-rw-r--r-- | lisp/emacs-lisp/ert.el | 6 | ||||
-rw-r--r-- | lisp/emacs-lisp/lisp.el | 15 | ||||
-rw-r--r-- | lisp/emacs-lisp/package-x.el | 1 | ||||
-rw-r--r-- | lisp/emacs-lisp/package.el | 274 | ||||
-rw-r--r-- | lisp/emacs-lisp/pcase.el | 10 | ||||
-rw-r--r-- | lisp/emacs-lisp/seq.el | 104 | ||||
-rw-r--r-- | lisp/emacs-lisp/subr-x.el | 3 | ||||
-rw-r--r-- | lisp/emacs-lisp/tabulated-list.el | 30 | ||||
-rw-r--r-- | lisp/emacs-lisp/testcover.el | 27 |
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) |