diff options
| author | Daniel Colascione <dancol@dancol.org> | 2012-10-07 14:31:58 -0800 |
|---|---|---|
| committer | Daniel Colascione <dancol@dancol.org> | 2012-10-07 14:31:58 -0800 |
| commit | 36a305a723c63fd345be65c536c52fe9765c14be (patch) | |
| tree | fb89d9e103552863214c60297a65320917109357 /lisp/emacs-lisp | |
| parent | 2ab329f3b5d52a39f0a45c3d9c129f1c19560142 (diff) | |
| parent | 795b1482a9e314cda32d62ac2988f573d359366e (diff) | |
| download | emacs-36a305a723c63fd345be65c536c52fe9765c14be.tar.gz | |
Merge from trunk
Diffstat (limited to 'lisp/emacs-lisp')
30 files changed, 545 insertions, 196 deletions
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index e6e2d1e60e0..382e25f3121 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -153,7 +153,7 @@ expression, in which case we want to handle forms differently." easy-mmode-define-minor-mode define-minor-mode cl-defun defun* cl-defmacro defmacro* define-overloadable-function)) - (let* ((macrop (memq car '(defmacro defmacro*))) + (let* ((macrop (memq car '(defmacro cl-defmacro defmacro*))) (name (nth 1 form)) (args (pcase car ((or `defun `defmacro diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index 93e890a20c9..d740574f1e4 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -253,7 +253,9 @@ convention was modified." advertised-signature-table)) (defun make-obsolete (obsolete-name current-name &optional when) - "Make the byte-compiler warn that OBSOLETE-NAME is obsolete. + "Make the byte-compiler warn that function OBSOLETE-NAME is obsolete. +OBSOLETE-NAME should be a function name or macro name (a symbol). + The warning will say that CURRENT-NAME should be used instead. If CURRENT-NAME is a string, that is the `use instead' message \(it should end with a period, and not start with a capital). diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index c42ae21aae5..4dd44bb6f22 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -846,7 +846,7 @@ CONST2 may be evaluated multiple times." (defun byte-compile-cl-file-p (file) "Return non-nil if FILE is one of the CL files." (and (stringp file) - (string-match "^cl\\>" (file-name-nondirectory file)))) + (string-match "^cl\\.el" (file-name-nondirectory file)))) (defun byte-compile-eval (form) "Eval FORM and mark the functions defined therein. @@ -1005,13 +1005,20 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'." (defvar byte-compile-root-dir nil "Directory relative to which file names in error messages are written.") +;; FIXME: We should maybe extend abbreviate-file-name with an optional DIR +;; argument to try and use a relative file-name. +(defun byte-compile-abbreviate-file (file &optional dir) + (let ((f1 (abbreviate-file-name file)) + (f2 (file-relative-name file dir))) + (if (< (length f2) (length f1)) f2 f1))) + ;; This is used as warning-prefix for the compiler. ;; It is always called with the warnings buffer current. (defun byte-compile-warning-prefix (level entry) (let* ((inhibit-read-only t) (dir (or byte-compile-root-dir default-directory)) (file (cond ((stringp byte-compile-current-file) - (format "%s:" (file-relative-name + (format "%s:" (byte-compile-abbreviate-file byte-compile-current-file dir))) ((bufferp byte-compile-current-file) (format "Buffer %s:" @@ -1019,7 +1026,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'." ;; We might be simply loading a file that ;; contains explicit calls to byte-compile functions. ((stringp load-file-name) - (format "%s:" (file-relative-name load-file-name dir))) + (format "%s:" (byte-compile-abbreviate-file + load-file-name dir))) (t ""))) (pos (if (and byte-compile-current-file (integerp byte-compile-read-position)) @@ -1115,18 +1123,12 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'." "Warn that SYMBOL (a variable or function) is obsolete." (when (byte-compile-warning-enabled-p 'obsolete) (let* ((funcp (get symbol 'byte-obsolete-info)) - (obsolete (or funcp (get symbol 'byte-obsolete-variable))) - (instead (car obsolete)) - (asof (nth 2 obsolete))) + (msg (macroexp--obsolete-warning + symbol + (or funcp (get symbol 'byte-obsolete-variable)) + (if funcp "function" "variable")))) (unless (and funcp (memq symbol byte-compile-not-obsolete-funcs)) - (byte-compile-warn "`%s' is an obsolete %s%s%s" symbol - (if funcp "function" "variable") - (if asof (concat " (as of " asof ")") "") - (cond ((stringp instead) - (concat "; " instead)) - (instead - (format "; use `%s' instead." instead)) - (t "."))))))) + (byte-compile-warn "%s" msg))))) (defun byte-compile-report-error (error-info) "Report Lisp error in compilation. ERROR-INFO is the error data." @@ -1752,11 +1754,11 @@ The value is non-nil if there were no errors, nil if errors." (if (with-current-buffer input-buffer no-byte-compile) (progn ;; (message "%s not compiled because of `no-byte-compile: %s'" - ;; (file-relative-name filename) + ;; (byte-compile-abbreviate-file filename) ;; (with-current-buffer input-buffer no-byte-compile)) (when (file-exists-p target-file) (message "%s deleted because of `no-byte-compile: %s'" - (file-relative-name target-file) + (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. diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el index ea5e1cf9beb..913ebf2015f 100644 --- a/lisp/emacs-lisp/cl-extra.el +++ b/lisp/emacs-lisp/cl-extra.el @@ -689,7 +689,6 @@ PROPLIST is a list of the sort returned by `symbol-plist'. ;; Local variables: ;; byte-compile-dynamic: t -;; byte-compile-warnings: (not cl-functions) ;; generated-autoload-file: "cl-loaddefs.el" ;; End: diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el index 5749ff91b40..2eda628e262 100644 --- a/lisp/emacs-lisp/cl-lib.el +++ b/lisp/emacs-lisp/cl-lib.el @@ -745,7 +745,6 @@ If ALIST is non-nil, the new pairs are prepended to it." ;; Local variables: ;; byte-compile-dynamic: t -;; byte-compile-warnings: (not cl-functions) ;; End: ;;; cl-lib.el ends here diff --git a/lisp/emacs-lisp/cl-loaddefs.el b/lisp/emacs-lisp/cl-loaddefs.el index c12e8ccacb1..e25ac5f9708 100644 --- a/lisp/emacs-lisp/cl-loaddefs.el +++ b/lisp/emacs-lisp/cl-loaddefs.el @@ -11,7 +11,7 @@ ;;;;;; cl--map-overlays cl--map-intervals cl--map-keymap-recursively ;;;;;; cl-notevery cl-notany cl-every cl-some cl-mapcon cl-mapcan ;;;;;; cl-mapl cl-maplist cl-map cl--mapcar-many cl-equalp cl-coerce) -;;;;;; "cl-extra" "cl-extra.el" "535a24c1cff55a16e3d51219498a7858") +;;;;;; "cl-extra" "cl-extra.el" "1572ae52fa4fbd9c4bf89b49a068a865") ;;; Generated autoloads from cl-extra.el (autoload 'cl-coerce "cl-extra" "\ @@ -260,7 +260,7 @@ Remove from SYMBOL's plist the property PROPNAME and its value. ;;;;;; cl-typecase cl-ecase cl-case cl-load-time-value cl-eval-when ;;;;;; cl-destructuring-bind cl-function cl-defmacro cl-defun cl-gentemp ;;;;;; cl-gensym cl--compiler-macro-cXXr cl--compiler-macro-list*) -;;;;;; "cl-macs" "cl-macs.el" "6d0676869af66e5b5a671f95ee069461") +;;;;;; "cl-macs" "cl-macs.el" "6951d080daefb5194b1d21fe9b2deae4") ;;; Generated autoloads from cl-macs.el (autoload 'cl--compiler-macro-list* "cl-macs" "\ @@ -657,8 +657,9 @@ copier, a `NAME-p' predicate, and slot accessors named `NAME-SLOT'. You can use the accessors to set the corresponding slots, via `setf'. NAME may instead take the form (NAME OPTIONS...), where each -OPTION is either a single keyword or (KEYWORD VALUE). -See Info node `(cl)Structures' for a list of valid keywords. +OPTION is either a single keyword or (KEYWORD VALUE) where +KEYWORD can be one of :conc-name, :constructor, :copier, :predicate, +:type, :named, :initial-offset, :print-function, or :include. Each SLOT may instead take the form (SLOT SLOT-OPTS...), where SLOT-OPTS are keyword-value pairs for that slot. Currently, only @@ -748,7 +749,7 @@ surrounded by (cl-block NAME ...). ;;;;;; cl-nsubstitute-if cl-nsubstitute cl-substitute-if-not cl-substitute-if ;;;;;; cl-substitute cl-delete-duplicates cl-remove-duplicates cl-delete-if-not ;;;;;; cl-delete-if cl-delete cl-remove-if-not cl-remove-if cl-remove -;;;;;; cl-replace cl-fill cl-reduce) "cl-seq" "cl-seq.el" "b444601641dcbd14a23ca5182bc80ffa") +;;;;;; cl-replace cl-fill cl-reduce) "cl-seq" "cl-seq.el" "4c1e1191e82dc8d5449a5ec4d59efc10") ;;; Generated autoloads from cl-seq.el (autoload 'cl-reduce "cl-seq" "\ diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 16ac14f8fe9..99bae1944e8 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -2154,8 +2154,9 @@ copier, a `NAME-p' predicate, and slot accessors named `NAME-SLOT'. You can use the accessors to set the corresponding slots, via `setf'. NAME may instead take the form (NAME OPTIONS...), where each -OPTION is either a single keyword or (KEYWORD VALUE). -See Info node `(cl)Structures' for a list of valid keywords. +OPTION is either a single keyword or (KEYWORD VALUE) where +KEYWORD can be one of :conc-name, :constructor, :copier, :predicate, +:type, :named, :initial-offset, :print-function, or :include. Each SLOT may instead take the form (SLOT SLOT-OPTS...), where SLOT-OPTS are keyword-value pairs for that slot. Currently, only @@ -2686,7 +2687,6 @@ surrounded by (cl-block NAME ...). ;; Local variables: ;; byte-compile-dynamic: t -;; byte-compile-warnings: (not cl-functions) ;; generated-autoload-file: "cl-loaddefs.el" ;; End: diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el index b55f1df5ba5..1fa562e328a 100644 --- a/lisp/emacs-lisp/cl-seq.el +++ b/lisp/emacs-lisp/cl-seq.el @@ -1010,7 +1010,6 @@ Atoms are compared by `eql'; cons cells are compared recursively. ;; Local variables: ;; byte-compile-dynamic: t -;; byte-compile-warnings: (not cl-functions) ;; generated-autoload-file: "cl-loaddefs.el" ;; End: diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el index ae0852d6c87..34beed0d9ef 100644 --- a/lisp/emacs-lisp/cl.el +++ b/lisp/emacs-lisp/cl.el @@ -452,7 +452,7 @@ definitions, or lack thereof). \(fn ((FUNC ARGLIST BODY...) ...) FORM...)" (declare (indent 1) (debug cl-flet) - (obsolete "Use either `cl-flet' or `cl-letf'." "24.3")) + (obsolete "use either `cl-flet' or `cl-letf'." "24.3")) `(letf ,(mapcar (lambda (x) (if (or (and (fboundp (car x)) diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index 774b4d3d600..6b308119abb 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el @@ -75,9 +75,9 @@ window previously showing the debugger buffer. The value used here is passed to `quit-restore-window'." :type '(choice (const :tag "Keep alive" nil) - (const :tag "Append" 'append) - (const :tag "Bury" 'bury) - (const :tag "Kill" 'kill)) + (const :tag "Append" append) + (const :tag "Bury" bury) + (const :tag "Kill" kill)) :group 'debugger :version "24.2") @@ -166,6 +166,7 @@ first will be printed into the backtrace buffer." (with-current-buffer (get-buffer "*Backtrace*") (list major-mode (buffer-string))))) (debugger-buffer (get-buffer-create "*Backtrace*")) + (debugger-old-buffer (current-buffer)) (debugger-window nil) (debugger-step-after-exit nil) (debugger-will-be-back nil) @@ -265,13 +266,16 @@ first will be printed into the backtrace buffer." ;; Make sure we unbind buffer-read-only in the right buffer. (save-excursion (recursive-edit)))) - (when (and (window-live-p debugger-window) + (when (and (not debugger-will-be-back) + (window-live-p debugger-window) (eq (window-buffer debugger-window) debugger-buffer)) ;; Record height of debugger window. (setq debugger-previous-window-height (window-total-size debugger-window)) ;; Unshow debugger-buffer. - (quit-restore-window debugger-window debugger-bury-or-kill)) + (quit-restore-window debugger-window debugger-bury-or-kill) + ;; Restore current buffer (Bug#12502). + (set-buffer debugger-old-buffer)) ;; Restore previous state of debugger-buffer in case we were ;; in a recursive invocation of the debugger, otherwise just ;; erase the buffer and put it into fundamental mode. diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el index ea72e9492f0..8c8d37b2194 100644 --- a/lisp/emacs-lisp/derived.el +++ b/lisp/emacs-lisp/derived.el @@ -276,10 +276,10 @@ A mode's class is the first ancestor which is NOT a derived mode. Use the `derived-mode-parent' property of the symbol to trace backwards. Since major-modes might all derive from `fundamental-mode', this function is not very useful." + (declare (obsolete derived-mode-p "22.1")) (while (get mode 'derived-mode-parent) (setq mode (get mode 'derived-mode-parent))) mode) -(make-obsolete 'derived-mode-class 'derived-mode-p "22.1") ;;; PRIVATE diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index ee4e36a9eba..4951368aebe 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -90,12 +90,17 @@ MODE (you can override this with the :variable keyword, see below). DOC is the documentation for the mode toggle command. The defined mode command takes one optional (prefix) argument. -Interactively with no prefix argument it toggles the mode. -With a prefix argument, it enables the mode if the argument is -positive and otherwise disables it. When called from Lisp, it -enables the mode if the argument is omitted or nil, and toggles -the mode if the argument is `toggle'. If DOC is nil this -function adds a basic doc-string stating these facts. +Interactively with no prefix argument, it toggles the mode. +A prefix argument enables the mode if the argument is positive, +and disables it otherwise. + +When called from Lisp, the mode command toggles the mode if the +argument is `toggle', disables the mode if the argument is a +non-positive integer, and enables the mode otherwise (including +if the argument is omitted or nil or a positive integer). + +If DOC is nil, give the mode command a basic doc-string +documenting what its argument does. Optional INIT-VALUE is the initial value of the mode's variable. Optional LIGHTER is displayed in the mode line when the mode is on. diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index d656dcf9526..18d1661e985 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -383,12 +383,9 @@ Return the result of the last expression in BODY." ;; All windows are dedicated or show `edebug-trace-buffer', split ;; selected one. (t (split-window)))) - (select-window window) (set-window-buffer window buffer) - (set-window-hscroll window 0);; should this be?? - ;; Selecting the window does not set the buffer until command loop. - ;;(set-buffer buffer) - ) + (select-window window) + (set-window-hscroll window 0)) ;; should this be?? (defun edebug-get-displayed-buffer-points () ;; Return a list of buffer point pairs, for all displayed buffers. diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el index b5600560cdd..69fe762887f 100644 --- a/lisp/emacs-lisp/eieio-base.el +++ b/lisp/emacs-lisp/eieio-base.el @@ -4,7 +4,6 @@ ;;; Free Software Foundation, Inc. ;; Author: Eric M. Ludlam <zappo@gnu.org> -;; Version: 0.2 ;; Keywords: OO, lisp ;; Package: eieio @@ -225,8 +224,16 @@ a file. Optional argument NAME specifies a default file name." )))) (oref this file)) -(defun eieio-persistent-read (filename) - "Read a persistent object from FILENAME, and return it." +(defun eieio-persistent-read (filename &optional class allow-subclass) + "Read a persistent object from FILENAME, and return it. +Signal an error if the object in FILENAME is not a constructor +for CLASS. Optional ALLOW-SUBCLASS says that it is ok for +`eieio-persistent-read' to load in subclasses of class instead of +being pedantic." + (unless class + (message "Unsafe call to `eieio-persistent-read'.")) + (when (and class (not (class-p class))) + (signal 'wrong-type-argument (list 'class-p class))) (let ((ret nil) (buffstr nil)) (unwind-protect @@ -239,13 +246,171 @@ a file. Optional argument NAME specifies a default file name." ;; so that any initialize-instance calls that depend on ;; the current buffer will work. (setq ret (read buffstr)) - (if (not (child-of-class-p (car ret) 'eieio-persistent)) - (error "Corrupt object on disk")) - (setq ret (eval ret)) + (when (not (child-of-class-p (car ret) 'eieio-persistent)) + (error "Corrupt object on disk: Unknown saved object")) + (when (and class + (not (or (eq (car ret) class ) ; same class + (and allow-subclass + (child-of-class-p (car ret) class)) ; subclasses + ))) + (error "Corrupt object on disk: Invalid saved class")) + (setq ret (eieio-persistent-convert-list-to-object ret)) (oset ret file filename)) (kill-buffer " *tmp eieio read*")) ret)) +(defun eieio-persistent-convert-list-to-object (inputlist) + "Convert the INPUTLIST, representing object creation to an object. +While it is possible to just `eval' the INPUTLIST, this code instead +validates the existing list, and explicitly creates objects instead of +calling eval. This avoids the possibility of accidentally running +malicious code. + +Note: This function recurses when a slot of :type of some object is +identified, and needing more object creation." + (let ((objclass (nth 0 inputlist)) + (objname (nth 1 inputlist)) + (slots (nthcdr 2 inputlist)) + (createslots nil)) + + ;; If OBJCLASS is an eieio autoload object, then we need to load it. + (eieio-class-un-autoload objclass) + + (while slots + (let ((name (car slots)) + (value (car (cdr slots)))) + + ;; Make sure that the value proposed for SLOT is valid. + ;; In addition, strip out quotes, list functions, and update + ;; object constructors as needed. + (setq value (eieio-persistent-validate/fix-slot-value + objclass name value)) + + (push name createslots) + (push value createslots) + ) + + (setq slots (cdr (cdr slots)))) + + (apply 'make-instance objclass objname (nreverse createslots)) + + ;;(eval inputlist) + )) + +(defun eieio-persistent-validate/fix-slot-value (class slot proposed-value) + "Validate that in CLASS, the SLOT with PROPOSED-VALUE is good, then fix. +A limited number of functions, such as quote, list, and valid object +constructor functions are considered valid. +Second, any text properties will be stripped from strings." + (cond ((consp proposed-value) + ;; Lists with something in them need special treatment. + (let ((slot-idx (eieio-slot-name-index class nil slot)) + (type nil) + (classtype nil)) + (setq slot-idx (- slot-idx 3)) + (setq type (aref (aref (class-v class) class-public-type) + slot-idx)) + + (setq classtype (eieio-persistent-slot-type-is-class-p + type)) + + (cond ((eq (car proposed-value) 'quote) + (car (cdr proposed-value))) + + ;; An empty list sometimes shows up as (list), which is dumb, but + ;; we need to support it for backward compat. + ((and (eq (car proposed-value) 'list) + (= (length proposed-value) 1)) + nil) + + ;; We have a slot with a single object that can be + ;; saved here. Recurse and evaluate that + ;; sub-object. + ((and classtype (class-p classtype) + (child-of-class-p (car proposed-value) classtype)) + (eieio-persistent-convert-list-to-object + proposed-value)) + + ;; List of object constructors. + ((and (eq (car proposed-value) 'list) + ;; 2nd item is a list. + (consp (car (cdr proposed-value))) + ;; 1st elt of 2nd item is a class name. + (class-p (car (car (cdr proposed-value)))) + ) + + ;; Check the value against the input class type. + ;; If something goes wrong, issue a smart warning + ;; about how a :type is needed for this to work. + (unless (and + ;; Do we have a type? + (consp classtype) (class-p (car classtype))) + (error "In save file, list of object constructors found, but no :type specified for slot %S" + slot)) + + ;; We have a predicate, but it doesn't satisfy the predicate? + (dolist (PV (cdr proposed-value)) + (unless (child-of-class-p (car PV) (car classtype)) + (error "Corrupt object on disk"))) + + ;; We have a list of objects here. Lets load them + ;; in. + (let ((objlist nil)) + (dolist (subobj (cdr proposed-value)) + (push (eieio-persistent-convert-list-to-object subobj) + objlist)) + ;; return the list of objects ... reversed. + (nreverse objlist))) + (t + proposed-value)))) + + ((stringp proposed-value) + ;; Else, check for strings, remove properties. + (substring-no-properties proposed-value)) + + (t + ;; Else, just return whatever the constant was. + proposed-value)) + ) + +(defun eieio-persistent-slot-type-is-class-p (type) + "Return the class refered to in TYPE. +If no class is referenced there, then return nil." + (cond ((class-p type) + ;; If the type is a class, then return it. + type) + + ((and (symbolp type) (string-match "-child$" (symbol-name type)) + (class-p (intern-soft (substring (symbol-name type) 0 + (match-beginning 0))))) + ;; If it is the predicate ending with -child, then return + ;; that class. Unfortunately, in EIEIO, typep of just the + ;; class is the same as if we used -child, so no further work needed. + (intern-soft (substring (symbol-name type) 0 + (match-beginning 0)))) + + ((and (symbolp type) (string-match "-list$" (symbol-name type)) + (class-p (intern-soft (substring (symbol-name type) 0 + (match-beginning 0))))) + ;; If it is the predicate ending with -list, then return + ;; that class and the predicate to use. + (cons (intern-soft (substring (symbol-name type) 0 + (match-beginning 0))) + type)) + + ((and (consp type) (eq (car type) 'or)) + ;; If type is a list, and is an or, it is possibly something + ;; like (or null myclass), so check for that. + (let ((ans nil)) + (dolist (subtype (cdr type)) + (setq ans (eieio-persistent-slot-type-is-class-p + subtype))) + ans)) + + (t + ;; No match, not a class. + nil))) + (defmethod object-write ((this eieio-persistent) &optional comment) "Write persistent object THIS out to the current stream. Optional argument COMMENT is a header line comment." diff --git a/lisp/emacs-lisp/eieio-custom.el b/lisp/emacs-lisp/eieio-custom.el index 59aeb161d8e..cab9caad108 100644 --- a/lisp/emacs-lisp/eieio-custom.el +++ b/lisp/emacs-lisp/eieio-custom.el @@ -332,6 +332,16 @@ Argument OBJ is the object that has been customized." Optional argument GROUP is the sub-group of slots to display." (eieio-customize-object obj group)) +(defvar eieio-custom-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map widget-keymap) + map) + "Keymap for EIEIO Custom mode") + +(define-derived-mode eieio-custom-mode fundamental-mode "EIEIO Custom" + "Major mode for customizing EIEIO objects. +\\{eieio-custom-mode-map}") + (defmethod eieio-customize-object ((obj eieio-default-superclass) &optional group) "Customize OBJ in a specialized custom buffer. @@ -347,6 +357,7 @@ These groups are specified with the `:group' slot flag." (symbol-name g) "*"))) (setq buffer-read-only nil) (kill-all-local-variables) + (eieio-custom-mode) (erase-buffer) (let ((all (overlay-lists))) ;; Delete all the overlays. @@ -363,7 +374,6 @@ These groups are specified with the `:group' slot flag." (widget-insert "\n") (eieio-custom-object-apply-reset obj) ;; Now initialize the buffer - (use-local-map widget-keymap) (widget-setup) ;;(widget-minor-mode) (goto-char (point-min)) @@ -461,8 +471,4 @@ Return the symbol for the group, or nil" (provide 'eieio-custom) -;; Local variables: -;; generated-autoload-file: "eieio.el" -;; End: - ;;; eieio-custom.el ends here diff --git a/lisp/emacs-lisp/eieio-datadebug.el b/lisp/emacs-lisp/eieio-datadebug.el index b7f0deb0ee2..ec470d21bf3 100644 --- a/lisp/emacs-lisp/eieio-datadebug.el +++ b/lisp/emacs-lisp/eieio-datadebug.el @@ -92,12 +92,11 @@ PREBUTTONTEXT is some text between PREFIX and the object button." "Class: ") ;; Loop over all the public slots (let ((publa (aref cv class-public-a)) - (publd (aref cv class-public-d)) ) (while publa (if (slot-boundp obj (car publa)) - (let ((i (class-slot-initarg cl (car publa))) - (v (eieio-oref obj (car publa)))) + (let* ((i (class-slot-initarg cl (car publa))) + (v (eieio-oref obj (car publa)))) (data-debug-insert-thing v prefix (concat (if i (symbol-name i) @@ -112,7 +111,7 @@ PREBUTTONTEXT is some text between PREFIX and the object button." " ") 'font-lock-keyword-face)) ) - (setq publa (cdr publa) publd (cdr publd)))))) + (setq publa (cdr publa)))))) ;;; Augment the Data debug thing display list. (data-debug-add-specialized-thing (lambda (thing) (object-p thing)) diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el index a899839f68a..64b240b9d5d 100644 --- a/lisp/emacs-lisp/eieio-opt.el +++ b/lisp/emacs-lisp/eieio-opt.el @@ -4,7 +4,6 @@ ;; Free Software Foundation, Inc. ;; Author: Eric M. Ludlam <zappo@gnu.org> -;; Version: 0.2 ;; Keywords: OO, lisp ;; Package: eieio @@ -30,6 +29,9 @@ ;; (require 'eieio) +(require 'button) +(require 'help-mode) +(require 'find-func) ;;; Code: ;;;###autoload @@ -85,11 +87,16 @@ Optional HEADERFCN should be called to insert a few bits of info first." (called-interactively-p 'interactive)) (when headerfcn (funcall headerfcn)) - - (if (class-option class :abstract) - (princ "Abstract ")) - (princ "Class ") (prin1 class) + (princ " is a") + (if (class-option class :abstract) + (princ "n abstract")) + (princ " class") + ;; Print file location + (when (get class 'class-location) + (princ " in `") + (princ (file-name-nondirectory (get class 'class-location))) + (princ "'")) (terpri) ;; Inheritance tree information (let ((pl (class-parents class))) @@ -251,8 +258,13 @@ Uses `eieio-describe-class' to describe the class being constructed." (eieio-describe-class fcn (lambda () ;; Describe the constructor part. - (princ "Object Constructor Function: ") (prin1 fcn) + (princ " is an object constructor function") + ;; Print file location + (when (get fcn 'class-location) + (princ " in `") + (princ (file-name-nondirectory (get fcn 'class-location))) + (princ "'")) (terpri) (princ "Creates an object of class ") (prin1 fcn) @@ -262,6 +274,16 @@ Uses `eieio-describe-class' to describe the class being constructed." )) ) +(defun eieio-build-class-list (class) + "Return a list of all classes that inherit from CLASS." + (if (class-p class) + (apply #'append + (mapcar + (lambda (c) + (append (list c) (eieio-build-class-list c))) + (class-children-fast class))) + (list class))) + (defun eieio-build-class-alist (&optional class instantiable-only buildlist) "Return an alist of all currently active classes for completion purposes. Optional argument CLASS is the class to start with. @@ -270,8 +292,9 @@ are not abstract, otherwise allow all classes. Optional argument BUILDLIST is more list to attach and is used internally." (let* ((cc (or class eieio-default-superclass)) (sublst (aref (class-v cc) class-children))) - (if (or (not instantiable-only) (not (class-abstract-p cc))) - (setq buildlist (cons (cons (symbol-name cc) 1) buildlist))) + (unless (assoc (symbol-name cc) buildlist) + (when (or (not instantiable-only) (not (class-abstract-p cc))) + (setq buildlist (cons (cons (symbol-name cc) 1) buildlist)))) (while sublst (setq buildlist (eieio-build-class-alist (car sublst) instantiable-only buildlist)) @@ -342,10 +365,10 @@ Also extracts information about all methods specific to this generic." (princ "Implementations:") (terpri) (terpri) - (let ((i 3) + (let ((i 4) (prefix [ ":STATIC" ":BEFORE" ":PRIMARY" ":AFTER" ] )) ;; Loop over fanciful generics - (while (< i 6) + (while (< i 7) (let ((gm (aref (get generic 'eieio-method-tree) i))) (when gm (princ "Generic ") @@ -357,8 +380,9 @@ Also extracts information about all methods specific to this generic." (setq i (1+ i))) (setq i 0) ;; Loop over defined class-specific methods - (while (< i 3) - (let ((gm (reverse (aref (get generic 'eieio-method-tree) i)))) + (while (< i 4) + (let ((gm (reverse (aref (get generic 'eieio-method-tree) i))) + location) (while gm (princ "`") (prin1 (car (car gm))) @@ -375,6 +399,13 @@ Also extracts information about all methods specific to this generic." ;; 3 because of cdr (princ (or (documentation (cdr (car gm))) "Undocumented")) + ;; Print file location if available + (when (and (setq location (get generic 'method-locations)) + (setq location (assoc (caar gm) location))) + (setq location (cadr location)) + (princ "\n\nDefined in `") + (princ (file-name-nondirectory location)) + (princ "'\n")) (setq gm (cdr gm)) (terpri) (terpri))) @@ -554,7 +585,65 @@ Optional argument HISTORYVAR is the variable to use as history." ;;; HELP AUGMENTATION ;; -;;;###autoload +(define-button-type 'eieio-method-def + :supertype 'help-xref + 'help-function (lambda (class method file) + (eieio-help-find-method-definition class method file)) + 'help-echo (purecopy "mouse-2, RET: find method's definition")) + +(define-button-type 'eieio-class-def + :supertype 'help-xref + 'help-function (lambda (class file) + (eieio-help-find-class-definition class file)) + 'help-echo (purecopy "mouse-2, RET: find class definition")) + +(defun eieio-help-find-method-definition (class method file) + (let ((filename (find-library-name file)) + location buf) + (when (null filename) + (error "Cannot find library %s" file)) + (setq buf (find-file-noselect filename)) + (with-current-buffer buf + (goto-char (point-min)) + (when + (re-search-forward + ;; Regexp for searching methods. + (concat "(defmethod[ \t\r\n]+" method + "\\([ \t\r\n]+:[a-zA-Z]+\\)?" + "[ \t\r\n]+(\\s-*(\\(\\sw\\|\\s_\\)+\\s-+" + class + "\\s-*)") + nil t) + (setq location (match-beginning 0)))) + (if (null location) + (message "Unable to find location in file") + (pop-to-buffer buf) + (goto-char location) + (recenter) + (beginning-of-line)))) + +(defun eieio-help-find-class-definition (class file) + (let ((filename (find-library-name file)) + location buf) + (when (null filename) + (error "Cannot find library %s" file)) + (setq buf (find-file-noselect filename)) + (with-current-buffer buf + (goto-char (point-min)) + (when + (re-search-forward + ;; Regexp for searching a class. + (concat "(defclass[ \t\r\n]+" class "[ \t\r\n]+") + nil t) + (setq location (match-beginning 0)))) + (if (null location) + (message "Unable to find location in file") + (pop-to-buffer buf) + (goto-char location) + (recenter) + (beginning-of-line)))) + + (defun eieio-help-mode-augmentation-maybee (&rest unused) "For buffers thrown into help mode, augment for EIEIO. Arguments UNUSED are not used." @@ -597,6 +686,26 @@ Arguments UNUSED are not used." (goto-char (point-min)) (while (re-search-forward "^\\(Private \\)?Slot:" nil t) (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)) + (goto-char (point-min)) + (cond + ((looking-at "\\(.+\\) is a generic function") + (let ((mname (match-string 1)) + cname) + (while (re-search-forward "^`\\(.+\\)'[^\0]+?Defined in `\\(.+\\)'" nil t) + (setq cname (match-string-no-properties 1)) + (help-xref-button 2 'eieio-method-def cname + mname + (cadr (assoc (intern cname) + (get (intern mname) + 'method-locations))))))) + ((looking-at "\\(.+\\) is an object constructor function in `\\(.+\\)'") + (let ((cname (match-string-no-properties 1))) + (help-xref-button 2 'eieio-class-def cname + (get (intern cname) 'class-location)))) + ((looking-at "\\(.+\\) is a\\(n abstract\\)? class in `\\(.+\\)'") + (let ((cname (match-string-no-properties 1))) + (help-xref-button 3 'eieio-class-def cname + (get (intern cname) 'class-location))))) )))) ;;; SPEEDBAR SUPPORT @@ -698,8 +807,4 @@ INDENT is the current indentation level." (provide 'eieio-opt) -;; Local variables: -;; generated-autoload-file: "eieio.el" -;; End: - ;;; eieio-opt.el ends here diff --git a/lisp/emacs-lisp/eieio-speedbar.el b/lisp/emacs-lisp/eieio-speedbar.el index f169e3f0cd2..327e5ced0e3 100644 --- a/lisp/emacs-lisp/eieio-speedbar.el +++ b/lisp/emacs-lisp/eieio-speedbar.el @@ -3,7 +3,6 @@ ;; Copyright (C) 1999-2002, 2005, 2007-2012 Free Software Foundation, Inc. ;; Author: Eric M. Ludlam <zappo@gnu.org> -;; Version: 0.2 ;; Keywords: OO, tools ;; Package: eieio @@ -191,23 +190,24 @@ that path." ;;; DEFAULT SUPERCLASS baseline methods ;; -;; First, define methods onto the superclass so all classes -;; will have some minor support. +;; First, define methods with no class defined. These will work as if +;; on the default superclass. Specifying no class will allow these to be used +;; when no other methods are found, allowing multiple inheritance to work +;; reliably with eieio-speedbar. -(defmethod eieio-speedbar-description ((object eieio-default-superclass)) +(defmethod eieio-speedbar-description (object) "Return a string describing OBJECT." (object-name-string object)) -(defmethod eieio-speedbar-derive-line-path ((object eieio-default-superclass)) +(defmethod eieio-speedbar-derive-line-path (object) "Return the path which OBJECT has something to do with." nil) -(defmethod eieio-speedbar-object-buttonname ((object eieio-default-superclass)) +(defmethod eieio-speedbar-object-buttonname (object) "Return a string to use as a speedbar button for OBJECT." (object-name-string object)) -(defmethod eieio-speedbar-make-tag-line ((object eieio-default-superclass) - depth) +(defmethod eieio-speedbar-make-tag-line (object depth) "Insert a tag line into speedbar at point for OBJECT. By default, all objects appear as simple TAGS with no need to inherit from the special `eieio-speedbar' classes. Child classes should redefine this @@ -220,7 +220,7 @@ Argument DEPTH is the depth at which the tag line is inserted." 'speedbar-tag-face depth)) -(defmethod eieio-speedbar-handle-click ((object eieio-default-superclass)) +(defmethod eieio-speedbar-handle-click (object) "Handle a click action on OBJECT in speedbar. Any object can be represented as a tag in SPEEDBAR without special attributes. These default objects will be pulled up in a custom diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index 9304f0e3918..7e64b42d9e4 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el @@ -94,21 +94,6 @@ default setting for optimization purposes.") (defvar eieio-optimize-primary-methods-flag t "Non-nil means to optimize the method dispatch on primary methods.") -;; State Variables -;; FIXME: These two constants below should have an `eieio-' prefix added!! -(defvar this nil - "Inside a method, this variable is the object in question. -DO NOT SET THIS YOURSELF unless you are trying to simulate friendly slots. - -Note: Embedded methods are no longer supported. The variable THIS is -still set for CLOS methods for the sake of routines like -`call-next-method'.") - -(defvar scoped-class nil - "This is set to a class when a method is running. -This is so we know we are allowed to check private parts or how to -execute a `call-next-method'. DO NOT SET THIS YOURSELF!") - (defvar eieio-initializing-object nil "Set to non-nil while initializing an object.") @@ -410,6 +395,7 @@ It creates an autoload function for CNAME's constructor." (autoload cname filename doc nil nil) (autoload (intern (concat (symbol-name cname) "-p")) filename "" nil nil) (autoload (intern (concat (symbol-name cname) "-child-p")) filename "" nil nil) + (autoload (intern (concat (symbol-name cname) "-list-p")) filename "" nil nil) )))) @@ -539,6 +525,23 @@ See `defclass' for more information." (and (eieio-object-p obj) (object-of-class-p obj ,cname)))) + ;; Create a handy list of the class test too + (let ((csym (intern (concat (symbol-name cname) "-list-p")))) + (fset csym + `(lambda (obj) + ,(format + "Test OBJ to see if it a list of objects which are a child of type %s" + cname) + (when (listp obj) + (let ((ans t)) ;; nil is valid + ;; Loop over all the elements of the input list, test + ;; each to make sure it is a child of the desired object class. + (while (and obj ans) + (setq ans (and (eieio-object-p (car obj)) + (object-of-class-p (car obj) ,cname))) + (setq obj (cdr obj))) + ans))))) + ;; When using typep, (typep OBJ 'myclass) returns t for objects which ;; are subclasses of myclass. For our predicates, however, it is ;; important for EIEIO to be backwards compatible, where @@ -781,6 +784,16 @@ See `defclass' for more information." (put cname 'variable-documentation (class-option-assoc options :documentation)) + ;; Save the file location where this class is defined. + (let ((fname (if load-in-progress + load-file-name + buffer-file-name)) + loc) + (when fname + (when (string-match "\\.elc$" fname) + (setq fname (substring fname 0 (1- (length fname))))) + (put cname 'class-location fname))) + ;; We have a list of custom groups. Store them into the options. (let ((g (class-option-assoc options :custom-groups))) (mapc (lambda (cg) (add-to-list 'g cg)) groups) @@ -1254,8 +1267,10 @@ IMPL is the symbol holding the method implementation." (eieio-generic-call-methodname ',method) (eieio-generic-call-arglst local-args) ) - (apply #',impl local-args) - ;;(,impl local-args) + ,(if (< emacs-major-version 24) + `(apply ,(list 'quote impl) local-args) + `(apply #',impl local-args)) + ;(,impl local-args) ))))))) (defsubst eieio-defgeneric-reset-generic-form-primary-only-one (method) @@ -2008,13 +2023,13 @@ reverse-lookup that name, and recurse with the associated slot value." ((not (get fsym 'protection)) (+ 3 fsi)) ((and (eq (get fsym 'protection) 'protected) - scoped-class + (bound-and-true-p scoped-class) (or (child-of-class-p class scoped-class) (and (eieio-object-p obj) (child-of-class-p class (object-class obj))))) (+ 3 fsi)) ((and (eq (get fsym 'protection) 'private) - (or (and scoped-class + (or (and (bound-and-true-p scoped-class) (eieio-slot-originating-class-p scoped-class slot)) eieio-initializing-object)) (+ 3 fsi)) @@ -2319,7 +2334,7 @@ If REPLACEMENT-ARGS is non-nil, then use them instead of arguments passed in at the top level. Use `next-method-p' to find out if there is a next method to call." - (if (not scoped-class) + (if (not (bound-and-true-p scoped-class)) (error "`call-next-method' not called within a class specific method")) (if (and (/= eieio-generic-call-key method-primary) (/= eieio-generic-call-key method-static)) @@ -2403,6 +2418,18 @@ CLASS is the class this method is associated with." (if (< key method-num-lists) (let ((nsym (intern (symbol-name class) (aref emto key)))) (fset nsym method))) + ;; Save the defmethod file location in a symbol property. + (let ((fname (if load-in-progress + load-file-name + buffer-file-name)) + loc) + (when fname + (when (string-match "\\.elc$" fname) + (setq fname (substring fname 0 (1- (length fname))))) + (setq loc (get method-name 'method-locations)) + (add-to-list 'loc + (list class fname)) + (put method-name 'method-locations loc))) ;; Now optimize the entire obarray (if (< key method-num-lists) (let ((eieiomt-optimizing-obarray (aref emto key))) @@ -2807,9 +2834,9 @@ this object." (princ (make-string (* eieio-print-depth 2) ? )) (princ "(") (princ (symbol-name (class-constructor (object-class this)))) - (princ " \"") - (princ (object-name-string this)) - (princ "\"\n") + (princ " ") + (prin1 (object-name-string this)) + (princ "\n") ;; Loop over all the public slots (let ((publa (aref cv class-public-a)) (publd (aref cv class-public-d)) @@ -2876,7 +2903,6 @@ of `eq'." ) - ;;; Obsolete backward compatibility functions. ;; Needed to run byte-code compiled with the EIEIO of Emacs-23. diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el index a7916354c91..c3b8e5e10d4 100644 --- a/lisp/emacs-lisp/ert-x.el +++ b/lisp/emacs-lisp/ert-x.el @@ -7,18 +7,18 @@ ;; This file is part of GNU Emacs. -;; This program is free software: you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation, either version 3 of the -;; License, or (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. -;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + ;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see `http://www.gnu.org/licenses/'. +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. ;;; Commentary: diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index ad5e20cb8a4..ff00be7a237 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -7,18 +7,18 @@ ;; This file is part of GNU Emacs. -;; This program is free software: you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation, either version 3 of the -;; License, or (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. -;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + ;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see `http://www.gnu.org/licenses/'. +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. ;;; Commentary: diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el index 4caa0a73866..7858c183e4b 100644 --- a/lisp/emacs-lisp/gv.el +++ b/lisp/emacs-lisp/gv.el @@ -1,22 +1,25 @@ -;;; gv.el --- Generalized variables -*- lexical-binding: t -*- +;;; gv.el --- generalized variables -*- lexical-binding: t -*- ;; Copyright (C) 2012 Free Software Foundation, Inc. ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> ;; Keywords: extensions +;; Package: emacs -;; This program is free software; you can redistribute it and/or modify +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. -;; This program is distributed in the hope that it will be useful, +;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. ;;; Commentary: @@ -266,7 +269,7 @@ The return value is the last VAL in the list. ;;;###autoload (put 'gv-place 'edebug-form-spec 'edebug-match-form) ;; CL did the equivalent of: -;;(gv-define-expand edebug-after (lambda (before index place) place)) +;;(gv-define-macroexpand edebug-after (lambda (before index place) place)) (put 'edebug-after 'gv-expander (lambda (do before index place) diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index 394225d697e..cab693fecac 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -100,17 +100,42 @@ each clause." (error (message "Compiler-macro error for %S: %S" (car form) err) form))) -(defun macroexp--eval-if-compile (&rest _forms) +(defun macroexp--funcall-if-compiled (_form) "Pseudo function used internally by macroexp to delay warnings. The purpose is to delay warnings to bytecomp.el, so they can use things like `byte-compile-log-warning' to get better file-and-line-number data and also to avoid outputting the warning during normal execution." nil) -(put 'macroexp--eval-if-compile 'byte-compile +(put 'macroexp--funcall-if-compiled 'byte-compile (lambda (form) - (mapc (lambda (x) (funcall (eval x))) (cdr form)) + (funcall (eval (cadr form))) (byte-compile-constant nil))) +(defun macroexp--warn-and-return (msg form) + (let ((when-compiled (lambda () (byte-compile-log-warning msg t)))) + (cond + ((null msg) form) + ;; FIXME: ¡¡Major Ugly Hack!! To determine whether the output of this + ;; macro-expansion will be processed by the byte-compiler, we check + ;; circumstantial evidence. + ((member '(declare-function . byte-compile-macroexpand-declare-function) + macroexpand-all-environment) + `(progn + (macroexp--funcall-if-compiled ',when-compiled) + ,form)) + (t + (message "%s" msg) + form)))) + +(defun macroexp--obsolete-warning (fun obsolescence-data type) + (let ((instead (car obsolescence-data)) + (asof (nth 2 obsolescence-data))) + (format "`%s' is an obsolete %s%s%s" fun type + (if asof (concat " (as of " asof ")") "") + (cond ((stringp instead) (concat "; " instead)) + (instead (format "; use `%s' instead." instead)) + (t "."))))) + (defun macroexp--expand-all (form) "Expand all macros in FORM. This is an internal version of `macroexpand-all'. @@ -130,9 +155,11 @@ Assumes the caller has bound `macroexpand-all-environment'." (car-safe form) (symbolp (car form)) (get (car form) 'byte-obsolete-info)) - `(progn (macroexp--eval-if-compile - (lambda () (byte-compile-warn-obsolete ',(car form)))) - ,new-form) + (let* ((fun (car form)) + (obsolete (get fun 'byte-obsolete-info))) + (macroexp--warn-and-return + (macroexp--obsolete-warning fun obsolete "macro") + new-form)) new-form))) (pcase form (`(cond . ,clauses) @@ -175,26 +202,16 @@ Assumes the caller has bound `macroexpand-all-environment'." ;; First arg is a function: (`(,(and fun (or `funcall `apply `mapcar `mapatoms `mapconcat `mapc)) ',(and f `(lambda . ,_)) . ,args) - (byte-compile-log-warning + (macroexp--warn-and-return (format "%s quoted with ' rather than with #'" (list 'lambda (nth 1 f) '...)) - t) - ;; We don't use `macroexp--cons' since there's clearly a change. - (cons fun - (cons (macroexp--expand-all (list 'function f)) - (macroexp--all-forms args)))) + (macroexp--expand-all `(,fun ,f . ,args)))) ;; Second arg is a function: (`(,(and fun (or `sort)) ,arg1 ',(and f `(lambda . ,_)) . ,args) - (byte-compile-log-warning + (macroexp--warn-and-return (format "%s quoted with ' rather than with #'" (list 'lambda (nth 1 f) '...)) - t) - ;; We don't use `macroexp--cons' since there's clearly a change. - (cons fun - (cons (macroexp--expand-all arg1) - (cons (macroexp--expand-all - (list 'function f)) - (macroexp--all-forms args))))) + (macroexp--expand-all `(,fun ,arg1 ,f . ,args)))) (`(,func . ,_) ;; Macro expand compiler macros. This cannot be delayed to ;; byte-optimize-form because the output of the compiler-macro can diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el index 761d27a2e28..0b6fd277ae2 100644 --- a/lisp/emacs-lisp/package-x.el +++ b/lisp/emacs-lisp/package-x.el @@ -10,10 +10,10 @@ ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,9 +21,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. ;;; Commentary: diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index b01cdbc7b8e..28d166271fb 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -9,10 +9,10 @@ ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,9 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. ;;; Change Log: diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 09e47b69b91..1312fc3731d 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -517,6 +517,10 @@ MATCH is the pattern that needs to be matched, of the form: (defun pcase--self-quoting-p (upat) (or (keywordp upat) (numberp upat) (stringp upat))) +(defsubst pcase--mark-used (sym) + ;; Exceptionally, `sym' may be a constant expression rather than a symbol. + (if (symbolp sym) (put sym 'pcase-used t))) + ;; It's very tempting to use `pcase' below, tho obviously, it'd create ;; bootstrapping problems. (defun pcase--u1 (matches code vars rest) @@ -581,7 +585,7 @@ Otherwise, it defers to REST which is a list of branches of the form ((memq upat '(t _)) (pcase--u1 matches code vars rest)) ((eq upat 'pcase--dontcare) :pcase--dontcare) ((memq (car-safe upat) '(guard pred)) - (if (eq (car upat) 'pred) (put sym 'pcase-used t)) + (if (eq (car upat) 'pred) (pcase--mark-used sym)) (let* ((splitrest (pcase--split-rest sym (lambda (pat) (pcase--split-pred upat pat)) rest)) @@ -614,10 +618,10 @@ Otherwise, it defers to REST which is a list of branches of the form (pcase--u1 matches code vars then-rest) (pcase--u else-rest)))) ((pcase--self-quoting-p upat) - (put sym 'pcase-used t) + (pcase--mark-used sym) (pcase--q1 sym upat matches code vars rest)) ((symbolp upat) - (put sym 'pcase-used t) + (pcase--mark-used sym) (if (not (assq upat vars)) (pcase--u1 matches code (cons (cons upat sym) vars) rest) ;; Non-linear pattern. Turn it into an `eq' test. @@ -640,7 +644,7 @@ Otherwise, it defers to REST which is a list of branches of the form (pcase--u1 (cons `(match ,sym . ,(nth 1 upat)) matches) code vars rest))) ((eq (car-safe upat) '\`) - (put sym 'pcase-used t) + (pcase--mark-used sym) (pcase--q1 sym (cadr upat) matches code vars rest)) ((eq (car-safe upat) 'or) (let ((all (> (length (cdr upat)) 1)) @@ -662,7 +666,7 @@ Otherwise, it defers to REST which is a list of branches of the form sym (lambda (pat) (pcase--split-member elems pat)) rest)) (then-rest (car splitrest)) (else-rest (cdr splitrest))) - (put sym 'pcase-used t) + (pcase--mark-used sym) (pcase--if `(,(if memq-fine #'memq #'member) ,sym ',elems) (pcase--u1 matches code vars then-rest) (pcase--u else-rest))) diff --git a/lisp/emacs-lisp/shadow.el b/lisp/emacs-lisp/shadow.el index 286c4937b5b..bceec296ad8 100644 --- a/lisp/emacs-lisp/shadow.el +++ b/lisp/emacs-lisp/shadow.el @@ -158,8 +158,14 @@ See the documentation for `list-load-path-shadows' for further information." (eq 0 (call-process "cmp" nil nil nil "-s" f1 f2)))))))) (defvar load-path-shadows-font-lock-keywords + ;; The idea is that shadows of files supplied with Emacs are more + ;; serious than various versions of external packages shadowing each + ;; other. `((,(format "hides \\(%s.*\\)" - (file-name-directory (locate-library "simple.el"))) + (file-name-directory + (or (locate-library "simple") + (file-name-as-directory + (expand-file-name "../lisp" data-directory))))) . (1 font-lock-warning-face))) "Keywords to highlight in `load-path-shadows-mode'.") diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el index a56a7619ea9..8aa722521eb 100644 --- a/lisp/emacs-lisp/tabulated-list.el +++ b/lisp/emacs-lisp/tabulated-list.el @@ -7,10 +7,10 @@ ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el index 3999529f7ac..5fdc8c55a85 100644 --- a/lisp/emacs-lisp/testcover.el +++ b/lisp/emacs-lisp/testcover.el @@ -270,9 +270,9 @@ value, 'maybe if either is acceptable." (setq id (nth 2 form)) (setcdr form (nthcdr 2 form)) (setq val (testcover-reinstrument (nth 2 form))) - (if (eq val t) - (setcar form 'testcover-1value) - (setcar form 'testcover-after)) + (setcar form (if (eq val t) + 'testcover-1value + 'testcover-after)) (when val ;;1-valued or potentially 1-valued (aset testcover-vector id '1value)) @@ -359,9 +359,9 @@ value, 'maybe if either is acceptable." ,(nth 3 (cadr form)))) t) (t - (if (eq (car (cadr form)) 'edebug-after) - (setq id (car (nth 3 (cadr form)))) - (setq id (car (cadr form)))) + (setq id (car (if (eq (car (cadr form)) 'edebug-after) + (nth 3 (cadr form)) + (cadr form)))) (let ((testcover-1value-functions (cons id testcover-1value-functions))) (testcover-reinstrument (cadr form)))))) @@ -379,9 +379,9 @@ value, 'maybe if either is acceptable." ,(nth 3 (cadr form)))) 'maybe) (t - (if (eq (car (cadr form)) 'edebug-after) - (setq id (car (nth 3 (cadr form)))) - (setq id (car (cadr form)))) + (setq id (car (if (eq (car (cadr form)) 'edebug-after) + (nth 3 (cadr form)) + (cadr form)))) (let ((testcover-noreturn-functions (cons id testcover-noreturn-functions))) (testcover-reinstrument (cadr form)))))) @@ -447,6 +447,12 @@ binding `testcover-vector' to the code-coverage vector for TESTCOVER-SYM (defun testcover-after (idx val) "Internal function for coverage testing. Returns VAL after installing it in `testcover-vector' at offset IDX." + (declare (gv-expander (lambda (do) + (gv-letplace (getter setter) val + (funcall do getter + (lambda (store) + `(progn (testcover-after ,idx ,getter) + ,(funcall setter store)))))))) (cond ((eq (aref testcover-vector idx) 'unknown) (aset testcover-vector idx val)) diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el index 2248dde8c03..284c591fc61 100644 --- a/lisp/emacs-lisp/timer.el +++ b/lisp/emacs-lisp/timer.el @@ -146,14 +146,13 @@ TIME must be in the internal format returned by, e.g., `current-time'. The microsecond count from TIME is ignored, and USECS is used instead. If optional fourth argument DELTA is a positive number, make the timer fire repeatedly that many seconds apart." + (declare (obsolete "use `timer-set-time' and `timer-inc-time' instead." + "22.1")) (setf (timer--time timer) time) (setf (timer--usecs timer) usecs) (setf (timer--psecs timer) 0) (setf (timer--repeat-delay timer) (and (numberp delta) (> delta 0) delta)) timer) -(make-obsolete 'timer-set-time-with-usecs - "use `timer-set-time' and `timer-inc-time' instead." - "22.1") (defun timer-set-function (timer function &optional args) "Make TIMER call FUNCTION with optional ARGS when triggering." @@ -205,12 +204,19 @@ timers). If nil, allocate a new cell." "Insert TIMER into `timer-idle-list'. This arranges to activate TIMER whenever Emacs is next idle. If optional argument DONT-WAIT is non-nil, set TIMER to activate -immediately, or at the right time, if Emacs is already idle. +immediately \(see below\), or at the right time, if Emacs is +already idle. REUSE-CELL, if non-nil, is a cons cell to reuse when inserting TIMER into `timer-idle-list' (usually a cell removed from that list by `cancel-timer-internal'; using this reduces consing for -repeat timers). If nil, allocate a new cell." +repeat timers). If nil, allocate a new cell. + +Using non-nil DONT-WAIT is not recommended when activating an +idle timer from an idle timer handler, if the timer being +activated has an idleness time that is smaller or equal to +the time of the current timer. That's because the activated +timer will fire right away." (timer--activate timer (not dont-wait) reuse-cell 'idle)) (defalias 'disable-timeout 'cancel-timer) @@ -403,7 +409,9 @@ The action is to call FUNCTION with arguments ARGS. SECS may be an integer, a floating point number, or the internal time format returned by, e.g., `current-idle-time'. If Emacs is currently idle, and has been idle for N seconds (N < SECS), -then it will call FUNCTION in SECS - N seconds from now. +then it will call FUNCTION in SECS - N seconds from now. Using +SECS <= N is not recommended if this function is invoked from an idle +timer, because FUNCTION will then be called immediately. If REPEAT is non-nil, do the action each time Emacs has been idle for exactly SECS seconds (that is, only once for each time Emacs becomes idle). @@ -442,7 +450,7 @@ be detected. (with-timeout-timers (cons -with-timeout-timer- with-timeout-timers))) (unwind-protect - ,@body + (progn ,@body) (cancel-timer -with-timeout-timer-)))))) ;; It is tempting to avoid the `if' altogether and instead run ;; timeout-forms in the timer, just before throwing `timeout'. |
