diff options
| author | Joakim Verona | 2012-11-13 03:01:33 +0100 |
|---|---|---|
| committer | Joakim Verona | 2012-11-13 03:01:33 +0100 |
| commit | 74fa27af7f4b50a6f5e2a378802b4c5edc11d044 (patch) | |
| tree | 7030d55ecc2e06df59c08047b6f89e5b11a329dc /lisp | |
| parent | 2a4942ed0e4cca22145a0d973112454c410c3dd7 (diff) | |
| parent | b95a9c0cba301ef8f1920a1d123ccd6873c14a63 (diff) | |
| download | emacs-74fa27af7f4b50a6f5e2a378802b4c5edc11d044.tar.gz emacs-74fa27af7f4b50a6f5e2a378802b4c5edc11d044.zip | |
upstream
Diffstat (limited to 'lisp')
31 files changed, 1426 insertions, 883 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7c51b139ec3..f53b58b0129 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,228 @@ | |||
| 1 | 2012-11-12 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * emacs-lisp/nadvice.el: New package. | ||
| 4 | * subr.el (special-form-p): New function. | ||
| 5 | * emacs-lisp/elp.el: Use lexical-binding and advice-add. | ||
| 6 | (elp-all-instrumented-list): Remove var. | ||
| 7 | (elp-not-profilable): Remove elp-wrapper. | ||
| 8 | (elp-profilable-p): Use autoloadp and special-form-p. | ||
| 9 | (elp--advice-name): New const. | ||
| 10 | (elp-instrument-function): Use advice-add. | ||
| 11 | (elp--instrumented-p): New predicate. | ||
| 12 | (elp-restore-function): Use advice-remove. | ||
| 13 | (elp-restore-all, elp-reset-all): Use mapatoms. | ||
| 14 | (elp-set-master): Use elp--instrumented-p. | ||
| 15 | (elp--make-wrapper): Rename from elp-wrapper, return a function | ||
| 16 | suitable for advice-add. Use cl-inf. | ||
| 17 | (elp-results): Use mapatoms+elp--instrumented-p. | ||
| 18 | * emacs-lisp/debug.el: Use lexical-binding and advice-add. | ||
| 19 | (debug-function-list): Remove var. | ||
| 20 | (debug): Rename arg, and then let-bind it explicitly inside. | ||
| 21 | (debugger-setup-buffer): Rename arg. | ||
| 22 | (debugger-setup-buffer): Adjust counts to new debug-on-entry setup. | ||
| 23 | (debugger-frame-number): Adjust to new debug-on-entry setup. | ||
| 24 | (debug--implement-debug-on-entry): Rename from | ||
| 25 | implement-debug-on-entry, add argument. | ||
| 26 | (debugger-special-form-p): Remove, use special-form-p instead. | ||
| 27 | (debug-on-entry): Use advice-add. | ||
| 28 | (debug--function-list): New function. | ||
| 29 | (cancel-debug-on-entry): Use it, along with advice-remove. | ||
| 30 | (debug-arglist, debug-convert-byte-code, debug-on-entry-1): Remove. | ||
| 31 | (debugger-list-functions): Use debug--function-list instead of | ||
| 32 | debug-function-list. | ||
| 33 | * emacs-lisp/advice.el (ad-save-real-definition): Remove, unused. | ||
| 34 | (ad-special-form-p): Remove, use special-form-p instead. | ||
| 35 | (ad-set-advice-info): Use add-function and remove-function. | ||
| 36 | (ad--defalias-fset): Adjust accordingly. | ||
| 37 | |||
| 38 | 2012-11-10 Glenn Morris <rgm@gnu.org> | ||
| 39 | |||
| 40 | * mail/emacsbug.el (report-emacs-bug-tracker-url) | ||
| 41 | (report-emacs-bug-bug-alist, report-emacs-bug-choice-widget) | ||
| 42 | (report-emacs-bug-create-existing-bugs-buffer) | ||
| 43 | (report-emacs-bug-parse-query-results) | ||
| 44 | (report-emacs-bug-query-existing-bugs): Remove. (Bug#7449) | ||
| 45 | |||
| 46 | * term.el (term-default-fg-color, term-default-bg-color): | ||
| 47 | Make obsolete, rather than just saying "deprecated" in the doc. | ||
| 48 | |||
| 49 | * term.el (term): Rename from `term-face'. | ||
| 50 | (term-current-face, ansi-term-color-vector) | ||
| 51 | (term-default-fg-color, term-default-bg-color, term-ansi-reset): | ||
| 52 | Update all users. | ||
| 53 | |||
| 54 | 2012-11-10 Jan Djärv <jan.h.d@swipnet.se> | ||
| 55 | |||
| 56 | * server.el (server-create-window-system-frame): Handle Nextstep | ||
| 57 | specially (Bug#12780). | ||
| 58 | |||
| 59 | 2012-11-10 Glenn Morris <rgm@gnu.org> | ||
| 60 | |||
| 61 | * mail/emacsbug.el (report-emacs-bug-query-existing-bugs): | ||
| 62 | Unautoload, and make obsolete. (Bug#7449) | ||
| 63 | |||
| 64 | 2012-11-10 Chong Yidong <cyd@gnu.org> | ||
| 65 | |||
| 66 | * vc/diff-mode.el (diff-delete-trailing-whitespace): Rewrite, and | ||
| 67 | rename from diff-remove-trailing-whitespace (Bug#12831). | ||
| 68 | |||
| 69 | 2012-11-10 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 70 | |||
| 71 | * emacs-lisp/advice.el: Require `cl-lib' at run-time to fix | ||
| 72 | miscompilation of trace.el. | ||
| 73 | |||
| 74 | 2012-11-10 Glenn Morris <rgm@gnu.org> | ||
| 75 | |||
| 76 | * vc/diff-mode.el (diff-remove-trailing-whitespace): Doc fix. | ||
| 77 | |||
| 78 | 2012-11-10 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 79 | |||
| 80 | * emacs-lisp/gv.el (gv-define-simple-setter): Fix last change | ||
| 81 | (bug#12812). | ||
| 82 | |||
| 83 | 2012-11-10 Chong Yidong <cyd@gnu.org> | ||
| 84 | |||
| 85 | * minibuf-eldef.el (minibuffer-eldef-shorten-default): Convert to | ||
| 86 | a defcustom with an appropriate :set function. | ||
| 87 | (minibuffer-default--in-prompt-regexps): New function. | ||
| 88 | |||
| 89 | 2012-11-10 Glenn Morris <rgm@gnu.org> | ||
| 90 | |||
| 91 | * emacs-lisp/cl.el (define-setf-expander, defsetf) | ||
| 92 | (define-modify-macro): Doc fixes. | ||
| 93 | |||
| 94 | * emacs-lisp/gv.el (gv-letplace): Fix doc typo. | ||
| 95 | (gv-define-simple-setter): Update doc of `fix-return'. | ||
| 96 | |||
| 97 | 2012-11-10 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 98 | |||
| 99 | * emacs-lisp/gv.el (gv-define-simple-setter): Don't evaluate `val' | ||
| 100 | twice when `fix-return' is set (bug#12813). | ||
| 101 | |||
| 102 | * emacs-lisp/cl.el (defsetf): Pass the third arg to | ||
| 103 | gv-define-simple-setter (bug#12812). | ||
| 104 | |||
| 105 | * woman.el (woman-decode-region): Disable adaptive-fill when rendering | ||
| 106 | (bug#12756). | ||
| 107 | |||
| 108 | 2012-11-10 Glenn Morris <rgm@gnu.org> | ||
| 109 | |||
| 110 | * emacs-lisp/gv.el (gv-define-setter): Fix doc typo. | ||
| 111 | |||
| 112 | * emacs-lisp/cl-extra.el (cl-prettyexpand): | ||
| 113 | * emacs-lisp/cl-lib.el (cl-proclaim, cl-declaim): | ||
| 114 | * emacs-lisp/cl-macs.el (cl-destructuring-bind, cl-locally) | ||
| 115 | (cl-the, cl-compiler-macroexpand): Add basic doc strings. | ||
| 116 | |||
| 117 | * emacs-lisp/cl-extra.el (cl-maplist, cl-mapcan): Doc fix. | ||
| 118 | |||
| 119 | 2012-11-10 Leo Liu <sdl.web@gmail.com> | ||
| 120 | |||
| 121 | * ido.el (ido-set-matches-1): Improve flex matching performance by | ||
| 122 | removing backtracking in the regexp (suggested by Stefan). (Bug#12796) | ||
| 123 | |||
| 124 | 2012-11-09 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 125 | |||
| 126 | * emacs-lisp/advice.el (ad-set-advice-info): Set defalias-fset-function. | ||
| 127 | (ad--defalias-fset): New function. | ||
| 128 | (ad-safe-fset): Remove. | ||
| 129 | (ad-make-freeze-definition): Use cl-letf*. | ||
| 130 | |||
| 131 | 2012-11-09 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 132 | |||
| 133 | * subr.el (dolist): Don't bind VAR in RESULT. | ||
| 134 | |||
| 135 | * emacs-lisp/advice.el: Miscellaneous cleanup. Use lexical-binding. | ||
| 136 | (fset, documentation): Don't save real def since we don't advise. | ||
| 137 | (ad-do-advised-functions): Remove problematic `result-form'. | ||
| 138 | (ad-safe-fset): `ad-real-fset' => `fset'. | ||
| 139 | (ad-read-advised-function): Don't assume that ad-do-advised-functions | ||
| 140 | uses CL's dolist internally. | ||
| 141 | (ad-arglist): Remove unused arg `name'. | ||
| 142 | (ad-docstring, ad-make-advised-docstring): | ||
| 143 | `ad-real-documentation' => `documentation'. | ||
| 144 | (warning-suppress-types): Declare. | ||
| 145 | (ad-set-arguments): Simple CSE. | ||
| 146 | (ad-recover-normality): Sanity check. | ||
| 147 | |||
| 148 | * emacs-lisp/bytecomp.el (byte-compile-out-toplevel): Don't turn | ||
| 149 | (funcall '(lambda ..) ..) into ((lambda ..) ..). | ||
| 150 | |||
| 151 | 2012-11-09 Vincent Belaïche <vincentb1@users.sourceforge.net> | ||
| 152 | |||
| 153 | * ses.el: symbol to coordinate mapping is made by symbol property | ||
| 154 | `ses-cell'. This means that the same mapping is done for all SES | ||
| 155 | sheets. That is good enough for cells with standard A1 names, but | ||
| 156 | not for named cell. So a hash map is added for the latter. | ||
| 157 | (defconst ses-localvars): Add local variable ses--named-cell-hashmap | ||
| 158 | (ses-sym-rowcol): Use hashmap for named cell. | ||
| 159 | (ses-is-cell-sym-p): New defun. | ||
| 160 | (ses-decode-cell-symbol): New defun. | ||
| 161 | (ses-create-cell-variable): Add cell to hashmap when name is not | ||
| 162 | A1-like. | ||
| 163 | (ses-rename-cell): Check that cell new name is not already in | ||
| 164 | spreadsheet with the use of ses-is-cell-sym-p | ||
| 165 | (ses-rename-cell): Use hash map for named cells, but accept also | ||
| 166 | renaming back to A1-like. | ||
| 167 | |||
| 168 | 2012-11-09 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 169 | |||
| 170 | * emacs-lisp/advice.el: Use new dynamic docstrings. | ||
| 171 | (ad-make-advised-definition-docstring, ad-advised-definition-p): | ||
| 172 | Use dynamic-docstring-function instead of ad-advice-info. | ||
| 173 | (ad--make-advised-docstring): New function extracted from | ||
| 174 | ad-make-advised-docstring. | ||
| 175 | (ad-make-advised-docstring): Use it. | ||
| 176 | * progmodes/sql.el (sql--make-help-docstring): New function, extracted | ||
| 177 | from sql-help. | ||
| 178 | (sql-help): Use it with dynamic-docstring-function. | ||
| 179 | |||
| 180 | * env.el (env--substitute-vars-regexp): Don't use rx (for bootstrap). | ||
| 181 | |||
| 182 | 2012-11-08 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 183 | |||
| 184 | * files.el (hack-one-local-variable--obsolete): New function. | ||
| 185 | (hack-one-local-variable): Use it for obsolete settings. | ||
| 186 | |||
| 187 | * subr.el (locate-user-emacs-file): If both old and new name exist, use | ||
| 188 | the new name. | ||
| 189 | |||
| 190 | * progmodes/js.el (js--filling-paragraph): New var. | ||
| 191 | (c-forward-sws, c-backward-sws, c-beginning-of-macro): Advise. | ||
| 192 | (js-c-fill-paragraph): Prefer advice to cl-letf so the rebinding is | ||
| 193 | less sneaky. | ||
| 194 | |||
| 195 | 2012-11-08 Julien Danjou <julien@danjou.info> | ||
| 196 | |||
| 197 | * progmodes/ruby-mode.el (auto-mode-alist): Add Rakefile in | ||
| 198 | `auto-mode-alist' (Bug#12835). | ||
| 199 | |||
| 200 | 2012-11-08 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 201 | |||
| 202 | * progmodes/perl-mode.el (perl-prettify-symbols): New defcustom. | ||
| 203 | (perl--prettify-symbols-alist): New const. | ||
| 204 | (perl--font-lock-compose-symbol, perl--font-lock-symbols-keywords): | ||
| 205 | New functions. | ||
| 206 | (perl-font-lock-keywords-2): Use them. | ||
| 207 | (perl-electric-noindent-p): New function. | ||
| 208 | (perl-mode): Use it to set up electric-indent-mode. | ||
| 209 | (perl-electric-terminator, perl-indent-command): Mark obsolete. | ||
| 210 | (perl-mode-map): Remove bindings for them. | ||
| 211 | (perl-imenu-generic-expression, perl-outline-level): | ||
| 212 | Match functions&packages in column>0. | ||
| 213 | |||
| 214 | * env.el (env--substitute-vars-regexp): New const. | ||
| 215 | (substitute-env-vars): Use it. Add `only-defined' arg. | ||
| 216 | * net/tramp.el (tramp-replace-environment-variables): Use it. | ||
| 217 | |||
| 218 | * emacs-lisp/bytecomp.el (byte-compile-initial-macro-environment): | ||
| 219 | Byte-compile *before* eval in eval-and-compile. | ||
| 220 | (byte-compile-log-warning): Remove redundant inhibit-read-only. | ||
| 221 | (byte-compile-file-form-autoload): Don't hide actual definition. | ||
| 222 | (byte-compile-maybe-guarded): Accept `functionp' as well. | ||
| 223 | |||
| 224 | * emacs-lisp/gv.el (gv-ref, gv-deref): New function and macro. | ||
| 225 | |||
| 1 | 2012-11-07 Michael Albinus <michael.albinus@gmx.de> | 226 | 2012-11-07 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 227 | ||
| 3 | * notifications.el (notifications-get-server-information-method): | 228 | * notifications.el (notifications-get-server-information-method): |
| @@ -45,8 +270,8 @@ | |||
| 45 | 270 | ||
| 46 | 2012-11-05 Agustín Martín Domingo <agustin.martin@hispalinux.es> | 271 | 2012-11-05 Agustín Martín Domingo <agustin.martin@hispalinux.es> |
| 47 | 272 | ||
| 48 | * textmodes/ispell.el (ispell-program-name): Update | 273 | * textmodes/ispell.el (ispell-program-name): |
| 49 | spellchecker parameters when customized. | 274 | Update spellchecker parameters when customized. |
| 50 | 275 | ||
| 51 | 2012-11-04 Glenn Morris <rgm@gnu.org> | 276 | 2012-11-04 Glenn Morris <rgm@gnu.org> |
| 52 | 277 | ||
| @@ -440,7 +665,7 @@ | |||
| 440 | 2012-10-19 Stefan Monnier <monnier@iro.umontreal.ca> | 665 | 2012-10-19 Stefan Monnier <monnier@iro.umontreal.ca> |
| 441 | 666 | ||
| 442 | * minibuffer.el (minibuffer-force-complete): Make the next completion use | 667 | * minibuffer.el (minibuffer-force-complete): Make the next completion use |
| 443 | the same completion-field (bug@12221). | 668 | the same completion-field (bug#12221). |
| 444 | 669 | ||
| 445 | 2012-10-19 Martin Rudalics <rudalics@gmx.at> | 670 | 2012-10-19 Martin Rudalics <rudalics@gmx.at> |
| 446 | 671 | ||
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el index bd85238e23e..16c12aad29b 100644 --- a/lisp/emacs-lisp/advice.el +++ b/lisp/emacs-lisp/advice.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; advice.el --- An overloading mechanism for Emacs Lisp functions | 1 | ;;; advice.el --- An overloading mechanism for Emacs Lisp functions -*- lexical-binding: t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1993-1994, 2000-2012 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1993-1994, 2000-2012 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -1709,7 +1709,8 @@ | |||
| 1709 | ;; During a normal load this is a noop: | 1709 | ;; During a normal load this is a noop: |
| 1710 | (require 'advice-preload "advice.el") | 1710 | (require 'advice-preload "advice.el") |
| 1711 | (require 'macroexp) | 1711 | (require 'macroexp) |
| 1712 | (eval-when-compile (require 'cl-lib)) | 1712 | ;; At run-time also, since ad-do-advised-functions returns code that uses it. |
| 1713 | (require 'cl-lib) | ||
| 1713 | 1714 | ||
| 1714 | ;; @@ Variable definitions: | 1715 | ;; @@ Variable definitions: |
| 1715 | ;; ======================== | 1716 | ;; ======================== |
| @@ -1775,36 +1776,6 @@ generates a copy of TREE." | |||
| 1775 | (funcall fUnCtIoN tReE)) | 1776 | (funcall fUnCtIoN tReE)) |
| 1776 | (t tReE))) | 1777 | (t tReE))) |
| 1777 | 1778 | ||
| 1778 | ;; @@ Save real definitions of subrs used by Advice: | ||
| 1779 | ;; ================================================= | ||
| 1780 | ;; Advice depends on the real, unmodified functionality of various subrs, | ||
| 1781 | ;; we save them here so advised versions will not interfere (eventually, | ||
| 1782 | ;; we will save all subrs used in code generated by Advice): | ||
| 1783 | |||
| 1784 | (defmacro ad-save-real-definition (function) | ||
| 1785 | (let ((saved-function (intern (format "ad-real-%s" function)))) | ||
| 1786 | ;; Make sure the compiler is loaded during macro expansion: | ||
| 1787 | (require 'byte-compile "bytecomp") | ||
| 1788 | `(if (not (fboundp ',saved-function)) | ||
| 1789 | (progn (fset ',saved-function (symbol-function ',function)) | ||
| 1790 | ;; Copy byte-compiler properties: | ||
| 1791 | ,@(if (get function 'byte-compile) | ||
| 1792 | `((put ',saved-function 'byte-compile | ||
| 1793 | ',(get function 'byte-compile)))) | ||
| 1794 | ,@(if (get function 'byte-opcode) | ||
| 1795 | `((put ',saved-function 'byte-opcode | ||
| 1796 | ',(get function 'byte-opcode)))))))) | ||
| 1797 | |||
| 1798 | (defun ad-save-real-definitions () | ||
| 1799 | ;; Macro expansion will hardcode the values of the various byte-compiler | ||
| 1800 | ;; properties into the compiled version of this function such that the | ||
| 1801 | ;; proper values will be available at runtime without loading the compiler: | ||
| 1802 | (ad-save-real-definition fset) | ||
| 1803 | (ad-save-real-definition documentation)) | ||
| 1804 | |||
| 1805 | (ad-save-real-definitions) | ||
| 1806 | |||
| 1807 | |||
| 1808 | ;; @@ Advice info access fns: | 1779 | ;; @@ Advice info access fns: |
| 1809 | ;; ========================== | 1780 | ;; ========================== |
| 1810 | 1781 | ||
| @@ -1839,15 +1810,13 @@ generates a copy of TREE." | |||
| 1839 | ad-advised-functions))) | 1810 | ad-advised-functions))) |
| 1840 | 1811 | ||
| 1841 | (defmacro ad-do-advised-functions (varform &rest body) | 1812 | (defmacro ad-do-advised-functions (varform &rest body) |
| 1842 | "`dolist'-style iterator that maps over `ad-advised-functions'. | 1813 | "`dolist'-style iterator that maps over advised functions. |
| 1843 | \(ad-do-advised-functions (VAR [RESULT-FORM]) | 1814 | \(ad-do-advised-functions (VAR) |
| 1844 | BODY-FORM...) | 1815 | BODY-FORM...) |
| 1845 | On each iteration VAR will be bound to the name of an advised function | 1816 | On each iteration VAR will be bound to the name of an advised function |
| 1846 | \(a symbol)." | 1817 | \(a symbol)." |
| 1847 | (declare (indent 1)) | 1818 | (declare (indent 1)) |
| 1848 | `(cl-dolist (,(car varform) | 1819 | `(cl-dolist (,(car varform) ad-advised-functions) |
| 1849 | ad-advised-functions | ||
| 1850 | ,(car (cdr varform))) | ||
| 1851 | (setq ,(car varform) (intern (car ,(car varform)))) | 1820 | (setq ,(car varform) (intern (car ,(car varform)))) |
| 1852 | ,@body)) | 1821 | ,@body)) |
| 1853 | 1822 | ||
| @@ -1857,8 +1826,15 @@ On each iteration VAR will be bound to the name of an advised function | |||
| 1857 | (defmacro ad-get-advice-info-macro (function) | 1826 | (defmacro ad-get-advice-info-macro (function) |
| 1858 | `(get ,function 'ad-advice-info)) | 1827 | `(get ,function 'ad-advice-info)) |
| 1859 | 1828 | ||
| 1860 | (defmacro ad-set-advice-info (function advice-info) | 1829 | (defsubst ad-set-advice-info (function advice-info) |
| 1861 | `(put ,function 'ad-advice-info ,advice-info)) | 1830 | (cond |
| 1831 | (advice-info | ||
| 1832 | (add-function :around (get function 'defalias-fset-function) | ||
| 1833 | #'ad--defalias-fset)) | ||
| 1834 | ((get function 'defalias-fset-function) | ||
| 1835 | (remove-function (get function 'defalias-fset-function) | ||
| 1836 | #'ad--defalias-fset))) | ||
| 1837 | (put function 'ad-advice-info advice-info)) | ||
| 1862 | 1838 | ||
| 1863 | (defmacro ad-copy-advice-info (function) | 1839 | (defmacro ad-copy-advice-info (function) |
| 1864 | `(copy-tree (get ,function 'ad-advice-info))) | 1840 | `(copy-tree (get ,function 'ad-advice-info))) |
| @@ -1866,7 +1842,7 @@ On each iteration VAR will be bound to the name of an advised function | |||
| 1866 | (defmacro ad-is-advised (function) | 1842 | (defmacro ad-is-advised (function) |
| 1867 | "Return non-nil if FUNCTION has any advice info associated with it. | 1843 | "Return non-nil if FUNCTION has any advice info associated with it. |
| 1868 | This does not mean that the advice is also active." | 1844 | This does not mean that the advice is also active." |
| 1869 | (list 'ad-get-advice-info-macro function)) | 1845 | `(ad-get-advice-info-macro ,function)) |
| 1870 | 1846 | ||
| 1871 | (defun ad-initialize-advice-info (function) | 1847 | (defun ad-initialize-advice-info (function) |
| 1872 | "Initialize the advice info for FUNCTION. | 1848 | "Initialize the advice info for FUNCTION. |
| @@ -1949,7 +1925,7 @@ Redefining advices affect the construction of an advised definition." | |||
| 1949 | (defun ad-has-any-advice (function) | 1925 | (defun ad-has-any-advice (function) |
| 1950 | "True if the advice info of FUNCTION defines at least one advice." | 1926 | "True if the advice info of FUNCTION defines at least one advice." |
| 1951 | (and (ad-is-advised function) | 1927 | (and (ad-is-advised function) |
| 1952 | (cl-dolist (class ad-advice-classes nil) | 1928 | (cl-dolist (class ad-advice-classes) |
| 1953 | (if (ad-get-advice-info-field function class) | 1929 | (if (ad-get-advice-info-field function class) |
| 1954 | (cl-return t))))) | 1930 | (cl-return t))))) |
| 1955 | 1931 | ||
| @@ -1965,18 +1941,10 @@ Redefining advices affect the construction of an advised definition." | |||
| 1965 | ;; @@ Dealing with automatic advice activation via `fset/defalias': | 1941 | ;; @@ Dealing with automatic advice activation via `fset/defalias': |
| 1966 | ;; ================================================================ | 1942 | ;; ================================================================ |
| 1967 | 1943 | ||
| 1968 | ;; Since Emacs 19.26 the built-in versions of `fset' and `defalias' | 1944 | ;; Automatic activation happens when a function gets defined via `defalias', |
| 1969 | ;; take care of automatic advice activation, hence, we don't have to | 1945 | ;; which calls the `defalias-fset-function' (which we set to |
| 1970 | ;; hack it anymore by advising `fset/defun/defmacro/byte-code/etc'. | 1946 | ;; `ad--defalias-fset') instead of `fset', if non-nil. |
| 1971 | 1947 | ||
| 1972 | ;; The functionality of the new `fset' is as follows: | ||
| 1973 | ;; | ||
| 1974 | ;; fset(sym,newdef) | ||
| 1975 | ;; assign NEWDEF to SYM | ||
| 1976 | ;; if (get SYM 'ad-advice-info) | ||
| 1977 | ;; ad-activate-internal(SYM, nil) | ||
| 1978 | ;; return (symbol-function SYM) | ||
| 1979 | ;; | ||
| 1980 | ;; Whether advised definitions created by automatic activations will be | 1948 | ;; Whether advised definitions created by automatic activations will be |
| 1981 | ;; compiled depends on the value of `ad-default-compilation-action'. | 1949 | ;; compiled depends on the value of `ad-default-compilation-action'. |
| 1982 | 1950 | ||
| @@ -1988,13 +1956,17 @@ Redefining advices affect the construction of an advised definition." | |||
| 1988 | ;; to `ad-activate' by using `ad-with-auto-activation-disabled' where | 1956 | ;; to `ad-activate' by using `ad-with-auto-activation-disabled' where |
| 1989 | ;; appropriate, especially in a safe version of `fset'. | 1957 | ;; appropriate, especially in a safe version of `fset'. |
| 1990 | 1958 | ||
| 1959 | (defun ad--defalias-fset (fsetfun function definition) | ||
| 1960 | (funcall (or fsetfun #'fset) function definition) | ||
| 1961 | (ad-activate-internal function nil)) | ||
| 1962 | |||
| 1991 | ;; For now define `ad-activate-internal' to the dummy definition: | 1963 | ;; For now define `ad-activate-internal' to the dummy definition: |
| 1992 | (defun ad-activate-internal (function &optional compile) | 1964 | (defun ad-activate-internal (_function &optional _compile) |
| 1993 | "Automatic advice activation is disabled. `ad-start-advice' enables it." | 1965 | "Automatic advice activation is disabled. `ad-start-advice' enables it." |
| 1994 | nil) | 1966 | nil) |
| 1995 | 1967 | ||
| 1996 | ;; This is just a copy of the above: | 1968 | ;; This is just a copy of the above: |
| 1997 | (defun ad-activate-internal-off (function &optional compile) | 1969 | (defun ad-activate-internal-off (_function &optional _compile) |
| 1998 | "Automatic advice activation is disabled. `ad-start-advice' enables it." | 1970 | "Automatic advice activation is disabled. `ad-start-advice' enables it." |
| 1999 | nil) | 1971 | nil) |
| 2000 | 1972 | ||
| @@ -2005,12 +1977,6 @@ Redefining advices affect the construction of an advised definition." | |||
| 2005 | `(let ((ad-activate-on-top-level nil)) | 1977 | `(let ((ad-activate-on-top-level nil)) |
| 2006 | ,@body)) | 1978 | ,@body)) |
| 2007 | 1979 | ||
| 2008 | (defun ad-safe-fset (symbol definition) | ||
| 2009 | "A safe `fset' which will never call `ad-activate-internal' recursively." | ||
| 2010 | (ad-with-auto-activation-disabled | ||
| 2011 | (ad-real-fset symbol definition))) | ||
| 2012 | |||
| 2013 | |||
| 2014 | ;; @@ Access functions for original definitions: | 1980 | ;; @@ Access functions for original definitions: |
| 2015 | ;; ============================================ | 1981 | ;; ============================================ |
| 2016 | ;; The advice-info of an advised function contains its `origname' which is | 1982 | ;; The advice-info of an advised function contains its `origname' which is |
| @@ -2030,8 +1996,7 @@ Redefining advices affect the construction of an advised definition." | |||
| 2030 | (symbol-function origname)))) | 1996 | (symbol-function origname)))) |
| 2031 | 1997 | ||
| 2032 | (defmacro ad-set-orig-definition (function definition) | 1998 | (defmacro ad-set-orig-definition (function definition) |
| 2033 | `(ad-safe-fset | 1999 | `(fset (ad-get-advice-info-field ,function 'origname) ,definition)) |
| 2034 | (ad-get-advice-info-field ,function 'origname) ,definition)) | ||
| 2035 | 2000 | ||
| 2036 | (defmacro ad-clear-orig-definition (function) | 2001 | (defmacro ad-clear-orig-definition (function) |
| 2037 | `(fmakunbound (ad-get-advice-info-field ,function 'origname))) | 2002 | `(fmakunbound (ad-get-advice-info-field ,function 'origname))) |
| @@ -2052,7 +2017,7 @@ function at point for which PREDICATE returns non-nil)." | |||
| 2052 | (error "ad-read-advised-function: There are no advised functions")) | 2017 | (error "ad-read-advised-function: There are no advised functions")) |
| 2053 | (setq default | 2018 | (setq default |
| 2054 | (or default | 2019 | (or default |
| 2055 | ;; Prefer func name at point, if it's in ad-advised-functions etc. | 2020 | ;; Prefer func name at point, if it's an advised function etc. |
| 2056 | (let ((function (progn | 2021 | (let ((function (progn |
| 2057 | (require 'help) | 2022 | (require 'help) |
| 2058 | (function-called-at-point)))) | 2023 | (function-called-at-point)))) |
| @@ -2061,24 +2026,20 @@ function at point for which PREDICATE returns non-nil)." | |||
| 2061 | (or (null predicate) | 2026 | (or (null predicate) |
| 2062 | (funcall predicate function)) | 2027 | (funcall predicate function)) |
| 2063 | function)) | 2028 | function)) |
| 2064 | (ad-do-advised-functions (function) | 2029 | (cl-block nil |
| 2065 | (if (or (null predicate) | 2030 | (ad-do-advised-functions (function) |
| 2066 | (funcall predicate function)) | 2031 | (if (or (null predicate) |
| 2067 | (cl-return function))) | 2032 | (funcall predicate function)) |
| 2033 | (cl-return function)))) | ||
| 2068 | (error "ad-read-advised-function: %s" | 2034 | (error "ad-read-advised-function: %s" |
| 2069 | "There are no qualifying advised functions"))) | 2035 | "There are no qualifying advised functions"))) |
| 2070 | (let* ((ad-pReDiCaTe predicate) | 2036 | (let* ((function |
| 2071 | (function | ||
| 2072 | (completing-read | 2037 | (completing-read |
| 2073 | (format "%s (default %s): " (or prompt "Function") default) | 2038 | (format "%s (default %s): " (or prompt "Function") default) |
| 2074 | ad-advised-functions | 2039 | ad-advised-functions |
| 2075 | (if predicate | 2040 | (if predicate |
| 2076 | (function | 2041 | (lambda (function) |
| 2077 | (lambda (function) | 2042 | (funcall predicate (intern (car function))))) |
| 2078 | ;; Oops, no closures - the joys of dynamic scoping: | ||
| 2079 | ;; `predicate' clashed with the `predicate' argument | ||
| 2080 | ;; of `completing-read'..... | ||
| 2081 | (funcall ad-pReDiCaTe (intern (car function)))))) | ||
| 2082 | t))) | 2043 | t))) |
| 2083 | (if (equal function "") | 2044 | (if (equal function "") |
| 2084 | (if (ad-is-advised default) | 2045 | (if (ad-is-advised default) |
| @@ -2331,12 +2292,6 @@ See Info node `(elisp)Computed Advice' for detailed documentation." | |||
| 2331 | "Take a macro function DEFINITION and make a lambda out of it." | 2292 | "Take a macro function DEFINITION and make a lambda out of it." |
| 2332 | `(cdr ,definition)) | 2293 | `(cdr ,definition)) |
| 2333 | 2294 | ||
| 2334 | (defun ad-special-form-p (definition) | ||
| 2335 | "Non-nil if and only if DEFINITION is a special form." | ||
| 2336 | (if (and (symbolp definition) (fboundp definition)) | ||
| 2337 | (setq definition (indirect-function definition))) | ||
| 2338 | (and (subrp definition) (eq (cdr (subr-arity definition)) 'unevalled))) | ||
| 2339 | |||
| 2340 | (defmacro ad-subr-p (definition) | 2295 | (defmacro ad-subr-p (definition) |
| 2341 | ;;"non-nil if DEFINITION is a subr." | 2296 | ;;"non-nil if DEFINITION is a subr." |
| 2342 | (list 'subrp definition)) | 2297 | (list 'subrp definition)) |
| @@ -2376,10 +2331,8 @@ See Info node `(elisp)Computed Advice' for detailed documentation." | |||
| 2376 | (cdr definition)) | 2331 | (cdr definition)) |
| 2377 | (t nil))) | 2332 | (t nil))) |
| 2378 | 2333 | ||
| 2379 | (defun ad-arglist (definition &optional name) | 2334 | (defun ad-arglist (definition) |
| 2380 | "Return the argument list of DEFINITION. | 2335 | "Return the argument list of DEFINITION." |
| 2381 | If DEFINITION could be from a subr then its NAME should be | ||
| 2382 | supplied to make subr arglist lookup more efficient." | ||
| 2383 | (require 'help-fns) | 2336 | (require 'help-fns) |
| 2384 | (help-function-arglist | 2337 | (help-function-arglist |
| 2385 | (if (or (ad-macro-p definition) (ad-advice-p definition)) | 2338 | (if (or (ad-macro-p definition) (ad-advice-p definition)) |
| @@ -2391,7 +2344,7 @@ supplied to make subr arglist lookup more efficient." | |||
| 2391 | "Return the unexpanded docstring of DEFINITION." | 2344 | "Return the unexpanded docstring of DEFINITION." |
| 2392 | (let ((docstring | 2345 | (let ((docstring |
| 2393 | (if (ad-compiled-p definition) | 2346 | (if (ad-compiled-p definition) |
| 2394 | (ad-real-documentation definition t) | 2347 | (documentation definition t) |
| 2395 | (car (cdr (cdr (ad-lambda-expression definition))))))) | 2348 | (car (cdr (cdr (ad-lambda-expression definition))))))) |
| 2396 | (if (or (stringp docstring) | 2349 | (if (or (stringp docstring) |
| 2397 | (natnump docstring)) | 2350 | (natnump docstring)) |
| @@ -2414,13 +2367,15 @@ Like `interactive-form', but also works on pieces of advice." | |||
| 2414 | (if (ad-interactive-form definition) 1 0)) | 2367 | (if (ad-interactive-form definition) 1 0)) |
| 2415 | (cdr (cdr (ad-lambda-expression definition))))))) | 2368 | (cdr (cdr (ad-lambda-expression definition))))))) |
| 2416 | 2369 | ||
| 2417 | (defun ad-make-advised-definition-docstring (function) | 2370 | (defun ad-make-advised-definition-docstring (_function) |
| 2418 | "Make an identifying docstring for the advised definition of FUNCTION. | 2371 | "Make an identifying docstring for the advised definition of FUNCTION. |
| 2419 | Put function name into the documentation string so we can infer | 2372 | Put function name into the documentation string so we can infer |
| 2420 | the name of the advised function from the docstring. This is needed | 2373 | the name of the advised function from the docstring. This is needed |
| 2421 | to generate a proper advised docstring even if we are just given a | 2374 | to generate a proper advised docstring even if we are just given a |
| 2422 | definition (see the code for `documentation')." | 2375 | definition (see the code for `documentation')." |
| 2423 | (propertize "Advice doc string" 'ad-advice-info function)) | 2376 | (eval-when-compile |
| 2377 | (propertize "Advice doc string" 'dynamic-docstring-function | ||
| 2378 | #'ad--make-advised-docstring))) | ||
| 2424 | 2379 | ||
| 2425 | (defun ad-advised-definition-p (definition) | 2380 | (defun ad-advised-definition-p (definition) |
| 2426 | "Return non-nil if DEFINITION was generated from advice information." | 2381 | "Return non-nil if DEFINITION was generated from advice information." |
| @@ -2429,14 +2384,14 @@ definition (see the code for `documentation')." | |||
| 2429 | (ad-compiled-p definition)) | 2384 | (ad-compiled-p definition)) |
| 2430 | (let ((docstring (ad-docstring definition))) | 2385 | (let ((docstring (ad-docstring definition))) |
| 2431 | (and (stringp docstring) | 2386 | (and (stringp docstring) |
| 2432 | (get-text-property 0 'ad-advice-info docstring))))) | 2387 | (get-text-property 0 'dynamic-docstring-function docstring))))) |
| 2433 | 2388 | ||
| 2434 | (defun ad-definition-type (definition) | 2389 | (defun ad-definition-type (definition) |
| 2435 | "Return symbol that describes the type of DEFINITION." | 2390 | "Return symbol that describes the type of DEFINITION." |
| 2436 | (cond | 2391 | (cond |
| 2437 | ((ad-macro-p definition) 'macro) | 2392 | ((ad-macro-p definition) 'macro) |
| 2438 | ((ad-subr-p definition) | 2393 | ((ad-subr-p definition) |
| 2439 | (if (ad-special-form-p definition) | 2394 | (if (special-form-p definition) |
| 2440 | 'special-form | 2395 | 'special-form |
| 2441 | 'subr)) | 2396 | 'subr)) |
| 2442 | ((or (ad-lambda-p definition) | 2397 | ((or (ad-lambda-p definition) |
| @@ -2473,6 +2428,7 @@ For that it has to be fbound with a non-autoload definition." | |||
| 2473 | (ad-macro-p (symbol-function function))) | 2428 | (ad-macro-p (symbol-function function))) |
| 2474 | (not (ad-compiled-p (symbol-function function))))) | 2429 | (not (ad-compiled-p (symbol-function function))))) |
| 2475 | 2430 | ||
| 2431 | (defvar warning-suppress-types) ;From warnings.el. | ||
| 2476 | (defun ad-compile-function (function) | 2432 | (defun ad-compile-function (function) |
| 2477 | "Byte-compiles FUNCTION (or macro) if it is not yet compiled." | 2433 | "Byte-compiles FUNCTION (or macro) if it is not yet compiled." |
| 2478 | (interactive "aByte-compile function: ") | 2434 | (interactive "aByte-compile function: ") |
| @@ -2603,24 +2559,20 @@ The assignment starts at position INDEX." | |||
| 2603 | (let ((values-index 0) | 2559 | (let ((values-index 0) |
| 2604 | argument-access set-forms) | 2560 | argument-access set-forms) |
| 2605 | (while (setq argument-access (ad-access-argument arglist index)) | 2561 | (while (setq argument-access (ad-access-argument arglist index)) |
| 2606 | (if (symbolp argument-access) | 2562 | (push (if (symbolp argument-access) |
| 2607 | (setq set-forms | 2563 | (ad-set-argument |
| 2608 | (cons (ad-set-argument | 2564 | arglist index |
| 2609 | arglist index | 2565 | (ad-element-access values-index 'ad-vAlUeS)) |
| 2610 | (ad-element-access values-index 'ad-vAlUeS)) | 2566 | (setq arglist nil) ;; Terminate loop. |
| 2611 | set-forms)) | 2567 | (if (= (car argument-access) 0) |
| 2612 | (setq set-forms | 2568 | `(setq |
| 2613 | (cons (if (= (car argument-access) 0) | 2569 | ,(car (cdr argument-access)) |
| 2614 | (list 'setq | 2570 | ,(ad-list-access values-index 'ad-vAlUeS)) |
| 2615 | (car (cdr argument-access)) | 2571 | `(setcdr |
| 2616 | (ad-list-access values-index 'ad-vAlUeS)) | 2572 | ,(ad-list-access (1- (car argument-access)) |
| 2617 | (list 'setcdr | 2573 | (car (cdr argument-access))) |
| 2618 | (ad-list-access (1- (car argument-access)) | 2574 | ,(ad-list-access values-index 'ad-vAlUeS)))) |
| 2619 | (car (cdr argument-access))) | 2575 | set-forms) |
| 2620 | (ad-list-access values-index 'ad-vAlUeS))) | ||
| 2621 | set-forms)) | ||
| 2622 | ;; terminate loop | ||
| 2623 | (setq arglist nil)) | ||
| 2624 | (setq index (1+ index)) | 2576 | (setq index (1+ index)) |
| 2625 | (setq values-index (1+ values-index))) | 2577 | (setq values-index (1+ values-index))) |
| 2626 | (if (null set-forms) | 2578 | (if (null set-forms) |
| @@ -2629,8 +2581,8 @@ The assignment starts at position INDEX." | |||
| 2629 | (if (= (length set-forms) 1) | 2581 | (if (= (length set-forms) 1) |
| 2630 | ;; For exactly one set-form we can use values-form directly,... | 2582 | ;; For exactly one set-form we can use values-form directly,... |
| 2631 | (ad-substitute-tree | 2583 | (ad-substitute-tree |
| 2632 | (function (lambda (form) (eq form 'ad-vAlUeS))) | 2584 | (lambda (form) (eq form 'ad-vAlUeS)) |
| 2633 | (function (lambda (form) values-form)) | 2585 | (lambda (_form) values-form) |
| 2634 | (car set-forms)) | 2586 | (car set-forms)) |
| 2635 | ;; ...if we have more we have to bind it to a variable: | 2587 | ;; ...if we have more we have to bind it to a variable: |
| 2636 | `(let ((ad-vAlUeS ,values-form)) | 2588 | `(let ((ad-vAlUeS ,values-form)) |
| @@ -2700,11 +2652,10 @@ Example: `(ad-map-arglists '(a &rest args) '(w x y z))' will return | |||
| 2700 | (cond (need-apply | 2652 | (cond (need-apply |
| 2701 | ;; `apply' can take care of that directly: | 2653 | ;; `apply' can take care of that directly: |
| 2702 | (append source-reqopt-args (list source-rest-arg))) | 2654 | (append source-reqopt-args (list source-rest-arg))) |
| 2703 | (t (mapcar (function | 2655 | (t (mapcar (lambda (_arg) |
| 2704 | (lambda (arg) | 2656 | (setq target-arg-index (1+ target-arg-index)) |
| 2705 | (setq target-arg-index (1+ target-arg-index)) | 2657 | (ad-get-argument |
| 2706 | (ad-get-argument | 2658 | source-arglist target-arg-index)) |
| 2707 | source-arglist target-arg-index))) | ||
| 2708 | (append target-reqopt-args | 2659 | (append target-reqopt-args |
| 2709 | (and target-rest-arg | 2660 | (and target-rest-arg |
| 2710 | ;; If we have a rest arg gobble up | 2661 | ;; If we have a rest arg gobble up |
| @@ -2752,6 +2703,13 @@ Example: `(ad-map-arglists '(a &rest args) '(w x y z))' will return | |||
| 2752 | (require 'help-fns) ;For help-split-fundoc and help-add-fundoc-usage. | 2703 | (require 'help-fns) ;For help-split-fundoc and help-add-fundoc-usage. |
| 2753 | 2704 | ||
| 2754 | (defun ad-make-advised-docstring (function &optional style) | 2705 | (defun ad-make-advised-docstring (function &optional style) |
| 2706 | (let* ((origdef (ad-real-orig-definition function)) | ||
| 2707 | (origdoc | ||
| 2708 | ;; Retrieve raw doc, key substitution will be taken care of later: | ||
| 2709 | (documentation origdef t))) | ||
| 2710 | (ad--make-advised-docstring origdoc function style))) | ||
| 2711 | |||
| 2712 | (defun ad--make-advised-docstring (origdoc function &optional style) | ||
| 2755 | "Construct a documentation string for the advised FUNCTION. | 2713 | "Construct a documentation string for the advised FUNCTION. |
| 2756 | It concatenates the original documentation with the documentation | 2714 | It concatenates the original documentation with the documentation |
| 2757 | strings of the individual pieces of advice which will be formatted | 2715 | strings of the individual pieces of advice which will be formatted |
| @@ -2761,11 +2719,8 @@ strings corresponds to before/around/after and the individual ordering | |||
| 2761 | in any of these classes." | 2719 | in any of these classes." |
| 2762 | (let* ((origdef (ad-real-orig-definition function)) | 2720 | (let* ((origdef (ad-real-orig-definition function)) |
| 2763 | (origtype (symbol-name (ad-definition-type origdef))) | 2721 | (origtype (symbol-name (ad-definition-type origdef))) |
| 2764 | (origdoc | ||
| 2765 | ;; Retrieve raw doc, key substitution will be taken care of later: | ||
| 2766 | (ad-real-documentation origdef t)) | ||
| 2767 | (usage (help-split-fundoc origdoc function)) | 2722 | (usage (help-split-fundoc origdoc function)) |
| 2768 | paragraphs advice-docstring ad-usage) | 2723 | paragraphs advice-docstring) |
| 2769 | (setq usage (if (null usage) t (setq origdoc (cdr usage)) (car usage))) | 2724 | (setq usage (if (null usage) t (setq origdoc (cdr usage)) (car usage))) |
| 2770 | (if origdoc (setq paragraphs (list origdoc))) | 2725 | (if origdoc (setq paragraphs (list origdoc))) |
| 2771 | (unless (eq style 'plain) | 2726 | (unless (eq style 'plain) |
| @@ -2780,7 +2735,9 @@ in any of these classes." | |||
| 2780 | (propertize | 2735 | (propertize |
| 2781 | ;; separate paragraphs with blank lines: | 2736 | ;; separate paragraphs with blank lines: |
| 2782 | (mapconcat 'identity (nreverse paragraphs) "\n\n") | 2737 | (mapconcat 'identity (nreverse paragraphs) "\n\n") |
| 2783 | 'ad-advice-info function))) | 2738 | ;; FIXME: what is this for? |
| 2739 | 'dynamic-docstring-function | ||
| 2740 | #'ad--make-advised-docstring))) | ||
| 2784 | (help-add-fundoc-usage origdoc usage))) | 2741 | (help-add-fundoc-usage origdoc usage))) |
| 2785 | 2742 | ||
| 2786 | (defun ad-make-plain-docstring (function) | 2743 | (defun ad-make-plain-docstring (function) |
| @@ -2823,10 +2780,10 @@ in any of these classes." | |||
| 2823 | (origname (ad-get-advice-info-field function 'origname)) | 2780 | (origname (ad-get-advice-info-field function 'origname)) |
| 2824 | (orig-interactive-p (commandp origdef)) | 2781 | (orig-interactive-p (commandp origdef)) |
| 2825 | (orig-subr-p (ad-subr-p origdef)) | 2782 | (orig-subr-p (ad-subr-p origdef)) |
| 2826 | (orig-special-form-p (ad-special-form-p origdef)) | 2783 | (orig-special-form-p (special-form-p origdef)) |
| 2827 | (orig-macro-p (ad-macro-p origdef)) | 2784 | (orig-macro-p (ad-macro-p origdef)) |
| 2828 | ;; Construct the individual pieces that we need for assembly: | 2785 | ;; Construct the individual pieces that we need for assembly: |
| 2829 | (orig-arglist (ad-arglist origdef function)) | 2786 | (orig-arglist (ad-arglist origdef)) |
| 2830 | (advised-arglist (or (ad-advised-arglist function) | 2787 | (advised-arglist (or (ad-advised-arglist function) |
| 2831 | orig-arglist)) | 2788 | orig-arglist)) |
| 2832 | (advised-interactive-form (ad-advised-interactive-form function)) | 2789 | (advised-interactive-form (ad-advised-interactive-form function)) |
| @@ -2921,8 +2878,8 @@ should be modified. The assembled function will be returned." | |||
| 2921 | (setq around-form-protected t)) | 2878 | (setq around-form-protected t)) |
| 2922 | (setq around-form | 2879 | (setq around-form |
| 2923 | (ad-substitute-tree | 2880 | (ad-substitute-tree |
| 2924 | (function (lambda (form) (eq form 'ad-do-it))) | 2881 | (lambda (form) (eq form 'ad-do-it)) |
| 2925 | (function (lambda (form) around-form)) | 2882 | (lambda (_form) around-form) |
| 2926 | (macroexp-progn (ad-body-forms (ad-advice-definition advice)))))) | 2883 | (macroexp-progn (ad-body-forms (ad-advice-definition advice)))))) |
| 2927 | 2884 | ||
| 2928 | (setq after-forms | 2885 | (setq after-forms |
| @@ -3057,10 +3014,10 @@ advised definition from scratch." | |||
| 3057 | (mapcar (function (lambda (advice) (ad-advice-name advice))) | 3014 | (mapcar (function (lambda (advice) (ad-advice-name advice))) |
| 3058 | (ad-get-enabled-advices function 'after)) | 3015 | (ad-get-enabled-advices function 'after)) |
| 3059 | (ad-definition-type original-definition) | 3016 | (ad-definition-type original-definition) |
| 3060 | (if (equal (ad-arglist original-definition function) | 3017 | (if (equal (ad-arglist original-definition) |
| 3061 | (ad-arglist cached-definition)) | 3018 | (ad-arglist cached-definition)) |
| 3062 | t | 3019 | t |
| 3063 | (ad-arglist original-definition function)) | 3020 | (ad-arglist original-definition)) |
| 3064 | (if (eq (ad-definition-type original-definition) 'function) | 3021 | (if (eq (ad-definition-type original-definition) 'function) |
| 3065 | (equal (interactive-form original-definition) | 3022 | (equal (interactive-form original-definition) |
| 3066 | (interactive-form cached-definition)))))) | 3023 | (interactive-form cached-definition)))))) |
| @@ -3105,7 +3062,7 @@ advised definition from scratch." | |||
| 3105 | (and (eq (nth 3 cache-id) (ad-definition-type original-definition)) | 3062 | (and (eq (nth 3 cache-id) (ad-definition-type original-definition)) |
| 3106 | (setq code 'arglist-mismatch) | 3063 | (setq code 'arglist-mismatch) |
| 3107 | (equal (if (eq (nth 4 cache-id) t) | 3064 | (equal (if (eq (nth 4 cache-id) t) |
| 3108 | (ad-arglist original-definition function) | 3065 | (ad-arglist original-definition) |
| 3109 | (nth 4 cache-id) ) | 3066 | (nth 4 cache-id) ) |
| 3110 | (ad-arglist cached-definition)) | 3067 | (ad-arglist cached-definition)) |
| 3111 | (setq code 'interactive-form-mismatch) | 3068 | (setq code 'interactive-form-mismatch) |
| @@ -3164,7 +3121,7 @@ advised definition from scratch." | |||
| 3164 | (ad-set-advice-info function old-advice-info) | 3121 | (ad-set-advice-info function old-advice-info) |
| 3165 | ;; Don't `fset' function to nil if it was previously unbound: | 3122 | ;; Don't `fset' function to nil if it was previously unbound: |
| 3166 | (if function-defined-p | 3123 | (if function-defined-p |
| 3167 | (ad-safe-fset function old-definition) | 3124 | (fset function old-definition) |
| 3168 | (fmakunbound function))))) | 3125 | (fmakunbound function))))) |
| 3169 | 3126 | ||
| 3170 | 3127 | ||
| @@ -3195,61 +3152,54 @@ advised definition from scratch." | |||
| 3195 | (error | 3152 | (error |
| 3196 | "ad-make-freeze-definition: `%s' is not yet defined" | 3153 | "ad-make-freeze-definition: `%s' is not yet defined" |
| 3197 | function)) | 3154 | function)) |
| 3198 | (let* ((name (ad-advice-name advice)) | 3155 | (cl-letf* |
| 3199 | ;; With a unique origname we can have multiple freeze advices | 3156 | ((name (ad-advice-name advice)) |
| 3200 | ;; for the same function, each overloading the previous one: | 3157 | ;; With a unique origname we can have multiple freeze advices |
| 3201 | (unique-origname | 3158 | ;; for the same function, each overloading the previous one: |
| 3202 | (intern (format "%s-%s-%s" (ad-make-origname function) class name))) | 3159 | (unique-origname |
| 3203 | (orig-definition | 3160 | (intern (format "%s-%s-%s" (ad-make-origname function) class name))) |
| 3204 | ;; If FUNCTION is already advised, we'll use its current origdef | 3161 | (orig-definition |
| 3205 | ;; as the original definition of the frozen advice: | 3162 | ;; If FUNCTION is already advised, we'll use its current origdef |
| 3206 | (or (ad-get-orig-definition function) | 3163 | ;; as the original definition of the frozen advice: |
| 3207 | (symbol-function function))) | 3164 | (or (ad-get-orig-definition function) |
| 3208 | (old-advice-info | 3165 | (symbol-function function))) |
| 3209 | (if (ad-is-advised function) | 3166 | (old-advice-info |
| 3210 | (ad-copy-advice-info function))) | 3167 | (if (ad-is-advised function) |
| 3211 | (real-docstring-fn | 3168 | (ad-copy-advice-info function))) |
| 3212 | (symbol-function 'ad-make-advised-definition-docstring)) | 3169 | ;; Make sure we construct a proper docstring: |
| 3213 | (real-origname-fn | 3170 | ((symbol-function 'ad-make-advised-definition-docstring) |
| 3214 | (symbol-function 'ad-make-origname)) | 3171 | #'ad-make-freeze-docstring) |
| 3215 | (frozen-definition | 3172 | ;; Make sure `unique-origname' is used as the origname: |
| 3216 | (unwind-protect | 3173 | ((symbol-function 'ad-make-origname) (lambda (_x) unique-origname)) |
| 3217 | (progn | 3174 | (frozen-definition |
| 3218 | ;; Make sure we construct a proper docstring: | 3175 | (unwind-protect |
| 3219 | (ad-safe-fset 'ad-make-advised-definition-docstring | 3176 | (progn |
| 3220 | 'ad-make-freeze-docstring) | 3177 | ;; No we reset all current advice information to nil and |
| 3221 | ;; Make sure `unique-origname' is used as the origname: | 3178 | ;; generate an advised definition that's solely determined |
| 3222 | (ad-safe-fset 'ad-make-origname (lambda (x) unique-origname)) | 3179 | ;; by ADVICE and the current origdef of FUNCTION: |
| 3223 | ;; No we reset all current advice information to nil and | 3180 | (ad-set-advice-info function nil) |
| 3224 | ;; generate an advised definition that's solely determined | 3181 | (ad-add-advice function advice class position) |
| 3225 | ;; by ADVICE and the current origdef of FUNCTION: | 3182 | ;; The following will provide proper real docstrings as |
| 3226 | (ad-set-advice-info function nil) | 3183 | ;; well as a definition that will make the compiler happy: |
| 3227 | (ad-add-advice function advice class position) | 3184 | (ad-set-orig-definition function orig-definition) |
| 3228 | ;; The following will provide proper real docstrings as | 3185 | (ad-make-advised-definition function)) |
| 3229 | ;; well as a definition that will make the compiler happy: | 3186 | ;; Restore the old advice state: |
| 3230 | (ad-set-orig-definition function orig-definition) | 3187 | (ad-set-advice-info function old-advice-info)))) |
| 3231 | (ad-make-advised-definition function)) | ||
| 3232 | ;; Restore the old advice state: | ||
| 3233 | (ad-set-advice-info function old-advice-info) | ||
| 3234 | ;; Restore functions: | ||
| 3235 | (ad-safe-fset | ||
| 3236 | 'ad-make-advised-definition-docstring real-docstring-fn) | ||
| 3237 | (ad-safe-fset 'ad-make-origname real-origname-fn)))) | ||
| 3238 | (if frozen-definition | 3188 | (if frozen-definition |
| 3239 | (let* ((macro-p (ad-macro-p frozen-definition)) | 3189 | (let* ((macro-p (ad-macro-p frozen-definition)) |
| 3240 | (body (cdr (if macro-p | 3190 | (body (cdr (if macro-p |
| 3241 | (ad-lambdafy frozen-definition) | 3191 | (ad-lambdafy frozen-definition) |
| 3242 | frozen-definition)))) | 3192 | frozen-definition)))) |
| 3243 | `(progn | 3193 | `(progn |
| 3244 | (if (not (fboundp ',unique-origname)) | 3194 | (if (not (fboundp ',unique-origname)) |
| 3245 | (fset ',unique-origname | 3195 | (fset ',unique-origname |
| 3246 | ;; avoid infinite recursion in case the function | 3196 | ;; avoid infinite recursion in case the function |
| 3247 | ;; we want to freeze is already advised: | 3197 | ;; we want to freeze is already advised: |
| 3248 | (or (ad-get-orig-definition ',function) | 3198 | (or (ad-get-orig-definition ',function) |
| 3249 | (symbol-function ',function)))) | 3199 | (symbol-function ',function)))) |
| 3250 | (,(if macro-p 'defmacro 'defun) | 3200 | (,(if macro-p 'defmacro 'defun) |
| 3251 | ,function | 3201 | ,function |
| 3252 | ,@body)))))) | 3202 | ,@body)))))) |
| 3253 | 3203 | ||
| 3254 | 3204 | ||
| 3255 | ;; @@ Activation and definition handling: | 3205 | ;; @@ Activation and definition handling: |
| @@ -3282,7 +3232,7 @@ The current definition and its cache-id will be put into the cache." | |||
| 3282 | (let ((verified-cached-definition | 3232 | (let ((verified-cached-definition |
| 3283 | (if (ad-verify-cache-id function) | 3233 | (if (ad-verify-cache-id function) |
| 3284 | (ad-get-cache-definition function)))) | 3234 | (ad-get-cache-definition function)))) |
| 3285 | (ad-safe-fset function | 3235 | (fset function |
| 3286 | (or verified-cached-definition | 3236 | (or verified-cached-definition |
| 3287 | (ad-make-advised-definition function))) | 3237 | (ad-make-advised-definition function))) |
| 3288 | (if (ad-should-compile function compile) | 3238 | (if (ad-should-compile function compile) |
| @@ -3324,7 +3274,7 @@ the value of `ad-redefinition-action' and de/activate again." | |||
| 3324 | (error "ad-handle-definition (see its doc): `%s' %s" | 3274 | (error "ad-handle-definition (see its doc): `%s' %s" |
| 3325 | function "invalidly redefined") | 3275 | function "invalidly redefined") |
| 3326 | (if (eq ad-redefinition-action 'discard) | 3276 | (if (eq ad-redefinition-action 'discard) |
| 3327 | (ad-safe-fset function original-definition) | 3277 | (fset function original-definition) |
| 3328 | (ad-set-orig-definition function current-definition) | 3278 | (ad-set-orig-definition function current-definition) |
| 3329 | (if (eq ad-redefinition-action 'warn) | 3279 | (if (eq ad-redefinition-action 'warn) |
| 3330 | (message "ad-handle-definition: `%s' got redefined" | 3280 | (message "ad-handle-definition: `%s' got redefined" |
| @@ -3399,7 +3349,7 @@ a call to `ad-activate'." | |||
| 3399 | (if (not (ad-get-orig-definition function)) | 3349 | (if (not (ad-get-orig-definition function)) |
| 3400 | (error "ad-deactivate: `%s' has no original definition" | 3350 | (error "ad-deactivate: `%s' has no original definition" |
| 3401 | function) | 3351 | function) |
| 3402 | (ad-safe-fset function (ad-get-orig-definition function)) | 3352 | (fset function (ad-get-orig-definition function)) |
| 3403 | (ad-set-advice-info-field function 'active nil) | 3353 | (ad-set-advice-info-field function 'active nil) |
| 3404 | (eval (ad-make-hook-form function 'deactivation)) | 3354 | (eval (ad-make-hook-form function 'deactivation)) |
| 3405 | function))))) | 3355 | function))))) |
| @@ -3437,7 +3387,7 @@ Use in emergencies." | |||
| 3437 | (completing-read "Recover advised function: " obarray nil t)))) | 3387 | (completing-read "Recover advised function: " obarray nil t)))) |
| 3438 | (cond ((ad-is-advised function) | 3388 | (cond ((ad-is-advised function) |
| 3439 | (cond ((ad-get-orig-definition function) | 3389 | (cond ((ad-get-orig-definition function) |
| 3440 | (ad-safe-fset function (ad-get-orig-definition function)) | 3390 | (fset function (ad-get-orig-definition function)) |
| 3441 | (ad-clear-orig-definition function))) | 3391 | (ad-clear-orig-definition function))) |
| 3442 | (ad-set-advice-info function nil) | 3392 | (ad-set-advice-info function nil) |
| 3443 | (ad-pop-advised-function function)))) | 3393 | (ad-pop-advised-function function)))) |
| @@ -3669,28 +3619,22 @@ undone on exit of this macro." | |||
| 3669 | ;; Make forms to redefine functions to their | 3619 | ;; Make forms to redefine functions to their |
| 3670 | ;; original definitions if they are advised: | 3620 | ;; original definitions if they are advised: |
| 3671 | (setq index -1) | 3621 | (setq index -1) |
| 3672 | (mapcar | 3622 | (mapcar (lambda (function) |
| 3673 | (function | 3623 | (setq index (1+ index)) |
| 3674 | (lambda (function) | 3624 | `(fset ',function |
| 3675 | (setq index (1+ index)) | 3625 | (or (ad-get-orig-definition ',function) |
| 3676 | `(ad-safe-fset | 3626 | ,(car (nth index current-bindings))))) |
| 3677 | ',function | 3627 | functions)) |
| 3678 | (or (ad-get-orig-definition ',function) | ||
| 3679 | ,(car (nth index current-bindings)))))) | ||
| 3680 | functions)) | ||
| 3681 | ,@body) | 3628 | ,@body) |
| 3682 | ,@(progn | 3629 | ,@(progn |
| 3683 | ;; Make forms to back-define functions to the definitions | 3630 | ;; Make forms to back-define functions to the definitions |
| 3684 | ;; they had outside this macro call: | 3631 | ;; they had outside this macro call: |
| 3685 | (setq index -1) | 3632 | (setq index -1) |
| 3686 | (mapcar | 3633 | (mapcar (lambda (function) |
| 3687 | (function | 3634 | (setq index (1+ index)) |
| 3688 | (lambda (function) | 3635 | `(fset ',function |
| 3689 | (setq index (1+ index)) | 3636 | ,(car (nth index current-bindings)))) |
| 3690 | `(ad-safe-fset | 3637 | functions)))))) |
| 3691 | ',function | ||
| 3692 | ,(car (nth index current-bindings))))) | ||
| 3693 | functions)))))) | ||
| 3694 | 3638 | ||
| 3695 | 3639 | ||
| 3696 | ;; @@ Starting, stopping and recovering from the advice package magic: | 3640 | ;; @@ Starting, stopping and recovering from the advice package magic: |
| @@ -3701,7 +3645,7 @@ undone on exit of this macro." | |||
| 3701 | (interactive) | 3645 | (interactive) |
| 3702 | ;; Advising `ad-activate-internal' means death!! | 3646 | ;; Advising `ad-activate-internal' means death!! |
| 3703 | (ad-set-advice-info 'ad-activate-internal nil) | 3647 | (ad-set-advice-info 'ad-activate-internal nil) |
| 3704 | (ad-safe-fset 'ad-activate-internal 'ad-activate)) | 3648 | (fset 'ad-activate-internal 'ad-activate)) |
| 3705 | 3649 | ||
| 3706 | (defun ad-stop-advice () | 3650 | (defun ad-stop-advice () |
| 3707 | "Stop the automatic advice handling magic. | 3651 | "Stop the automatic advice handling magic. |
| @@ -3709,7 +3653,7 @@ You should only need this in case of Advice-related emergencies." | |||
| 3709 | (interactive) | 3653 | (interactive) |
| 3710 | ;; Advising `ad-activate-internal' means death!! | 3654 | ;; Advising `ad-activate-internal' means death!! |
| 3711 | (ad-set-advice-info 'ad-activate-internal nil) | 3655 | (ad-set-advice-info 'ad-activate-internal nil) |
| 3712 | (ad-safe-fset 'ad-activate-internal 'ad-activate-internal-off)) | 3656 | (fset 'ad-activate-internal 'ad-activate-internal-off)) |
| 3713 | 3657 | ||
| 3714 | (defun ad-recover-normality () | 3658 | (defun ad-recover-normality () |
| 3715 | "Undo all advice related redefinitions and unadvises everything. | 3659 | "Undo all advice related redefinitions and unadvises everything. |
| @@ -3717,9 +3661,11 @@ Use only in REAL emergencies." | |||
| 3717 | (interactive) | 3661 | (interactive) |
| 3718 | ;; Advising `ad-activate-internal' means death!! | 3662 | ;; Advising `ad-activate-internal' means death!! |
| 3719 | (ad-set-advice-info 'ad-activate-internal nil) | 3663 | (ad-set-advice-info 'ad-activate-internal nil) |
| 3720 | (ad-safe-fset 'ad-activate-internal 'ad-activate-internal-off) | 3664 | (fset 'ad-activate-internal 'ad-activate-internal-off) |
| 3721 | (ad-recover-all) | 3665 | (ad-recover-all) |
| 3722 | (setq ad-advised-functions nil)) | 3666 | (ad-do-advised-functions (function) |
| 3667 | (message "Oops! Left over advised function %S" function) | ||
| 3668 | (ad-pop-advised-function function))) | ||
| 3723 | 3669 | ||
| 3724 | (ad-start-advice) | 3670 | (ad-start-advice) |
| 3725 | 3671 | ||
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index e776df4ef37..a325e0f3e44 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -419,8 +419,8 @@ This list lives partly on the stack.") | |||
| 419 | 419 | ||
| 420 | (defconst byte-compile-initial-macro-environment | 420 | (defconst byte-compile-initial-macro-environment |
| 421 | '( | 421 | '( |
| 422 | ;; (byte-compiler-options . (lambda (&rest forms) | 422 | ;; (byte-compiler-options . (lambda (&rest forms) |
| 423 | ;; (apply 'byte-compiler-options-handler forms))) | 423 | ;; (apply 'byte-compiler-options-handler forms))) |
| 424 | (declare-function . byte-compile-macroexpand-declare-function) | 424 | (declare-function . byte-compile-macroexpand-declare-function) |
| 425 | (eval-when-compile . (lambda (&rest body) | 425 | (eval-when-compile . (lambda (&rest body) |
| 426 | (list | 426 | (list |
| @@ -429,8 +429,19 @@ This list lives partly on the stack.") | |||
| 429 | (byte-compile-top-level | 429 | (byte-compile-top-level |
| 430 | (byte-compile-preprocess (cons 'progn body))))))) | 430 | (byte-compile-preprocess (cons 'progn body))))))) |
| 431 | (eval-and-compile . (lambda (&rest body) | 431 | (eval-and-compile . (lambda (&rest body) |
| 432 | (byte-compile-eval-before-compile (cons 'progn body)) | 432 | ;; Byte compile before running it. Do it piece by |
| 433 | (cons 'progn body)))) | 433 | ;; piece, in case further expressions need earlier |
| 434 | ;; ones to be evaluated already, as is the case in | ||
| 435 | ;; eieio.el. | ||
| 436 | `(progn | ||
| 437 | ,@(mapcar (lambda (exp) | ||
| 438 | (let ((cexp | ||
| 439 | (byte-compile-top-level | ||
| 440 | (byte-compile-preprocess | ||
| 441 | exp)))) | ||
| 442 | (eval cexp) | ||
| 443 | cexp)) | ||
| 444 | body))))) | ||
| 434 | "The default macro-environment passed to macroexpand by the compiler. | 445 | "The default macro-environment passed to macroexpand by the compiler. |
| 435 | Placing a macro here will cause a macro to have different semantics when | 446 | Placing a macro here will cause a macro to have different semantics when |
| 436 | expanded by the compiler as when expanded by the interpreter.") | 447 | expanded by the compiler as when expanded by the interpreter.") |
| @@ -731,9 +742,11 @@ otherwise pop it") | |||
| 731 | ;; Also, this lets us notice references to free variables. | 742 | ;; Also, this lets us notice references to free variables. |
| 732 | 743 | ||
| 733 | (defmacro byte-compile-push-bytecodes (&rest args) | 744 | (defmacro byte-compile-push-bytecodes (&rest args) |
| 734 | "Push BYTE... onto BYTES, and increment PC by the number of bytes pushed. | 745 | "Push bytes onto BVAR, and increment CVAR by the number of bytes pushed. |
| 735 | ARGS is of the form (BYTE... BYTES PC), where BYTES and PC are variable names. | 746 | BVAR and CVAR are variables which are updated after evaluating |
| 736 | BYTES and PC are updated after evaluating all the arguments." | 747 | all the arguments. |
| 748 | |||
| 749 | \(fn BYTE1 BYTE2 ... BYTEn BVAR CVAR)" | ||
| 737 | (let ((byte-exprs (butlast args 2)) | 750 | (let ((byte-exprs (butlast args 2)) |
| 738 | (bytes-var (car (last args 2))) | 751 | (bytes-var (car (last args 2))) |
| 739 | (pc-var (car (last args)))) | 752 | (pc-var (car (last args)))) |
| @@ -1097,8 +1110,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'." | |||
| 1097 | (defun byte-compile-log-warning (string &optional fill level) | 1110 | (defun byte-compile-log-warning (string &optional fill level) |
| 1098 | (let ((warning-prefix-function 'byte-compile-warning-prefix) | 1111 | (let ((warning-prefix-function 'byte-compile-warning-prefix) |
| 1099 | (warning-type-format "") | 1112 | (warning-type-format "") |
| 1100 | (warning-fill-prefix (if fill " ")) | 1113 | (warning-fill-prefix (if fill " "))) |
| 1101 | (inhibit-read-only t)) | ||
| 1102 | (display-warning 'bytecomp string level byte-compile-log-buffer))) | 1114 | (display-warning 'bytecomp string level byte-compile-log-buffer))) |
| 1103 | 1115 | ||
| 1104 | (defun byte-compile-warn (format &rest args) | 1116 | (defun byte-compile-warn (format &rest args) |
| @@ -2189,7 +2201,10 @@ list that represents a doc string reference. | |||
| 2189 | (when (and (consp (nth 1 form)) | 2201 | (when (and (consp (nth 1 form)) |
| 2190 | (eq (car (nth 1 form)) 'quote) | 2202 | (eq (car (nth 1 form)) 'quote) |
| 2191 | (consp (cdr (nth 1 form))) | 2203 | (consp (cdr (nth 1 form))) |
| 2192 | (symbolp (nth 1 (nth 1 form)))) | 2204 | (symbolp (nth 1 (nth 1 form))) |
| 2205 | ;; Don't add it if it's already defined. Otherwise, it might | ||
| 2206 | ;; hide the actual definition. | ||
| 2207 | (not (fboundp (nth 1 (nth 1 form))))) | ||
| 2193 | (push (cons (nth 1 (nth 1 form)) | 2208 | (push (cons (nth 1 (nth 1 form)) |
| 2194 | (cons 'autoload (cdr (cdr form)))) | 2209 | (cons 'autoload (cdr (cdr form)))) |
| 2195 | byte-compile-function-environment) | 2210 | byte-compile-function-environment) |
| @@ -2808,7 +2823,8 @@ for symbols generated by the byte compiler itself." | |||
| 2808 | (setq body (nreverse body)) | 2823 | (setq body (nreverse body)) |
| 2809 | (setq body (list | 2824 | (setq body (list |
| 2810 | (if (and (eq tmp 'funcall) | 2825 | (if (and (eq tmp 'funcall) |
| 2811 | (eq (car-safe (car body)) 'quote)) | 2826 | (eq (car-safe (car body)) 'quote) |
| 2827 | (symbolp (nth 1 (car body)))) | ||
| 2812 | (cons (nth 1 (car body)) (cdr body)) | 2828 | (cons (nth 1 (car body)) (cdr body)) |
| 2813 | (cons tmp body)))) | 2829 | (cons tmp body)))) |
| 2814 | (or (eq output-type 'file) | 2830 | (or (eq output-type 'file) |
| @@ -3689,10 +3705,10 @@ If CONDITION's value is (not (featurep 'emacs)) or (featurep 'xemacs), | |||
| 3689 | that suppresses all warnings during execution of BODY." | 3705 | that suppresses all warnings during execution of BODY." |
| 3690 | (declare (indent 1) (debug t)) | 3706 | (declare (indent 1) (debug t)) |
| 3691 | `(let* ((fbound-list (byte-compile-find-bound-condition | 3707 | `(let* ((fbound-list (byte-compile-find-bound-condition |
| 3692 | ,condition (list 'fboundp) | 3708 | ,condition '(fboundp functionp) |
| 3693 | byte-compile-unresolved-functions)) | 3709 | byte-compile-unresolved-functions)) |
| 3694 | (bound-list (byte-compile-find-bound-condition | 3710 | (bound-list (byte-compile-find-bound-condition |
| 3695 | ,condition (list 'boundp 'default-boundp))) | 3711 | ,condition '(boundp default-boundp))) |
| 3696 | ;; Maybe add to the bound list. | 3712 | ;; Maybe add to the bound list. |
| 3697 | (byte-compile-bound-variables | 3713 | (byte-compile-bound-variables |
| 3698 | (append bound-list byte-compile-bound-variables))) | 3714 | (append bound-list byte-compile-bound-variables))) |
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el index a57de344cf3..7c25972835b 100644 --- a/lisp/emacs-lisp/cl-extra.el +++ b/lisp/emacs-lisp/cl-extra.el | |||
| @@ -131,7 +131,7 @@ TYPE is the sequence type to return. | |||
| 131 | ;;;###autoload | 131 | ;;;###autoload |
| 132 | (defun cl-maplist (cl-func cl-list &rest cl-rest) | 132 | (defun cl-maplist (cl-func cl-list &rest cl-rest) |
| 133 | "Map FUNCTION to each sublist of LIST or LISTs. | 133 | "Map FUNCTION to each sublist of LIST or LISTs. |
| 134 | Like `mapcar', except applies to lists and their cdr's rather than to | 134 | Like `cl-mapcar', except applies to lists and their cdr's rather than to |
| 135 | the elements themselves. | 135 | the elements themselves. |
| 136 | \n(fn FUNCTION LIST...)" | 136 | \n(fn FUNCTION LIST...)" |
| 137 | (if cl-rest | 137 | (if cl-rest |
| @@ -170,7 +170,7 @@ the elements themselves. | |||
| 170 | 170 | ||
| 171 | ;;;###autoload | 171 | ;;;###autoload |
| 172 | (defun cl-mapcan (cl-func cl-seq &rest cl-rest) | 172 | (defun cl-mapcan (cl-func cl-seq &rest cl-rest) |
| 173 | "Like `mapcar', but nconc's together the values returned by the function. | 173 | "Like `cl-mapcar', but nconc's together the values returned by the function. |
| 174 | \n(fn FUNCTION SEQUENCE...)" | 174 | \n(fn FUNCTION SEQUENCE...)" |
| 175 | (apply 'nconc (apply 'cl-mapcar cl-func cl-seq cl-rest))) | 175 | (apply 'nconc (apply 'cl-mapcar cl-func cl-seq cl-rest))) |
| 176 | 176 | ||
| @@ -675,6 +675,9 @@ PROPLIST is a list of the sort returned by `symbol-plist'. | |||
| 675 | 675 | ||
| 676 | ;;;###autoload | 676 | ;;;###autoload |
| 677 | (defun cl-prettyexpand (form &optional full) | 677 | (defun cl-prettyexpand (form &optional full) |
| 678 | "Expand macros in FORM and insert the pretty-printed result. | ||
| 679 | Optional argument FULL non-nil means to expand all macros, | ||
| 680 | including `cl-block' and `cl-eval-when'." | ||
| 678 | (message "Expanding...") | 681 | (message "Expanding...") |
| 679 | (let ((cl--compiling-file full) | 682 | (let ((cl--compiling-file full) |
| 680 | (byte-compile-macro-environment nil)) | 683 | (byte-compile-macro-environment nil)) |
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el index 034a5c7517e..a9be08b1383 100644 --- a/lisp/emacs-lisp/cl-lib.el +++ b/lisp/emacs-lisp/cl-lib.el | |||
| @@ -251,12 +251,17 @@ one value. | |||
| 251 | (defvar cl-proclaims-deferred nil) | 251 | (defvar cl-proclaims-deferred nil) |
| 252 | 252 | ||
| 253 | (defun cl-proclaim (spec) | 253 | (defun cl-proclaim (spec) |
| 254 | "Record a global declaration specified by SPEC." | ||
| 254 | (if (fboundp 'cl-do-proclaim) (cl-do-proclaim spec t) | 255 | (if (fboundp 'cl-do-proclaim) (cl-do-proclaim spec t) |
| 255 | (push spec cl-proclaims-deferred)) | 256 | (push spec cl-proclaims-deferred)) |
| 256 | nil) | 257 | nil) |
| 257 | 258 | ||
| 258 | (defmacro cl-declaim (&rest specs) | 259 | (defmacro cl-declaim (&rest specs) |
| 259 | (let ((body (mapcar (function (lambda (x) (list 'cl-proclaim (list 'quote x)))) | 260 | "Like `cl-proclaim', but takes any number of unevaluated, unquoted arguments. |
| 261 | Puts `(cl-eval-when (compile load eval) ...)' around the declarations | ||
| 262 | so that they are registered at compile-time as well as run-time." | ||
| 263 | (let ((body (mapcar (function (lambda (x) | ||
| 264 | (list 'cl-proclaim (list 'quote x)))) | ||
| 260 | specs))) | 265 | specs))) |
| 261 | (if (cl--compiling-file) (cl-list* 'cl-eval-when '(compile load eval) body) | 266 | (if (cl--compiling-file) (cl-list* 'cl-eval-when '(compile load eval) body) |
| 262 | (cons 'progn body)))) ; avoid loading cl-macs.el for cl-eval-when | 267 | (cons 'progn body)))) ; avoid loading cl-macs.el for cl-eval-when |
diff --git a/lisp/emacs-lisp/cl-loaddefs.el b/lisp/emacs-lisp/cl-loaddefs.el index 5687f92083f..bf99af2f7e6 100644 --- a/lisp/emacs-lisp/cl-loaddefs.el +++ b/lisp/emacs-lisp/cl-loaddefs.el | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | ;;;;;; cl--map-overlays cl--map-intervals cl--map-keymap-recursively | 11 | ;;;;;; cl--map-overlays cl--map-intervals cl--map-keymap-recursively |
| 12 | ;;;;;; cl-notevery cl-notany cl-every cl-some cl-mapcon cl-mapcan | 12 | ;;;;;; cl-notevery cl-notany cl-every cl-some cl-mapcon cl-mapcan |
| 13 | ;;;;;; cl-mapl cl-mapc cl-maplist cl-map cl--mapcar-many cl-equalp | 13 | ;;;;;; cl-mapl cl-mapc cl-maplist cl-map cl--mapcar-many cl-equalp |
| 14 | ;;;;;; cl-coerce) "cl-extra" "cl-extra.el" "0e9284b6492cc98eee7c85ae4e5322ee") | 14 | ;;;;;; cl-coerce) "cl-extra" "cl-extra.el" "8e9fee941c465ac0fee9b92a92d64154") |
| 15 | ;;; Generated autoloads from cl-extra.el | 15 | ;;; Generated autoloads from cl-extra.el |
| 16 | 16 | ||
| 17 | (autoload 'cl-coerce "cl-extra" "\ | 17 | (autoload 'cl-coerce "cl-extra" "\ |
| @@ -41,7 +41,7 @@ TYPE is the sequence type to return. | |||
| 41 | 41 | ||
| 42 | (autoload 'cl-maplist "cl-extra" "\ | 42 | (autoload 'cl-maplist "cl-extra" "\ |
| 43 | Map FUNCTION to each sublist of LIST or LISTs. | 43 | Map FUNCTION to each sublist of LIST or LISTs. |
| 44 | Like `mapcar', except applies to lists and their cdr's rather than to | 44 | Like `cl-mapcar', except applies to lists and their cdr's rather than to |
| 45 | the elements themselves. | 45 | the elements themselves. |
| 46 | 46 | ||
| 47 | \(fn FUNCTION LIST...)" nil nil) | 47 | \(fn FUNCTION LIST...)" nil nil) |
| @@ -57,7 +57,7 @@ Like `cl-maplist', but does not accumulate values returned by the function. | |||
| 57 | \(fn FUNCTION LIST...)" nil nil) | 57 | \(fn FUNCTION LIST...)" nil nil) |
| 58 | 58 | ||
| 59 | (autoload 'cl-mapcan "cl-extra" "\ | 59 | (autoload 'cl-mapcan "cl-extra" "\ |
| 60 | Like `mapcar', but nconc's together the values returned by the function. | 60 | Like `cl-mapcar', but nconc's together the values returned by the function. |
| 61 | 61 | ||
| 62 | \(fn FUNCTION SEQUENCE...)" nil nil) | 62 | \(fn FUNCTION SEQUENCE...)" nil nil) |
| 63 | 63 | ||
| @@ -248,7 +248,9 @@ Remove from SYMBOL's plist the property PROPNAME and its value. | |||
| 248 | \(fn SYMBOL PROPNAME)" nil nil) | 248 | \(fn SYMBOL PROPNAME)" nil nil) |
| 249 | 249 | ||
| 250 | (autoload 'cl-prettyexpand "cl-extra" "\ | 250 | (autoload 'cl-prettyexpand "cl-extra" "\ |
| 251 | 251 | Expand macros in FORM and insert the pretty-printed result. | |
| 252 | Optional argument FULL non-nil means to expand all macros, | ||
| 253 | including `cl-block' and `cl-eval-when'. | ||
| 252 | 254 | ||
| 253 | \(fn FORM &optional FULL)" nil nil) | 255 | \(fn FORM &optional FULL)" nil nil) |
| 254 | 256 | ||
| @@ -265,7 +267,7 @@ Remove from SYMBOL's plist the property PROPNAME and its value. | |||
| 265 | ;;;;;; cl-typecase cl-ecase cl-case cl-load-time-value cl-eval-when | 267 | ;;;;;; cl-typecase cl-ecase cl-case cl-load-time-value cl-eval-when |
| 266 | ;;;;;; cl-destructuring-bind cl-function cl-defmacro cl-defun cl-gentemp | 268 | ;;;;;; cl-destructuring-bind cl-function cl-defmacro cl-defun cl-gentemp |
| 267 | ;;;;;; cl-gensym cl--compiler-macro-cXXr cl--compiler-macro-list*) | 269 | ;;;;;; cl-gensym cl--compiler-macro-cXXr cl--compiler-macro-list*) |
| 268 | ;;;;;; "cl-macs" "cl-macs.el" "146e82321e05b9e3fe8c70d7dbbab8a6") | 270 | ;;;;;; "cl-macs" "cl-macs.el" "a7228877484d2b39e1c2bee40b011734") |
| 269 | ;;; Generated autoloads from cl-macs.el | 271 | ;;; Generated autoloads from cl-macs.el |
| 270 | 272 | ||
| 271 | (autoload 'cl--compiler-macro-list* "cl-macs" "\ | 273 | (autoload 'cl--compiler-macro-list* "cl-macs" "\ |
| @@ -320,7 +322,7 @@ its argument list allows full Common Lisp conventions. | |||
| 320 | \(fn FUNC)" nil t) | 322 | \(fn FUNC)" nil t) |
| 321 | 323 | ||
| 322 | (autoload 'cl-destructuring-bind "cl-macs" "\ | 324 | (autoload 'cl-destructuring-bind "cl-macs" "\ |
| 323 | 325 | Bind the variables in ARGS to the result of EXPR and execute BODY. | |
| 324 | 326 | ||
| 325 | \(fn ARGS EXPR &rest BODY)" nil t) | 327 | \(fn ARGS EXPR &rest BODY)" nil t) |
| 326 | 328 | ||
| @@ -564,12 +566,12 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C). | |||
| 564 | (put 'cl-multiple-value-setq 'lisp-indent-function '1) | 566 | (put 'cl-multiple-value-setq 'lisp-indent-function '1) |
| 565 | 567 | ||
| 566 | (autoload 'cl-locally "cl-macs" "\ | 568 | (autoload 'cl-locally "cl-macs" "\ |
| 567 | 569 | Equivalent to `progn'. | |
| 568 | 570 | ||
| 569 | \(fn &rest BODY)" nil t) | 571 | \(fn &rest BODY)" nil t) |
| 570 | 572 | ||
| 571 | (autoload 'cl-the "cl-macs" "\ | 573 | (autoload 'cl-the "cl-macs" "\ |
| 572 | 574 | At present this ignores _TYPE and is simply equivalent to FORM. | |
| 573 | 575 | ||
| 574 | \(fn TYPE FORM)" nil t) | 576 | \(fn TYPE FORM)" nil t) |
| 575 | 577 | ||
| @@ -721,7 +723,10 @@ and then returning foo. | |||
| 721 | \(fn FUNC ARGS &rest BODY)" nil t) | 723 | \(fn FUNC ARGS &rest BODY)" nil t) |
| 722 | 724 | ||
| 723 | (autoload 'cl-compiler-macroexpand "cl-macs" "\ | 725 | (autoload 'cl-compiler-macroexpand "cl-macs" "\ |
| 724 | 726 | Like `macroexpand', but for compiler macros. | |
| 727 | Expands FORM repeatedly until no further expansion is possible. | ||
| 728 | Returns FORM unchanged if it has no compiler macro, or if it has a | ||
| 729 | macro that returns its `&whole' argument. | ||
| 725 | 730 | ||
| 726 | \(fn FORM)" nil nil) | 731 | \(fn FORM)" nil nil) |
| 727 | 732 | ||
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index cd537cd43d6..f3bf36de376 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el | |||
| @@ -554,6 +554,7 @@ its argument list allows full Common Lisp conventions." | |||
| 554 | 554 | ||
| 555 | ;;;###autoload | 555 | ;;;###autoload |
| 556 | (defmacro cl-destructuring-bind (args expr &rest body) | 556 | (defmacro cl-destructuring-bind (args expr &rest body) |
| 557 | "Bind the variables in ARGS to the result of EXPR and execute BODY." | ||
| 557 | (declare (indent 2) | 558 | (declare (indent 2) |
| 558 | (debug (&define cl-macro-list def-form cl-declarations def-body))) | 559 | (debug (&define cl-macro-list def-form cl-declarations def-body))) |
| 559 | (let* ((cl--bind-lets nil) (cl--bind-forms nil) (cl--bind-inits nil) | 560 | (let* ((cl--bind-lets nil) (cl--bind-forms nil) (cl--bind-inits nil) |
| @@ -1886,10 +1887,12 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C). | |||
| 1886 | 1887 | ||
| 1887 | ;;;###autoload | 1888 | ;;;###autoload |
| 1888 | (defmacro cl-locally (&rest body) | 1889 | (defmacro cl-locally (&rest body) |
| 1890 | "Equivalent to `progn'." | ||
| 1889 | (declare (debug t)) | 1891 | (declare (debug t)) |
| 1890 | (cons 'progn body)) | 1892 | (cons 'progn body)) |
| 1891 | ;;;###autoload | 1893 | ;;;###autoload |
| 1892 | (defmacro cl-the (_type form) | 1894 | (defmacro cl-the (_type form) |
| 1895 | "At present this ignores _TYPE and is simply equivalent to FORM." | ||
| 1893 | (declare (indent 1) (debug (cl-type-spec form))) | 1896 | (declare (indent 1) (debug (cl-type-spec form))) |
| 1894 | form) | 1897 | form) |
| 1895 | 1898 | ||
| @@ -2537,6 +2540,10 @@ and then returning foo." | |||
| 2537 | 2540 | ||
| 2538 | ;;;###autoload | 2541 | ;;;###autoload |
| 2539 | (defun cl-compiler-macroexpand (form) | 2542 | (defun cl-compiler-macroexpand (form) |
| 2543 | "Like `macroexpand', but for compiler macros. | ||
| 2544 | Expands FORM repeatedly until no further expansion is possible. | ||
| 2545 | Returns FORM unchanged if it has no compiler macro, or if it has a | ||
| 2546 | macro that returns its `&whole' argument." | ||
| 2540 | (while | 2547 | (while |
| 2541 | (let ((func (car-safe form)) (handler nil)) | 2548 | (let ((func (car-safe form)) (handler nil)) |
| 2542 | (while (and (symbolp func) | 2549 | (while (and (symbolp func) |
diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el index c5d0edf2009..3fb5b227c73 100644 --- a/lisp/emacs-lisp/cl.el +++ b/lisp/emacs-lisp/cl.el | |||
| @@ -547,13 +547,15 @@ deprecated usage of `symbol-function' in place forms)." ; bug#12760 | |||
| 547 | 547 | ||
| 548 | (defmacro define-setf-expander (name arglist &rest body) | 548 | (defmacro define-setf-expander (name arglist &rest body) |
| 549 | "Define a `setf' method. | 549 | "Define a `setf' method. |
| 550 | This method shows how to handle `setf's to places of the form (NAME ARGS...). | 550 | This method shows how to handle `setf's to places of the form |
| 551 | The argument forms ARGS are bound according to ARGLIST, as if NAME were | 551 | \(NAME ARGS...). The argument forms ARGS are bound according to |
| 552 | going to be expanded as a macro, then the BODY forms are executed and must | 552 | ARGLIST, as if NAME were going to be expanded as a macro, then |
| 553 | return a list of five elements: a temporary-variables list, a value-forms | 553 | the BODY forms are executed and must return a list of five elements: |
| 554 | list, a store-variables list (of length one), a store-form, and an access- | 554 | a temporary-variables list, a value-forms list, a store-variables list |
| 555 | form. See `gv-define-expander', `gv-define-setter', and `gv-define-expander' | 555 | \(of length one), a store-form, and an access- form. |
| 556 | for a better and simpler ways to define setf-methods." | 556 | |
| 557 | See `gv-define-expander', and `gv-define-setter' for better and | ||
| 558 | simpler ways to define setf-methods." | ||
| 557 | (declare (debug | 559 | (declare (debug |
| 558 | (&define name cl-lambda-list cl-declarations-or-string def-body))) | 560 | (&define name cl-lambda-list cl-declarations-or-string def-body))) |
| 559 | `(progn | 561 | `(progn |
| @@ -566,23 +568,31 @@ for a better and simpler ways to define setf-methods." | |||
| 566 | 568 | ||
| 567 | (defmacro defsetf (name arg1 &rest args) | 569 | (defmacro defsetf (name arg1 &rest args) |
| 568 | "Define a `setf' method. | 570 | "Define a `setf' method. |
| 569 | This macro is an easy-to-use substitute for `define-setf-expander' that works | 571 | This macro is an easy-to-use substitute for `define-setf-expander' |
| 570 | well for simple place forms. In the simple `defsetf' form, `setf's of | 572 | that works well for simple place forms. |
| 571 | the form (setf (NAME ARGS...) VAL) are transformed to function or macro | 573 | |
| 572 | calls of the form (FUNC ARGS... VAL). Example: | 574 | In the simple `defsetf' form, `setf's of the form (setf (NAME |
| 575 | ARGS...) VAL) are transformed to function or macro calls of the | ||
| 576 | form (FUNC ARGS... VAL). For example: | ||
| 573 | 577 | ||
| 574 | (defsetf aref aset) | 578 | (defsetf aref aset) |
| 575 | 579 | ||
| 580 | You can replace this form with `gv-define-simple-setter'. | ||
| 581 | |||
| 576 | Alternate form: (defsetf NAME ARGLIST (STORE) BODY...). | 582 | Alternate form: (defsetf NAME ARGLIST (STORE) BODY...). |
| 577 | Here, the above `setf' call is expanded by binding the argument forms ARGS | 583 | |
| 578 | according to ARGLIST, binding the value form VAL to STORE, then executing | 584 | Here, the above `setf' call is expanded by binding the argument |
| 579 | BODY, which must return a Lisp form that does the necessary `setf' operation. | 585 | forms ARGS according to ARGLIST, binding the value form VAL to |
| 580 | Actually, ARGLIST and STORE may be bound to temporary variables which are | 586 | STORE, then executing BODY, which must return a Lisp form that |
| 581 | introduced automatically to preserve proper execution order of the arguments. | 587 | does the necessary `setf' operation. Actually, ARGLIST and STORE |
| 582 | Example: | 588 | may be bound to temporary variables which are introduced |
| 589 | automatically to preserve proper execution order of the arguments. | ||
| 590 | For example: | ||
| 583 | 591 | ||
| 584 | (defsetf nth (n x) (v) `(setcar (nthcdr ,n ,x) ,v)) | 592 | (defsetf nth (n x) (v) `(setcar (nthcdr ,n ,x) ,v)) |
| 585 | 593 | ||
| 594 | You can replace this form with `gv-define-setter'. | ||
| 595 | |||
| 586 | \(fn NAME [FUNC | ARGLIST (STORE) BODY...])" | 596 | \(fn NAME [FUNC | ARGLIST (STORE) BODY...])" |
| 587 | (declare (debug | 597 | (declare (debug |
| 588 | (&define name | 598 | (&define name |
| @@ -597,7 +607,7 @@ Example: | |||
| 597 | (cl-function | 607 | (cl-function |
| 598 | (lambda (,@(car args) ,@arg1) ,@(cdr args))) | 608 | (lambda (,@(car args) ,@arg1) ,@(cdr args))) |
| 599 | do args))) | 609 | do args))) |
| 600 | `(gv-define-simple-setter ,name ,arg1))) | 610 | `(gv-define-simple-setter ,name ,arg1 ,(car args)))) |
| 601 | 611 | ||
| 602 | ;; FIXME: CL used to provide a setf method for `apply', but I haven't been able | 612 | ;; FIXME: CL used to provide a setf method for `apply', but I haven't been able |
| 603 | ;; to find a case where it worked. The code below tries to handle it as well. | 613 | ;; to find a case where it worked. The code below tries to handle it as well. |
| @@ -639,8 +649,12 @@ Example: | |||
| 639 | 649 | ||
| 640 | (defmacro define-modify-macro (name arglist func &optional doc) | 650 | (defmacro define-modify-macro (name arglist func &optional doc) |
| 641 | "Define a `setf'-like modify macro. | 651 | "Define a `setf'-like modify macro. |
| 642 | If NAME is called, it combines its PLACE argument with the other arguments | 652 | If NAME is called, it combines its PLACE argument with the other |
| 643 | from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" | 653 | arguments from ARGLIST using FUNC. For example: |
| 654 | |||
| 655 | (define-modify-macro incf (&optional (n 1)) +) | ||
| 656 | |||
| 657 | You can replace this macro with `gv-letplace'." | ||
| 644 | (declare (debug | 658 | (declare (debug |
| 645 | (&define name cl-lambda-list ;; should exclude &key | 659 | (&define name cl-lambda-list ;; should exclude &key |
| 646 | symbolp &optional stringp))) | 660 | symbolp &optional stringp))) |
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index c04e68c0cfa..3d4f41be8ee 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; debug.el --- debuggers and related commands for Emacs | 1 | ;;; debug.el --- debuggers and related commands for Emacs -*- lexical-binding: t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1985-1986, 1994, 2001-2012 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1985-1986, 1994, 2001-2012 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -81,9 +81,6 @@ The value used here is passed to `quit-restore-window'." | |||
| 81 | :group 'debugger | 81 | :group 'debugger |
| 82 | :version "24.2") | 82 | :version "24.2") |
| 83 | 83 | ||
| 84 | (defvar debug-function-list nil | ||
| 85 | "List of functions currently set for debug on entry.") | ||
| 86 | |||
| 87 | (defvar debugger-step-after-exit nil | 84 | (defvar debugger-step-after-exit nil |
| 88 | "Non-nil means \"single-step\" after the debugger exits.") | 85 | "Non-nil means \"single-step\" after the debugger exits.") |
| 89 | 86 | ||
| @@ -146,7 +143,7 @@ where CAUSE can be: | |||
| 146 | ;;;###autoload | 143 | ;;;###autoload |
| 147 | (setq debugger 'debug) | 144 | (setq debugger 'debug) |
| 148 | ;;;###autoload | 145 | ;;;###autoload |
| 149 | (defun debug (&rest debugger-args) | 146 | (defun debug (&rest args) |
| 150 | "Enter debugger. \\<debugger-mode-map>`\\[debugger-continue]' returns from the debugger. | 147 | "Enter debugger. \\<debugger-mode-map>`\\[debugger-continue]' returns from the debugger. |
| 151 | Arguments are mainly for use when this is called from the internals | 148 | Arguments are mainly for use when this is called from the internals |
| 152 | of the evaluator. | 149 | of the evaluator. |
| @@ -165,6 +162,7 @@ first will be printed into the backtrace buffer." | |||
| 165 | (if (get-buffer "*Backtrace*") | 162 | (if (get-buffer "*Backtrace*") |
| 166 | (with-current-buffer (get-buffer "*Backtrace*") | 163 | (with-current-buffer (get-buffer "*Backtrace*") |
| 167 | (list major-mode (buffer-string))))) | 164 | (list major-mode (buffer-string))))) |
| 165 | (debugger-args args) | ||
| 168 | (debugger-buffer (get-buffer-create "*Backtrace*")) | 166 | (debugger-buffer (get-buffer-create "*Backtrace*")) |
| 169 | (debugger-old-buffer (current-buffer)) | 167 | (debugger-old-buffer (current-buffer)) |
| 170 | (debugger-window nil) | 168 | (debugger-window nil) |
| @@ -219,7 +217,7 @@ first will be printed into the backtrace buffer." | |||
| 219 | (save-excursion | 217 | (save-excursion |
| 220 | (when (eq (car debugger-args) 'debug) | 218 | (when (eq (car debugger-args) 'debug) |
| 221 | ;; Skip the frames for backtrace-debug, byte-code, | 219 | ;; Skip the frames for backtrace-debug, byte-code, |
| 222 | ;; and implement-debug-on-entry. | 220 | ;; debug--implement-debug-on-entry and the advice's `apply'. |
| 223 | (backtrace-debug 4 t) | 221 | (backtrace-debug 4 t) |
| 224 | ;; Place an extra debug-on-exit for macro's. | 222 | ;; Place an extra debug-on-exit for macro's. |
| 225 | (when (eq 'lambda (car-safe (cadr (backtrace-frame 4)))) | 223 | (when (eq 'lambda (car-safe (cadr (backtrace-frame 4)))) |
| @@ -318,7 +316,7 @@ first will be printed into the backtrace buffer." | |||
| 318 | (setq debug-on-next-call debugger-step-after-exit) | 316 | (setq debug-on-next-call debugger-step-after-exit) |
| 319 | debugger-value))) | 317 | debugger-value))) |
| 320 | 318 | ||
| 321 | (defun debugger-setup-buffer (debugger-args) | 319 | (defun debugger-setup-buffer (args) |
| 322 | "Initialize the `*Backtrace*' buffer for entry to the debugger. | 320 | "Initialize the `*Backtrace*' buffer for entry to the debugger. |
| 323 | That buffer should be current already." | 321 | That buffer should be current already." |
| 324 | (setq buffer-read-only nil) | 322 | (setq buffer-read-only nil) |
| @@ -334,20 +332,22 @@ That buffer should be current already." | |||
| 334 | (delete-region (point) | 332 | (delete-region (point) |
| 335 | (progn | 333 | (progn |
| 336 | (search-forward "\n debug(") | 334 | (search-forward "\n debug(") |
| 337 | (forward-line (if (eq (car debugger-args) 'debug) | 335 | (forward-line (if (eq (car args) 'debug) |
| 338 | 2 ; Remove implement-debug-on-entry frame. | 336 | ;; Remove debug--implement-debug-on-entry |
| 337 | ;; and the advice's `apply' frame. | ||
| 338 | 3 | ||
| 339 | 1)) | 339 | 1)) |
| 340 | (point))) | 340 | (point))) |
| 341 | (insert "Debugger entered") | 341 | (insert "Debugger entered") |
| 342 | ;; lambda is for debug-on-call when a function call is next. | 342 | ;; lambda is for debug-on-call when a function call is next. |
| 343 | ;; debug is for debug-on-entry function called. | 343 | ;; debug is for debug-on-entry function called. |
| 344 | (pcase (car debugger-args) | 344 | (pcase (car args) |
| 345 | ((or `lambda `debug) | 345 | ((or `lambda `debug) |
| 346 | (insert "--entering a function:\n")) | 346 | (insert "--entering a function:\n")) |
| 347 | ;; Exiting a function. | 347 | ;; Exiting a function. |
| 348 | (`exit | 348 | (`exit |
| 349 | (insert "--returning value: ") | 349 | (insert "--returning value: ") |
| 350 | (setq debugger-value (nth 1 debugger-args)) | 350 | (setq debugger-value (nth 1 args)) |
| 351 | (prin1 debugger-value (current-buffer)) | 351 | (prin1 debugger-value (current-buffer)) |
| 352 | (insert ?\n) | 352 | (insert ?\n) |
| 353 | (delete-char 1) | 353 | (delete-char 1) |
| @@ -356,7 +356,7 @@ That buffer should be current already." | |||
| 356 | ;; Debugger entered for an error. | 356 | ;; Debugger entered for an error. |
| 357 | (`error | 357 | (`error |
| 358 | (insert "--Lisp error: ") | 358 | (insert "--Lisp error: ") |
| 359 | (prin1 (nth 1 debugger-args) (current-buffer)) | 359 | (prin1 (nth 1 args) (current-buffer)) |
| 360 | (insert ?\n)) | 360 | (insert ?\n)) |
| 361 | ;; debug-on-call, when the next thing is an eval. | 361 | ;; debug-on-call, when the next thing is an eval. |
| 362 | (`t | 362 | (`t |
| @@ -364,8 +364,8 @@ That buffer should be current already." | |||
| 364 | ;; User calls debug directly. | 364 | ;; User calls debug directly. |
| 365 | (_ | 365 | (_ |
| 366 | (insert ": ") | 366 | (insert ": ") |
| 367 | (prin1 (if (eq (car debugger-args) 'nil) | 367 | (prin1 (if (eq (car args) 'nil) |
| 368 | (cdr debugger-args) debugger-args) | 368 | (cdr args) args) |
| 369 | (current-buffer)) | 369 | (current-buffer)) |
| 370 | (insert ?\n))) | 370 | (insert ?\n))) |
| 371 | ;; After any frame that uses eval-buffer, | 371 | ;; After any frame that uses eval-buffer, |
| @@ -525,9 +525,10 @@ removes itself from that hook." | |||
| 525 | (count 0)) | 525 | (count 0)) |
| 526 | (while (not (eq (cadr (backtrace-frame count)) 'debug)) | 526 | (while (not (eq (cadr (backtrace-frame count)) 'debug)) |
| 527 | (setq count (1+ count))) | 527 | (setq count (1+ count))) |
| 528 | ;; Skip implement-debug-on-entry frame. | 528 | ;; Skip debug--implement-debug-on-entry frame. |
| 529 | (when (eq 'implement-debug-on-entry (cadr (backtrace-frame (1+ count)))) | 529 | (when (eq 'debug--implement-debug-on-entry |
| 530 | (setq count (1+ count))) | 530 | (cadr (backtrace-frame (1+ count)))) |
| 531 | (setq count (+ 2 count))) | ||
| 531 | (goto-char (point-min)) | 532 | (goto-char (point-min)) |
| 532 | (when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):") | 533 | (when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):") |
| 533 | (goto-char (match-end 0)) | 534 | (goto-char (match-end 0)) |
| @@ -694,10 +695,10 @@ Applies to the frame whose line point is on in the backtrace." | |||
| 694 | :help "Continue to exit from this frame, with all debug-on-entry suspended")) | 695 | :help "Continue to exit from this frame, with all debug-on-entry suspended")) |
| 695 | (define-key menu-map [deb-cont] | 696 | (define-key menu-map [deb-cont] |
| 696 | '(menu-item "Continue" debugger-continue | 697 | '(menu-item "Continue" debugger-continue |
| 697 | :help "Continue, evaluating this expression without stopping")) | 698 | :help "Continue, evaluating this expression without stopping")) |
| 698 | (define-key menu-map [deb-step] | 699 | (define-key menu-map [deb-step] |
| 699 | '(menu-item "Step through" debugger-step-through | 700 | '(menu-item "Step through" debugger-step-through |
| 700 | :help "Proceed, stepping through subexpressions of this expression")) | 701 | :help "Proceed, stepping through subexpressions of this expression")) |
| 701 | map)) | 702 | map)) |
| 702 | 703 | ||
| 703 | (put 'debugger-mode 'mode-class 'special) | 704 | (put 'debugger-mode 'mode-class 'special) |
| @@ -777,7 +778,7 @@ For the cross-reference format, see `help-make-xrefs'." | |||
| 777 | 778 | ||
| 778 | ;; When you change this, you may also need to change the number of | 779 | ;; When you change this, you may also need to change the number of |
| 779 | ;; frames that the debugger skips. | 780 | ;; frames that the debugger skips. |
| 780 | (defun implement-debug-on-entry () | 781 | (defun debug--implement-debug-on-entry (&rest _ignore) |
| 781 | "Conditionally call the debugger. | 782 | "Conditionally call the debugger. |
| 782 | A call to this function is inserted by `debug-on-entry' to cause | 783 | A call to this function is inserted by `debug-on-entry' to cause |
| 783 | functions to break on entry." | 784 | functions to break on entry." |
| @@ -785,12 +786,6 @@ functions to break on entry." | |||
| 785 | nil | 786 | nil |
| 786 | (funcall debugger 'debug))) | 787 | (funcall debugger 'debug))) |
| 787 | 788 | ||
| 788 | (defun debugger-special-form-p (symbol) | ||
| 789 | "Return whether SYMBOL is a special form." | ||
| 790 | (and (fboundp symbol) | ||
| 791 | (subrp (symbol-function symbol)) | ||
| 792 | (eq (cdr (subr-arity (symbol-function symbol))) 'unevalled))) | ||
| 793 | |||
| 794 | ;;;###autoload | 789 | ;;;###autoload |
| 795 | (defun debug-on-entry (function) | 790 | (defun debug-on-entry (function) |
| 796 | "Request FUNCTION to invoke debugger each time it is called. | 791 | "Request FUNCTION to invoke debugger each time it is called. |
| @@ -808,7 +803,7 @@ Use \\[cancel-debug-on-entry] to cancel the effect of this command. | |||
| 808 | Redefining FUNCTION also cancels it." | 803 | Redefining FUNCTION also cancels it." |
| 809 | (interactive | 804 | (interactive |
| 810 | (let ((fn (function-called-at-point)) val) | 805 | (let ((fn (function-called-at-point)) val) |
| 811 | (when (debugger-special-form-p fn) | 806 | (when (special-form-p fn) |
| 812 | (setq fn nil)) | 807 | (setq fn nil)) |
| 813 | (setq val (completing-read | 808 | (setq val (completing-read |
| 814 | (if fn | 809 | (if fn |
| @@ -817,36 +812,21 @@ Redefining FUNCTION also cancels it." | |||
| 817 | obarray | 812 | obarray |
| 818 | #'(lambda (symbol) | 813 | #'(lambda (symbol) |
| 819 | (and (fboundp symbol) | 814 | (and (fboundp symbol) |
| 820 | (not (debugger-special-form-p symbol)))) | 815 | (not (special-form-p symbol)))) |
| 821 | t nil nil (symbol-name fn))) | 816 | t nil nil (symbol-name fn))) |
| 822 | (list (if (equal val "") fn (intern val))))) | 817 | (list (if (equal val "") fn (intern val))))) |
| 823 | ;; FIXME: Use advice.el. | 818 | (advice-add function :before #'debug--implement-debug-on-entry) |
| 824 | (when (debugger-special-form-p function) | ||
| 825 | (error "Function %s is a special form" function)) | ||
| 826 | (if (or (symbolp (symbol-function function)) | ||
| 827 | (subrp (symbol-function function))) | ||
| 828 | ;; The function is built-in or aliased to another function. | ||
| 829 | ;; Create a wrapper in which we can add the debug call. | ||
| 830 | (fset function `(lambda (&rest debug-on-entry-args) | ||
| 831 | ,(interactive-form (symbol-function function)) | ||
| 832 | (apply ',(symbol-function function) | ||
| 833 | debug-on-entry-args))) | ||
| 834 | (when (autoloadp (symbol-function function)) | ||
| 835 | ;; The function is autoloaded. Load its real definition. | ||
| 836 | (autoload-do-load (symbol-function function) function)) | ||
| 837 | (when (or (not (consp (symbol-function function))) | ||
| 838 | (and (eq (car (symbol-function function)) 'macro) | ||
| 839 | (not (consp (cdr (symbol-function function)))))) | ||
| 840 | ;; The function is byte-compiled. Create a wrapper in which | ||
| 841 | ;; we can add the debug call. | ||
| 842 | (debug-convert-byte-code function))) | ||
| 843 | (unless (consp (symbol-function function)) | ||
| 844 | (error "Definition of %s is not a list" function)) | ||
| 845 | (fset function (debug-on-entry-1 function t)) | ||
| 846 | (unless (memq function debug-function-list) | ||
| 847 | (push function debug-function-list)) | ||
| 848 | function) | 819 | function) |
| 849 | 820 | ||
| 821 | (defun debug--function-list () | ||
| 822 | "List of functions currently set for debug on entry." | ||
| 823 | (let ((funs '())) | ||
| 824 | (mapatoms | ||
| 825 | (lambda (s) | ||
| 826 | (when (advice-member-p #'debug--implement-debug-on-entry s) | ||
| 827 | (push s funs)))) | ||
| 828 | funs)) | ||
| 829 | |||
| 850 | ;;;###autoload | 830 | ;;;###autoload |
| 851 | (defun cancel-debug-on-entry (&optional function) | 831 | (defun cancel-debug-on-entry (&optional function) |
| 852 | "Undo effect of \\[debug-on-entry] on FUNCTION. | 832 | "Undo effect of \\[debug-on-entry] on FUNCTION. |
| @@ -857,80 +837,16 @@ To specify a nil argument interactively, exit with an empty minibuffer." | |||
| 857 | (list (let ((name | 837 | (list (let ((name |
| 858 | (completing-read | 838 | (completing-read |
| 859 | "Cancel debug on entry to function (default all functions): " | 839 | "Cancel debug on entry to function (default all functions): " |
| 860 | (mapcar 'symbol-name debug-function-list) nil t))) | 840 | (mapcar #'symbol-name (debug--function-list)) nil t))) |
| 861 | (when name | 841 | (when name |
| 862 | (unless (string= name "") | 842 | (unless (string= name "") |
| 863 | (intern name)))))) | 843 | (intern name)))))) |
| 864 | (if (and function | 844 | (if function |
| 865 | (not (string= function ""))) ; Pre 22.1 compatibility test. | ||
| 866 | (progn | 845 | (progn |
| 867 | (let ((defn (debug-on-entry-1 function nil))) | 846 | (advice-remove function #'debug--implement-debug-on-entry) |
| 868 | (condition-case nil | ||
| 869 | (when (and (equal (nth 1 defn) '(&rest debug-on-entry-args)) | ||
| 870 | (eq (car (nth 3 defn)) 'apply)) | ||
| 871 | ;; `defn' is a wrapper introduced in debug-on-entry. | ||
| 872 | ;; Get rid of it since we don't need it any more. | ||
| 873 | (setq defn (nth 1 (nth 1 (nth 3 defn))))) | ||
| 874 | (error nil)) | ||
| 875 | (fset function defn)) | ||
| 876 | (setq debug-function-list (delq function debug-function-list)) | ||
| 877 | function) | 847 | function) |
| 878 | (message "Cancelling debug-on-entry for all functions") | 848 | (message "Cancelling debug-on-entry for all functions") |
| 879 | (mapcar 'cancel-debug-on-entry debug-function-list))) | 849 | (mapcar #'cancel-debug-on-entry (debug--function-list)))) |
| 880 | |||
| 881 | (defun debug-arglist (definition) | ||
| 882 | ;; FIXME: copied from ad-arglist. | ||
| 883 | "Return the argument list of DEFINITION." | ||
| 884 | (require 'help-fns) | ||
| 885 | (help-function-arglist definition 'preserve-names)) | ||
| 886 | |||
| 887 | (defun debug-convert-byte-code (function) | ||
| 888 | (let* ((defn (symbol-function function)) | ||
| 889 | (macro (eq (car-safe defn) 'macro))) | ||
| 890 | (when macro (setq defn (cdr defn))) | ||
| 891 | (when (byte-code-function-p defn) | ||
| 892 | (let* ((args (debug-arglist defn)) | ||
| 893 | (body | ||
| 894 | `((,(if (memq '&rest args) #'apply #'funcall) | ||
| 895 | ,defn | ||
| 896 | ,@(remq '&rest (remq '&optional args)))))) | ||
| 897 | (if (> (length defn) 5) | ||
| 898 | ;; The mere presence of field 5 is sufficient to make | ||
| 899 | ;; it interactive. | ||
| 900 | (push `(interactive ,(aref defn 5)) body)) | ||
| 901 | (if (and (> (length defn) 4) (aref defn 4)) | ||
| 902 | ;; Use `documentation' here, to get the actual string, | ||
| 903 | ;; in case the compiled function has a reference | ||
| 904 | ;; to the .elc file. | ||
| 905 | (setq body (cons (documentation function) body))) | ||
| 906 | (setq defn `(closure (t) ,args ,@body))) | ||
| 907 | (when macro (setq defn (cons 'macro defn))) | ||
| 908 | (fset function defn)))) | ||
| 909 | |||
| 910 | (defun debug-on-entry-1 (function flag) | ||
| 911 | (let* ((defn (symbol-function function)) | ||
| 912 | (tail defn)) | ||
| 913 | (when (eq (car-safe tail) 'macro) | ||
| 914 | (setq tail (cdr tail))) | ||
| 915 | (if (not (memq (car-safe tail) '(closure lambda))) | ||
| 916 | ;; Only signal an error when we try to set debug-on-entry. | ||
| 917 | ;; When we try to clear debug-on-entry, we are now done. | ||
| 918 | (when flag | ||
| 919 | (error "%s is not a user-defined Lisp function" function)) | ||
| 920 | (if (eq (car tail) 'closure) (setq tail (cdr tail))) | ||
| 921 | (setq tail (cdr tail)) | ||
| 922 | ;; Skip the docstring. | ||
| 923 | (when (and (stringp (cadr tail)) (cddr tail)) | ||
| 924 | (setq tail (cdr tail))) | ||
| 925 | ;; Skip the interactive form. | ||
| 926 | (when (eq 'interactive (car-safe (cadr tail))) | ||
| 927 | (setq tail (cdr tail))) | ||
| 928 | (unless (eq flag (equal (cadr tail) '(implement-debug-on-entry))) | ||
| 929 | ;; Add/remove debug statement as needed. | ||
| 930 | (setcdr tail (if flag | ||
| 931 | (cons '(implement-debug-on-entry) (cdr tail)) | ||
| 932 | (cddr tail))))) | ||
| 933 | defn)) | ||
| 934 | 850 | ||
| 935 | (defun debugger-list-functions () | 851 | (defun debugger-list-functions () |
| 936 | "Display a list of all the functions now set to debug on entry." | 852 | "Display a list of all the functions now set to debug on entry." |
| @@ -940,17 +856,18 @@ To specify a nil argument interactively, exit with an empty minibuffer." | |||
| 940 | (called-interactively-p 'interactive)) | 856 | (called-interactively-p 'interactive)) |
| 941 | (with-output-to-temp-buffer (help-buffer) | 857 | (with-output-to-temp-buffer (help-buffer) |
| 942 | (with-current-buffer standard-output | 858 | (with-current-buffer standard-output |
| 943 | (if (null debug-function-list) | 859 | (let ((funs (debug--function-list))) |
| 944 | (princ "No debug-on-entry functions now\n") | 860 | (if (null funs) |
| 945 | (princ "Functions set to debug on entry:\n\n") | 861 | (princ "No debug-on-entry functions now\n") |
| 946 | (dolist (fun debug-function-list) | 862 | (princ "Functions set to debug on entry:\n\n") |
| 947 | (make-text-button (point) (progn (prin1 fun) (point)) | 863 | (dolist (fun funs) |
| 948 | 'type 'help-function | 864 | (make-text-button (point) (progn (prin1 fun) (point)) |
| 949 | 'help-args (list fun)) | 865 | 'type 'help-function |
| 950 | (terpri)) | 866 | 'help-args (list fun)) |
| 951 | (terpri) | 867 | (terpri)) |
| 952 | (princ "Note: if you have redefined a function, then it may no longer\n") | 868 | (terpri) |
| 953 | (princ "be set to debug on entry, even if it is in the list."))))) | 869 | (princ "Note: if you have redefined a function, then it may no longer\n") |
| 870 | (princ "be set to debug on entry, even if it is in the list.")))))) | ||
| 954 | 871 | ||
| 955 | (provide 'debug) | 872 | (provide 'debug) |
| 956 | 873 | ||
diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el index b94817cdb02..067b45f5cd8 100644 --- a/lisp/emacs-lisp/elp.el +++ b/lisp/emacs-lisp/elp.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; elp.el --- Emacs Lisp Profiler | 1 | ;;; elp.el --- Emacs Lisp Profiler -*- lexical-binding: t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1994-1995, 1997-1998, 2001-2012 | 3 | ;; Copyright (C) 1994-1995, 1997-1998, 2001-2012 |
| 4 | ;; Free Software Foundation, Inc. | 4 | ;; Free Software Foundation, Inc. |
| @@ -124,6 +124,7 @@ | |||
| 124 | 124 | ||
| 125 | ;;; Code: | 125 | ;;; Code: |
| 126 | 126 | ||
| 127 | (eval-when-compile (require 'cl-lib)) | ||
| 127 | 128 | ||
| 128 | ;; start of user configuration variables | 129 | ;; start of user configuration variables |
| 129 | ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 130 | ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv |
| @@ -148,9 +149,9 @@ Results are displayed with the `elp-results' command." | |||
| 148 | "Non-nil specifies ELP results sorting function. | 149 | "Non-nil specifies ELP results sorting function. |
| 149 | These functions are currently available: | 150 | These functions are currently available: |
| 150 | 151 | ||
| 151 | elp-sort-by-call-count -- sort by the highest call count | 152 | `elp-sort-by-call-count' -- sort by the highest call count |
| 152 | elp-sort-by-total-time -- sort by the highest total time | 153 | `elp-sort-by-total-time' -- sort by the highest total time |
| 153 | elp-sort-by-average-time -- sort by the highest average times | 154 | `elp-sort-by-average-time' -- sort by the highest average times |
| 154 | 155 | ||
| 155 | You can write your own sort function. It should adhere to the | 156 | You can write your own sort function. It should adhere to the |
| 156 | interface specified by the PREDICATE argument for `sort'. | 157 | interface specified by the PREDICATE argument for `sort'. |
| @@ -167,7 +168,7 @@ If a number, no function that has been called fewer than that number | |||
| 167 | of times will be displayed in the output buffer. If nil, all | 168 | of times will be displayed in the output buffer. If nil, all |
| 168 | functions will be displayed." | 169 | functions will be displayed." |
| 169 | :type '(choice integer | 170 | :type '(choice integer |
| 170 | (const :tag "Show All" nil)) | 171 | (const :tag "Show All" nil)) |
| 171 | :group 'elp) | 172 | :group 'elp) |
| 172 | 173 | ||
| 173 | (defcustom elp-use-standard-output nil | 174 | (defcustom elp-use-standard-output nil |
| @@ -193,9 +194,6 @@ In other words, a new unique buffer is create every time you run | |||
| 193 | (defconst elp-timer-info-property 'elp-info | 194 | (defconst elp-timer-info-property 'elp-info |
| 194 | "ELP information property name.") | 195 | "ELP information property name.") |
| 195 | 196 | ||
| 196 | (defvar elp-all-instrumented-list nil | ||
| 197 | "List of all functions currently being instrumented.") | ||
| 198 | |||
| 199 | (defvar elp-record-p t | 197 | (defvar elp-record-p t |
| 200 | "Controls whether functions should record times or not. | 198 | "Controls whether functions should record times or not. |
| 201 | This variable is set by the master function.") | 199 | This variable is set by the master function.") |
| @@ -205,7 +203,7 @@ This variable is set by the master function.") | |||
| 205 | 203 | ||
| 206 | (defvar elp-not-profilable | 204 | (defvar elp-not-profilable |
| 207 | ;; First, the functions used inside each instrumented function: | 205 | ;; First, the functions used inside each instrumented function: |
| 208 | '(elp-wrapper called-interactively-p | 206 | '(called-interactively-p |
| 209 | ;; Then the functions used by the above functions. I used | 207 | ;; Then the functions used by the above functions. I used |
| 210 | ;; (delq nil (mapcar (lambda (x) (and (symbolp x) (fboundp x) x)) | 208 | ;; (delq nil (mapcar (lambda (x) (and (symbolp x) (fboundp x) x)) |
| 211 | ;; (aref (symbol-function 'elp-wrapper) 2))) | 209 | ;; (aref (symbol-function 'elp-wrapper) 2))) |
| @@ -223,60 +221,21 @@ them would thus lead to infinite recursion.") | |||
| 223 | (fboundp fun) | 221 | (fboundp fun) |
| 224 | (not (or (memq fun elp-not-profilable) | 222 | (not (or (memq fun elp-not-profilable) |
| 225 | (keymapp fun) | 223 | (keymapp fun) |
| 226 | (memq (car-safe (symbol-function fun)) '(autoload macro)) | 224 | (autoloadp (symbol-function fun)) ;FIXME: Why not just load it? |
| 227 | (condition-case nil | 225 | (special-form-p fun))))) |
| 228 | (when (subrp (indirect-function fun)) | ||
| 229 | (eq 'unevalled | ||
| 230 | (cdr (subr-arity (indirect-function fun))))) | ||
| 231 | (error nil)))))) | ||
| 232 | 226 | ||
| 227 | (defconst elp--advice-name 'ELP-instrumentation\ ) | ||
| 233 | 228 | ||
| 234 | ;;;###autoload | 229 | ;;;###autoload |
| 235 | (defun elp-instrument-function (funsym) | 230 | (defun elp-instrument-function (funsym) |
| 236 | "Instrument FUNSYM for profiling. | 231 | "Instrument FUNSYM for profiling. |
| 237 | FUNSYM must be a symbol of a defined function." | 232 | FUNSYM must be a symbol of a defined function." |
| 238 | (interactive "aFunction to instrument: ") | 233 | (interactive "aFunction to instrument: ") |
| 239 | ;; restore the function. this is necessary to avoid infinite | 234 | (let* ((infovec (vector 0 0))) |
| 240 | ;; recursion of already instrumented functions (i.e. elp-wrapper | ||
| 241 | ;; calling elp-wrapper ad infinitum). it is better to simply | ||
| 242 | ;; restore the function than to throw an error. this will work | ||
| 243 | ;; properly in the face of eval-defun because if the function was | ||
| 244 | ;; redefined, only the timer info will be nil'd out since | ||
| 245 | ;; elp-restore-function is smart enough not to trash the new | ||
| 246 | ;; definition. | ||
| 247 | (elp-restore-function funsym) | ||
| 248 | (let* ((funguts (symbol-function funsym)) | ||
| 249 | (infovec (vector 0 0 funguts)) | ||
| 250 | (newguts '(lambda (&rest args)))) | ||
| 251 | ;; we cannot profile macros | ||
| 252 | (and (eq (car-safe funguts) 'macro) | ||
| 253 | (error "ELP cannot profile macro: %s" funsym)) | ||
| 254 | ;; TBD: at some point it might be better to load the autoloaded | ||
| 255 | ;; function instead of throwing an error. if we do this, then we | ||
| 256 | ;; probably want elp-instrument-package to be updated with the | ||
| 257 | ;; newly loaded list of functions. i'm not sure it's smart to do | ||
| 258 | ;; the autoload here, since that could have side effects, and | ||
| 259 | ;; elp-instrument-function is similar (in my mind) to defun-ish | ||
| 260 | ;; type functionality (i.e. it shouldn't execute the function). | ||
| 261 | (and (autoloadp funguts) | ||
| 262 | (error "ELP cannot profile autoloaded function: %s" funsym)) | ||
| 263 | ;; We cannot profile functions used internally during profiling. | 235 | ;; We cannot profile functions used internally during profiling. |
| 264 | (unless (elp-profilable-p funsym) | 236 | (unless (elp-profilable-p funsym) |
| 265 | (error "ELP cannot profile the function: %s" funsym)) | 237 | (error "ELP cannot profile the function: %s" funsym)) |
| 266 | ;; put rest of newguts together | 238 | ;; The info vector data structure is a 2 element vector. The 0th |
| 267 | (if (commandp funsym) | ||
| 268 | (setq newguts (append newguts '((interactive))))) | ||
| 269 | (setq newguts (append newguts `((elp-wrapper | ||
| 270 | (quote ,funsym) | ||
| 271 | ,(when (commandp funsym) | ||
| 272 | '(called-interactively-p 'any)) | ||
| 273 | args)))) | ||
| 274 | ;; to record profiling times, we set the symbol's function | ||
| 275 | ;; definition so that it runs the elp-wrapper function with the | ||
| 276 | ;; function symbol as an argument. We place the old function | ||
| 277 | ;; definition on the info vector. | ||
| 278 | ;; | ||
| 279 | ;; The info vector data structure is a 3 element vector. The 0th | ||
| 280 | ;; element is the call-count, i.e. the total number of times this | 239 | ;; element is the call-count, i.e. the total number of times this |
| 281 | ;; function has been entered. This value is bumped up on entry to | 240 | ;; function has been entered. This value is bumped up on entry to |
| 282 | ;; the function so that non-local exists are still recorded. TBD: | 241 | ;; the function so that non-local exists are still recorded. TBD: |
| @@ -285,72 +244,45 @@ FUNSYM must be a symbol of a defined function." | |||
| 285 | ;; The 1st element is the total amount of time in seconds that has | 244 | ;; The 1st element is the total amount of time in seconds that has |
| 286 | ;; been spent inside this function. This number is added to on | 245 | ;; been spent inside this function. This number is added to on |
| 287 | ;; function exit. | 246 | ;; function exit. |
| 288 | ;; | ||
| 289 | ;; The 2nd element is the old function definition list. This gets | ||
| 290 | ;; funcall'd in between start/end time retrievals. I believe that | ||
| 291 | ;; this lets us profile even byte-compiled functions. | ||
| 292 | 247 | ||
| 293 | ;; put the info vector on the property list | 248 | ;; Put the info vector on the property list. |
| 294 | (put funsym elp-timer-info-property infovec) | 249 | (put funsym elp-timer-info-property infovec) |
| 295 | 250 | ||
| 296 | ;; Set the symbol's new profiling function definition to run | 251 | ;; Set the symbol's new profiling function definition to run |
| 297 | ;; elp-wrapper. | 252 | ;; ELP wrapper. |
| 298 | (let ((advice-info (get funsym 'ad-advice-info))) | 253 | (advice-add funsym :around (elp--make-wrapper funsym) |
| 299 | (if advice-info | 254 | `((name . ,elp--advice-name))))) |
| 300 | (progn | 255 | |
| 301 | ;; If function is advised, don't let Advice change | 256 | (defun elp--instrumented-p (sym) |
| 302 | ;; its definition from under us during the `fset'. | 257 | (advice-member-p elp--advice-name sym)) |
| 303 | (put funsym 'ad-advice-info nil) | ||
| 304 | (fset funsym newguts) | ||
| 305 | (put funsym 'ad-advice-info advice-info)) | ||
| 306 | (fset funsym newguts))) | ||
| 307 | |||
| 308 | ;; add this function to the instrumentation list | ||
| 309 | (unless (memq funsym elp-all-instrumented-list) | ||
| 310 | (push funsym elp-all-instrumented-list)))) | ||
| 311 | 258 | ||
| 312 | (defun elp-restore-function (funsym) | 259 | (defun elp-restore-function (funsym) |
| 313 | "Restore an instrumented function to its original definition. | 260 | "Restore an instrumented function to its original definition. |
| 314 | Argument FUNSYM is the symbol of a defined function." | 261 | Argument FUNSYM is the symbol of a defined function." |
| 315 | (interactive "aFunction to restore: ") | 262 | (interactive |
| 316 | (let ((info (get funsym elp-timer-info-property))) | 263 | (list |
| 317 | ;; delete the function from the all instrumented list | 264 | (intern |
| 318 | (setq elp-all-instrumented-list | 265 | (completing-read "Function to restore: " obarray |
| 319 | (delq funsym elp-all-instrumented-list)) | 266 | #'elp--instrumented-p t)))) |
| 320 | 267 | ;; If the function was the master, reset the master. | |
| 321 | ;; if the function was the master, reset the master | 268 | (if (eq funsym elp-master) |
| 322 | (if (eq funsym elp-master) | 269 | (setq elp-master nil |
| 323 | (setq elp-master nil | 270 | elp-record-p t)) |
| 324 | elp-record-p t)) | 271 | |
| 325 | 272 | ;; Zap the properties. | |
| 326 | ;; zap the properties | 273 | (put funsym elp-timer-info-property nil) |
| 327 | (put funsym elp-timer-info-property nil) | 274 | |
| 328 | 275 | (advice-remove funsym elp--advice-name)) | |
| 329 | ;; restore the original function definition, but if the function | ||
| 330 | ;; wasn't instrumented do nothing. we do this after the above | ||
| 331 | ;; because its possible the function got un-instrumented due to | ||
| 332 | ;; circumstances beyond our control. Also, check to make sure | ||
| 333 | ;; that the current function symbol points to elp-wrapper. If | ||
| 334 | ;; not, then the user probably did an eval-defun, or loaded a | ||
| 335 | ;; byte-compiled version, while the function was instrumented and | ||
| 336 | ;; we don't want to destroy the new definition. can it ever be | ||
| 337 | ;; the case that a lisp function can be compiled instrumented? | ||
| 338 | (and info | ||
| 339 | (functionp funsym) | ||
| 340 | (not (byte-code-function-p (symbol-function funsym))) | ||
| 341 | (assq 'elp-wrapper (symbol-function funsym)) | ||
| 342 | (fset funsym (aref info 2))))) | ||
| 343 | 276 | ||
| 344 | ;;;###autoload | 277 | ;;;###autoload |
| 345 | (defun elp-instrument-list (&optional list) | 278 | (defun elp-instrument-list (&optional list) |
| 346 | "Instrument, for profiling, all functions in `elp-function-list'. | 279 | "Instrument, for profiling, all functions in `elp-function-list'. |
| 347 | Use optional LIST if provided instead. | 280 | Use optional LIST if provided instead. |
| 348 | If called interactively, read LIST using the minibuffer." | 281 | If called interactively, read LIST using the minibuffer." |
| 349 | (interactive "PList of functions to instrument: ") | 282 | (interactive "PList of functions to instrument: ") ;FIXME: Doesn't work?! |
| 350 | (unless (listp list) | 283 | (unless (listp list) |
| 351 | (signal 'wrong-type-argument (list 'listp list))) | 284 | (signal 'wrong-type-argument (list 'listp list))) |
| 352 | (let ((list (or list elp-function-list))) | 285 | (mapcar #'elp-instrument-function (or list elp-function-list))) |
| 353 | (mapcar 'elp-instrument-function list))) | ||
| 354 | 286 | ||
| 355 | ;;;###autoload | 287 | ;;;###autoload |
| 356 | (defun elp-instrument-package (prefix) | 288 | (defun elp-instrument-package (prefix) |
| @@ -371,15 +303,13 @@ For example, to instrument all ELP functions, do the following: | |||
| 371 | (defun elp-restore-list (&optional list) | 303 | (defun elp-restore-list (&optional list) |
| 372 | "Restore the original definitions for all functions in `elp-function-list'. | 304 | "Restore the original definitions for all functions in `elp-function-list'. |
| 373 | Use optional LIST if provided instead." | 305 | Use optional LIST if provided instead." |
| 374 | (interactive "PList of functions to restore: ") | 306 | (interactive "PList of functions to restore: ") ;FIXME: Doesn't work!? |
| 375 | (let ((list (or list elp-function-list))) | 307 | (mapcar #'elp-restore-function (or list elp-function-list))) |
| 376 | (mapcar 'elp-restore-function list))) | ||
| 377 | 308 | ||
| 378 | (defun elp-restore-all () | 309 | (defun elp-restore-all () |
| 379 | "Restore the original definitions of all functions being profiled." | 310 | "Restore the original definitions of all functions being profiled." |
| 380 | (interactive) | 311 | (interactive) |
| 381 | (elp-restore-list elp-all-instrumented-list)) | 312 | (mapatoms #'elp-restore-function)) |
| 382 | |||
| 383 | 313 | ||
| 384 | (defun elp-reset-function (funsym) | 314 | (defun elp-reset-function (funsym) |
| 385 | "Reset the profiling information for FUNSYM." | 315 | "Reset the profiling information for FUNSYM." |
| @@ -395,30 +325,36 @@ Use optional LIST if provided instead." | |||
| 395 | (defun elp-reset-list (&optional list) | 325 | (defun elp-reset-list (&optional list) |
| 396 | "Reset the profiling information for all functions in `elp-function-list'. | 326 | "Reset the profiling information for all functions in `elp-function-list'. |
| 397 | Use optional LIST if provided instead." | 327 | Use optional LIST if provided instead." |
| 398 | (interactive "PList of functions to reset: ") | 328 | (interactive "PList of functions to reset: ") ;FIXME: Doesn't work!? |
| 399 | (let ((list (or list elp-function-list))) | 329 | (let ((list (or list elp-function-list))) |
| 400 | (mapcar 'elp-reset-function list))) | 330 | (mapcar 'elp-reset-function list))) |
| 401 | 331 | ||
| 402 | (defun elp-reset-all () | 332 | (defun elp-reset-all () |
| 403 | "Reset the profiling information for all functions being profiled." | 333 | "Reset the profiling information for all functions being profiled." |
| 404 | (interactive) | 334 | (interactive) |
| 405 | (elp-reset-list elp-all-instrumented-list)) | 335 | (mapatoms (lambda (sym) |
| 336 | (if (get sym elp-timer-info-property) | ||
| 337 | (elp-reset-function sym))))) | ||
| 406 | 338 | ||
| 407 | (defun elp-set-master (funsym) | 339 | (defun elp-set-master (funsym) |
| 408 | "Set the master function for profiling." | 340 | "Set the master function for profiling." |
| 409 | (interactive "aMaster function: ") | 341 | (interactive |
| 410 | ;; when there's a master function, recording is turned off by | 342 | (list |
| 411 | ;; default | 343 | (intern |
| 344 | (completing-read "Master function: " obarray | ||
| 345 | #'elp--instrumented-p | ||
| 346 | t nil nil (if elp-master (symbol-name elp-master)))))) | ||
| 347 | ;; When there's a master function, recording is turned off by default. | ||
| 412 | (setq elp-master funsym | 348 | (setq elp-master funsym |
| 413 | elp-record-p nil) | 349 | elp-record-p nil) |
| 414 | ;; make sure master function is instrumented | 350 | ;; Make sure master function is instrumented. |
| 415 | (or (memq funsym elp-all-instrumented-list) | 351 | (or (elp--instrumented-p funsym) |
| 416 | (elp-instrument-function funsym))) | 352 | (elp-instrument-function funsym))) |
| 417 | 353 | ||
| 418 | (defun elp-unset-master () | 354 | (defun elp-unset-master () |
| 419 | "Unset the master function." | 355 | "Unset the master function." |
| 420 | (interactive) | 356 | (interactive) |
| 421 | ;; when there's no master function, recording is turned on by default. | 357 | ;; When there's no master function, recording is turned on by default. |
| 422 | (setq elp-master nil | 358 | (setq elp-master nil |
| 423 | elp-record-p t)) | 359 | elp-record-p t)) |
| 424 | 360 | ||
| @@ -426,49 +362,40 @@ Use optional LIST if provided instead." | |||
| 426 | (defsubst elp-elapsed-time (start end) | 362 | (defsubst elp-elapsed-time (start end) |
| 427 | (float-time (time-subtract end start))) | 363 | (float-time (time-subtract end start))) |
| 428 | 364 | ||
| 429 | (defun elp-wrapper (funsym interactive-p args) | 365 | (defun elp--make-wrapper (funsym) |
| 430 | "This function has been instrumented for profiling by the ELP. | 366 | "Make the piece of advice that instruments FUNSYM." |
| 367 | (lambda (func &rest args) | ||
| 368 | "This function has been instrumented for profiling by the ELP. | ||
| 431 | ELP is the Emacs Lisp Profiler. To restore the function to its | 369 | ELP is the Emacs Lisp Profiler. To restore the function to its |
| 432 | original definition, use \\[elp-restore-function] or \\[elp-restore-all]." | 370 | original definition, use \\[elp-restore-function] or \\[elp-restore-all]." |
| 433 | ;; turn on recording if this is the master function | 371 | ;; turn on recording if this is the master function |
| 434 | (if (and elp-master | 372 | (if (and elp-master |
| 435 | (eq funsym elp-master)) | 373 | (eq funsym elp-master)) |
| 436 | (setq elp-record-p t)) | 374 | (setq elp-record-p t)) |
| 437 | ;; get info vector and original function symbol | 375 | ;; get info vector and original function symbol |
| 438 | (let* ((info (get funsym elp-timer-info-property)) | 376 | (let* ((info (get funsym elp-timer-info-property)) |
| 439 | (func (aref info 2)) | 377 | result) |
| 440 | result) | 378 | (or func |
| 441 | (or func | 379 | (error "%s is not instrumented for profiling" funsym)) |
| 442 | (error "%s is not instrumented for profiling" funsym)) | 380 | (if (not elp-record-p) |
| 443 | (if (not elp-record-p) | 381 | ;; when not recording, just call the original function symbol |
| 444 | ;; when not recording, just call the original function symbol | 382 | ;; and return the results. |
| 445 | ;; and return the results. | 383 | (setq result (apply func args)) |
| 446 | (setq result | 384 | ;; we are recording times |
| 447 | (if interactive-p | 385 | (let (enter-time exit-time) |
| 448 | (call-interactively func) | 386 | ;; increment the call-counter |
| 449 | (apply func args))) | 387 | (cl-incf (aref info 0)) |
| 450 | ;; we are recording times | ||
| 451 | (let (enter-time exit-time) | ||
| 452 | ;; increment the call-counter | ||
| 453 | (aset info 0 (1+ (aref info 0))) | ||
| 454 | ;; now call the old symbol function, checking to see if it | ||
| 455 | ;; should be called interactively. make sure we return the | ||
| 456 | ;; correct value | ||
| 457 | (if interactive-p | ||
| 458 | (setq enter-time (current-time) | ||
| 459 | result (call-interactively func) | ||
| 460 | exit-time (current-time)) | ||
| 461 | (setq enter-time (current-time) | 388 | (setq enter-time (current-time) |
| 462 | result (apply func args) | 389 | result (apply func args) |
| 463 | exit-time (current-time))) | 390 | exit-time (current-time)) |
| 464 | ;; calculate total time in function | 391 | ;; calculate total time in function |
| 465 | (aset info 1 (+ (aref info 1) (elp-elapsed-time enter-time exit-time))) | 392 | (cl-incf (aref info 1) (elp-elapsed-time enter-time exit-time)) |
| 466 | )) | 393 | )) |
| 467 | ;; turn off recording if this is the master function | 394 | ;; turn off recording if this is the master function |
| 468 | (if (and elp-master | 395 | (if (and elp-master |
| 469 | (eq funsym elp-master)) | 396 | (eq funsym elp-master)) |
| 470 | (setq elp-record-p nil)) | 397 | (setq elp-record-p nil)) |
| 471 | result)) | 398 | result))) |
| 472 | 399 | ||
| 473 | 400 | ||
| 474 | ;; shut the byte-compiler up | 401 | ;; shut the byte-compiler up |
| @@ -582,57 +509,58 @@ displayed." | |||
| 582 | (elp-et-len (length et-header)) | 509 | (elp-et-len (length et-header)) |
| 583 | (at-header "Average Time") | 510 | (at-header "Average Time") |
| 584 | (elp-at-len (length at-header)) | 511 | (elp-at-len (length at-header)) |
| 585 | (resvec | 512 | (resvec '()) |
| 586 | (mapcar | ||
| 587 | (function | ||
| 588 | (lambda (funsym) | ||
| 589 | (let* ((info (get funsym elp-timer-info-property)) | ||
| 590 | (symname (format "%s" funsym)) | ||
| 591 | (cc (aref info 0)) | ||
| 592 | (tt (aref info 1))) | ||
| 593 | (if (not info) | ||
| 594 | (insert "No profiling information found for: " | ||
| 595 | symname) | ||
| 596 | (setq longest (max longest (length symname))) | ||
| 597 | (vector cc tt (if (zerop cc) | ||
| 598 | 0.0 ;avoid arithmetic div-by-zero errors | ||
| 599 | (/ (float tt) (float cc))) | ||
| 600 | symname))))) | ||
| 601 | elp-all-instrumented-list)) | ||
| 602 | ) ; end let* | 513 | ) ; end let* |
| 514 | (mapatoms | ||
| 515 | (lambda (funsym) | ||
| 516 | (when (elp--instrumented-p funsym) | ||
| 517 | (let* ((info (get funsym elp-timer-info-property)) | ||
| 518 | (symname (format "%s" funsym)) | ||
| 519 | (cc (aref info 0)) | ||
| 520 | (tt (aref info 1))) | ||
| 521 | (if (not info) | ||
| 522 | (insert "No profiling information found for: " | ||
| 523 | symname) | ||
| 524 | (setq longest (max longest (length symname))) | ||
| 525 | (push | ||
| 526 | (vector cc tt (if (zerop cc) | ||
| 527 | 0.0 ;avoid arithmetic div-by-zero errors | ||
| 528 | (/ (float tt) (float cc))) | ||
| 529 | symname) | ||
| 530 | resvec)))))) | ||
| 603 | ;; If printing to stdout, insert the header so it will print. | 531 | ;; If printing to stdout, insert the header so it will print. |
| 604 | ;; Otherwise use header-line-format. | 532 | ;; Otherwise use header-line-format. |
| 605 | (setq elp-field-len (max titlelen longest)) | 533 | (setq elp-field-len (max titlelen longest)) |
| 606 | (if (or elp-use-standard-output noninteractive) | 534 | (if (or elp-use-standard-output noninteractive) |
| 607 | (progn | 535 | (progn |
| 608 | (insert title) | 536 | (insert title) |
| 609 | (if (> longest titlelen) | 537 | (if (> longest titlelen) |
| 610 | (progn | 538 | (progn |
| 611 | (insert-char 32 (- longest titlelen)))) | 539 | (insert-char 32 (- longest titlelen)))) |
| 612 | (insert " " cc-header " " et-header " " at-header "\n") | 540 | (insert " " cc-header " " et-header " " at-header "\n") |
| 613 | (insert-char ?= elp-field-len) | 541 | (insert-char ?= elp-field-len) |
| 614 | (insert " ") | 542 | (insert " ") |
| 615 | (insert-char ?= elp-cc-len) | 543 | (insert-char ?= elp-cc-len) |
| 616 | (insert " ") | 544 | (insert " ") |
| 617 | (insert-char ?= elp-et-len) | 545 | (insert-char ?= elp-et-len) |
| 618 | (insert " ") | 546 | (insert " ") |
| 619 | (insert-char ?= elp-at-len) | 547 | (insert-char ?= elp-at-len) |
| 620 | (insert "\n")) | 548 | (insert "\n")) |
| 621 | (let ((column 0)) | 549 | (let ((column 0)) |
| 622 | (setq header-line-format | 550 | (setq header-line-format |
| 623 | (mapconcat | 551 | (mapconcat |
| 624 | (lambda (title) | 552 | (lambda (title) |
| 625 | (prog1 | 553 | (prog1 |
| 626 | (concat | 554 | (concat |
| 627 | (propertize " " | 555 | (propertize " " |
| 628 | 'display (list 'space :align-to column) | 556 | 'display (list 'space :align-to column) |
| 629 | 'face 'fixed-pitch) | 557 | 'face 'fixed-pitch) |
| 630 | title) | 558 | title) |
| 631 | (setq column (+ column 2 | 559 | (setq column (+ column 2 |
| 632 | (if (= column 0) | 560 | (if (= column 0) |
| 633 | elp-field-len | 561 | elp-field-len |
| 634 | (length title)))))) | 562 | (length title)))))) |
| 635 | (list title cc-header et-header at-header) "")))) | 563 | (list title cc-header et-header at-header) "")))) |
| 636 | ;; if sorting is enabled, then sort the results list. in either | 564 | ;; if sorting is enabled, then sort the results list. in either |
| 637 | ;; case, call elp-output-result to output the result in the | 565 | ;; case, call elp-output-result to output the result in the |
| 638 | ;; buffer | 566 | ;; buffer |
| @@ -644,7 +572,7 @@ displayed." | |||
| 644 | (pop-to-buffer resultsbuf) | 572 | (pop-to-buffer resultsbuf) |
| 645 | ;; copy results to standard-output? | 573 | ;; copy results to standard-output? |
| 646 | (if (or elp-use-standard-output noninteractive) | 574 | (if (or elp-use-standard-output noninteractive) |
| 647 | (princ (buffer-substring (point-min) (point-max))) | 575 | (princ (buffer-substring (point-min) (point-max))) |
| 648 | (goto-char (point-min))) | 576 | (goto-char (point-min))) |
| 649 | ;; reset profiling info if desired | 577 | ;; reset profiling info if desired |
| 650 | (and elp-reset-after-results | 578 | (and elp-reset-after-results |
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el index d6c91539a90..58bfae5b503 100644 --- a/lisp/emacs-lisp/gv.el +++ b/lisp/emacs-lisp/gv.el | |||
| @@ -111,7 +111,7 @@ DO must return an Elisp expression." | |||
| 111 | GETTER will be bound to a copyable expression that returns the value | 111 | GETTER will be bound to a copyable expression that returns the value |
| 112 | of PLACE. | 112 | of PLACE. |
| 113 | SETTER will be bound to a function that takes an expression V and returns | 113 | SETTER will be bound to a function that takes an expression V and returns |
| 114 | and new expression that sets PLACE to V. | 114 | a new expression that sets PLACE to V. |
| 115 | BODY should return some Elisp expression E manipulating PLACE via GETTER | 115 | BODY should return some Elisp expression E manipulating PLACE via GETTER |
| 116 | and SETTER. | 116 | and SETTER. |
| 117 | The returned value will then be an Elisp expression that first evaluates | 117 | The returned value will then be an Elisp expression that first evaluates |
| @@ -194,7 +194,7 @@ well for simple place forms. | |||
| 194 | Assignments of VAL to (NAME ARGS...) are expanded by binding the argument | 194 | Assignments of VAL to (NAME ARGS...) are expanded by binding the argument |
| 195 | forms (VAL ARGS...) according to ARGLIST, then executing BODY, which must | 195 | forms (VAL ARGS...) according to ARGLIST, then executing BODY, which must |
| 196 | return a Lisp form that does the assignment. | 196 | return a Lisp form that does the assignment. |
| 197 | The first arg in ARLIST (the one that receives VAL) receives an expression | 197 | The first arg in ARGLIST (the one that receives VAL) receives an expression |
| 198 | which can do arbitrary things, whereas the other arguments are all guaranteed | 198 | which can do arbitrary things, whereas the other arguments are all guaranteed |
| 199 | to be pure and copyable. Example use: | 199 | to be pure and copyable. Example use: |
| 200 | (gv-define-setter aref (v a i) `(aset ,a ,i ,v))" | 200 | (gv-define-setter aref (v a i) `(aset ,a ,i ,v))" |
| @@ -209,13 +209,20 @@ to be pure and copyable. Example use: | |||
| 209 | This macro is an easy-to-use substitute for `gv-define-expander' that works | 209 | This macro is an easy-to-use substitute for `gv-define-expander' that works |
| 210 | well for simple place forms. Assignments of VAL to (NAME ARGS...) are | 210 | well for simple place forms. Assignments of VAL to (NAME ARGS...) are |
| 211 | turned into calls of the form (SETTER ARGS... VAL). | 211 | turned into calls of the form (SETTER ARGS... VAL). |
| 212 | |||
| 212 | If FIX-RETURN is non-nil, then SETTER is not assumed to return VAL and | 213 | If FIX-RETURN is non-nil, then SETTER is not assumed to return VAL and |
| 213 | instead the assignment is turned into (prog1 VAL (SETTER ARGS... VAL)) | 214 | instead the assignment is turned into something equivalent to |
| 215 | \(let ((temp VAL)) | ||
| 216 | (SETTER ARGS... temp) | ||
| 217 | temp) | ||
| 214 | so as to preserve the semantics of `setf'." | 218 | so as to preserve the semantics of `setf'." |
| 215 | (declare (debug (sexp (&or symbolp lambda-expr) &optional sexp))) | 219 | (declare (debug (sexp (&or symbolp lambda-expr) &optional sexp))) |
| 216 | (let ((set-call `(cons ',setter (append args (list val))))) | ||
| 217 | `(gv-define-setter ,name (val &rest args) | 220 | `(gv-define-setter ,name (val &rest args) |
| 218 | ,(if fix-return `(list 'prog1 val ,set-call) set-call)))) | 221 | ,(if fix-return |
| 222 | `(macroexp-let2 nil v val | ||
| 223 | (cons ',setter (append args (list v))) | ||
| 224 | v) | ||
| 225 | `(cons ',setter (append args (list val)))))) | ||
| 219 | 226 | ||
| 220 | ;;; Typical operations on generalized variables. | 227 | ;;; Typical operations on generalized variables. |
| 221 | 228 | ||
| @@ -433,6 +440,26 @@ The return value is the last VAL in the list. | |||
| 433 | `(logior (logand ,v ,mask) | 440 | `(logior (logand ,v ,mask) |
| 434 | (logand ,getter (lognot ,mask)))))))))) | 441 | (logand ,getter (lognot ,mask)))))))))) |
| 435 | 442 | ||
| 443 | ;;; References | ||
| 444 | |||
| 445 | ;;;###autoload | ||
| 446 | (defmacro gv-ref (place) | ||
| 447 | "Return a reference to PLACE. | ||
| 448 | This is like the `&' operator of the C language." | ||
| 449 | (gv-letplace (getter setter) place | ||
| 450 | `(cons (lambda () ,getter) | ||
| 451 | (lambda (gv--val) ,(funcall setter 'gv--val))))) | ||
| 452 | |||
| 453 | (defsubst gv-deref (ref) | ||
| 454 | "Dereference REF, returning the referenced value. | ||
| 455 | This is like the `*' operator of the C language. | ||
| 456 | REF must have been previously obtained with `gv-ref'." | ||
| 457 | (funcall (car ref))) | ||
| 458 | ;; Don't use `declare' because it seems to introduce circularity problems: | ||
| 459 | ;; Warning: Eager macro-expansion skipped due to cycle: | ||
| 460 | ;; … => (load "gv.el") => (macroexpand-all (defsubst gv-deref …)) => (macroexpand (defun …)) => (load "gv.el") | ||
| 461 | (gv-define-setter gv-deref (v ref) `(funcall (cdr ,ref) ,v)) | ||
| 462 | |||
| 436 | ;;; Vaguely related definitions that should be moved elsewhere. | 463 | ;;; Vaguely related definitions that should be moved elsewhere. |
| 437 | 464 | ||
| 438 | ;; (defun alist-get (key alist) | 465 | ;; (defun alist-get (key alist) |
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el new file mode 100644 index 00000000000..020a2f89bdb --- /dev/null +++ b/lisp/emacs-lisp/nadvice.el | |||
| @@ -0,0 +1,348 @@ | |||
| 1 | ;;; nadvice.el --- Light-weight advice primitives for Elisp functions -*- lexical-binding: t -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2012 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 6 | ;; Keywords: extensions, lisp, tools | ||
| 7 | ;; Package: emacs | ||
| 8 | |||
| 9 | ;; This program is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 12 | ;; (at your option) any later version. | ||
| 13 | |||
| 14 | ;; This program is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | |||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 21 | |||
| 22 | ;;; Commentary: | ||
| 23 | |||
| 24 | ;; This package lets you add behavior (which we call "piece of advice") to | ||
| 25 | ;; existing functions, like the old `advice.el' package, but with much fewer | ||
| 26 | ;; bells ans whistles. It comes in 2 parts: | ||
| 27 | ;; | ||
| 28 | ;; - The first part lets you add/remove functions, similarly to | ||
| 29 | ;; add/remove-hook, from any "place" (i.e. as accepted by `setf') that | ||
| 30 | ;; holds a function. | ||
| 31 | ;; This part provides mainly 2 macros: `add-function' and `remove-function'. | ||
| 32 | ;; | ||
| 33 | ;; - The second part provides `add-advice' and `remove-advice' which are | ||
| 34 | ;; refined version of the previous macros specially tailored for the case | ||
| 35 | ;; where the place that we want to modify is a `symbol-function'. | ||
| 36 | |||
| 37 | ;;; Code: | ||
| 38 | |||
| 39 | ;;;; Lightweight advice/hook | ||
| 40 | (defvar advice--where-alist | ||
| 41 | '((:around "\300\301\302\003#\207" 5) | ||
| 42 | (:before "\300\301\002\"\210\300\302\002\"\207" 4) | ||
| 43 | (:after "\300\302\002\"\300\301\003\"\210\207" 5) | ||
| 44 | (:after-until "\300\302\002\"\206\013\000\300\301\002\"\207" 4) | ||
| 45 | (:after-while "\300\302\002\"\205\013\000\300\301\002\"\207" 4) | ||
| 46 | (:before-until "\300\301\002\"\206\013\000\300\302\002\"\207" 4) | ||
| 47 | (:before-while "\300\301\002\"\205\013\000\300\302\002\"\207" 4)) | ||
| 48 | "List of descriptions of how to add a function. | ||
| 49 | Each element has the form (WHERE BYTECODE STACK) where: | ||
| 50 | WHERE is a keyword indicating where the function is added. | ||
| 51 | BYTECODE is the corresponding byte-code that will be used. | ||
| 52 | STACK is the amount of stack space needed by the byte-code.") | ||
| 53 | |||
| 54 | (defvar advice--bytecodes (mapcar #'cadr advice--where-alist)) | ||
| 55 | |||
| 56 | (defun advice--p (object) | ||
| 57 | (and (byte-code-function-p object) | ||
| 58 | (eq 128 (aref object 0)) | ||
| 59 | (memq (length object) '(5 6)) | ||
| 60 | (memq (aref object 1) advice--bytecodes) | ||
| 61 | (eq #'apply (aref (aref object 2) 0)))) | ||
| 62 | |||
| 63 | (defsubst advice--car (f) (aref (aref f 2) 1)) | ||
| 64 | (defsubst advice--cdr (f) (aref (aref f 2) 2)) | ||
| 65 | (defsubst advice--props (f) (aref (aref f 2) 3)) | ||
| 66 | |||
| 67 | (defun advice--make-docstring (_string function) | ||
| 68 | "Build the raw doc-string of SYMBOL, presumably advised." | ||
| 69 | (let ((flist (indirect-function function)) | ||
| 70 | (docstring nil)) | ||
| 71 | (if (eq 'macro (car-safe flist)) (setq flist (cdr flist))) | ||
| 72 | (while (advice--p flist) | ||
| 73 | (let ((bytecode (aref flist 1)) | ||
| 74 | (where nil)) | ||
| 75 | (dolist (elem advice--where-alist) | ||
| 76 | (if (eq bytecode (cadr elem)) (setq where (car elem)))) | ||
| 77 | (setq docstring | ||
| 78 | (concat | ||
| 79 | docstring | ||
| 80 | (propertize (format "%s advice: " where) | ||
| 81 | 'face 'warning) | ||
| 82 | (let ((fun (advice--car flist))) | ||
| 83 | (if (symbolp fun) (format "`%S'" fun) | ||
| 84 | (let* ((name (cdr (assq 'name (advice--props flist)))) | ||
| 85 | (doc (documentation fun t)) | ||
| 86 | (usage (help-split-fundoc doc function))) | ||
| 87 | (if usage (setq doc (cdr usage))) | ||
| 88 | (if name | ||
| 89 | (if doc | ||
| 90 | (format "%s\n%s" name doc) | ||
| 91 | (format "%s" name)) | ||
| 92 | (or doc "No documentation"))))) | ||
| 93 | "\n"))) | ||
| 94 | (setq flist (advice--cdr flist))) | ||
| 95 | (if docstring (setq docstring (concat docstring "\n"))) | ||
| 96 | (let* ((origdoc (unless (eq function flist) ;Avoid inf-loops. | ||
| 97 | (documentation flist t))) | ||
| 98 | (usage (help-split-fundoc origdoc function))) | ||
| 99 | (setq usage (if (null usage) | ||
| 100 | (let ((arglist (help-function-arglist flist))) | ||
| 101 | (format "%S" (help-make-usage function arglist))) | ||
| 102 | (setq origdoc (cdr usage)) (car usage))) | ||
| 103 | (help-add-fundoc-usage (concat docstring origdoc) usage)))) | ||
| 104 | |||
| 105 | (defvar advice--docstring | ||
| 106 | ;; Can't eval-when-compile nor use defconst because it then gets pure-copied, | ||
| 107 | ;; which drops the text-properties. | ||
| 108 | ;;(eval-when-compile | ||
| 109 | (propertize "Advised function" | ||
| 110 | 'dynamic-docstring-function #'advice--make-docstring)) ;; ) | ||
| 111 | |||
| 112 | (defun advice--make-interactive-form (function main) | ||
| 113 | ;; TODO: Make it possible to do around-like advising on the | ||
| 114 | ;; interactive forms (bug#12844). | ||
| 115 | ;; TODO: make it so that interactive spec can be a constant which | ||
| 116 | ;; dynamically checks the advice--car/cdr to do its job. | ||
| 117 | ;; TODO: Implement interactive-read-args: | ||
| 118 | ;;(when (or (commandp function) (commandp main)) | ||
| 119 | ;; `(interactive-read-args | ||
| 120 | ;; (cadr (or (interactive-form function) (interactive-form main))))) | ||
| 121 | ;; FIXME: This loads autoloaded functions too eagerly. | ||
| 122 | (cadr (or (interactive-form function) | ||
| 123 | (interactive-form main)))) | ||
| 124 | |||
| 125 | (defsubst advice--make-1 (byte-code stack-depth function main props) | ||
| 126 | "Build a function value that adds FUNCTION to MAIN." | ||
| 127 | (let ((adv-sig (gethash main advertised-signature-table)) | ||
| 128 | (advice | ||
| 129 | (apply #'make-byte-code 128 byte-code | ||
| 130 | (vector #'apply function main props) stack-depth | ||
| 131 | advice--docstring | ||
| 132 | (when (or (commandp function) (commandp main)) | ||
| 133 | (list (advice--make-interactive-form | ||
| 134 | function main)))))) | ||
| 135 | (when adv-sig (puthash advice adv-sig advertised-signature-table)) | ||
| 136 | advice)) | ||
| 137 | |||
| 138 | (defun advice--make (where function main props) | ||
| 139 | "Build a function value that adds FUNCTION to MAIN at WHERE. | ||
| 140 | WHERE is a symbol to select an entry in `advice--where-alist'." | ||
| 141 | (let ((desc (assq where advice--where-alist))) | ||
| 142 | (unless desc (error "Unknown add-function location `%S'" where)) | ||
| 143 | (advice--make-1 (nth 1 desc) (nth 2 desc) | ||
| 144 | function main props))) | ||
| 145 | |||
| 146 | (defun advice--member-p (function definition) | ||
| 147 | (let ((found nil)) | ||
| 148 | (while (and (not found) (advice--p definition)) | ||
| 149 | (if (or (equal function (advice--car definition)) | ||
| 150 | (equal function (cdr (assq 'name (advice--props definition))))) | ||
| 151 | (setq found t) | ||
| 152 | (setq definition (advice--cdr definition)))) | ||
| 153 | found)) | ||
| 154 | |||
| 155 | ;;;###autoload | ||
| 156 | (defun advice--remove-function (flist function) | ||
| 157 | (if (not (advice--p flist)) | ||
| 158 | flist | ||
| 159 | (let ((first (advice--car flist)) | ||
| 160 | (props (advice--props flist))) | ||
| 161 | (if (or (equal function first) | ||
| 162 | (equal function (cdr (assq 'name props)))) | ||
| 163 | (advice--cdr flist) | ||
| 164 | (let* ((rest (advice--cdr flist)) | ||
| 165 | (nrest (advice--remove-function rest function))) | ||
| 166 | (if (eq rest nrest) flist | ||
| 167 | (advice--make-1 (aref flist 1) (aref flist 3) | ||
| 168 | first nrest props))))))) | ||
| 169 | |||
| 170 | ;;;###autoload | ||
| 171 | (defmacro add-function (where place function &optional props) | ||
| 172 | ;; TODO: | ||
| 173 | ;; - provide something like `around' for interactive forms. | ||
| 174 | ;; - provide some kind of buffer-local functionality at least when `place' | ||
| 175 | ;; is a variable. | ||
| 176 | ;; - obsolete with-wrapper-hook (mostly requires buffer-local support). | ||
| 177 | ;; - provide some kind of control over ordering. E.g. debug-on-entry, ELP | ||
| 178 | ;; and tracing want to stay first. | ||
| 179 | ;; - maybe also let `where' specify some kind of predicate and use it | ||
| 180 | ;; to implement things like mode-local or eieio-defmethod. | ||
| 181 | ;; :before is like a normal add-hook on a normal hook. | ||
| 182 | ;; :before-while is like add-hook on run-hook-with-args-until-failure. | ||
| 183 | ;; :before-until is like add-hook on run-hook-with-args-until-success. | ||
| 184 | ;; Same with :after-* but for (add-hook ... 'append). | ||
| 185 | "Add a piece of advice on the function stored at PLACE. | ||
| 186 | FUNCTION describes the code to add. WHERE describes where to add it. | ||
| 187 | WHERE can be explained by showing the resulting new function, as the | ||
| 188 | result of combining FUNCTION and the previous value of PLACE, which we | ||
| 189 | call OLDFUN here: | ||
| 190 | `:before' (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r)) | ||
| 191 | `:after' (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r))) | ||
| 192 | `:around' (lambda (&rest r) (apply FUNCTION OLDFUN r)) | ||
| 193 | `:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r))) | ||
| 194 | `:before-until' (lambda (&rest r) (or (apply FUNCTION r) (apply OLDFUN r))) | ||
| 195 | `:after-while' (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r))) | ||
| 196 | `:after-until' (lambda (&rest r) (or (apply OLDFUN r) (apply FUNCTION r))) | ||
| 197 | If FUNCTION was already added, do nothing. | ||
| 198 | PROPS is an alist of additional properties, among which the following have | ||
| 199 | a special meaning: | ||
| 200 | - `name': a string or symbol. It can be used to refer to this piece of advice." | ||
| 201 | (declare (debug t)) ;;(indent 2) | ||
| 202 | `(advice--add-function ,where (gv-ref ,place) ,function ,props)) | ||
| 203 | |||
| 204 | ;;;###autoload | ||
| 205 | (defun advice--add-function (where ref function props) | ||
| 206 | (unless (advice--member-p function (gv-deref ref)) | ||
| 207 | (setf (gv-deref ref) | ||
| 208 | (advice--make where function (gv-deref ref) props)))) | ||
| 209 | |||
| 210 | (defmacro remove-function (place function) | ||
| 211 | "Remove the FUNCTION piece of advice from PLACE. | ||
| 212 | If FUNCTION was not added to PLACE, do nothing. | ||
| 213 | Instead of FUNCTION being the actual function, it can also be the `name' | ||
| 214 | of the piece of advice." | ||
| 215 | (declare (debug t)) | ||
| 216 | (gv-letplace (getter setter) place | ||
| 217 | (macroexp-let2 nil new `(advice--remove-function ,getter ,function) | ||
| 218 | `(unless (eq ,new ,getter) ,(funcall setter new))))) | ||
| 219 | |||
| 220 | ;;;; Specific application of add-function to `symbol-function' for advice. | ||
| 221 | |||
| 222 | (defun advice--subst-main (old new) | ||
| 223 | (if (not (advice--p old)) | ||
| 224 | new | ||
| 225 | (let* ((first (advice--car old)) | ||
| 226 | (rest (advice--cdr old)) | ||
| 227 | (props (advice--props old)) | ||
| 228 | (nrest (advice--subst-main rest new))) | ||
| 229 | (if (equal rest nrest) old | ||
| 230 | (advice--make-1 (aref old 1) (aref old 3) | ||
| 231 | first nrest props))))) | ||
| 232 | |||
| 233 | (defun advice--defalias-fset (fsetfun symbol newdef) | ||
| 234 | (let* ((olddef (if (fboundp symbol) (symbol-function symbol))) | ||
| 235 | (oldadv | ||
| 236 | (cond | ||
| 237 | ((null (get symbol 'advice--pending)) | ||
| 238 | (or olddef | ||
| 239 | (progn | ||
| 240 | (message "Delayed advice activation failed for %s: no data" | ||
| 241 | symbol) | ||
| 242 | nil))) | ||
| 243 | ((or (not olddef) (autoloadp olddef)) | ||
| 244 | (prog1 (get symbol 'advice--pending) | ||
| 245 | (put symbol 'advice--pending nil))) | ||
| 246 | (t (message "Dropping left-over advice--pending for %s" symbol) | ||
| 247 | (put symbol 'advice--pending nil) | ||
| 248 | olddef)))) | ||
| 249 | (funcall (or fsetfun #'fset) symbol (advice--subst-main oldadv newdef)))) | ||
| 250 | |||
| 251 | |||
| 252 | ;;;###autoload | ||
| 253 | (defun advice-add (symbol where function &optional props) | ||
| 254 | "Like `add-function' but for the function named SYMBOL. | ||
| 255 | Contrary to `add-function', this will properly handle the cases where SYMBOL | ||
| 256 | is defined as a macro, alias, command, ..." | ||
| 257 | ;; TODO: | ||
| 258 | ;; - record the advice location, to display in describe-function. | ||
| 259 | ;; - change all defadvice in lisp/**/*.el. | ||
| 260 | ;; - rewrite advice.el on top of this. | ||
| 261 | ;; - obsolete advice.el. | ||
| 262 | ;; To make advice.el and nadvice.el interoperate properly I see 2 different | ||
| 263 | ;; ways: | ||
| 264 | ;; - keep them separate: complete the defalias-fset-function setter with | ||
| 265 | ;; a matching accessor which both nadvice.el and advice.el will have to use | ||
| 266 | ;; in place of symbol-function. This can probably be made to work, but | ||
| 267 | ;; they have to agree on a "protocol". | ||
| 268 | ;; - layer advice.el on top of nadvice.el. I prefer this approach. the | ||
| 269 | ;; simplest way is to make advice.el build one ad-Advice-foo function for | ||
| 270 | ;; each advised function which is advice-added/removed whenever ad-activate | ||
| 271 | ;; ad-deactivate is called. | ||
| 272 | (let ((f (and (fboundp symbol) (symbol-function symbol)))) | ||
| 273 | (cond | ||
| 274 | ((special-form-p f) | ||
| 275 | ;; Not worth the trouble trying to handle this, I think. | ||
| 276 | (error "add-advice failure: %S is a special form" symbol)) | ||
| 277 | ((and (symbolp f) | ||
| 278 | (eq 'macro (car-safe (ignore-errors (indirect-function f))))) | ||
| 279 | (let ((newval (cons 'macro (cdr (indirect-function f))))) | ||
| 280 | (put symbol 'advice--saved-rewrite (cons f newval)) | ||
| 281 | (fset symbol newval))) | ||
| 282 | ;; `f' might be a pure (hence read-only) cons! | ||
| 283 | ((and (eq 'macro (car-safe f)) (not (ignore-errors (setcdr f (cdr f)) t))) | ||
| 284 | (fset symbol (cons 'macro (cdr f)))) | ||
| 285 | )) | ||
| 286 | (let ((f (and (fboundp symbol) (symbol-function symbol)))) | ||
| 287 | (add-function where (cond | ||
| 288 | ((eq (car-safe f) 'macro) (cdr f)) | ||
| 289 | ;; If the function is not yet defined, we can't yet | ||
| 290 | ;; install the advice. | ||
| 291 | ;; FIXME: If it's an autoloaded command, we also | ||
| 292 | ;; have a problem because we need to load the | ||
| 293 | ;; command to build the interactive-form. | ||
| 294 | ((or (not f) (and (autoloadp f))) ;; (commandp f) | ||
| 295 | (get symbol 'advice--pending)) | ||
| 296 | (t (symbol-function symbol))) | ||
| 297 | function props) | ||
| 298 | (add-function :around (get symbol 'defalias-fset-function) | ||
| 299 | #'advice--defalias-fset)) | ||
| 300 | nil) | ||
| 301 | |||
| 302 | ;;;###autoload | ||
| 303 | (defun advice-remove (symbol function) | ||
| 304 | "Like `remove-function' but for the function named SYMBOL. | ||
| 305 | Contrary to `remove-function', this will work also when SYMBOL is a macro | ||
| 306 | and it will not signal an error if SYMBOL is not `fboundp'. | ||
| 307 | Instead of the actual function to remove, FUNCTION can also be the `name' | ||
| 308 | of the piece of advice." | ||
| 309 | (when (fboundp symbol) | ||
| 310 | (let ((f (symbol-function symbol))) | ||
| 311 | ;; Can't use the `if' place here, because the body is too large, | ||
| 312 | ;; resulting in use of code that only works with lexical-scoping. | ||
| 313 | (remove-function (if (eq (car-safe f) 'macro) | ||
| 314 | (cdr f) | ||
| 315 | (symbol-function symbol)) | ||
| 316 | function) | ||
| 317 | (unless (advice--p | ||
| 318 | (if (eq (car-safe f) 'macro) (cdr f) (symbol-function symbol))) | ||
| 319 | ;; Not adviced any more. | ||
| 320 | (remove-function (get symbol 'defalias-fset-function) | ||
| 321 | #'advice--defalias-fset) | ||
| 322 | (if (eq (symbol-function symbol) | ||
| 323 | (cdr (get symbol 'advice--saved-rewrite))) | ||
| 324 | (fset symbol (car (get symbol 'advice--saved-rewrite)))))) | ||
| 325 | nil)) | ||
| 326 | |||
| 327 | ;; (defun advice-mapc (fun symbol) | ||
| 328 | ;; "Apply FUN to every function added as advice to SYMBOL. | ||
| 329 | ;; FUN is called with a two arguments: the function that was added, and the | ||
| 330 | ;; properties alist that was specified when it was added." | ||
| 331 | ;; (let ((def (or (get symbol 'advice--pending) | ||
| 332 | ;; (if (fboundp symbol) (symbol-function symbol))))) | ||
| 333 | ;; (while (advice--p def) | ||
| 334 | ;; (funcall fun (advice--car def) (advice--props def)) | ||
| 335 | ;; (setq def (advice--cdr def))))) | ||
| 336 | |||
| 337 | ;;;###autoload | ||
| 338 | (defun advice-member-p (function symbol) | ||
| 339 | "Return non-nil if advice FUNCTION has been added to function SYMBOL. | ||
| 340 | Instead of FUNCTION being the actual function, it can also be the `name' | ||
| 341 | of the piece of advice." | ||
| 342 | (advice--member-p function | ||
| 343 | (or (get symbol 'advice--pending) | ||
| 344 | (if (fboundp symbol) (symbol-function symbol))))) | ||
| 345 | |||
| 346 | |||
| 347 | (provide 'nadvice) | ||
| 348 | ;;; nadvice.el ends here | ||
diff --git a/lisp/env.el b/lisp/env.el index d0d8ed0b998..5f7c61b719a 100644 --- a/lisp/env.el +++ b/lisp/env.el | |||
| @@ -57,31 +57,28 @@ If it is also not t, RET does not exit if it does non-null completion." | |||
| 57 | ;; History list for VALUE argument to setenv. | 57 | ;; History list for VALUE argument to setenv. |
| 58 | (defvar setenv-history nil) | 58 | (defvar setenv-history nil) |
| 59 | 59 | ||
| 60 | (defconst env--substitute-vars-regexp | ||
| 61 | "\\$\\(?:\\(?1:[[:alnum:]_]+\\)\\|{\\(?1:[^{}]+\\)}\\|\\$\\)") | ||
| 60 | 62 | ||
| 61 | (defun substitute-env-vars (string) | 63 | (defun substitute-env-vars (string &optional only-defined) |
| 62 | "Substitute environment variables referred to in STRING. | 64 | "Substitute environment variables referred to in STRING. |
| 63 | `$FOO' where FOO is an environment variable name means to substitute | 65 | `$FOO' where FOO is an environment variable name means to substitute |
| 64 | the value of that variable. The variable name should be terminated | 66 | the value of that variable. The variable name should be terminated |
| 65 | with a character not a letter, digit or underscore; otherwise, enclose | 67 | with a character not a letter, digit or underscore; otherwise, enclose |
| 66 | the entire variable name in braces. For instance, in `ab$cd-x', | 68 | the entire variable name in braces. For instance, in `ab$cd-x', |
| 67 | `$cd' is treated as an environment variable. | 69 | `$cd' is treated as an environment variable. |
| 70 | If ONLY-DEFINED is nil, references to undefined environment variables | ||
| 71 | are replaced by the empty string; if it is non-nil, they are left unchanged. | ||
| 68 | 72 | ||
| 69 | Use `$$' to insert a single dollar sign." | 73 | Use `$$' to insert a single dollar sign." |
| 70 | (let ((start 0)) | 74 | (let ((start 0)) |
| 71 | (while (string-match | 75 | (while (string-match env--substitute-vars-regexp string start) |
| 72 | (eval-when-compile | ||
| 73 | (rx (or (and "$" (submatch (1+ (regexp "[[:alnum:]_]")))) | ||
| 74 | (and "${" (submatch (minimal-match (0+ anything))) "}") | ||
| 75 | "$$"))) | ||
| 76 | string start) | ||
| 77 | (cond ((match-beginning 1) | 76 | (cond ((match-beginning 1) |
| 78 | (let ((value (getenv (match-string 1 string)))) | 77 | (let ((value (getenv (match-string 1 string)))) |
| 78 | (if (and (null value) only-defined) | ||
| 79 | (setq start (match-end 0)) | ||
| 79 | (setq string (replace-match (or value "") t t string) | 80 | (setq string (replace-match (or value "") t t string) |
| 80 | start (+ (match-beginning 0) (length value))))) | 81 | start (+ (match-beginning 0) (length value)))))) |
| 81 | ((match-beginning 2) | ||
| 82 | (let ((value (getenv (match-string 2 string)))) | ||
| 83 | (setq string (replace-match (or value "") t t string) | ||
| 84 | start (+ (match-beginning 0) (length value))))) | ||
| 85 | (t | 82 | (t |
| 86 | (setq string (replace-match "$" t t string) | 83 | (setq string (replace-match "$" t t string) |
| 87 | start (+ (match-beginning 0) 1))))) | 84 | start (+ (match-beginning 0) 1))))) |
| @@ -185,7 +182,7 @@ VARIABLE should be a string. Value is nil if VARIABLE is undefined in | |||
| 185 | the environment. Otherwise, value is a string. | 182 | the environment. Otherwise, value is a string. |
| 186 | 183 | ||
| 187 | If optional parameter FRAME is non-nil, then it should be a | 184 | If optional parameter FRAME is non-nil, then it should be a |
| 188 | frame. This function will look up VARIABLE in its 'environment | 185 | frame. This function will look up VARIABLE in its `environment' |
| 189 | parameter. | 186 | parameter. |
| 190 | 187 | ||
| 191 | Otherwise, this function searches `process-environment' for | 188 | Otherwise, this function searches `process-environment' for |
diff --git a/lisp/files.el b/lisp/files.el index 26c5c683b3d..8e8a178caab 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -3387,30 +3387,39 @@ It is dangerous if either of these conditions are met: | |||
| 3387 | (setq ok t))) | 3387 | (setq ok t))) |
| 3388 | ok)))))))) | 3388 | ok)))))))) |
| 3389 | 3389 | ||
| 3390 | (defun hack-one-local-variable--obsolete (var) | ||
| 3391 | (let ((o (get var 'byte-obsolete-variable))) | ||
| 3392 | (when o | ||
| 3393 | (let ((instead (nth 0 o)) | ||
| 3394 | (since (nth 2 o))) | ||
| 3395 | (message "%s is obsolete%s; %s" | ||
| 3396 | var (if since (format " (since %s)" since)) | ||
| 3397 | (if (stringp instead) instead | ||
| 3398 | (format "use `%s' instead" instead))))))) | ||
| 3399 | |||
| 3390 | (defun hack-one-local-variable (var val) | 3400 | (defun hack-one-local-variable (var val) |
| 3391 | "Set local variable VAR with value VAL. | 3401 | "Set local variable VAR with value VAL. |
| 3392 | If VAR is `mode', call `VAL-mode' as a function unless it's | 3402 | If VAR is `mode', call `VAL-mode' as a function unless it's |
| 3393 | already the major mode." | 3403 | already the major mode." |
| 3394 | (cond ((eq var 'mode) | 3404 | (pcase var |
| 3395 | (let ((mode (intern (concat (downcase (symbol-name val)) | 3405 | (`mode |
| 3396 | "-mode")))) | 3406 | (let ((mode (intern (concat (downcase (symbol-name val)) |
| 3397 | (unless (eq (indirect-function mode) | 3407 | "-mode")))) |
| 3398 | (indirect-function major-mode)) | 3408 | (unless (eq (indirect-function mode) |
| 3399 | (if (memq mode minor-mode-list) | 3409 | (indirect-function major-mode)) |
| 3400 | ;; A minor mode must be passed an argument. | 3410 | (funcall mode)))) |
| 3401 | ;; Otherwise, if the user enables the minor mode in a | 3411 | (`eval |
| 3402 | ;; major mode hook, this would toggle it off. | 3412 | (pcase val |
| 3403 | (funcall mode 1) | 3413 | (`(add-hook ',hook . ,_) (hack-one-local-variable--obsolete hook))) |
| 3404 | (funcall mode))))) | 3414 | (save-excursion (eval val))) |
| 3405 | ((eq var 'eval) | 3415 | (_ |
| 3406 | (save-excursion (eval val))) | 3416 | (hack-one-local-variable--obsolete var) |
| 3407 | (t | 3417 | ;; Make sure the string has no text properties. |
| 3408 | ;; Make sure the string has no text properties. | 3418 | ;; Some text properties can get evaluated in various ways, |
| 3409 | ;; Some text properties can get evaluated in various ways, | 3419 | ;; so it is risky to put them on with a local variable list. |
| 3410 | ;; so it is risky to put them on with a local variable list. | 3420 | (if (stringp val) |
| 3411 | (if (stringp val) | 3421 | (set-text-properties 0 (length val) nil val)) |
| 3412 | (set-text-properties 0 (length val) nil val)) | 3422 | (set (make-local-variable var) val)))) |
| 3413 | (set (make-local-variable var) val)))) | ||
| 3414 | 3423 | ||
| 3415 | ;;; Handling directory-local variables, aka project settings. | 3424 | ;;; Handling directory-local variables, aka project settings. |
| 3416 | 3425 | ||
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 78204897cf1..5f635e59cdf 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2012-11-08 Katsumi Yamaoka <yamaoka@jpl.org> | ||
| 2 | |||
| 3 | * gnus-art.el (gnus-article-browse-html-parts): Always replace charset | ||
| 4 | in meta tag with the one the part specifies in its header. | ||
| 5 | |||
| 1 | 2012-11-02 Stephen Eglen <S.J.Eglen@damtp.cam.ac.uk> | 6 | 2012-11-02 Stephen Eglen <S.J.Eglen@damtp.cam.ac.uk> |
| 2 | 7 | ||
| 3 | * gnus-dired.el (gnus-dired-attach): Attach to last used message buffer | 8 | * gnus-dired.el (gnus-dired-attach): Attach to last used message buffer |
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 6c827e070cb..edcd7da2ddd 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el | |||
| @@ -2877,7 +2877,7 @@ message header will be added to the bodies of the \"text/html\" parts." | |||
| 2877 | ;; Add a meta html tag to specify charset and a header. | 2877 | ;; Add a meta html tag to specify charset and a header. |
| 2878 | (cond | 2878 | (cond |
| 2879 | (header | 2879 | (header |
| 2880 | (let (title eheader body hcharset coding force-charset) | 2880 | (let (title eheader body hcharset coding) |
| 2881 | (with-temp-buffer | 2881 | (with-temp-buffer |
| 2882 | (mm-enable-multibyte) | 2882 | (mm-enable-multibyte) |
| 2883 | (setq case-fold-search t) | 2883 | (setq case-fold-search t) |
| @@ -2900,8 +2900,7 @@ message header will be added to the bodies of the \"text/html\" parts." | |||
| 2900 | charset) | 2900 | charset) |
| 2901 | title (when title | 2901 | title (when title |
| 2902 | (mm-encode-coding-string title charset)) | 2902 | (mm-encode-coding-string title charset)) |
| 2903 | body (mm-encode-coding-string content charset) | 2903 | body (mm-encode-coding-string content charset)) |
| 2904 | force-charset t) | ||
| 2905 | (setq hcharset (mm-find-mime-charset-region (point-min) | 2904 | (setq hcharset (mm-find-mime-charset-region (point-min) |
| 2906 | (point-max))) | 2905 | (point-max))) |
| 2907 | (cond ((= (length hcharset) 1) | 2906 | (cond ((= (length hcharset) 1) |
| @@ -2932,8 +2931,7 @@ message header will be added to the bodies of the \"text/html\" parts." | |||
| 2932 | body (mm-encode-coding-string | 2931 | body (mm-encode-coding-string |
| 2933 | (mm-decode-coding-string | 2932 | (mm-decode-coding-string |
| 2934 | content body) | 2933 | content body) |
| 2935 | charset) | 2934 | charset)))) |
| 2936 | force-charset t))) | ||
| 2937 | (setq charset hcharset | 2935 | (setq charset hcharset |
| 2938 | eheader (mm-encode-coding-string | 2936 | eheader (mm-encode-coding-string |
| 2939 | (buffer-string) coding) | 2937 | (buffer-string) coding) |
| @@ -2947,7 +2945,7 @@ message header will be added to the bodies of the \"text/html\" parts." | |||
| 2947 | (mm-disable-multibyte) | 2945 | (mm-disable-multibyte) |
| 2948 | (insert body) | 2946 | (insert body) |
| 2949 | (when charset | 2947 | (when charset |
| 2950 | (mm-add-meta-html-tag handle charset force-charset)) | 2948 | (mm-add-meta-html-tag handle charset t)) |
| 2951 | (when title | 2949 | (when title |
| 2952 | (goto-char (point-min)) | 2950 | (goto-char (point-min)) |
| 2953 | (unless (search-forward "<title>" nil t) | 2951 | (unless (search-forward "<title>" nil t) |
diff --git a/lisp/ido.el b/lisp/ido.el index 4ab183b3207..f4f9c27c847 100644 --- a/lisp/ido.el +++ b/lisp/ido.el | |||
| @@ -3764,7 +3764,11 @@ This is to make them appear as if they were \"virtual buffers\"." | |||
| 3764 | ido-enable-flex-matching | 3764 | ido-enable-flex-matching |
| 3765 | (> (length ido-text) 1) | 3765 | (> (length ido-text) 1) |
| 3766 | (not ido-enable-regexp)) | 3766 | (not ido-enable-regexp)) |
| 3767 | (setq re (mapconcat #'regexp-quote (split-string ido-text "") ".*")) | 3767 | (setq re (concat (regexp-quote (string (aref ido-text 0))) |
| 3768 | (mapconcat (lambda (c) | ||
| 3769 | (concat "[^" (string c) "]*" | ||
| 3770 | (regexp-quote (string c)))) | ||
| 3771 | (substring ido-text 1) ""))) | ||
| 3768 | (if ido-enable-prefix | 3772 | (if ido-enable-prefix |
| 3769 | (setq re (concat "\\`" re))) | 3773 | (setq re (concat "\\`" re))) |
| 3770 | (mapc | 3774 | (mapc |
diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el index 0066847e995..1d9d098e71c 100644 --- a/lisp/mail/emacsbug.el +++ b/lisp/mail/emacsbug.el | |||
| @@ -60,10 +60,6 @@ | |||
| 60 | 60 | ||
| 61 | ;; User options end here. | 61 | ;; User options end here. |
| 62 | 62 | ||
| 63 | (defvar report-emacs-bug-tracker-url "http://debbugs.gnu.org/cgi/" | ||
| 64 | "Base URL of the GNU bugtracker. | ||
| 65 | Used for querying duplicates and linking to existing bugs.") | ||
| 66 | |||
| 67 | (defvar report-emacs-bug-orig-text nil | 63 | (defvar report-emacs-bug-orig-text nil |
| 68 | "The automatically-created initial text of the bug report.") | 64 | "The automatically-created initial text of the bug report.") |
| 69 | 65 | ||
| @@ -444,90 +440,6 @@ and send the mail again%s." | |||
| 444 | (delete-region pos (field-end (1+ pos))))))) | 440 | (delete-region pos (field-end (1+ pos))))))) |
| 445 | 441 | ||
| 446 | 442 | ||
| 447 | ;; Querying the bug database | ||
| 448 | |||
| 449 | (defvar report-emacs-bug-bug-alist nil) | ||
| 450 | (make-variable-buffer-local 'report-emacs-bug-bug-alist) | ||
| 451 | (defvar report-emacs-bug-choice-widget nil) | ||
| 452 | (make-variable-buffer-local 'report-emacs-bug-choice-widget) | ||
| 453 | |||
| 454 | (defun report-emacs-bug-create-existing-bugs-buffer (bugs keywords) | ||
| 455 | (switch-to-buffer (get-buffer-create "*Existing Emacs Bugs*")) | ||
| 456 | (setq buffer-read-only t) | ||
| 457 | (let ((inhibit-read-only t)) | ||
| 458 | (erase-buffer) | ||
| 459 | (setq report-emacs-bug-bug-alist bugs) | ||
| 460 | (widget-insert (propertize (concat "Already known bugs (" | ||
| 461 | keywords "):\n\n") | ||
| 462 | 'face 'bold)) | ||
| 463 | (if bugs | ||
| 464 | (setq report-emacs-bug-choice-widget | ||
| 465 | (apply 'widget-create 'radio-button-choice | ||
| 466 | :value (caar bugs) | ||
| 467 | (let (items) | ||
| 468 | (dolist (bug bugs) | ||
| 469 | (push (list | ||
| 470 | 'url-link | ||
| 471 | :format (concat "Bug#" (number-to-string (nth 2 bug)) | ||
| 472 | ": " (cadr bug) "\n %[%v%]\n") | ||
| 473 | ;; FIXME: Why is only the link of the | ||
| 474 | ;; active item clickable? | ||
| 475 | (car bug)) | ||
| 476 | items)) | ||
| 477 | (nreverse items)))) | ||
| 478 | (widget-insert "No bugs matching your keywords found.\n")) | ||
| 479 | (widget-insert "\n") | ||
| 480 | (widget-create 'push-button | ||
| 481 | :notify (lambda (&rest ignore) | ||
| 482 | ;; TODO: Do something! | ||
| 483 | (message "Reporting new bug!")) | ||
| 484 | "Report new bug") | ||
| 485 | (when bugs | ||
| 486 | (widget-insert " ") | ||
| 487 | (widget-create 'push-button | ||
| 488 | :notify (lambda (&rest ignore) | ||
| 489 | (let ((val (widget-value report-emacs-bug-choice-widget))) | ||
| 490 | ;; TODO: Do something! | ||
| 491 | (message "Appending to bug %s!" | ||
| 492 | (nth 2 (assoc val report-emacs-bug-bug-alist))))) | ||
| 493 | "Append to chosen bug")) | ||
| 494 | (widget-insert " ") | ||
| 495 | (widget-create 'push-button | ||
| 496 | :notify (lambda (&rest ignore) | ||
| 497 | (kill-buffer)) | ||
| 498 | "Quit reporting bug") | ||
| 499 | (widget-insert "\n")) | ||
| 500 | (use-local-map widget-keymap) | ||
| 501 | (widget-setup) | ||
| 502 | (goto-char (point-min))) | ||
| 503 | |||
| 504 | (defun report-emacs-bug-parse-query-results (status keywords) | ||
| 505 | (goto-char (point-min)) | ||
| 506 | (let (buglist) | ||
| 507 | (while (re-search-forward "<a href=\"bugreport\\.cgi\\?bug=\\([[:digit:]]+\\)\">\\([^<]+\\)</a>" nil t) | ||
| 508 | (let ((number (match-string 1)) | ||
| 509 | (subject (match-string 2))) | ||
| 510 | (when (not (string-match "^#" subject)) | ||
| 511 | (push (list | ||
| 512 | ;; first the bug URL | ||
| 513 | (concat report-emacs-bug-tracker-url | ||
| 514 | "bugreport.cgi?bug=" number) | ||
| 515 | ;; then the subject and number | ||
| 516 | subject (string-to-number number)) | ||
| 517 | buglist)))) | ||
| 518 | (report-emacs-bug-create-existing-bugs-buffer (nreverse buglist) keywords))) | ||
| 519 | |||
| 520 | ;;;###autoload | ||
| 521 | (defun report-emacs-bug-query-existing-bugs (keywords) | ||
| 522 | "Query for KEYWORDS at `report-emacs-bug-tracker-url', and return the result. | ||
| 523 | The result is an alist with items of the form (URL SUBJECT NO)." | ||
| 524 | (interactive "sBug keywords (comma separated): ") | ||
| 525 | (url-retrieve (concat report-emacs-bug-tracker-url | ||
| 526 | "pkgreport.cgi?include=subject%3A" | ||
| 527 | (replace-regexp-in-string "[[:space:]]+" "+" keywords) | ||
| 528 | ";package=emacs") | ||
| 529 | 'report-emacs-bug-parse-query-results (list keywords))) | ||
| 530 | |||
| 531 | (provide 'emacsbug) | 443 | (provide 'emacsbug) |
| 532 | 444 | ||
| 533 | ;;; emacsbug.el ends here | 445 | ;;; emacsbug.el ends here |
diff --git a/lisp/minibuf-eldef.el b/lisp/minibuf-eldef.el index 92d5ec821b0..950c28b227f 100644 --- a/lisp/minibuf-eldef.el +++ b/lisp/minibuf-eldef.el | |||
| @@ -33,13 +33,25 @@ | |||
| 33 | 33 | ||
| 34 | ;;; Code: | 34 | ;;; Code: |
| 35 | 35 | ||
| 36 | (defvar minibuffer-eldef-shorten-default nil | 36 | (defvar minibuffer-eldef-shorten-default) |
| 37 | "If non-nil, shorten \"(default ...)\" to \"[...]\" in minibuffer prompts.") | ||
| 38 | 37 | ||
| 39 | (defvar minibuffer-default-in-prompt-regexps | 38 | (defun minibuffer-default--in-prompt-regexps () |
| 40 | `(("\\( (default\\(?: is\\)? \\(.*\\))\\):? \\'" | 39 | `(("\\( (default\\(?: is\\)? \\(.*\\))\\):? \\'" |
| 41 | 1 ,(if minibuffer-eldef-shorten-default " [\\2]")) | 40 | 1 ,(if minibuffer-eldef-shorten-default " [\\2]")) |
| 42 | ("\\( \\[.*\\]\\):? *\\'" 1)) | 41 | ("\\( \\[.*\\]\\):? *\\'" 1))) |
| 42 | |||
| 43 | (defcustom minibuffer-eldef-shorten-default nil | ||
| 44 | "If non-nil, shorten \"(default ...)\" to \"[...]\" in minibuffer prompts." | ||
| 45 | :set (lambda (symbol value) | ||
| 46 | (set-default symbol value) | ||
| 47 | (setq-default minibuffer-default-in-prompt-regexps | ||
| 48 | (minibuffer-default--in-prompt-regexps))) | ||
| 49 | :type 'boolean | ||
| 50 | :group 'minibuffer | ||
| 51 | :version "24.3") | ||
| 52 | |||
| 53 | (defvar minibuffer-default-in-prompt-regexps | ||
| 54 | (minibuffer-default--in-prompt-regexps) | ||
| 43 | "A list of regexps matching the parts of minibuffer prompts showing defaults. | 55 | "A list of regexps matching the parts of minibuffer prompts showing defaults. |
| 44 | When `minibuffer-electric-default-mode' is active, these regexps are | 56 | When `minibuffer-electric-default-mode' is active, these regexps are |
| 45 | used to identify the portions of prompts to elide. | 57 | used to identify the portions of prompts to elide. |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 38347f23f7d..6e704fad807 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -51,6 +51,9 @@ | |||
| 51 | 51 | ||
| 52 | ;;; Todo: | 52 | ;;; Todo: |
| 53 | 53 | ||
| 54 | ;; - Make *Completions* readable even if some of the completion | ||
| 55 | ;; entries have LF chars or spaces in them (including at | ||
| 56 | ;; beginning/end) or are very long. | ||
| 54 | ;; - for M-x, cycle-sort commands that have no key binding first. | 57 | ;; - for M-x, cycle-sort commands that have no key binding first. |
| 55 | ;; - Make things like icomplete-mode or lightning-completion work with | 58 | ;; - Make things like icomplete-mode or lightning-completion work with |
| 56 | ;; completion-in-region-mode. | 59 | ;; completion-in-region-mode. |
| @@ -74,6 +77,9 @@ | |||
| 74 | ;; - whether the user wants completion to pay attention to case. | 77 | ;; - whether the user wants completion to pay attention to case. |
| 75 | ;; e.g. we may want to make it possible for the user to say "first try | 78 | ;; e.g. we may want to make it possible for the user to say "first try |
| 76 | ;; completion case-sensitively, and if that fails, try to ignore case". | 79 | ;; completion case-sensitively, and if that fails, try to ignore case". |
| 80 | ;; Maybe the trick is that we should distinguish completion-ignore-case in | ||
| 81 | ;; try/all-completions (obey user's preference) from its use in | ||
| 82 | ;; test-completion (obey the underlying object's semantics). | ||
| 77 | 83 | ||
| 78 | ;; - add support for ** to pcm. | 84 | ;; - add support for ** to pcm. |
| 79 | ;; - Add vc-file-name-completion-table to read-file-name-internal. | 85 | ;; - Add vc-file-name-completion-table to read-file-name-internal. |
| @@ -2048,6 +2054,8 @@ This is only used when the minibuffer area has no active minibuffer.") | |||
| 2048 | process-environment)) | 2054 | process-environment)) |
| 2049 | 2055 | ||
| 2050 | (defconst completion--embedded-envvar-re | 2056 | (defconst completion--embedded-envvar-re |
| 2057 | ;; We can't reuse env--substitute-vars-regexp because we need to match only | ||
| 2058 | ;; potentially-unfinished envvars at end of string. | ||
| 2051 | (concat "\\(?:^\\|[^$]\\(?:\\$\\$\\)*\\)" | 2059 | (concat "\\(?:^\\|[^$]\\(?:\\$\\$\\)*\\)" |
| 2052 | "$\\([[:alnum:]_]*\\|{\\([^}]*\\)\\)\\'")) | 2060 | "$\\([[:alnum:]_]*\\|{\\([^}]*\\)\\)\\'")) |
| 2053 | 2061 | ||
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 874c0aa7fef..caaae5d553e 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el | |||
| @@ -1748,20 +1748,26 @@ value of `default-file-modes', without execute permissions." | |||
| 1748 | (or (file-modes filename) | 1748 | (or (file-modes filename) |
| 1749 | (logand (default-file-modes) (tramp-compat-octal-to-decimal "0666")))) | 1749 | (logand (default-file-modes) (tramp-compat-octal-to-decimal "0666")))) |
| 1750 | 1750 | ||
| 1751 | (defun tramp-replace-environment-variables (filename) | 1751 | (defalias 'tramp-replace-environment-variables |
| 1752 | "Replace environment variables in FILENAME. | 1752 | (if (ignore-errors |
| 1753 | (equal "${ tramp?}" (substitute-env-vars "${ tramp?}" 'only-defined))) | ||
| 1754 | (lambda (filename) | ||
| 1755 | "Like `substitute-env-vars' with `only-defined' non-nil." | ||
| 1756 | (substitute-env-vars filename 'only-defined)) | ||
| 1757 | (lambda (filename) | ||
| 1758 | "Replace environment variables in FILENAME. | ||
| 1753 | Return the string with the replaced variables." | 1759 | Return the string with the replaced variables." |
| 1754 | (save-match-data | 1760 | (save-match-data |
| 1755 | (let ((idx (string-match "$\\(\\w+\\)" filename))) | 1761 | (let ((idx (string-match "$\\(\\w+\\)" filename))) |
| 1756 | ;; `$' is coded as `$$'. | 1762 | ;; `$' is coded as `$$'. |
| 1757 | (when (and idx | 1763 | (when (and idx |
| 1758 | (or (zerop idx) (not (eq ?$ (aref filename (1- idx))))) | 1764 | (or (zerop idx) (not (eq ?$ (aref filename (1- idx))))) |
| 1759 | (getenv (match-string 1 filename))) | 1765 | (getenv (match-string 1 filename))) |
| 1760 | (setq filename | 1766 | (setq filename |
| 1761 | (replace-match | 1767 | (replace-match |
| 1762 | (substitute-in-file-name (match-string 0 filename)) | 1768 | (substitute-in-file-name (match-string 0 filename)) |
| 1763 | t nil filename))) | 1769 | t nil filename))) |
| 1764 | filename))) | 1770 | filename))))) |
| 1765 | 1771 | ||
| 1766 | ;; In XEmacs, electricity is implemented via a key map for ?/ and ?~, | 1772 | ;; In XEmacs, electricity is implemented via a key map for ?/ and ?~, |
| 1767 | ;; which calls corresponding functions (see minibuf.el). | 1773 | ;; which calls corresponding functions (see minibuf.el). |
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index d954cd53e0a..33ef7607671 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el | |||
| @@ -1823,22 +1823,31 @@ nil." | |||
| 1823 | 1823 | ||
| 1824 | ;;; Filling | 1824 | ;;; Filling |
| 1825 | 1825 | ||
| 1826 | (defvar js--filling-paragraph nil) | ||
| 1827 | |||
| 1828 | ;; FIXME: Such redefinitions are bad style. We should try and use some other | ||
| 1829 | ;; way to get the same result. | ||
| 1830 | (defadvice c-forward-sws (around js-fill-paragraph activate) | ||
| 1831 | (if js--filling-paragraph | ||
| 1832 | (setq ad-return-value (js--forward-syntactic-ws (ad-get-arg 0))) | ||
| 1833 | ad-do-it)) | ||
| 1834 | |||
| 1835 | (defadvice c-backward-sws (around js-fill-paragraph activate) | ||
| 1836 | (if js--filling-paragraph | ||
| 1837 | (setq ad-return-value (js--backward-syntactic-ws (ad-get-arg 0))) | ||
| 1838 | ad-do-it)) | ||
| 1839 | |||
| 1840 | (defadvice c-beginning-of-macro (around js-fill-paragraph activate) | ||
| 1841 | (if js--filling-paragraph | ||
| 1842 | (setq ad-return-value (js--beginning-of-macro (ad-get-arg 0))) | ||
| 1843 | ad-do-it)) | ||
| 1844 | |||
| 1826 | (defun js-c-fill-paragraph (&optional justify) | 1845 | (defun js-c-fill-paragraph (&optional justify) |
| 1827 | "Fill the paragraph with `c-fill-paragraph'." | 1846 | "Fill the paragraph with `c-fill-paragraph'." |
| 1828 | (interactive "*P") | 1847 | (interactive "*P") |
| 1829 | ;; FIXME: Such redefinitions are bad style. We should try and use some other | 1848 | (let ((js--filling-paragraph t) |
| 1830 | ;; way to get the same result. | 1849 | (fill-paragraph-function 'c-fill-paragraph)) |
| 1831 | (cl-letf (((symbol-function 'c-forward-sws) | 1850 | (c-fill-paragraph justify))) |
| 1832 | (lambda (&optional limit) | ||
| 1833 | (js--forward-syntactic-ws limit))) | ||
| 1834 | ((symbol-function 'c-backward-sws) | ||
| 1835 | (lambda (&optional limit) | ||
| 1836 | (js--backward-syntactic-ws limit))) | ||
| 1837 | ((symbol-function 'c-beginning-of-macro) | ||
| 1838 | (lambda (&optional limit) | ||
| 1839 | (js--beginning-of-macro limit)))) | ||
| 1840 | (let ((fill-paragraph-function 'c-fill-paragraph)) | ||
| 1841 | (c-fill-paragraph justify)))) | ||
| 1842 | 1851 | ||
| 1843 | ;;; Type database and Imenu | 1852 | ;;; Type database and Imenu |
| 1844 | 1853 | ||
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el index 3dd9a48bb33..d2f7fc7a059 100644 --- a/lisp/progmodes/perl-mode.el +++ b/lisp/progmodes/perl-mode.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; perl-mode.el --- Perl code editing commands for GNU Emacs | 1 | ;;; perl-mode.el --- Perl code editing commands for GNU Emacs -*- coding: utf-8 -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1990, 1994, 2001-2012 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1990, 1994, 2001-2012 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -102,11 +102,6 @@ | |||
| 102 | 102 | ||
| 103 | ;;; Code: | 103 | ;;; Code: |
| 104 | 104 | ||
| 105 | |||
| 106 | (defvar font-lock-comment-face) | ||
| 107 | (defvar font-lock-doc-face) | ||
| 108 | (defvar font-lock-string-face) | ||
| 109 | |||
| 110 | (defgroup perl nil | 105 | (defgroup perl nil |
| 111 | "Major mode for editing Perl code." | 106 | "Major mode for editing Perl code." |
| 112 | :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces) | 107 | :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces) |
| @@ -119,16 +114,11 @@ | |||
| 119 | 114 | ||
| 120 | (defvar perl-mode-map | 115 | (defvar perl-mode-map |
| 121 | (let ((map (make-sparse-keymap))) | 116 | (let ((map (make-sparse-keymap))) |
| 122 | (define-key map "{" 'perl-electric-terminator) | ||
| 123 | (define-key map "}" 'perl-electric-terminator) | ||
| 124 | (define-key map ";" 'perl-electric-terminator) | ||
| 125 | (define-key map ":" 'perl-electric-terminator) | ||
| 126 | (define-key map "\e\C-a" 'perl-beginning-of-function) | 117 | (define-key map "\e\C-a" 'perl-beginning-of-function) |
| 127 | (define-key map "\e\C-e" 'perl-end-of-function) | 118 | (define-key map "\e\C-e" 'perl-end-of-function) |
| 128 | (define-key map "\e\C-h" 'perl-mark-function) | 119 | (define-key map "\e\C-h" 'perl-mark-function) |
| 129 | (define-key map "\e\C-q" 'perl-indent-exp) | 120 | (define-key map "\e\C-q" 'perl-indent-exp) |
| 130 | (define-key map "\177" 'backward-delete-char-untabify) | 121 | (define-key map "\177" 'backward-delete-char-untabify) |
| 131 | (define-key map "\t" 'perl-indent-command) | ||
| 132 | map) | 122 | map) |
| 133 | "Keymap used in Perl mode.") | 123 | "Keymap used in Perl mode.") |
| 134 | 124 | ||
| @@ -158,16 +148,54 @@ | |||
| 158 | 148 | ||
| 159 | (defvar perl-imenu-generic-expression | 149 | (defvar perl-imenu-generic-expression |
| 160 | '(;; Functions | 150 | '(;; Functions |
| 161 | (nil "^sub\\s-+\\([-A-Za-z0-9+_:]+\\)" 1) | 151 | (nil "^[ \t]*sub\\s-+\\([-A-Za-z0-9+_:]+\\)" 1) |
| 162 | ;;Variables | 152 | ;;Variables |
| 163 | ("Variables" "^\\(?:my\\|our\\)\\s-+\\([$@%][-A-Za-z0-9+_:]+\\)\\s-*=" 1) | 153 | ("Variables" "^\\(?:my\\|our\\)\\s-+\\([$@%][-A-Za-z0-9+_:]+\\)\\s-*=" 1) |
| 164 | ("Packages" "^package\\s-+\\([-A-Za-z0-9+_:]+\\);" 1) | 154 | ("Packages" "^[ \t]*package\\s-+\\([-A-Za-z0-9+_:]+\\);" 1) |
| 165 | ("Doc sections" "^=head[0-9][ \t]+\\(.*\\)" 1)) | 155 | ("Doc sections" "^=head[0-9][ \t]+\\(.*\\)" 1)) |
| 166 | "Imenu generic expression for Perl mode. See `imenu-generic-expression'.") | 156 | "Imenu generic expression for Perl mode. See `imenu-generic-expression'.") |
| 167 | 157 | ||
| 168 | ;; Regexps updated with help from Tom Tromey <tromey@cambric.colorado.edu> and | 158 | ;; Regexps updated with help from Tom Tromey <tromey@cambric.colorado.edu> and |
| 169 | ;; Jim Campbell <jec@murzim.ca.boeing.com>. | 159 | ;; Jim Campbell <jec@murzim.ca.boeing.com>. |
| 170 | 160 | ||
| 161 | (defcustom perl-prettify-symbols t | ||
| 162 | "If non-nil, some symbols will be displayed using Unicode chars." | ||
| 163 | :type 'boolean) | ||
| 164 | |||
| 165 | (defconst perl--prettify-symbols-alist | ||
| 166 | '(;;("andalso" . ?∧) ("orelse" . ?∨) ("as" . ?≡)("not" . ?¬) | ||
| 167 | ;;("div" . ?÷) ("*" . ?×) ("o" . ?○) | ||
| 168 | ("->" . ?→) | ||
| 169 | ("=>" . ?⇒) | ||
| 170 | ;;("<-" . ?←) ("<>" . ?≠) (">=" . ?≥) ("<=" . ?≤) ("..." . ?⋯) | ||
| 171 | ("::" . ?∷) | ||
| 172 | )) | ||
| 173 | |||
| 174 | (defun perl--font-lock-compose-symbol () | ||
| 175 | "Compose a sequence of ascii chars into a symbol. | ||
| 176 | Regexp match data 0 points to the chars." | ||
| 177 | ;; Check that the chars should really be composed into a symbol. | ||
| 178 | (let* ((start (match-beginning 0)) | ||
| 179 | (end (match-end 0)) | ||
| 180 | (syntaxes (if (eq (char-syntax (char-after start)) ?w) | ||
| 181 | '(?w) '(?. ?\\)))) | ||
| 182 | (if (or (memq (char-syntax (or (char-before start) ?\ )) syntaxes) | ||
| 183 | (memq (char-syntax (or (char-after end) ?\ )) syntaxes) | ||
| 184 | (nth 8 (syntax-ppss))) | ||
| 185 | ;; No composition for you. Let's actually remove any composition | ||
| 186 | ;; we may have added earlier and which is now incorrect. | ||
| 187 | (remove-text-properties start end '(composition)) | ||
| 188 | ;; That's a symbol alright, so add the composition. | ||
| 189 | (compose-region start end (cdr (assoc (match-string 0) | ||
| 190 | perl--prettify-symbols-alist))))) | ||
| 191 | ;; Return nil because we're not adding any face property. | ||
| 192 | nil) | ||
| 193 | |||
| 194 | (defun perl--font-lock-symbols-keywords () | ||
| 195 | (when perl-prettify-symbols | ||
| 196 | `((,(regexp-opt (mapcar 'car perl--prettify-symbols-alist) t) | ||
| 197 | (0 (perl--font-lock-compose-symbol)))))) | ||
| 198 | |||
| 171 | (defconst perl-font-lock-keywords-1 | 199 | (defconst perl-font-lock-keywords-1 |
| 172 | '(;; What is this for? | 200 | '(;; What is this for? |
| 173 | ;;("\\(--- .* ---\\|=== .* ===\\)" . font-lock-string-face) | 201 | ;;("\\(--- .* ---\\|=== .* ===\\)" . font-lock-string-face) |
| @@ -190,32 +218,32 @@ | |||
| 190 | "Subdued level highlighting for Perl mode.") | 218 | "Subdued level highlighting for Perl mode.") |
| 191 | 219 | ||
| 192 | (defconst perl-font-lock-keywords-2 | 220 | (defconst perl-font-lock-keywords-2 |
| 193 | (append perl-font-lock-keywords-1 | 221 | (append |
| 194 | (list | 222 | perl-font-lock-keywords-1 |
| 195 | ;; | 223 | `( ;; Fontify keywords, except those fontified otherwise. |
| 196 | ;; Fontify keywords, except those fontified otherwise. | 224 | ,(concat "\\<" |
| 197 | (concat "\\<" | 225 | (regexp-opt '("if" "until" "while" "elsif" "else" "unless" |
| 198 | (regexp-opt '("if" "until" "while" "elsif" "else" "unless" | 226 | "do" "dump" "for" "foreach" "exit" "die" |
| 199 | "do" "dump" "for" "foreach" "exit" "die" | 227 | "BEGIN" "END" "return" "exec" "eval") t) |
| 200 | "BEGIN" "END" "return" "exec" "eval") t) | 228 | "\\>") |
| 201 | "\\>") | 229 | ;; |
| 202 | ;; | 230 | ;; Fontify local and my keywords as types. |
| 203 | ;; Fontify local and my keywords as types. | 231 | ("\\<\\(local\\|my\\)\\>" . font-lock-type-face) |
| 204 | '("\\<\\(local\\|my\\)\\>" . font-lock-type-face) | 232 | ;; |
| 205 | ;; | 233 | ;; Fontify function, variable and file name references. |
| 206 | ;; Fontify function, variable and file name references. | 234 | ("&\\(\\sw+\\(::\\sw+\\)*\\)" 1 font-lock-function-name-face) |
| 207 | '("&\\(\\sw+\\(::\\sw+\\)*\\)" 1 font-lock-function-name-face) | 235 | ;; Additionally underline non-scalar variables. Maybe this is a bad idea. |
| 208 | ;; Additionally underline non-scalar variables. Maybe this is a bad idea. | 236 | ;;'("[$@%*][#{]?\\(\\sw+\\)" 1 font-lock-variable-name-face) |
| 209 | ;;'("[$@%*][#{]?\\(\\sw+\\)" 1 font-lock-variable-name-face) | 237 | ("[$*]{?\\(\\sw+\\(::\\sw+\\)*\\)" 1 font-lock-variable-name-face) |
| 210 | '("[$*]{?\\(\\sw+\\(::\\sw+\\)*\\)" 1 font-lock-variable-name-face) | 238 | ("\\([@%]\\|\\$#\\)\\(\\sw+\\(::\\sw+\\)*\\)" |
| 211 | '("\\([@%]\\|\\$#\\)\\(\\sw+\\(::\\sw+\\)*\\)" | ||
| 212 | (2 (cons font-lock-variable-name-face '(underline)))) | 239 | (2 (cons font-lock-variable-name-face '(underline)))) |
| 213 | '("<\\(\\sw+\\)>" 1 font-lock-constant-face) | 240 | ("<\\(\\sw+\\)>" 1 font-lock-constant-face) |
| 214 | ;; | 241 | ;; |
| 215 | ;; Fontify keywords with/and labels as we do in `c++-font-lock-keywords'. | 242 | ;; Fontify keywords with/and labels as we do in `c++-font-lock-keywords'. |
| 216 | '("\\<\\(continue\\|goto\\|last\\|next\\|redo\\)\\>[ \t]*\\(\\sw+\\)?" | 243 | ("\\<\\(continue\\|goto\\|last\\|next\\|redo\\)\\>[ \t]*\\(\\sw+\\)?" |
| 217 | (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) | 244 | (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) |
| 218 | '("^[ \t]*\\(\\sw+\\)[ \t]*:[^:]" 1 font-lock-constant-face))) | 245 | ("^[ \t]*\\(\\sw+\\)[ \t]*:[^:]" 1 font-lock-constant-face) |
| 246 | ,@(perl--font-lock-symbols-keywords))) | ||
| 219 | "Gaudy level highlighting for Perl mode.") | 247 | "Gaudy level highlighting for Perl mode.") |
| 220 | 248 | ||
| 221 | (defvar perl-font-lock-keywords perl-font-lock-keywords-1 | 249 | (defvar perl-font-lock-keywords perl-font-lock-keywords-1 |
| @@ -543,8 +571,10 @@ create a new comment." | |||
| 543 | 571 | ||
| 544 | (defun perl-outline-level () | 572 | (defun perl-outline-level () |
| 545 | (cond | 573 | (cond |
| 546 | ((looking-at "package\\s-") 0) | 574 | ((looking-at "[ \t]*\\(package\\)\\s-") |
| 547 | ((looking-at "sub\\s-") 1) | 575 | (- (match-beginning 1) (match-beginning 0))) |
| 576 | ((looking-at "[ \t]*s\\(ub\\)\\s-") | ||
| 577 | (- (match-beginning 1) (match-beginning 0))) | ||
| 548 | ((looking-at "=head[0-9]") (- (char-before (match-end 0)) ?0)) | 578 | ((looking-at "=head[0-9]") (- (char-before (match-end 0)) ?0)) |
| 549 | ((looking-at "=cut") 1) | 579 | ((looking-at "=cut") 1) |
| 550 | (t 3))) | 580 | (t 3))) |
| @@ -621,6 +651,11 @@ Turning on Perl mode runs the normal hook `perl-mode-hook'." | |||
| 621 | #'perl-syntax-propertize-function) | 651 | #'perl-syntax-propertize-function) |
| 622 | (add-hook 'syntax-propertize-extend-region-functions | 652 | (add-hook 'syntax-propertize-extend-region-functions |
| 623 | #'syntax-propertize-multiline 'append 'local) | 653 | #'syntax-propertize-multiline 'append 'local) |
| 654 | ;; Electricity. | ||
| 655 | ;; FIXME: setup electric-layout-rules. | ||
| 656 | (set (make-local-variable 'electric-indent-chars) | ||
| 657 | (append '(?\{ ?\} ?\; ?\:) electric-indent-chars)) | ||
| 658 | (add-hook 'electric-indent-functions #'perl-electric-noindent-p nil t) | ||
| 624 | ;; Tell imenu how to handle Perl. | 659 | ;; Tell imenu how to handle Perl. |
| 625 | (set (make-local-variable 'imenu-generic-expression) | 660 | (set (make-local-variable 'imenu-generic-expression) |
| 626 | perl-imenu-generic-expression) | 661 | perl-imenu-generic-expression) |
| @@ -637,7 +672,11 @@ Turning on Perl mode runs the normal hook `perl-mode-hook'." | |||
| 637 | 0 ;Existing comment at bol stays there. | 672 | 0 ;Existing comment at bol stays there. |
| 638 | comment-column)) | 673 | comment-column)) |
| 639 | 674 | ||
| 640 | (defalias 'electric-perl-terminator 'perl-electric-terminator) | 675 | (define-obsolete-function-alias 'electric-perl-terminator |
| 676 | 'perl-electric-terminator "22.1") | ||
| 677 | (defun perl-electric-noindent-p (char) | ||
| 678 | (unless (eolp) 'no-indent)) | ||
| 679 | |||
| 641 | (defun perl-electric-terminator (arg) | 680 | (defun perl-electric-terminator (arg) |
| 642 | "Insert character and maybe adjust indentation. | 681 | "Insert character and maybe adjust indentation. |
| 643 | If at end-of-line, and not in a comment or a quote, correct the indentation." | 682 | If at end-of-line, and not in a comment or a quote, correct the indentation." |
| @@ -661,6 +700,7 @@ If at end-of-line, and not in a comment or a quote, correct the indentation." | |||
| 661 | (perl-indent-line) | 700 | (perl-indent-line) |
| 662 | (delete-char -1)))) | 701 | (delete-char -1)))) |
| 663 | (self-insert-command (prefix-numeric-value arg))) | 702 | (self-insert-command (prefix-numeric-value arg))) |
| 703 | (make-obsolete 'perl-electric-terminator 'electric-indent-mode "24.4") | ||
| 664 | 704 | ||
| 665 | ;; not used anymore, but may be useful someday: | 705 | ;; not used anymore, but may be useful someday: |
| 666 | ;;(defun perl-inside-parens-p () | 706 | ;;(defun perl-inside-parens-p () |
| @@ -744,6 +784,7 @@ following list: | |||
| 744 | (t | 784 | (t |
| 745 | (message "Use backslash to quote # characters.") | 785 | (message "Use backslash to quote # characters.") |
| 746 | (ding t))))))))) | 786 | (ding t))))))))) |
| 787 | (make-obsolete 'perl-indent-command 'indent-according-to-mode "24.4") | ||
| 747 | 788 | ||
| 748 | (defun perl-indent-line (&optional nochange parse-start) | 789 | (defun perl-indent-line (&optional nochange parse-start) |
| 749 | "Indent current line as Perl code. | 790 | "Indent current line as Perl code. |
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 84cf7308d75..c9bfcefb748 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el | |||
| @@ -1638,6 +1638,8 @@ The variable `ruby-indent-level' controls the amount of indentation. | |||
| 1638 | 1638 | ||
| 1639 | ;;;###autoload | 1639 | ;;;###autoload |
| 1640 | (add-to-list 'auto-mode-alist (cons (purecopy "\\.rb\\'") 'ruby-mode)) | 1640 | (add-to-list 'auto-mode-alist (cons (purecopy "\\.rb\\'") 'ruby-mode)) |
| 1641 | ;;;###autoload | ||
| 1642 | (add-to-list 'auto-mode-alist '("Rakefile\\'" . ruby-mode)) | ||
| 1641 | 1643 | ||
| 1642 | ;;;###autoload | 1644 | ;;;###autoload |
| 1643 | (dolist (name (list "ruby" "rbx" "jruby" "ruby1.9" "ruby1.8")) | 1645 | (dolist (name (list "ruby" "rbx" "jruby" "ruby1.9" "ruby1.8")) |
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el index 3d5abc4df62..64b87d9e436 100644 --- a/lisp/progmodes/sql.el +++ b/lisp/progmodes/sql.el | |||
| @@ -2802,8 +2802,12 @@ each line with INDENT." | |||
| 2802 | doc)) | 2802 | doc)) |
| 2803 | 2803 | ||
| 2804 | ;;;###autoload | 2804 | ;;;###autoload |
| 2805 | (defun sql-help () | 2805 | (eval |
| 2806 | "Show short help for the SQL modes. | 2806 | ;; FIXME: This dynamic-docstring-function trick doesn't work for byte-compiled |
| 2807 | ;; functions, because of the lazy-loading of docstrings, which strips away | ||
| 2808 | ;; text properties. | ||
| 2809 | '(defun sql-help () | ||
| 2810 | #("Show short help for the SQL modes. | ||
| 2807 | 2811 | ||
| 2808 | Use an entry function to open an interactive SQL buffer. This buffer is | 2812 | Use an entry function to open an interactive SQL buffer. This buffer is |
| 2809 | usually named `*SQL*'. The name of the major mode is SQLi. | 2813 | usually named `*SQL*'. The name of the major mode is SQLi. |
| @@ -2834,32 +2838,23 @@ anything. The name of the major mode is SQL. | |||
| 2834 | In this SQL buffer (SQL mode), you can send the region or the entire | 2838 | In this SQL buffer (SQL mode), you can send the region or the entire |
| 2835 | buffer to the interactive SQL buffer (SQLi mode). The results are | 2839 | buffer to the interactive SQL buffer (SQLi mode). The results are |
| 2836 | appended to the SQLi buffer without disturbing your SQL buffer." | 2840 | appended to the SQLi buffer without disturbing your SQL buffer." |
| 2841 | 0 1 (dynamic-docstring-function sql--make-help-docstring)) | ||
| 2837 | (interactive) | 2842 | (interactive) |
| 2843 | (describe-function 'sql-help))) | ||
| 2838 | 2844 | ||
| 2839 | ;; Insert references to loaded products into the help buffer string | 2845 | (defun sql--make-help-docstring (doc _fun) |
| 2840 | (let ((doc (documentation 'sql-help t)) | 2846 | "Insert references to loaded products into the help buffer string." |
| 2841 | changedp) | 2847 | |
| 2842 | (setq changedp nil) | 2848 | ;; Insert FREE software list |
| 2843 | 2849 | (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]FREE\\s-*\n" doc 0) | |
| 2844 | ;; Insert FREE software list | 2850 | (setq doc (replace-match (sql-help-list-products (match-string 1 doc) t) |
| 2845 | (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]FREE\\s-*\n" doc 0) | 2851 | t t doc 0))) |
| 2846 | (setq doc (replace-match (sql-help-list-products (match-string 1 doc) t) | 2852 | |
| 2847 | t t doc 0) | 2853 | ;; Insert non-FREE software list |
| 2848 | changedp t)) | 2854 | (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]NONFREE\\s-*\n" doc 0) |
| 2849 | 2855 | (setq doc (replace-match (sql-help-list-products (match-string 1 doc) nil) | |
| 2850 | ;; Insert non-FREE software list | 2856 | t t doc 0))) |
| 2851 | (when (string-match "^\\(\\s-*\\)[\\\\][\\\\]NONFREE\\s-*\n" doc 0) | 2857 | doc) |
| 2852 | (setq doc (replace-match (sql-help-list-products (match-string 1 doc) nil) | ||
| 2853 | t t doc 0) | ||
| 2854 | changedp t)) | ||
| 2855 | |||
| 2856 | ;; If we changed the help text, save the change so that the help | ||
| 2857 | ;; sub-system will see it | ||
| 2858 | (when changedp | ||
| 2859 | (put 'sql-help 'function-documentation doc))) | ||
| 2860 | |||
| 2861 | ;; Call help on this function | ||
| 2862 | (describe-function 'sql-help)) | ||
| 2863 | 2858 | ||
| 2864 | (defun sql-read-passwd (prompt &optional default) | 2859 | (defun sql-read-passwd (prompt &optional default) |
| 2865 | "Read a password using PROMPT. Optional DEFAULT is password to start with." | 2860 | "Read a password using PROMPT. Optional DEFAULT is password to start with." |
diff --git a/lisp/server.el b/lisp/server.el index 7a356a90378..c78e3e376aa 100644 --- a/lisp/server.el +++ b/lisp/server.el | |||
| @@ -842,6 +842,15 @@ This handles splitting the command if it would be bigger than | |||
| 842 | (unless (assq w window-system-initialization-alist) | 842 | (unless (assq w window-system-initialization-alist) |
| 843 | (setq w nil)) | 843 | (setq w nil)) |
| 844 | 844 | ||
| 845 | ;; Special case for ns. This is because DISPLAY may not be set at all | ||
| 846 | ;; which in the ns case isn't an error. The variable display then becomes | ||
| 847 | ;; the fully qualified hostname, which make-frame-on-display below | ||
| 848 | ;; does not understand and throws an error. | ||
| 849 | ;; It may also be a valid X display, but if Emacs is compiled for ns, it | ||
| 850 | ;; can not make X frames. | ||
| 851 | (if (featurep 'ns-win) | ||
| 852 | (setq w 'ns display "ns")) | ||
| 853 | |||
| 845 | (cond (w | 854 | (cond (w |
| 846 | ;; Flag frame as client-created, but use a dummy client. | 855 | ;; Flag frame as client-created, but use a dummy client. |
| 847 | ;; This will prevent the frame from being deleted when | 856 | ;; This will prevent the frame from being deleted when |
diff --git a/lisp/ses.el b/lisp/ses.el index 7cdac74e310..27b906d22e3 100644 --- a/lisp/ses.el +++ b/lisp/ses.el | |||
| @@ -278,6 +278,7 @@ default printer and then modify its output.") | |||
| 278 | ses--default-printer | 278 | ses--default-printer |
| 279 | ses--deferred-narrow ses--deferred-recalc | 279 | ses--deferred-narrow ses--deferred-recalc |
| 280 | ses--deferred-write ses--file-format | 280 | ses--deferred-write ses--file-format |
| 281 | ses--named-cell-hashmap | ||
| 281 | (ses--header-hscroll . -1) ; Flag for "initial recalc needed" | 282 | (ses--header-hscroll . -1) ; Flag for "initial recalc needed" |
| 282 | ses--header-row ses--header-string ses--linewidth | 283 | ses--header-row ses--header-string ses--linewidth |
| 283 | ses--numcols ses--numrows ses--symbolic-formulas | 284 | ses--numcols ses--numrows ses--symbolic-formulas |
| @@ -511,9 +512,22 @@ PROPERTY-NAME." | |||
| 511 | `(aref ses--col-printers ,col)) | 512 | `(aref ses--col-printers ,col)) |
| 512 | 513 | ||
| 513 | (defmacro ses-sym-rowcol (sym) | 514 | (defmacro ses-sym-rowcol (sym) |
| 514 | "From a cell-symbol SYM, gets the cons (row . col). A1 => (0 . 0). | 515 | "From a cell-symbol SYM, gets the cons (row . col). A1 => (0 . 0). Result |
| 515 | Result is nil if SYM is not a symbol that names a cell." | 516 | is nil if SYM is not a symbol that names a cell." |
| 516 | `(and (symbolp ,sym) (get ,sym 'ses-cell))) | 517 | `(let ((rc (and (symbolp ,sym) (get ,sym 'ses-cell)))) |
| 518 | (if (eq rc :ses-named) | ||
| 519 | (gethash ,sym ses--named-cell-hashmap) | ||
| 520 | rc))) | ||
| 521 | |||
| 522 | (defun ses-is-cell-sym-p (sym) | ||
| 523 | "Check whether SYM point at a cell of this spread sheet." | ||
| 524 | (let ((rowcol (get sym 'ses-cell))) | ||
| 525 | (and rowcol | ||
| 526 | (if (eq rowcol :ses-named) | ||
| 527 | (and ses--named-cell-hashmap (gethash sym ses--named-cell-hashmap)) | ||
| 528 | (and (< (car rowcol) ses--numrows) | ||
| 529 | (< (cdr rowcol) ses--numcols) | ||
| 530 | (eq (ses-cell-symbol (car rowcol) (cdr rowcol)) sym)))))) | ||
| 517 | 531 | ||
| 518 | (defmacro ses-cell (sym value formula printer references) | 532 | (defmacro ses-cell (sym value formula printer references) |
| 519 | "Load a cell SYM from the spreadsheet file. Does not recompute VALUE from | 533 | "Load a cell SYM from the spreadsheet file. Does not recompute VALUE from |
| @@ -682,6 +696,28 @@ for this spreadsheet." | |||
| 682 | "Produce a symbol that names the cell (ROW,COL). (0,0) => 'A1." | 696 | "Produce a symbol that names the cell (ROW,COL). (0,0) => 'A1." |
| 683 | (intern (concat (ses-column-letter col) (number-to-string (1+ row))))) | 697 | (intern (concat (ses-column-letter col) (number-to-string (1+ row))))) |
| 684 | 698 | ||
| 699 | (defun ses-decode-cell-symbol (str) | ||
| 700 | "Decode a symbol \"A1\" => (0,0). Returns `nil' if STR is not a | ||
| 701 | canonical cell name. Does not save match data." | ||
| 702 | (let (case-fold-search) | ||
| 703 | (and (string-match "\\`\\([A-Z]+\\)\\([0-9]+\\)\\'" str) | ||
| 704 | (let* ((col-str (match-string-no-properties 1 str)) | ||
| 705 | (col 0) | ||
| 706 | (col-offset 0) | ||
| 707 | (col-base 1) | ||
| 708 | (col-idx (1- (length col-str))) | ||
| 709 | (row (1- (string-to-number (match-string-no-properties 2 str))))) | ||
| 710 | (and (>= row 0) | ||
| 711 | (progn | ||
| 712 | (while | ||
| 713 | (progn | ||
| 714 | (setq col (+ col (* (- (aref col-str col-idx) ?A) col-base)) | ||
| 715 | col-base (* col-base 26) | ||
| 716 | col-idx (1- col-idx)) | ||
| 717 | (and (>= col-idx 0) | ||
| 718 | (setq col (+ col col-base))))) | ||
| 719 | (cons row col))))))) | ||
| 720 | |||
| 685 | (defun ses-create-cell-variable-range (minrow maxrow mincol maxcol) | 721 | (defun ses-create-cell-variable-range (minrow maxrow mincol maxcol) |
| 686 | "Create buffer-local variables for cells. This is undoable." | 722 | "Create buffer-local variables for cells. This is undoable." |
| 687 | (push `(apply ses-destroy-cell-variable-range ,minrow ,maxrow ,mincol ,maxcol) | 723 | (push `(apply ses-destroy-cell-variable-range ,minrow ,maxrow ,mincol ,maxcol) |
| @@ -704,7 +740,11 @@ row and column of the cell, with numbering starting from 0. | |||
| 704 | Return nil in case of failure." | 740 | Return nil in case of failure." |
| 705 | (unless (local-variable-p sym) | 741 | (unless (local-variable-p sym) |
| 706 | (make-local-variable sym) | 742 | (make-local-variable sym) |
| 707 | (put sym 'ses-cell (cons row col)))) | 743 | (if (let (case-fold-search) (string-match "\\`[A-Z]+[0-9]+\\'" (symbol-name sym))) |
| 744 | (put sym 'ses-cell (cons row col)) | ||
| 745 | (put sym 'ses-cell :ses-named) | ||
| 746 | (setq ses--named-cell-hashmap (or ses--named-cell-hashmap (make-hash-table :test 'eq))) | ||
| 747 | (puthash sym (cons row col) ses--named-cell-hashmap)))) | ||
| 708 | 748 | ||
| 709 | ;; We do not delete the ses-cell properties for the cell-variables, in | 749 | ;; We do not delete the ses-cell properties for the cell-variables, in |
| 710 | ;; case a formula that refers to this cell is in the kill-ring and is | 750 | ;; case a formula that refers to this cell is in the kill-ring and is |
| @@ -3211,27 +3251,36 @@ highlighted range in the spreadsheet." | |||
| 3211 | (defun ses-rename-cell (new-name &optional cell) | 3251 | (defun ses-rename-cell (new-name &optional cell) |
| 3212 | "Rename current cell." | 3252 | "Rename current cell." |
| 3213 | (interactive "*SEnter new name: ") | 3253 | (interactive "*SEnter new name: ") |
| 3214 | (and (local-variable-p new-name) | 3254 | (or |
| 3215 | (ses-sym-rowcol new-name) | 3255 | (and (local-variable-p new-name) |
| 3216 | ;; this test is needed because ses-cell property of deleted cells | 3256 | (ses-is-cell-sym-p new-name) |
| 3217 | ;; is not deleted in case of subsequent undo | 3257 | (error "Already a cell name")) |
| 3218 | (memq new-name ses--renamed-cell-symb-list) | 3258 | (and (boundp new-name) |
| 3219 | (error "Already a cell name")) | 3259 | (null (yes-or-no-p (format "`%S' is already bound outside this buffer, continue? " |
| 3220 | (and (boundp new-name) | 3260 | new-name))) |
| 3221 | (null (yes-or-no-p (format "`%S' is already bound outside this buffer, continue? " | 3261 | (error "Already a bound cell name"))) |
| 3222 | new-name))) | 3262 | (let* (curcell |
| 3223 | (error "Already a bound cell name")) | 3263 | (sym (if (ses-cell-p cell) |
| 3224 | (let* ((sym (if (ses-cell-p cell) | ||
| 3225 | (ses-cell-symbol cell) | 3264 | (ses-cell-symbol cell) |
| 3226 | (setq cell nil) | 3265 | (setq cell nil |
| 3266 | curcell t) | ||
| 3227 | (ses-check-curcell) | 3267 | (ses-check-curcell) |
| 3228 | ses--curcell)) | 3268 | ses--curcell)) |
| 3229 | (rowcol (ses-sym-rowcol sym)) | 3269 | (rowcol (ses-sym-rowcol sym)) |
| 3230 | (row (car rowcol)) | 3270 | (row (car rowcol)) |
| 3231 | (col (cdr rowcol))) | 3271 | (col (cdr rowcol)) |
| 3232 | (setq cell (or cell (ses-get-cell row col))) | 3272 | new-rowcol old-name) |
| 3233 | (push `(ses-rename-cell ,(ses-cell-symbol cell) ,cell) buffer-undo-list) | 3273 | (setq cell (or cell (ses-get-cell row col)) |
| 3234 | (put new-name 'ses-cell rowcol) | 3274 | old-name (ses-cell-symbol cell) |
| 3275 | new-rowcol (ses-decode-cell-symbol (symbol-name new-name))) | ||
| 3276 | (if new-rowcol | ||
| 3277 | (if (equal new-rowcol rowcol) | ||
| 3278 | (put new-name 'ses-cell rowcol) | ||
| 3279 | (error "Not a valid name for this cell location")) | ||
| 3280 | (setq ses--named-cell-hashmap (or ses--named-cell-hashmap (make-hash-table :test 'eq))) | ||
| 3281 | (put new-name 'ses-cell :ses-named) | ||
| 3282 | (puthash new-name rowcol ses--named-cell-hashmap)) | ||
| 3283 | (push `(ses-rename-cell ,old-name ,cell) buffer-undo-list) | ||
| 3235 | ;; replace name by new name in formula of cells refering to renamed cell | 3284 | ;; replace name by new name in formula of cells refering to renamed cell |
| 3236 | (dolist (ref (ses-cell-references cell)) | 3285 | (dolist (ref (ses-cell-references cell)) |
| 3237 | (let* ((x (ses-sym-rowcol ref)) | 3286 | (let* ((x (ses-sym-rowcol ref)) |
| @@ -3251,9 +3300,8 @@ highlighted range in the spreadsheet." | |||
| 3251 | (push new-name ses--renamed-cell-symb-list) | 3300 | (push new-name ses--renamed-cell-symb-list) |
| 3252 | (set new-name (symbol-value sym)) | 3301 | (set new-name (symbol-value sym)) |
| 3253 | (aset cell 0 new-name) | 3302 | (aset cell 0 new-name) |
| 3254 | (put sym 'ses-cell nil) | ||
| 3255 | (makunbound sym) | 3303 | (makunbound sym) |
| 3256 | (setq sym new-name) | 3304 | (and curcell (setq ses--curcell new-name)) |
| 3257 | (let* ((pos (point)) | 3305 | (let* ((pos (point)) |
| 3258 | (inhibit-read-only t) | 3306 | (inhibit-read-only t) |
| 3259 | (col (current-column)) | 3307 | (col (current-column)) |
diff --git a/lisp/subr.el b/lisp/subr.el index d328b7cddf5..ebfcfbc0930 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -222,9 +222,7 @@ Then evaluate RESULT to get return value, default nil. | |||
| 222 | (let ((,(car spec) (car ,temp))) | 222 | (let ((,(car spec) (car ,temp))) |
| 223 | ,@body | 223 | ,@body |
| 224 | (setq ,temp (cdr ,temp)))) | 224 | (setq ,temp (cdr ,temp)))) |
| 225 | ,@(if (cdr (cdr spec)) | 225 | ,@(cdr (cdr spec))) |
| 226 | ;; FIXME: This let often leads to "unused var" warnings. | ||
| 227 | `((let ((,(car spec) nil)) ,@(cdr (cdr spec)))))) | ||
| 228 | `(let ((,temp ,(nth 1 spec)) | 226 | `(let ((,temp ,(nth 1 spec)) |
| 229 | ,(car spec)) | 227 | ,(car spec)) |
| 230 | (while ,temp | 228 | (while ,temp |
| @@ -2657,13 +2655,17 @@ See also `locate-user-emacs-file'.") | |||
| 2657 | 2655 | ||
| 2658 | (defun locate-user-emacs-file (new-name &optional old-name) | 2656 | (defun locate-user-emacs-file (new-name &optional old-name) |
| 2659 | "Return an absolute per-user Emacs-specific file name. | 2657 | "Return an absolute per-user Emacs-specific file name. |
| 2660 | If OLD-NAME is non-nil and ~/OLD-NAME exists, return ~/OLD-NAME. | 2658 | If NEW-NAME exists in `user-emacs-directory', return it. |
| 2659 | Else If OLD-NAME is non-nil and ~/OLD-NAME exists, return ~/OLD-NAME. | ||
| 2661 | Else return NEW-NAME in `user-emacs-directory', creating the | 2660 | Else return NEW-NAME in `user-emacs-directory', creating the |
| 2662 | directory if it does not exist." | 2661 | directory if it does not exist." |
| 2663 | (convert-standard-filename | 2662 | (convert-standard-filename |
| 2664 | (let* ((home (concat "~" (or init-file-user ""))) | 2663 | (let* ((home (concat "~" (or init-file-user ""))) |
| 2665 | (at-home (and old-name (expand-file-name old-name home)))) | 2664 | (at-home (and old-name (expand-file-name old-name home))) |
| 2666 | (if (and at-home (file-readable-p at-home)) | 2665 | (bestname (abbreviate-file-name |
| 2666 | (expand-file-name new-name user-emacs-directory)))) | ||
| 2667 | (if (and at-home (not (file-readable-p bestname)) | ||
| 2668 | (file-readable-p at-home)) | ||
| 2667 | at-home | 2669 | at-home |
| 2668 | ;; Make sure `user-emacs-directory' exists, | 2670 | ;; Make sure `user-emacs-directory' exists, |
| 2669 | ;; unless we're in batch mode or dumping Emacs | 2671 | ;; unless we're in batch mode or dumping Emacs |
| @@ -2677,8 +2679,7 @@ directory if it does not exist." | |||
| 2677 | (set-default-file-modes ?\700) | 2679 | (set-default-file-modes ?\700) |
| 2678 | (make-directory user-emacs-directory)) | 2680 | (make-directory user-emacs-directory)) |
| 2679 | (set-default-file-modes umask)))) | 2681 | (set-default-file-modes umask)))) |
| 2680 | (abbreviate-file-name | 2682 | bestname)))) |
| 2681 | (expand-file-name new-name user-emacs-directory)))))) | ||
| 2682 | 2683 | ||
| 2683 | ;;;; Misc. useful functions. | 2684 | ;;;; Misc. useful functions. |
| 2684 | 2685 | ||
| @@ -2808,6 +2809,12 @@ Otherwise, return nil." | |||
| 2808 | Otherwise, return nil." | 2809 | Otherwise, return nil." |
| 2809 | (and (memq object '(nil t)) t)) | 2810 | (and (memq object '(nil t)) t)) |
| 2810 | 2811 | ||
| 2812 | (defun special-form-p (object) | ||
| 2813 | "Non-nil if and only if OBJECT is a special form." | ||
| 2814 | (if (and (symbolp object) (fboundp object)) | ||
| 2815 | (setq object (indirect-function object))) | ||
| 2816 | (and (subrp object) (eq (cdr (subr-arity object)) 'unevalled))) | ||
| 2817 | |||
| 2811 | (defun field-at-pos (pos) | 2818 | (defun field-at-pos (pos) |
| 2812 | "Return the field at position POS, taking stickiness etc into account." | 2819 | "Return the field at position POS, taking stickiness etc into account." |
| 2813 | (let ((raw-field (get-char-property (field-beginning pos) 'field))) | 2820 | (let ((raw-field (get-char-property (field-beginning pos) 'field))) |
diff --git a/lisp/term.el b/lisp/term.el index 7567bd38f5a..e6466b8fa95 100644 --- a/lisp/term.el +++ b/lisp/term.el | |||
| @@ -452,7 +452,7 @@ state 4: term-terminal-parameter contains pending output.") | |||
| 452 | "A queue of strings whose echo we want suppressed.") | 452 | "A queue of strings whose echo we want suppressed.") |
| 453 | (defvar term-terminal-parameter) | 453 | (defvar term-terminal-parameter) |
| 454 | (defvar term-terminal-previous-parameter) | 454 | (defvar term-terminal-previous-parameter) |
| 455 | (defvar term-current-face 'term-face) | 455 | (defvar term-current-face 'term) |
| 456 | (defvar term-scroll-start 0 "Top-most line (inclusive) of scrolling region.") | 456 | (defvar term-scroll-start 0 "Top-most line (inclusive) of scrolling region.") |
| 457 | (defvar term-scroll-end) ; Number of line (zero-based) after scrolling region. | 457 | (defvar term-scroll-end) ; Number of line (zero-based) after scrolling region. |
| 458 | (defvar term-pager-count nil | 458 | (defvar term-pager-count nil |
| @@ -759,7 +759,7 @@ Buffer local variable.") | |||
| 759 | 759 | ||
| 760 | ;;; Faces | 760 | ;;; Faces |
| 761 | (defvar ansi-term-color-vector | 761 | (defvar ansi-term-color-vector |
| 762 | [term-face | 762 | [term |
| 763 | term-color-black | 763 | term-color-black |
| 764 | term-color-red | 764 | term-color-red |
| 765 | term-color-green | 765 | term-color-green |
| @@ -770,18 +770,20 @@ Buffer local variable.") | |||
| 770 | term-color-white]) | 770 | term-color-white]) |
| 771 | 771 | ||
| 772 | (defcustom term-default-fg-color nil | 772 | (defcustom term-default-fg-color nil |
| 773 | "If non-nil, default color for foreground in Term mode. | 773 | "If non-nil, default color for foreground in Term mode." |
| 774 | This is deprecated in favor of customizing the `term-face' face." | ||
| 775 | :group 'term | 774 | :group 'term |
| 776 | :type 'string) | 775 | :type 'string) |
| 776 | (make-obsolete-variable 'term-default-fg-color "use the face `term' instead." | ||
| 777 | "24.3") | ||
| 777 | 778 | ||
| 778 | (defcustom term-default-bg-color nil | 779 | (defcustom term-default-bg-color nil |
| 779 | "If non-nil, default color for foreground in Term mode. | 780 | "If non-nil, default color for foreground in Term mode." |
| 780 | This is deprecated in favor of customizing the `term-face' face." | ||
| 781 | :group 'term | 781 | :group 'term |
| 782 | :type 'string) | 782 | :type 'string) |
| 783 | (make-obsolete-variable 'term-default-bg-color "use the face `term' instead." | ||
| 784 | "24.3") | ||
| 783 | 785 | ||
| 784 | (defface term-face | 786 | (defface term |
| 785 | `((t | 787 | `((t |
| 786 | :foreground ,term-default-fg-color | 788 | :foreground ,term-default-fg-color |
| 787 | :background ,term-default-bg-color | 789 | :background ,term-default-bg-color |
| @@ -988,7 +990,7 @@ is buffer-local." | |||
| 988 | dt)) | 990 | dt)) |
| 989 | 991 | ||
| 990 | (defun term-ansi-reset () | 992 | (defun term-ansi-reset () |
| 991 | (setq term-current-face 'term-face) | 993 | (setq term-current-face 'term) |
| 992 | (setq term-ansi-current-underline nil) | 994 | (setq term-ansi-current-underline nil) |
| 993 | (setq term-ansi-current-bold nil) | 995 | (setq term-ansi-current-bold nil) |
| 994 | (setq term-ansi-current-reverse nil) | 996 | (setq term-ansi-current-reverse nil) |
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 49b76a8e3bc..26c64ce2ad3 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el | |||
| @@ -178,7 +178,7 @@ when editing big diffs)." | |||
| 178 | ["Unified -> Context" diff-unified->context | 178 | ["Unified -> Context" diff-unified->context |
| 179 | :help "Convert unified diffs to context diffs"] | 179 | :help "Convert unified diffs to context diffs"] |
| 180 | ;;["Fixup Headers" diff-fixup-modifs (not buffer-read-only)] | 180 | ;;["Fixup Headers" diff-fixup-modifs (not buffer-read-only)] |
| 181 | ["Remove trailing whitespace" diff-remove-trailing-whitespace | 181 | ["Remove trailing whitespace" diff-delete-trailing-whitespace |
| 182 | :help "Remove trailing whitespace problems introduced by the diff"] | 182 | :help "Remove trailing whitespace problems introduced by the diff"] |
| 183 | ["Show trailing whitespace" whitespace-mode | 183 | ["Show trailing whitespace" whitespace-mode |
| 184 | :style toggle :selected (bound-and-true-p whitespace-mode) | 184 | :style toggle :selected (bound-and-true-p whitespace-mode) |
| @@ -2048,35 +2048,71 @@ I.e. like `add-change-log-entry-other-window' but applied to all hunks." | |||
| 2048 | ;; When there's no more hunks, diff-hunk-next signals an error. | 2048 | ;; When there's no more hunks, diff-hunk-next signals an error. |
| 2049 | (error nil)))) | 2049 | (error nil)))) |
| 2050 | 2050 | ||
| 2051 | (defun diff-remove-trailing-whitespace () | 2051 | (defun diff-delete-trailing-whitespace (&optional other-file) |
| 2052 | "When on a buffer that contains a diff, inspects the | 2052 | "Remove trailing whitespace from lines modified in this diff. |
| 2053 | differences and removes trailing whitespace (spaces, tabs) from | 2053 | This edits both the current Diff mode buffer and the patched |
| 2054 | the lines modified or introduced by this diff. Shows a message | 2054 | source file(s). If `diff-jump-to-old-file' is non-nil, edit the |
| 2055 | with the name of the altered buffers, which are unsaved. If a | 2055 | original (unpatched) source file instead. With a prefix argument |
| 2056 | file referenced on the diff has no buffer and needs to be fixed, | 2056 | OTHER-FILE, flip the choice of which source file to edit. |
| 2057 | a buffer visiting that file is created." | 2057 | |
| 2058 | (interactive) | 2058 | If a file referenced in the diff has no buffer and needs to be |
| 2059 | ;; We assume that the diff header has no trailing whitespace. | 2059 | fixed, visit it in a buffer." |
| 2060 | (let ((modified-buffers nil)) | 2060 | (interactive "P") |
| 2061 | (save-excursion | 2061 | (save-excursion |
| 2062 | (goto-char (point-min)) | 2062 | (goto-char (point-min)) |
| 2063 | (while (re-search-forward "^[+!>].*[ \t]+$" (point-max) t) | 2063 | (let* ((other (diff-xor other-file diff-jump-to-old-file)) |
| 2064 | (pcase-let ((`(,buf ,line-offset ,pos ,src ,_dst ,_switched) | 2064 | (modified-buffers nil) |
| 2065 | (diff-find-source-location t t))) | 2065 | (style (save-excursion |
| 2066 | (when line-offset | 2066 | (when (re-search-forward diff-hunk-header-re nil t) |
| 2067 | (with-current-buffer buf | 2067 | (goto-char (match-beginning 0)) |
| 2068 | (save-excursion | 2068 | (diff-hunk-style)))) |
| 2069 | (goto-char (+ (car pos) (cdr src))) | 2069 | (regexp (concat "^[" (if other "-<" "+>") "!]" |
| 2070 | (beginning-of-line) | 2070 | (if (eq style 'context) " " "") |
| 2071 | (when (re-search-forward "\\([ \t]+\\)$" (line-end-position) t) | 2071 | ".*?\\([ \t]+\\)$")) |
| 2072 | (unless (memq buf modified-buffers) | 2072 | (inhibit-read-only t) |
| 2073 | (push buf modified-buffers)) | 2073 | (end-marker (make-marker)) |
| 2074 | (replace-match "")))))))) | 2074 | hunk-end) |
| 2075 | (if modified-buffers | 2075 | ;; Move to the first hunk. |
| 2076 | (message "Deleted new trailing whitespace from: %s" | 2076 | (re-search-forward diff-hunk-header-re nil 1) |
| 2077 | (mapconcat (lambda (buf) (concat "`" (buffer-name buf) "'")) | 2077 | (while (progn (save-excursion |
| 2078 | modified-buffers " ")) | 2078 | (re-search-forward diff-hunk-header-re nil 1) |
| 2079 | (message "No trailing whitespace fixes needed.")))) | 2079 | (setq hunk-end (point))) |
| 2080 | (< (point) hunk-end)) | ||
| 2081 | ;; For context diffs, search only in the appropriate half of | ||
| 2082 | ;; the hunk. For other diffs, search within the entire hunk. | ||
| 2083 | (if (not (eq style 'context)) | ||
| 2084 | (set-marker end-marker hunk-end) | ||
| 2085 | (let ((mid-hunk | ||
| 2086 | (save-excursion | ||
| 2087 | (re-search-forward diff-context-mid-hunk-header-re hunk-end) | ||
| 2088 | (point)))) | ||
| 2089 | (if other | ||
| 2090 | (set-marker end-marker mid-hunk) | ||
| 2091 | (goto-char mid-hunk) | ||
| 2092 | (set-marker end-marker hunk-end)))) | ||
| 2093 | (while (re-search-forward regexp end-marker t) | ||
| 2094 | (let ((match-data (match-data))) | ||
| 2095 | (pcase-let ((`(,buf ,line-offset ,pos ,src ,_dst ,_switched) | ||
| 2096 | (diff-find-source-location other-file))) | ||
| 2097 | (when line-offset | ||
| 2098 | ;; Remove the whitespace in the Diff mode buffer. | ||
| 2099 | (set-match-data match-data) | ||
| 2100 | (replace-match "" t t nil 1) | ||
| 2101 | ;; Remove the whitespace in the source buffer. | ||
| 2102 | (with-current-buffer buf | ||
| 2103 | (save-excursion | ||
| 2104 | (goto-char (+ (car pos) (cdr src))) | ||
| 2105 | (beginning-of-line) | ||
| 2106 | (when (re-search-forward "\\([ \t]+\\)$" (line-end-position) t) | ||
| 2107 | (unless (memq buf modified-buffers) | ||
| 2108 | (push buf modified-buffers)) | ||
| 2109 | (replace-match "")))))))) | ||
| 2110 | (goto-char hunk-end)) | ||
| 2111 | (if modified-buffers | ||
| 2112 | (message "Deleted trailing whitespace from %s." | ||
| 2113 | (mapconcat (lambda (buf) (concat "`" (buffer-name buf) "'")) | ||
| 2114 | modified-buffers ", ")) | ||
| 2115 | (message "No trailing whitespace to delete."))))) | ||
| 2080 | 2116 | ||
| 2081 | ;; provide the package | 2117 | ;; provide the package |
| 2082 | (provide 'diff-mode) | 2118 | (provide 'diff-mode) |
diff --git a/lisp/woman.el b/lisp/woman.el index e41c489dbfa..974a7d72465 100644 --- a/lisp/woman.el +++ b/lisp/woman.el | |||
| @@ -2253,7 +2253,9 @@ Currently set only from '\" t in the first line of the source file.") | |||
| 2253 | (set-face-font 'woman-symbol woman-symbol-font | 2253 | (set-face-font 'woman-symbol woman-symbol-font |
| 2254 | (and (frame-live-p woman-frame) woman-frame))) | 2254 | (and (frame-live-p woman-frame) woman-frame))) |
| 2255 | 2255 | ||
| 2256 | ;; Set syntax and display tables: | 2256 | (setq-local adaptive-fill-mode nil) ; No special "%" "#" etc filling. |
| 2257 | |||
| 2258 | ;; Set syntax and display tables: | ||
| 2257 | (set-syntax-table woman-syntax-table) | 2259 | (set-syntax-table woman-syntax-table) |
| 2258 | (woman-set-buffer-display-table) | 2260 | (woman-set-buffer-display-table) |
| 2259 | 2261 | ||