diff options
| author | Joakim Verona | 2015-01-15 14:54:25 +0100 |
|---|---|---|
| committer | Joakim Verona | 2015-01-15 14:54:25 +0100 |
| commit | 0298a2c6a10bc3b79cb2f45a1961dd7ac6da4e6d (patch) | |
| tree | 6c7ea25ac137f5764d931e841598a3c1ea434ab0 /lisp | |
| parent | a1124bc117e41019de49c82d13d1a72a50df977d (diff) | |
| parent | 0e97c44c3699c4606a04f589828acdf9c03f447e (diff) | |
| download | emacs-0298a2c6a10bc3b79cb2f45a1961dd7ac6da4e6d.tar.gz emacs-0298a2c6a10bc3b79cb2f45a1961dd7ac6da4e6d.zip | |
merge master
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 124 | ||||
| -rw-r--r-- | lisp/Makefile.in | 30 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-generic.el | 607 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 52 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-core.el | 28 | ||||
| -rw-r--r-- | lisp/files.el | 5 | ||||
| -rw-r--r-- | lisp/frame.el | 58 | ||||
| -rw-r--r-- | lisp/menu-bar.el | 3 | ||||
| -rw-r--r-- | lisp/net/eww.el | 38 | ||||
| -rw-r--r-- | lisp/progmodes/cc-bytecomp.el | 72 | ||||
| -rw-r--r-- | lisp/progmodes/cc-defs.el | 43 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 5 | ||||
| -rw-r--r-- | lisp/progmodes/xref.el | 1 |
13 files changed, 942 insertions, 124 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 674b26716a4..b7a38af9609 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,107 @@ | |||
| 1 | 2015-01-15 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * emacs-lisp/eieio-core.el: Provide support for cl-generic. | ||
| 4 | (eieio--generic-tagcode): New function. | ||
| 5 | (cl-generic-tagcode-function): Use it. | ||
| 6 | (eieio--generic-tag-types): New function. | ||
| 7 | (cl-generic-tag-types-function): Use it. | ||
| 8 | (eieio-object-p): Tighten up the test. | ||
| 9 | |||
| 10 | * emacs-lisp/cl-generic.el (cl-generic-define-method): Fix paren typo. | ||
| 11 | |||
| 12 | 2015-01-14 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 13 | |||
| 14 | * emacs-lisp/cl-generic.el: New file. | ||
| 15 | |||
| 16 | * emacs-lisp/cl-macs.el (cl-flet): Allow (FUN EXP) forms. | ||
| 17 | (cl-load-time-value, cl-labels): Use closures rather than | ||
| 18 | backquoted lambdas. | ||
| 19 | (cl-macrolet): Use `eval' to create the function value, and support CL | ||
| 20 | style arguments in for the defined macros. | ||
| 21 | |||
| 22 | 2015-01-14 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 23 | |||
| 24 | * net/eww.el: Use lexical-binding. | ||
| 25 | (eww-links-at-point): Remove unused arg. | ||
| 26 | (eww-mode-map): Inherit from special-mode-map. | ||
| 27 | (eww-mode): Derive from special-mode. Don't use `setq' on a hook. | ||
| 28 | |||
| 29 | 2015-01-13 Alan Mackenzie <acm@muc.de> | ||
| 30 | |||
| 31 | Allow compilation during loading of Modes derived from a CC Mode mode. | ||
| 32 | Fixes debbugs#19206. | ||
| 33 | |||
| 34 | * progmodes/cc-bytecomp.el (cc-bytecomp-compiling-or-loading): | ||
| 35 | New function which walks the stack to discover whether we're compiling | ||
| 36 | or loading. | ||
| 37 | (cc-bytecomp-is-compiling): Reformulate, and move towards | ||
| 38 | beginning. | ||
| 39 | (cc-bytecomp-is-loading): New defsubst. | ||
| 40 | (cc-bytecomp-setup-environment, cc-bytecomp-restore-environment): | ||
| 41 | Use the above defsubsts. | ||
| 42 | (cc-require-when-compile, cc-bytecomp-defvar) | ||
| 43 | (cc-bytecomp-defun): Simplify conditionals. | ||
| 44 | |||
| 45 | * progmodes/cc-defs.el (cc-bytecomp-compiling-or-loading): | ||
| 46 | "Borrow" this function from cc-bytecomp.el. | ||
| 47 | (c-get-current-file): Reformulate using the above. | ||
| 48 | (c-lang-defconst): Prevent duplicate entries of file names in a | ||
| 49 | symbol's 'source property. | ||
| 50 | (c-lang-const): Use cc-bytecomp-is-compiling. | ||
| 51 | |||
| 52 | * progmodes/cc-langs.el (c-make-init-lang-vars-fun): | ||
| 53 | Use cc-bytecomp-is-compiling. | ||
| 54 | |||
| 55 | 2015-01-13 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 56 | |||
| 57 | * emacs-lisp/eieio-core.el (eieio-defclass): Fix call to `defclass' | ||
| 58 | (bug#19552). | ||
| 59 | |||
| 60 | 2015-01-13 Dmitry Gutov <dgutov@yandex.ru> | ||
| 61 | |||
| 62 | * menu-bar.el (menu-bar-goto-menu): Before calling | ||
| 63 | `xref-marker-stack-empty-p', first check that `xref' is loaded. | ||
| 64 | (Bug#19554) | ||
| 65 | |||
| 66 | 2015-01-12 Martin Rudalics <rudalics@gmx.at> | ||
| 67 | |||
| 68 | * progmodes/xref.el (xref-marker-stack-empty-p): Add autoload | ||
| 69 | cookie (Bug#19554). | ||
| 70 | |||
| 71 | * frame.el (frame-notice-user-settings): Remove code dealing with | ||
| 72 | frame-initial-frame-tool-bar-height. Turn off `tool-bar-mode' | ||
| 73 | only if `window-system-frame-alist' or `default-frame-alist' ask | ||
| 74 | for it. | ||
| 75 | (make-frame): Update frame-adjust-size-history if needed. | ||
| 76 | |||
| 77 | 2015-01-12 Paul Eggert <eggert@cs.ucla.edu> | ||
| 78 | |||
| 79 | Have 'make' output better GEN names | ||
| 80 | * Makefile.in (PHONY_EXTRAS): New macro. | ||
| 81 | (.PHONY): Depend on it, and on $(lisp)/loaddefs.el, so that the | ||
| 82 | relevant files' time stamps are ignored. | ||
| 83 | (custom-deps, $(lisp)/cus-load.el, finder-data) | ||
| 84 | ($(lisp)/finder-inf.el): Use PHONY_EXTRAS. | ||
| 85 | (custom-deps, $(lisp)/cus-load.el, finder-data) | ||
| 86 | ($(lisp)/finder-inf.el, autoloads, $(lisp)/loaddefs.el) | ||
| 87 | ($(lisp)/subdirs.el, update-subdirs): | ||
| 88 | Output more-accurate destination names with GEN. | ||
| 89 | |||
| 90 | Say "ELC foo.elc" instead of "GEN foo.elc" | ||
| 91 | * Makefile.in (AM_V_ELC, am__v_ELC_, am__v_ELC_0, am__v_ELC_1): | ||
| 92 | New macros. | ||
| 93 | ($(THEFILE)c, .el.elc): Use them. | ||
| 94 | |||
| 95 | 2015-01-11 Michael Albinus <michael.albinus@gmx.de> | ||
| 96 | |||
| 97 | * files.el (directory-files-recursively): Do not include | ||
| 98 | superfluous remote file names. | ||
| 99 | |||
| 100 | 2015-01-11 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 101 | |||
| 102 | * net/eww.el (eww): Interpret anything that looks like a protocol | ||
| 103 | designator as a full URL. | ||
| 104 | |||
| 1 | 2015-01-10 Lars Magne Ingebrigtsen <larsi@gnus.org> | 105 | 2015-01-10 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 106 | ||
| 3 | * net/shr.el (shr-urlify): Don't bother the user about | 107 | * net/shr.el (shr-urlify): Don't bother the user about |
| @@ -363,8 +467,8 @@ | |||
| 363 | to `pre-command-hook'. | 467 | to `pre-command-hook'. |
| 364 | (xref--xref-buffer-mode-map): Don't remap `next-line' and | 468 | (xref--xref-buffer-mode-map): Don't remap `next-line' and |
| 365 | `previous-line'. Additionally bind `xref-next-line' and | 469 | `previous-line'. Additionally bind `xref-next-line' and |
| 366 | `xref-prev-line' to `n' and `p' respectively. Bind | 470 | `xref-prev-line' to `n' and `p' respectively. |
| 367 | `xref-show-location-at-point' to `C-o'. | 471 | Bind `xref-show-location-at-point' to `C-o'. |
| 368 | 472 | ||
| 369 | 2015-01-01 Eli Zaretskii <eliz@gnu.org> | 473 | 2015-01-01 Eli Zaretskii <eliz@gnu.org> |
| 370 | 474 | ||
| @@ -553,15 +657,15 @@ | |||
| 553 | Add argument MSG to display user-friendly message when no process | 657 | Add argument MSG to display user-friendly message when no process |
| 554 | is running. | 658 | is running. |
| 555 | (python-shell-switch-to-shell): Call pop-to-buffer with NORECORD. | 659 | (python-shell-switch-to-shell): Call pop-to-buffer with NORECORD. |
| 556 | (python-shell-make-comint): Rename argument SHOW from POP. Use | 660 | (python-shell-make-comint): Rename argument SHOW from POP. |
| 557 | display-buffer instead of pop-to-buffer. | 661 | Use display-buffer instead of pop-to-buffer. |
| 558 | (run-python): Doc fix. Return process. | 662 | (run-python): Doc fix. Return process. |
| 559 | (python-shell-get-or-create-process): Make obsolete. | 663 | (python-shell-get-or-create-process): Make obsolete. |
| 560 | 664 | ||
| 561 | 2014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org> | 665 | 2014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org> |
| 562 | 666 | ||
| 563 | * progmodes/python.el (python-shell-buffer-substring): Handle | 667 | * progmodes/python.el (python-shell-buffer-substring): |
| 564 | cornercase when region sent starts at point-min. | 668 | Handle cornercase when region sent starts at point-min. |
| 565 | 669 | ||
| 566 | 2014-12-27 Eli Zaretskii <eliz@gnu.org> | 670 | 2014-12-27 Eli Zaretskii <eliz@gnu.org> |
| 567 | 671 | ||
| @@ -733,8 +837,8 @@ | |||
| 733 | 837 | ||
| 734 | 2014-12-25 Filipp Gunbin <fgunbin@fastmail.fm> | 838 | 2014-12-25 Filipp Gunbin <fgunbin@fastmail.fm> |
| 735 | 839 | ||
| 736 | * dired-aux.el (dired-maybe-insert-subdir): Make | 840 | * dired-aux.el (dired-maybe-insert-subdir): |
| 737 | dired-maybe-insert-subdir always skip trivial files. | 841 | Make dired-maybe-insert-subdir always skip trivial files. |
| 738 | 842 | ||
| 739 | 2014-12-25 Helmut Eller <eller.helmut@gmail.com> | 843 | 2014-12-25 Helmut Eller <eller.helmut@gmail.com> |
| 740 | Dmitry Gutov <dgutov@yandex.ru> | 844 | Dmitry Gutov <dgutov@yandex.ru> |
| @@ -779,8 +883,8 @@ | |||
| 779 | 883 | ||
| 780 | * window.el (mouse-autoselect-window-position-1): New variable. | 884 | * window.el (mouse-autoselect-window-position-1): New variable. |
| 781 | (mouse-autoselect-window-cancel) | 885 | (mouse-autoselect-window-cancel) |
| 782 | (mouse-autoselect-window-select, handle-select-window): With | 886 | (mouse-autoselect-window-select, handle-select-window): |
| 783 | delayed autoselection select window only if mouse moves after | 887 | With delayed autoselection select window only if mouse moves after |
| 784 | selecting its frame. | 888 | selecting its frame. |
| 785 | 889 | ||
| 786 | 2014-12-24 Michael Albinus <michael.albinus@gmx.de> | 890 | 2014-12-24 Michael Albinus <michael.albinus@gmx.de> |
diff --git a/lisp/Makefile.in b/lisp/Makefile.in index 565ca77de3b..7bf53861e71 100644 --- a/lisp/Makefile.in +++ b/lisp/Makefile.in | |||
| @@ -31,6 +31,11 @@ XARGS_LIMIT = @XARGS_LIMIT@ | |||
| 31 | # 'make' verbosity. | 31 | # 'make' verbosity. |
| 32 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ | 32 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ |
| 33 | 33 | ||
| 34 | AM_V_ELC = $(am__v_ELC_@AM_V@) | ||
| 35 | am__v_ELC_ = $(am__v_ELC_@AM_DEFAULT_V@) | ||
| 36 | am__v_ELC_0 = @echo " ELC " $@; | ||
| 37 | am__v_ELC_1 = | ||
| 38 | |||
| 34 | AM_V_GEN = $(am__v_GEN_@AM_V@) | 39 | AM_V_GEN = $(am__v_GEN_@AM_V@) |
| 35 | am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) | 40 | am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) |
| 36 | am__v_GEN_0 = @echo " GEN " $@; | 41 | am__v_GEN_0 = @echo " GEN " $@; |
| @@ -145,7 +150,8 @@ setwins_for_subdirs=for file in `find ${srcdir} -type d -print`; do \ | |||
| 145 | # we add them here to make sure they get built. | 150 | # we add them here to make sure they get built. |
| 146 | all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el | 151 | all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el |
| 147 | 152 | ||
| 148 | .PHONY: all custom-deps finder-data autoloads update-subdirs | 153 | PHONY_EXTRAS = |
| 154 | .PHONY: all custom-deps finder-data autoloads update-subdirs $(PHONY_EXTRAS) | ||
| 149 | 155 | ||
| 150 | # custom-deps and finder-data both used to scan _all_ the *.el files. | 156 | # custom-deps and finder-data both used to scan _all_ the *.el files. |
| 151 | # This could lead to problems in parallel builds if automatically | 157 | # This could lead to problems in parallel builds if automatically |
| @@ -161,18 +167,19 @@ all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el | |||
| 161 | # Nowadays these commands don't scan automatically generated files, | 167 | # Nowadays these commands don't scan automatically generated files, |
| 162 | # since they will never contain any useful information | 168 | # since they will never contain any useful information |
| 163 | # (see finder-no-scan-regexp and custom-dependencies-no-scan-regexp). | 169 | # (see finder-no-scan-regexp and custom-dependencies-no-scan-regexp). |
| 164 | $(lisp)/cus-load.el: | ||
| 165 | $(MAKE) custom-deps | ||
| 166 | custom-deps: | 170 | custom-deps: |
| 171 | $(AM_V_at)$(MAKE) PHONY_EXTRAS=$(lisp)/cus-load.el $(lisp)/cus-load.el | ||
| 172 | $(lisp)/cus-load.el: | ||
| 167 | $(AM_V_GEN)$(setwins_almost); \ | 173 | $(AM_V_GEN)$(setwins_almost); \ |
| 168 | echo Directories: $$wins; \ | 174 | echo Directories: $$wins; \ |
| 169 | $(emacs) -l cus-dep \ | 175 | $(emacs) -l cus-dep \ |
| 170 | --eval '(setq generated-custom-dependencies-file (unmsys--file-name "$(srcdir)/cus-load.el"))' \ | 176 | --eval '(setq generated-custom-dependencies-file (unmsys--file-name "$(srcdir)/cus-load.el"))' \ |
| 171 | -f custom-make-dependencies $$wins | 177 | -f custom-make-dependencies $$wins |
| 172 | 178 | ||
| 173 | $(lisp)/finder-inf.el: | ||
| 174 | $(MAKE) finder-data | ||
| 175 | finder-data: | 179 | finder-data: |
| 180 | $(AM_V_at)$(MAKE) PHONY_EXTRAS=$(lisp)/finder-inf.el \ | ||
| 181 | $(lisp)/finder-inf.el | ||
| 182 | $(lisp)/finder-inf.el: | ||
| 176 | $(AM_V_GEN)$(setwins_finder); \ | 183 | $(AM_V_GEN)$(setwins_finder); \ |
| 177 | echo Directories: $$wins; \ | 184 | echo Directories: $$wins; \ |
| 178 | $(emacs) -l finder \ | 185 | $(emacs) -l finder \ |
| @@ -185,21 +192,22 @@ finder-data: | |||
| 185 | # Note that we set no-update-autoloads in _generated_ leim files. | 192 | # Note that we set no-update-autoloads in _generated_ leim files. |
| 186 | # If you want to allow autoloads in such files, remove that, | 193 | # If you want to allow autoloads in such files, remove that, |
| 187 | # and make this depend on leim. | 194 | # and make this depend on leim. |
| 188 | autoloads: $(LOADDEFS) | 195 | autoloads .PHONY: $(lisp)/loaddefs.el |
| 196 | $(lisp)/loaddefs.el: $(LOADDEFS) | ||
| 189 | $(AM_V_GEN)$(setwins_almost); \ | 197 | $(AM_V_GEN)$(setwins_almost); \ |
| 190 | echo Directories: $$wins; \ | 198 | echo Directories: $$wins; \ |
| 191 | $(emacs) -l autoload \ | 199 | $(emacs) -l autoload \ |
| 192 | --eval '(setq autoload-ensure-writable t)' \ | 200 | --eval '(setq autoload-ensure-writable t)' \ |
| 193 | --eval '(setq autoload-builtin-package-versions t)' \ | 201 | --eval '(setq autoload-builtin-package-versions t)' \ |
| 194 | --eval '(setq generated-autoload-file (expand-file-name (unmsys--file-name "$(srcdir)/loaddefs.el")))' \ | 202 | --eval '(setq generated-autoload-file (expand-file-name (unmsys--file-name "$@")))' \ |
| 195 | -f batch-update-autoloads $$wins | 203 | -f batch-update-autoloads $$wins |
| 196 | 204 | ||
| 197 | # This is required by the bootstrap-emacs target in ../src/Makefile, so | 205 | # This is required by the bootstrap-emacs target in ../src/Makefile, so |
| 198 | # we know that if we have an emacs executable, we also have a subdirs.el. | 206 | # we know that if we have an emacs executable, we also have a subdirs.el. |
| 199 | $(lisp)/subdirs.el: | 207 | $(lisp)/subdirs.el: |
| 200 | $(MAKE) update-subdirs | 208 | $(AM_V_GEN)$(MAKE) update-subdirs |
| 201 | update-subdirs: | 209 | update-subdirs: |
| 202 | $(AM_V_GEN)$(setwins_for_subdirs); \ | 210 | $(AM_V_at)$(setwins_for_subdirs); \ |
| 203 | for file in $$wins; do \ | 211 | for file in $$wins; do \ |
| 204 | $(srcdir)/../build-aux/update-subdirs $$file; \ | 212 | $(srcdir)/../build-aux/update-subdirs $$file; \ |
| 205 | done; | 213 | done; |
| @@ -260,7 +268,7 @@ TAGS: $(lisptagsfiles1) $(lisptagsfiles2) $(lisptagsfiles3) $(lisptagsfiles4) | |||
| 260 | THEFILE = no-such-file | 268 | THEFILE = no-such-file |
| 261 | .PHONY: $(THEFILE)c | 269 | .PHONY: $(THEFILE)c |
| 262 | $(THEFILE)c: | 270 | $(THEFILE)c: |
| 263 | $(AM_V_GEN)$(emacs) $(BYTE_COMPILE_FLAGS) \ | 271 | $(AM_V_ELC)$(emacs) $(BYTE_COMPILE_FLAGS) \ |
| 264 | -l bytecomp -f byte-compile-refresh-preloaded \ | 272 | -l bytecomp -f byte-compile-refresh-preloaded \ |
| 265 | -f batch-byte-compile $(THEFILE) | 273 | -f batch-byte-compile $(THEFILE) |
| 266 | 274 | ||
| @@ -276,7 +284,7 @@ $(THEFILE)c: | |||
| 276 | # An old-fashioned suffix rule, which, according to the GNU Make manual, | 284 | # An old-fashioned suffix rule, which, according to the GNU Make manual, |
| 277 | # cannot have prerequisites. | 285 | # cannot have prerequisites. |
| 278 | .el.elc: | 286 | .el.elc: |
| 279 | $(AM_V_GEN)$(emacs) $(BYTE_COMPILE_FLAGS) -f batch-byte-compile $< | 287 | $(AM_V_ELC)$(emacs) $(BYTE_COMPILE_FLAGS) -f batch-byte-compile $< |
| 280 | 288 | ||
| 281 | .PHONY: compile-first compile-main compile compile-always | 289 | .PHONY: compile-first compile-main compile compile-always |
| 282 | 290 | ||
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el new file mode 100644 index 00000000000..41a419a3c4a --- /dev/null +++ b/lisp/emacs-lisp/cl-generic.el | |||
| @@ -0,0 +1,607 @@ | |||
| 1 | ;;; cl-generic.el --- CLOS-style generic functions for Elisp -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2015 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | ;; GNU Emacs 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 | ;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 21 | |||
| 22 | ;;; Commentary: | ||
| 23 | |||
| 24 | ;; This implements the most of CLOS's multiple-dispatch generic functions. | ||
| 25 | ;; To use it you need either (require 'cl-generic) or (require 'cl-lib). | ||
| 26 | ;; The main entry points are: `cl-defgeneric' and `cl-defmethod'. | ||
| 27 | |||
| 28 | ;; Missing elements: | ||
| 29 | ;; - We don't support next-method-p, make-method, call-method, | ||
| 30 | ;; define-method-combination. | ||
| 31 | ;; - Method and generic function objects: CLOS defines methods as objects | ||
| 32 | ;; (same for generic functions), whereas we don't offer such an abstraction. | ||
| 33 | ;; - `no-next-method' should receive the "calling method" object, but since we | ||
| 34 | ;; don't have such a thing, we pass nil instead. | ||
| 35 | ;; - In defgeneric we don't support the options: | ||
| 36 | ;; declare, :method-combination, :generic-function-class, :method-class, | ||
| 37 | ;; :method. | ||
| 38 | ;; Added elements: | ||
| 39 | ;; - We support aliases to generic functions. | ||
| 40 | ;; - The kind of thing on which to dispatch can be extended. | ||
| 41 | ;; There is support in this file for (eql <val>) dispatch as well as dispatch | ||
| 42 | ;; on the type of CL structs, and eieio-core.el adds support for EIEIO | ||
| 43 | ;; defclass objects. | ||
| 44 | |||
| 45 | ;;; Code: | ||
| 46 | |||
| 47 | ;; Note: For generic functions that dispatch on several arguments (i.e. those | ||
| 48 | ;; which use the multiple-dispatch feature), we always use the same "tagcodes" | ||
| 49 | ;; and the same set of arguments on which to dispatch. This works, but is | ||
| 50 | ;; often suboptimal since after one dispatch, the remaining dispatches can | ||
| 51 | ;; usually be simplified, or even completely skipped. | ||
| 52 | |||
| 53 | (eval-when-compile (require 'cl-lib)) | ||
| 54 | (eval-when-compile (require 'pcase)) | ||
| 55 | |||
| 56 | (defvar cl-generic-tagcode-function | ||
| 57 | (lambda (type _name) | ||
| 58 | (if (eq type t) '(0 . 'cl--generic-type) | ||
| 59 | (error "Unknown specializer %S" type))) | ||
| 60 | "Function to get the Elisp code to extract the tag on which we dispatch. | ||
| 61 | Takes a \"parameter-specializer-name\" and a variable name, and returns | ||
| 62 | a pair (PRIORITY . CODE) where CODE is an Elisp expression that should be | ||
| 63 | used to extract the \"tag\" (from the object held in the named variable) | ||
| 64 | that should uniquely determine if we have a match | ||
| 65 | \(i.e. the \"tag\" is the value that will be used to dispatch to the proper | ||
| 66 | method(s)). | ||
| 67 | Such \"tagcodes\" will be or'd together. | ||
| 68 | PRIORITY is an integer from 0 to 100 which is used to sort the tagcodes | ||
| 69 | in the `or'. The higher the priority, the more specific the tag should be. | ||
| 70 | More specifically, if PRIORITY is N and we have two objects X and Y | ||
| 71 | whose tag (according to TAGCODE) is `eql', then it should be the case | ||
| 72 | that for all other (PRIORITY . TAGCODE) where PRIORITY ≤ N, then | ||
| 73 | \(eval TAGCODE) for X is `eql' to (eval TAGCODE) for Y.") | ||
| 74 | |||
| 75 | (defvar cl-generic-tag-types-function | ||
| 76 | (lambda (tag) (if (eq tag 'cl--generic-type) '(t))) | ||
| 77 | "Function to get the list of types that a given \"tag\" matches. | ||
| 78 | They should be sorted from most specific to least specific.") | ||
| 79 | |||
| 80 | (cl-defstruct (cl--generic | ||
| 81 | (:constructor nil) | ||
| 82 | (:constructor cl--generic-make | ||
| 83 | (name &optional dispatches method-table)) | ||
| 84 | (:predicate nil)) | ||
| 85 | (name nil :read-only t) ;Pointer back to the symbol. | ||
| 86 | ;; `dispatches' holds a list of (ARGNUM . TAGCODES) where ARGNUM is the index | ||
| 87 | ;; of the corresponding argument and TAGCODES is a list of (PRIORITY . EXP) | ||
| 88 | ;; where the EXPs are expressions (to be `or'd together) to compute the tag | ||
| 89 | ;; on which to dispatch and PRIORITY is the priority of each expression to | ||
| 90 | ;; decide in which order to sort them. | ||
| 91 | ;; The most important dispatch is last in the list (and the least is first). | ||
| 92 | dispatches | ||
| 93 | ;; `method-table' is a list of | ||
| 94 | ;; ((SPECIALIZERS . QUALIFIER) USES-CNM . FUNCTION), where | ||
| 95 | ;; USES-CNM is a boolean indicating if FUNCTION calls `cl-call-next-method' | ||
| 96 | ;; (and hence expects an extra argument holding the next-method). | ||
| 97 | method-table) | ||
| 98 | |||
| 99 | (defmacro cl--generic (name) | ||
| 100 | `(get ,name 'cl--generic)) | ||
| 101 | |||
| 102 | (defun cl-generic-ensure-function (name) | ||
| 103 | (let (generic | ||
| 104 | (origname name)) | ||
| 105 | (while (and (null (setq generic (cl--generic name))) | ||
| 106 | (fboundp name) | ||
| 107 | (symbolp (symbol-function name))) | ||
| 108 | (setq name (symbol-function name))) | ||
| 109 | (unless (or (not (fboundp name)) | ||
| 110 | (and (functionp name) generic)) | ||
| 111 | (error "%s is already defined as something else than a generic function" | ||
| 112 | origname)) | ||
| 113 | (if generic | ||
| 114 | (cl-assert (eq name (cl--generic-name generic))) | ||
| 115 | (setf (cl--generic name) (setq generic (cl--generic-make name))) | ||
| 116 | (defalias name (cl--generic-make-function generic))) | ||
| 117 | generic)) | ||
| 118 | |||
| 119 | (defun cl--generic-setf-rewrite (name) | ||
| 120 | (let ((setter (intern (format "cl-generic-setter--%s" name)))) | ||
| 121 | (cons setter | ||
| 122 | `(eval-and-compile | ||
| 123 | (unless (eq ',setter (get ',name 'cl-generic-setter)) | ||
| 124 | ;; (when (get ',name 'gv-expander) | ||
| 125 | ;; (error "gv-expander conflicts with (setf %S)" ',name)) | ||
| 126 | (setf (get ',name 'cl-generic-setter) ',setter) | ||
| 127 | (gv-define-setter ,name (val &rest args) | ||
| 128 | (cons ',setter (cons val args)))))))) | ||
| 129 | |||
| 130 | ;;;###autoload | ||
| 131 | (defmacro cl-defgeneric (name args &rest options-and-methods) | ||
| 132 | "Create a generic function NAME. | ||
| 133 | DOC-STRING is the base documentation for this class. A generic | ||
| 134 | function has no body, as its purpose is to decide which method body | ||
| 135 | is appropriate to use. Specific methods are defined with `defmethod'. | ||
| 136 | With this implementation the ARGS are currently ignored. | ||
| 137 | OPTIONS-AND-METHODS is currently only used to specify the docstring, | ||
| 138 | via (:documentation DOCSTRING)." | ||
| 139 | (declare (indent 2) (doc-string 3)) | ||
| 140 | (let* ((docprop (assq :documentation options-and-methods)) | ||
| 141 | (doc (cond ((stringp (car-safe options-and-methods)) | ||
| 142 | (pop options-and-methods)) | ||
| 143 | (docprop | ||
| 144 | (prog1 | ||
| 145 | (cadr docprop) | ||
| 146 | (setq options-and-methods | ||
| 147 | (delq docprop options-and-methods))))))) | ||
| 148 | `(progn | ||
| 149 | ,(when (eq 'setf (car-safe name)) | ||
| 150 | (pcase-let ((`(,setter . ,code) (cl--generic-setf-rewrite | ||
| 151 | (cadr name)))) | ||
| 152 | (setq name setter) | ||
| 153 | code)) | ||
| 154 | (defalias ',name | ||
| 155 | (cl-generic-define ',name ',args ',options-and-methods) | ||
| 156 | ,doc)))) | ||
| 157 | |||
| 158 | (defun cl--generic-mandatory-args (args) | ||
| 159 | (let ((res ())) | ||
| 160 | (while (not (memq (car args) '(nil &rest &optional &key))) | ||
| 161 | (push (pop args) res)) | ||
| 162 | (nreverse res))) | ||
| 163 | |||
| 164 | ;;;###autoload | ||
| 165 | (defun cl-generic-define (name args options-and-methods) | ||
| 166 | (let ((generic (cl-generic-ensure-function name)) | ||
| 167 | (mandatory (cl--generic-mandatory-args args)) | ||
| 168 | (apo (assq :argument-precedence-order options-and-methods))) | ||
| 169 | (setf (cl--generic-dispatches generic) nil) | ||
| 170 | (when apo | ||
| 171 | (dolist (arg (cdr apo)) | ||
| 172 | (let ((pos (memq arg mandatory))) | ||
| 173 | (unless pos (error "%S is not a mandatory argument" arg)) | ||
| 174 | (push (list (- (length mandatory) (length pos))) | ||
| 175 | (cl--generic-dispatches generic))))) | ||
| 176 | (setf (cl--generic-method-table generic) nil) | ||
| 177 | (cl--generic-make-function generic))) | ||
| 178 | |||
| 179 | (defvar cl-generic-current-method-specializers nil | ||
| 180 | ;; This is let-bound during macro-expansion of method bodies, so that those | ||
| 181 | ;; bodies can be optimized knowing that the specializers have matched. | ||
| 182 | ;; FIXME: This presumes the formal arguments aren't modified via `setq' and | ||
| 183 | ;; aren't shadowed either ;-( | ||
| 184 | ;; FIXME: This might leak outside the scope of the method if, during | ||
| 185 | ;; macroexpansion of the method, something causes some other macroexpansion | ||
| 186 | ;; (e.g. an autoload). | ||
| 187 | "List of (VAR . TYPE) where TYPE is var's specializer.") | ||
| 188 | |||
| 189 | (eval-and-compile ;Needed while compiling the cl-defmethod calls below! | ||
| 190 | (defun cl--generic-fgrep (vars sexp) ;Copied from pcase.el. | ||
| 191 | "Check which of the symbols VARS appear in SEXP." | ||
| 192 | (let ((res '())) | ||
| 193 | (while (consp sexp) | ||
| 194 | (dolist (var (cl--generic-fgrep vars (pop sexp))) | ||
| 195 | (unless (memq var res) (push var res)))) | ||
| 196 | (and (memq sexp vars) (not (memq sexp res)) (push sexp res)) | ||
| 197 | res)) | ||
| 198 | |||
| 199 | (defun cl--generic-lambda (args body with-cnm) | ||
| 200 | "Make the lambda expression for a method with ARGS and BODY." | ||
| 201 | (let ((plain-args ()) | ||
| 202 | (cl-generic-current-method-specializers nil) | ||
| 203 | (doc-string (if (stringp (car-safe body)) (pop body))) | ||
| 204 | (mandatory t)) | ||
| 205 | (dolist (arg args) | ||
| 206 | (push (pcase arg | ||
| 207 | ((or '&optional '&rest '&key) (setq mandatory nil) arg) | ||
| 208 | ((and `(,name . ,type) (guard mandatory)) | ||
| 209 | (push (cons name (car type)) | ||
| 210 | cl-generic-current-method-specializers) | ||
| 211 | name) | ||
| 212 | (_ arg)) | ||
| 213 | plain-args)) | ||
| 214 | (setq plain-args (nreverse plain-args)) | ||
| 215 | (let ((fun `(cl-function (lambda ,plain-args | ||
| 216 | ,@(if doc-string (list doc-string)) | ||
| 217 | ,@body)))) | ||
| 218 | (if (not with-cnm) | ||
| 219 | (cons nil fun) | ||
| 220 | ;; First macroexpand away the cl-function stuff (e.g. &key and | ||
| 221 | ;; destructuring args, `declare' and whatnot). | ||
| 222 | (pcase (macroexpand fun macroexpand-all-environment) | ||
| 223 | (`#'(lambda ,args . ,body) | ||
| 224 | (require 'cl-lib) ;Needed to expand `cl-flet'. | ||
| 225 | (let* ((doc-string (and doc-string (stringp (car body)) | ||
| 226 | (pop body))) | ||
| 227 | (cnm (make-symbol "cl--cnm")) | ||
| 228 | (nbody (macroexpand-all | ||
| 229 | `(cl-flet ((cl-call-next-method ,cnm)) | ||
| 230 | ,@body) | ||
| 231 | macroexpand-all-environment)) | ||
| 232 | ;; FIXME: Rather than `grep' after the fact, the | ||
| 233 | ;; macroexpansion should directly set some flag when cnm | ||
| 234 | ;; is used. | ||
| 235 | ;; FIXME: Also, optimize the case where call-next-method is | ||
| 236 | ;; only called with explicit arguments. | ||
| 237 | (uses-cnm (cl--generic-fgrep (list cnm) nbody))) | ||
| 238 | (cons (not (not uses-cnm)) | ||
| 239 | `#'(lambda (,@(if uses-cnm (list cnm)) ,@args) | ||
| 240 | ,@(if doc-string (list doc-string)) | ||
| 241 | ,nbody)))) | ||
| 242 | (f (error "Unexpected macroexpansion result: %S" f)))))))) | ||
| 243 | |||
| 244 | |||
| 245 | ;;;###autoload | ||
| 246 | (defmacro cl-defmethod (name args &rest body) | ||
| 247 | "Define a new method for generic function NAME. | ||
| 248 | I.e. it defines the implementation of NAME to use for invocations where the | ||
| 249 | value of the dispatch argument matches the specified TYPE. | ||
| 250 | The dispatch argument has to be one of the mandatory arguments, and | ||
| 251 | all methods of NAME have to use the same argument for dispatch. | ||
| 252 | The dispatch argument and TYPE are specified in ARGS where the corresponding | ||
| 253 | formal argument appears as (VAR TYPE) rather than just VAR. | ||
| 254 | |||
| 255 | The optional second argument QUALIFIER is a specifier that | ||
| 256 | modifies how the method is combined with other methods, including: | ||
| 257 | :before - Method will be called before the primary | ||
| 258 | :after - Method will be called after the primary | ||
| 259 | :around - Method will be called around everything else | ||
| 260 | The absence of QUALIFIER means this is a \"primary\" method. | ||
| 261 | |||
| 262 | Other than a type, TYPE can also be of the form `(eql VAL)' in | ||
| 263 | which case this method will be invoked when the argument is `eql' to VAL. | ||
| 264 | |||
| 265 | \(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" | ||
| 266 | (declare (doc-string 3) (indent 2)) | ||
| 267 | (let ((qualifiers nil)) | ||
| 268 | (while (keywordp args) | ||
| 269 | (push args qualifiers) | ||
| 270 | (setq args (pop body))) | ||
| 271 | (pcase-let* ((with-cnm (not (memq (car qualifiers) '(:before :after)))) | ||
| 272 | (`(,uses-cnm . ,fun) (cl--generic-lambda args body with-cnm))) | ||
| 273 | `(progn | ||
| 274 | ,(when (eq 'setf (car-safe name)) | ||
| 275 | (pcase-let ((`(,setter . ,code) (cl--generic-setf-rewrite | ||
| 276 | (cadr name)))) | ||
| 277 | (setq name setter) | ||
| 278 | code)) | ||
| 279 | (cl-generic-define-method ',name ',qualifiers ',args | ||
| 280 | ,uses-cnm ,fun))))) | ||
| 281 | |||
| 282 | ;;;###autoload | ||
| 283 | (defun cl-generic-define-method (name qualifiers args uses-cnm function) | ||
| 284 | (when (> (length qualifiers) 1) | ||
| 285 | (error "We only support a single qualifier per method: %S" qualifiers)) | ||
| 286 | (unless (memq (car qualifiers) '(nil :primary :around :after :before)) | ||
| 287 | (error "Unsupported qualifier in: %S" qualifiers)) | ||
| 288 | (let* ((generic (cl-generic-ensure-function name)) | ||
| 289 | (mandatory (cl--generic-mandatory-args args)) | ||
| 290 | (specializers | ||
| 291 | (mapcar (lambda (arg) (if (consp arg) (cadr arg) t)) mandatory)) | ||
| 292 | (key (cons specializers (or (car qualifiers) ':primary))) | ||
| 293 | (mt (cl--generic-method-table generic)) | ||
| 294 | (me (assoc key mt)) | ||
| 295 | (dispatches (cl--generic-dispatches generic)) | ||
| 296 | (i 0)) | ||
| 297 | (dolist (specializer specializers) | ||
| 298 | (let* ((tagcode (funcall cl-generic-tagcode-function specializer 'arg)) | ||
| 299 | (x (assq i dispatches))) | ||
| 300 | (if (not x) | ||
| 301 | (setf (cl--generic-dispatches generic) | ||
| 302 | (setq dispatches (cons (list i tagcode) dispatches))) | ||
| 303 | (unless (member tagcode (cdr x)) | ||
| 304 | (setf (cdr x) | ||
| 305 | (nreverse (sort (cons tagcode (cdr x)) | ||
| 306 | #'car-less-than-car))))) | ||
| 307 | (setq i (1+ i)))) | ||
| 308 | (if me (setcdr me (cons uses-cnm function)) | ||
| 309 | (setf (cl--generic-method-table generic) | ||
| 310 | (cons `(,key ,uses-cnm . ,function) mt))) | ||
| 311 | ;; For aliases, cl--generic-name gives us the actual name. | ||
| 312 | (defalias (cl--generic-name generic) | ||
| 313 | (cl--generic-make-function generic)))) | ||
| 314 | |||
| 315 | (defmacro cl--generic-with-memoization (place &rest code) | ||
| 316 | (declare (indent 1) (debug t)) | ||
| 317 | (gv-letplace (getter setter) place | ||
| 318 | `(or ,getter | ||
| 319 | ,(macroexp-let2 nil val (macroexp-progn code) | ||
| 320 | `(progn | ||
| 321 | ,(funcall setter val) | ||
| 322 | ,val))))) | ||
| 323 | |||
| 324 | (defvar cl--generic-dispatchers (make-hash-table :test #'equal)) | ||
| 325 | |||
| 326 | (defun cl--generic-get-dispatcher (tagcodes dispatch-arg) | ||
| 327 | (cl--generic-with-memoization | ||
| 328 | (gethash (cons dispatch-arg tagcodes) cl--generic-dispatchers) | ||
| 329 | (let ((lexical-binding t) | ||
| 330 | (extraargs ())) | ||
| 331 | (dotimes (_ dispatch-arg) | ||
| 332 | (push (make-symbol "arg") extraargs)) | ||
| 333 | (byte-compile | ||
| 334 | `(lambda (generic dispatches-left) | ||
| 335 | (let ((method-cache (make-hash-table :test #'eql))) | ||
| 336 | (lambda (,@extraargs arg &rest args) | ||
| 337 | (apply (cl--generic-with-memoization | ||
| 338 | (gethash (or ,@(mapcar #'cdr tagcodes)) method-cache) | ||
| 339 | (cl--generic-cache-miss | ||
| 340 | generic ',dispatch-arg dispatches-left | ||
| 341 | (list ,@(mapcar #'cdr tagcodes)))) | ||
| 342 | ,@extraargs arg args)))))))) | ||
| 343 | |||
| 344 | (defun cl--generic-make-function (generic) | ||
| 345 | (let* ((dispatches (cl--generic-dispatches generic)) | ||
| 346 | (dispatch | ||
| 347 | (progn | ||
| 348 | (while (and dispatches | ||
| 349 | (member (cdar dispatches) | ||
| 350 | '(nil ((0 . 'cl--generic-type))))) | ||
| 351 | (setq dispatches (cdr dispatches))) | ||
| 352 | (pop dispatches)))) | ||
| 353 | (if (null dispatch) | ||
| 354 | (cl--generic-build-combined-method | ||
| 355 | (cl--generic-name generic) | ||
| 356 | (cl--generic-method-table generic)) | ||
| 357 | (let ((dispatcher (cl--generic-get-dispatcher | ||
| 358 | (cdr dispatch) (car dispatch)))) | ||
| 359 | (funcall dispatcher generic dispatches))))) | ||
| 360 | |||
| 361 | (defun cl--generic-nest (fun methods) | ||
| 362 | (pcase-dolist (`(,uses-cnm . ,method) methods) | ||
| 363 | (setq fun | ||
| 364 | (if (not uses-cnm) method | ||
| 365 | (let ((next fun)) | ||
| 366 | (lambda (&rest args) | ||
| 367 | (apply method | ||
| 368 | ;; FIXME: This sucks: passing just `next' would | ||
| 369 | ;; be a lot more efficient than the lambda+apply | ||
| 370 | ;; quasi-η, but we need this to implement the | ||
| 371 | ;; "if call-next-method is called with no | ||
| 372 | ;; arguments, then use the previous arguments". | ||
| 373 | (lambda (&rest cnm-args) | ||
| 374 | (apply next (or cnm-args args))) | ||
| 375 | args)))))) | ||
| 376 | fun) | ||
| 377 | |||
| 378 | (defvar cl--generic-combined-method-memoization | ||
| 379 | (make-hash-table :test #'equal :weakness 'value) | ||
| 380 | "Table storing previously built combined-methods. | ||
| 381 | This is particularly useful when many different tags select the same set | ||
| 382 | of methods, since this table then allows us to share a single combined-method | ||
| 383 | for all those different tags in the method-cache.") | ||
| 384 | |||
| 385 | (defun cl--generic-build-combined-method (generic-name methods) | ||
| 386 | (let ((mets-by-qual ())) | ||
| 387 | (dolist (qm methods) | ||
| 388 | (push (cdr qm) (alist-get (cdar qm) mets-by-qual))) | ||
| 389 | (cl--generic-with-memoization | ||
| 390 | (gethash (cons generic-name mets-by-qual) | ||
| 391 | cl--generic-combined-method-memoization) | ||
| 392 | (cond | ||
| 393 | ((null mets-by-qual) (lambda (&rest args) | ||
| 394 | (cl-no-applicable-method generic-name args))) | ||
| 395 | (t | ||
| 396 | (let* ((fun (lambda (&rest args) | ||
| 397 | ;; FIXME: CLOS passes as second arg the "calling method". | ||
| 398 | ;; We don't currently have "method objects" like CLOS | ||
| 399 | ;; does so we can't really do it the CLOS way. | ||
| 400 | ;; The closest would be to pass the lambda corresponding | ||
| 401 | ;; to the method, but the caller wouldn't be able to do | ||
| 402 | ;; much with it anyway. So we pass nil for now. | ||
| 403 | (apply #'cl-no-next-method generic-name nil args))) | ||
| 404 | ;; We use `cdr' to drop the `uses-cnm' annotations. | ||
| 405 | (before | ||
| 406 | (mapcar #'cdr (reverse (alist-get :before mets-by-qual)))) | ||
| 407 | (after (mapcar #'cdr (alist-get :after mets-by-qual)))) | ||
| 408 | (setq fun (cl--generic-nest fun (alist-get :primary mets-by-qual))) | ||
| 409 | (when (or after before) | ||
| 410 | (let ((next fun)) | ||
| 411 | (setq fun (lambda (&rest args) | ||
| 412 | (dolist (bf before) | ||
| 413 | (apply bf args)) | ||
| 414 | (apply next args) | ||
| 415 | (dolist (af after) | ||
| 416 | (apply af args)))))) | ||
| 417 | (cl--generic-nest fun (alist-get :around mets-by-qual)))))))) | ||
| 418 | |||
| 419 | (defun cl--generic-cache-miss (generic dispatch-arg dispatches-left tags) | ||
| 420 | (let ((types (apply #'append (mapcar cl-generic-tag-types-function tags))) | ||
| 421 | (methods '())) | ||
| 422 | (dolist (method-desc (cl--generic-method-table generic)) | ||
| 423 | (let ((m (member (nth dispatch-arg (caar method-desc)) types))) | ||
| 424 | (when m | ||
| 425 | (push (cons (length m) method-desc) methods)))) | ||
| 426 | ;; Sort the methods, most specific first. | ||
| 427 | ;; It would be tempting to sort them once and for all in the method-table | ||
| 428 | ;; rather than here, but the order might depend on the actual argument | ||
| 429 | ;; (e.g. for multiple inheritance with defclass). | ||
| 430 | (setq methods (nreverse (mapcar #'cdr (sort methods #'car-less-than-car)))) | ||
| 431 | (cl--generic-make-function (cl--generic-make (cl--generic-name generic) | ||
| 432 | dispatches-left methods)))) | ||
| 433 | |||
| 434 | ;;; Define some pre-defined generic functions, used internally. | ||
| 435 | |||
| 436 | (define-error 'cl-no-method "No method for %S") | ||
| 437 | (define-error 'cl-no-next-method "No next method for %S" 'cl-no-method) | ||
| 438 | (define-error 'cl-no-applicable-method "No applicable method for %S" | ||
| 439 | 'cl-no-method) | ||
| 440 | |||
| 441 | (cl-defgeneric cl-no-next-method (generic method &rest args) | ||
| 442 | "Function called when `cl-call-next-method' finds no next method.") | ||
| 443 | (cl-defmethod cl-no-next-method ((generic t) method &rest args) | ||
| 444 | (signal 'cl-no-next-method `(,generic ,method ,@args))) | ||
| 445 | |||
| 446 | (cl-defgeneric cl-no-applicable-method (generic &rest args) | ||
| 447 | "Function called when a method call finds no applicable method.") | ||
| 448 | (cl-defmethod cl-no-applicable-method ((generic t) &rest args) | ||
| 449 | (signal 'cl-no-applicable-method `(,generic ,@args))) | ||
| 450 | |||
| 451 | (defun cl-call-next-method (&rest _args) | ||
| 452 | "Function to call the next applicable method. | ||
| 453 | Can only be used from within the lexical body of a primary or around method." | ||
| 454 | (error "cl-call-next-method only allowed inside primary and around methods")) | ||
| 455 | |||
| 456 | ;;; Add support for describe-function | ||
| 457 | |||
| 458 | (add-hook 'help-fns-describe-function-functions 'cl--generic-describe) | ||
| 459 | (defun cl--generic-describe (function) | ||
| 460 | ;; FIXME: Fix up the main "in `<file>'" hyperlink, and add such hyperlinks | ||
| 461 | ;; for each method. | ||
| 462 | (let ((generic (if (symbolp function) (cl--generic function)))) | ||
| 463 | (when generic | ||
| 464 | (save-excursion | ||
| 465 | (insert "\n\nThis is a generic function.\n\n") | ||
| 466 | (insert (propertize "Implementations:\n\n" 'face 'bold)) | ||
| 467 | ;; Loop over fanciful generics | ||
| 468 | (pcase-dolist (`((,type . ,qualifier) . ,method) | ||
| 469 | (cl--generic-method-table generic)) | ||
| 470 | (insert "`") | ||
| 471 | (if (symbolp type) | ||
| 472 | ;; FIXME: Add support for cl-structs in help-variable. | ||
| 473 | (help-insert-xref-button (symbol-name type) | ||
| 474 | 'help-variable type) | ||
| 475 | (insert (format "%S" type))) | ||
| 476 | (insert (format "' %S %S\n" | ||
| 477 | (car qualifier) | ||
| 478 | (let ((args (help-function-arglist method))) | ||
| 479 | ;; Drop cl--generic-next arg if present. | ||
| 480 | (if (memq (car qualifier) '(:after :before)) | ||
| 481 | args (cdr args))))) | ||
| 482 | (insert (or (documentation method) "Undocumented") "\n\n")))))) | ||
| 483 | |||
| 484 | ;;; Support for (eql <val>) specializers. | ||
| 485 | |||
| 486 | (defvar cl--generic-eql-used (make-hash-table :test #'eql)) | ||
| 487 | |||
| 488 | (add-function :before-until cl-generic-tagcode-function | ||
| 489 | #'cl--generic-eql-tagcode) | ||
| 490 | (defun cl--generic-eql-tagcode (type name) | ||
| 491 | (when (eq (car-safe type) 'eql) | ||
| 492 | (puthash (cadr type) type cl--generic-eql-used) | ||
| 493 | `(100 . (gethash ,name cl--generic-eql-used)))) | ||
| 494 | |||
| 495 | (add-function :before-until cl-generic-tag-types-function | ||
| 496 | #'cl--generic-eql-tag-types) | ||
| 497 | (defun cl--generic-eql-tag-types (tag) | ||
| 498 | (if (eq (car-safe tag) 'eql) (list tag))) | ||
| 499 | |||
| 500 | ;;; Support for cl-defstructs specializers. | ||
| 501 | |||
| 502 | (add-function :before-until cl-generic-tagcode-function | ||
| 503 | #'cl--generic-struct-tagcode) | ||
| 504 | (defun cl--generic-struct-tagcode (type name) | ||
| 505 | (and (symbolp type) | ||
| 506 | (get type 'cl-struct-type) | ||
| 507 | (or (eq 'vector (car (get type 'cl-struct-type))) | ||
| 508 | (error "Can't dispatch on cl-struct %S: type is %S" | ||
| 509 | type (car (get type 'cl-struct-type)))) | ||
| 510 | (or (equal '(cl-tag-slot) (car (get type 'cl-struct-slots))) | ||
| 511 | (error "Can't dispatch on cl-struct %S: no tag in slot 0" | ||
| 512 | type)) | ||
| 513 | ;; We could/should check the vector has length >0, | ||
| 514 | ;; but really, mixing vectors and structs is a bad idea, | ||
| 515 | ;; so let's not waste time trying to handle the case | ||
| 516 | ;; of an empty vector. | ||
| 517 | ;; BEWARE: this returns a bogus tag for non-struct vectors. | ||
| 518 | `(50 . (and (vectorp ,name) (aref ,name 0))))) | ||
| 519 | |||
| 520 | (add-function :before-until cl-generic-tag-types-function | ||
| 521 | #'cl--generic-struct-tag-types) | ||
| 522 | (defun cl--generic-struct-tag-types (tag) | ||
| 523 | ;; FIXME: cl-defstruct doesn't make it easy for us. | ||
| 524 | (and (symbolp tag) | ||
| 525 | ;; A method call shouldn't itself mess with the match-data. | ||
| 526 | (string-match-p "\\`cl-struct-\\(.*\\)" (symbol-name tag)) | ||
| 527 | (let ((types (list (intern (substring (symbol-name tag) 10))))) | ||
| 528 | (while (get (car types) 'cl-struct-include) | ||
| 529 | (push (get (car types) 'cl-struct-include) types)) | ||
| 530 | (push 'cl-struct types) ;The "parent type" of all cl-structs. | ||
| 531 | (nreverse types)))) | ||
| 532 | |||
| 533 | ;;; Dispatch on "old-style types". | ||
| 534 | |||
| 535 | (defconst cl--generic-typeof-types | ||
| 536 | ;; Hand made from the source code of `type-of'. | ||
| 537 | '((integer number) (symbol) (string array) (cons list) | ||
| 538 | ;; Markers aren't `numberp', yet they are accepted wherever integers are | ||
| 539 | ;; accepted, pretty much. | ||
| 540 | (marker) (overlay) (float number) (window-configuration) | ||
| 541 | (process) (window) (subr) (compiled-function) (buffer) (char-table array) | ||
| 542 | (bool-vector array) | ||
| 543 | (frame) (hash-table) (font-spec) (font-entity) (font-object) | ||
| 544 | (vector array) | ||
| 545 | ;; Plus, hand made: | ||
| 546 | (null list symbol) | ||
| 547 | (list) | ||
| 548 | (array) | ||
| 549 | (number))) | ||
| 550 | |||
| 551 | (add-function :before-until cl-generic-tagcode-function | ||
| 552 | #'cl--generic-typeof-tagcode) | ||
| 553 | (defun cl--generic-typeof-tagcode (type name) | ||
| 554 | ;; FIXME: Add support for other types accepted by `cl-typep' such | ||
| 555 | ;; as `character', `atom', `face', `function', ... | ||
| 556 | (and (assq type cl--generic-typeof-types) | ||
| 557 | (progn | ||
| 558 | (if (memq type '(vector array)) | ||
| 559 | (message "`%S' also matches CL structs and EIEIO classes" type)) | ||
| 560 | ;; FIXME: We could also change `type-of' to return `null' for nil. | ||
| 561 | `(10 . (if ,name (type-of ,name) 'null))))) | ||
| 562 | |||
| 563 | (add-function :before-until cl-generic-tag-types-function | ||
| 564 | #'cl--generic-typeof-types) | ||
| 565 | (defun cl--generic-typeof-types (tag) | ||
| 566 | (and (symbolp tag) | ||
| 567 | (assq tag cl--generic-typeof-types))) | ||
| 568 | |||
| 569 | ;;; Just for kicks: dispatch on major-mode | ||
| 570 | ;; | ||
| 571 | ;; Here's how you'd use it: | ||
| 572 | ;; (cl-defmethod foo ((x (major-mode text-mode)) y z) ...) | ||
| 573 | ;; And then | ||
| 574 | ;; (foo 'major-mode toto titi) | ||
| 575 | ;; | ||
| 576 | ;; FIXME: Better would be to do that via dispatch on an "implicit argument". | ||
| 577 | |||
| 578 | ;; (defvar cl--generic-major-modes (make-hash-table :test #'eq)) | ||
| 579 | ;; | ||
| 580 | ;; (add-function :before-until cl-generic-tagcode-function | ||
| 581 | ;; #'cl--generic-major-mode-tagcode) | ||
| 582 | ;; (defun cl--generic-major-mode-tagcode (type name) | ||
| 583 | ;; (if (eq 'major-mode (car-safe type)) | ||
| 584 | ;; `(50 . (if (eq ,name 'major-mode) | ||
| 585 | ;; (cl--generic-with-memoization | ||
| 586 | ;; (gethash major-mode cl--generic-major-modes) | ||
| 587 | ;; `(cl--generic-major-mode . ,major-mode)))))) | ||
| 588 | ;; | ||
| 589 | ;; (add-function :before-until cl-generic-tag-types-function | ||
| 590 | ;; #'cl--generic-major-mode-types) | ||
| 591 | ;; (defun cl--generic-major-mode-types (tag) | ||
| 592 | ;; (when (eq (car-safe tag) 'cl--generic-major-mode) | ||
| 593 | ;; (if (eq tag 'fundamental-mode) '(fundamental-mode t) | ||
| 594 | ;; (let ((types `((major-mode ,(cdr tag))))) | ||
| 595 | ;; (while (get (car types) 'derived-mode-parent) | ||
| 596 | ;; (push (list 'major-mode (get (car types) 'derived-mode-parent)) | ||
| 597 | ;; types)) | ||
| 598 | ;; (unless (eq 'fundamental-mode (car types)) | ||
| 599 | ;; (push '(major-mode fundamental-mode) types)) | ||
| 600 | ;; (nreverse types))))) | ||
| 601 | |||
| 602 | ;; Local variables: | ||
| 603 | ;; generated-autoload-file: "cl-loaddefs.el" | ||
| 604 | ;; End: | ||
| 605 | |||
| 606 | (provide 'cl-generic) | ||
| 607 | ;;; cl-generic.el ends here | ||
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index fff5b27315c..0070599af6f 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el | |||
| @@ -625,14 +625,20 @@ The result of the body appears to the compiler as a quoted constant." | |||
| 625 | (set `(setq ,temp ,form))) | 625 | (set `(setq ,temp ,form))) |
| 626 | (if (and (fboundp 'byte-compile-file-form-defmumble) | 626 | (if (and (fboundp 'byte-compile-file-form-defmumble) |
| 627 | (boundp 'this-kind) (boundp 'that-one)) | 627 | (boundp 'this-kind) (boundp 'that-one)) |
| 628 | (fset 'byte-compile-file-form | 628 | ;; Else, we can't output right away, so we have to delay it to the |
| 629 | `(lambda (form) | 629 | ;; next time we're at the top-level. |
| 630 | (fset 'byte-compile-file-form | 630 | ;; FIXME: Use advice-add/remove. |
| 631 | ',(symbol-function 'byte-compile-file-form)) | 631 | (fset 'byte-compile-file-form |
| 632 | (byte-compile-file-form ',set) | 632 | (let ((old (symbol-function 'byte-compile-file-form))) |
| 633 | (byte-compile-file-form form))) | 633 | (lambda (form) |
| 634 | (print set (symbol-value 'byte-compile--outbuffer))) | 634 | (fset 'byte-compile-file-form old) |
| 635 | `(symbol-value ',temp)) | 635 | (byte-compile-file-form set) |
| 636 | (byte-compile-file-form form)))) | ||
| 637 | ;; If we're not in the middle of compiling something, we can | ||
| 638 | ;; output directly to byte-compile-outbuffer, to make sure | ||
| 639 | ;; temp is set before we use it. | ||
| 640 | (print set byte-compile--outbuffer)) | ||
| 641 | temp) | ||
| 636 | `',(eval form))) | 642 | `',(eval form))) |
| 637 | 643 | ||
| 638 | 644 | ||
| @@ -1824,18 +1830,30 @@ a `let' form, except that the list of symbols can be computed at run-time." | |||
| 1824 | (defmacro cl-flet (bindings &rest body) | 1830 | (defmacro cl-flet (bindings &rest body) |
| 1825 | "Make local function definitions. | 1831 | "Make local function definitions. |
| 1826 | Like `cl-labels' but the definitions are not recursive. | 1832 | Like `cl-labels' but the definitions are not recursive. |
| 1833 | Each binding can take the form (FUNC EXP) where | ||
| 1834 | FUNC is the function name, and EXP is an expression that returns the | ||
| 1835 | function value to which it should be bound, or it can take the more common | ||
| 1836 | form \(FUNC ARGLIST BODY...) which is a shorthand | ||
| 1837 | for (FUNC (lambda ARGLIST BODY)). | ||
| 1827 | 1838 | ||
| 1828 | \(fn ((FUNC ARGLIST BODY...) ...) FORM...)" | 1839 | \(fn ((FUNC ARGLIST BODY...) ...) FORM...)" |
| 1829 | (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body))) | 1840 | (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body))) |
| 1830 | (let ((binds ()) (newenv macroexpand-all-environment)) | 1841 | (let ((binds ()) (newenv macroexpand-all-environment)) |
| 1831 | (dolist (binding bindings) | 1842 | (dolist (binding bindings) |
| 1832 | (let ((var (make-symbol (format "--cl-%s--" (car binding))))) | 1843 | (let ((var (make-symbol (format "--cl-%s--" (car binding)))) |
| 1833 | (push (list var `(cl-function (lambda . ,(cdr binding)))) binds) | 1844 | (args-and-body (cdr binding))) |
| 1845 | (if (and (= (length args-and-body) 1) (symbolp (car args-and-body))) | ||
| 1846 | ;; Optimize (cl-flet ((fun var)) body). | ||
| 1847 | (setq var (car args-and-body)) | ||
| 1848 | (push (list var (if (= (length args-and-body) 1) | ||
| 1849 | (car args-and-body) | ||
| 1850 | `(cl-function (lambda . ,args-and-body)))) | ||
| 1851 | binds)) | ||
| 1834 | (push (cons (car binding) | 1852 | (push (cons (car binding) |
| 1835 | `(lambda (&rest cl-labels-args) | 1853 | (lambda (&rest cl-labels-args) |
| 1836 | (cl-list* 'funcall ',var | 1854 | (cl-list* 'funcall var cl-labels-args))) |
| 1837 | cl-labels-args))) | ||
| 1838 | newenv))) | 1855 | newenv))) |
| 1856 | ;; FIXME: Eliminate those functions which aren't referenced. | ||
| 1839 | `(let ,(nreverse binds) | 1857 | `(let ,(nreverse binds) |
| 1840 | ,@(macroexp-unprogn | 1858 | ,@(macroexp-unprogn |
| 1841 | (macroexpand-all | 1859 | (macroexpand-all |
| @@ -1869,9 +1887,8 @@ in closures will only work if `lexical-binding' is in use. | |||
| 1869 | (let ((var (make-symbol (format "--cl-%s--" (car binding))))) | 1887 | (let ((var (make-symbol (format "--cl-%s--" (car binding))))) |
| 1870 | (push (list var `(cl-function (lambda . ,(cdr binding)))) binds) | 1888 | (push (list var `(cl-function (lambda . ,(cdr binding)))) binds) |
| 1871 | (push (cons (car binding) | 1889 | (push (cons (car binding) |
| 1872 | `(lambda (&rest cl-labels-args) | 1890 | (lambda (&rest cl-labels-args) |
| 1873 | (cl-list* 'funcall ',var | 1891 | (cl-list* 'funcall var cl-labels-args))) |
| 1874 | cl-labels-args))) | ||
| 1875 | newenv))) | 1892 | newenv))) |
| 1876 | (macroexpand-all `(letrec ,(nreverse binds) ,@body) | 1893 | (macroexpand-all `(letrec ,(nreverse binds) ,@body) |
| 1877 | ;; Don't override lexical-let's macro-expander. | 1894 | ;; Don't override lexical-let's macro-expander. |
| @@ -1898,7 +1915,8 @@ This is like `cl-flet', but for macros instead of functions. | |||
| 1898 | (res (cl--transform-lambda (cdar bindings) name))) | 1915 | (res (cl--transform-lambda (cdar bindings) name))) |
| 1899 | (eval (car res)) | 1916 | (eval (car res)) |
| 1900 | (macroexpand-all (macroexp-progn body) | 1917 | (macroexpand-all (macroexp-progn body) |
| 1901 | (cons (cons name `(lambda ,@(cdr res))) | 1918 | (cons (cons name |
| 1919 | (eval `(cl-function (lambda ,@(cdr res))) t)) | ||
| 1902 | macroexpand-all-environment)))))) | 1920 | macroexpand-all-environment)))))) |
| 1903 | 1921 | ||
| 1904 | (defconst cl--old-macroexpand | 1922 | (defconst cl--old-macroexpand |
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index dc2c873eb42..bfa922bade6 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el | |||
| @@ -264,7 +264,7 @@ Return nil if that option doesn't exist." | |||
| 264 | 264 | ||
| 265 | (defsubst eieio-object-p (obj) | 265 | (defsubst eieio-object-p (obj) |
| 266 | "Return non-nil if OBJ is an EIEIO object." | 266 | "Return non-nil if OBJ is an EIEIO object." |
| 267 | (and (arrayp obj) | 267 | (and (vectorp obj) |
| 268 | (condition-case nil | 268 | (condition-case nil |
| 269 | (eq (aref (eieio--object-class-object obj) 0) 'defclass) | 269 | (eq (aref (eieio--object-class-object obj) 0) 'defclass) |
| 270 | (error nil)))) | 270 | (error nil)))) |
| @@ -1303,11 +1303,35 @@ method invocation orders of the involved classes." | |||
| 1303 | (define-error 'unbound-slot "Unbound slot") | 1303 | (define-error 'unbound-slot "Unbound slot") |
| 1304 | (define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy") | 1304 | (define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy") |
| 1305 | 1305 | ||
| 1306 | ;;; Hooking into cl-generic. | ||
| 1307 | |||
| 1308 | (require 'cl-generic) | ||
| 1309 | |||
| 1310 | (add-function :before-until cl-generic-tagcode-function | ||
| 1311 | #'eieio--generic-tagcode) | ||
| 1312 | (defun eieio--generic-tagcode (type name) | ||
| 1313 | ;; CLHS says: | ||
| 1314 | ;; A class must be defined before it can be used as a parameter | ||
| 1315 | ;; specializer in a defmethod form. | ||
| 1316 | ;; So we can ignore types that are not known to denote classes. | ||
| 1317 | (and (class-p type) | ||
| 1318 | ;; Prefer (aref ,name 0) over (eieio--class-tag ,name) so that | ||
| 1319 | ;; the tagcode is identical to the tagcode used for cl-struct. | ||
| 1320 | `(50 . (and (vectorp ,name) (aref ,name 0))))) | ||
| 1321 | |||
| 1322 | (add-function :before-until cl-generic-tag-types-function | ||
| 1323 | #'eieio--generic-tag-types) | ||
| 1324 | (defun eieio--generic-tag-types (tag) | ||
| 1325 | (and (symbolp tag) (boundp tag) (eieio--class-p (symbol-value tag)) | ||
| 1326 | (mapcar #'eieio--class-symbol | ||
| 1327 | (eieio--class-precedence-list (symbol-value tag))))) | ||
| 1328 | |||
| 1306 | ;;; Backward compatibility functions | 1329 | ;;; Backward compatibility functions |
| 1307 | ;; To support .elc files compiled for older versions of EIEIO. | 1330 | ;; To support .elc files compiled for older versions of EIEIO. |
| 1308 | 1331 | ||
| 1309 | (defun eieio-defclass (cname superclasses slots options) | 1332 | (defun eieio-defclass (cname superclasses slots options) |
| 1310 | (eval `(defclass ,cname ,superclasses ,slots ,options))) | 1333 | (declare (obsolete eieio-defclass-internal "25.1")) |
| 1334 | (eval `(defclass ,cname ,superclasses ,slots ,@options))) | ||
| 1311 | 1335 | ||
| 1312 | 1336 | ||
| 1313 | (provide 'eieio-core) | 1337 | (provide 'eieio-core) |
diff --git a/lisp/files.el b/lisp/files.el index 1533c35e6ca..175f85b29d0 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -740,7 +740,10 @@ This function works recursively. Files are returned in \"depth first\" | |||
| 740 | and alphabetical order. | 740 | and alphabetical order. |
| 741 | If INCLUDE-DIRECTORIES, also include directories that have matching names." | 741 | If INCLUDE-DIRECTORIES, also include directories that have matching names." |
| 742 | (let ((result nil) | 742 | (let ((result nil) |
| 743 | (files nil)) | 743 | (files nil) |
| 744 | ;; When DIR is "/", remote file names like "/method:" could | ||
| 745 | ;; also be offered. We shall suppress them. | ||
| 746 | (tramp-mode (and tramp-mode (file-remote-p dir)))) | ||
| 744 | (dolist (file (sort (file-name-all-completions "" dir) | 747 | (dolist (file (sort (file-name-all-completions "" dir) |
| 745 | 'string<)) | 748 | 'string<)) |
| 746 | (unless (member file '("./" "../")) | 749 | (unless (member file '("./" "../")) |
diff --git a/lisp/frame.el b/lisp/frame.el index 8b927309f0a..1d5bbf2317e 100644 --- a/lisp/frame.el +++ b/lisp/frame.el | |||
| @@ -275,23 +275,22 @@ there (in decreasing order of priority)." | |||
| 275 | ;; by the lines added in x-create-frame for the tool-bar and | 275 | ;; by the lines added in x-create-frame for the tool-bar and |
| 276 | ;; switch `tool-bar-mode' off. | 276 | ;; switch `tool-bar-mode' off. |
| 277 | (when (display-graphic-p) | 277 | (when (display-graphic-p) |
| 278 | (let ((tool-bar-lines | 278 | (let* ((init-lines |
| 279 | (or (assq 'tool-bar-lines initial-frame-alist) | 279 | (assq 'tool-bar-lines initial-frame-alist)) |
| 280 | (assq 'tool-bar-lines window-system-frame-alist) | 280 | (other-lines |
| 281 | (assq 'tool-bar-lines default-frame-alist)))) | 281 | (or (assq 'tool-bar-lines window-system-frame-alist) |
| 282 | ;; Shrink frame by its initial tool bar height iff either zero | 282 | (assq 'tool-bar-lines default-frame-alist))) |
| 283 | ;; tool bar lines have been requested in one of the frame's | 283 | (lines (or init-lines other-lines)) |
| 284 | ;; alists or tool bar mode has been turned off explicitly in | 284 | (height (tool-bar-height frame-initial-frame t))) |
| 285 | ;; the user's init file. | 285 | ;; Adjust frame top if either zero (nil) tool bar lines have |
| 286 | (when (and tool-bar-lines | 286 | ;; been requested in the most relevant of the frame's alists |
| 287 | (> frame-initial-frame-tool-bar-height 0) | 287 | ;; or tool bar mode has been explicitly turned off in the |
| 288 | (or (not tool-bar-mode) | 288 | ;; user's init file. |
| 289 | (null (cdr tool-bar-lines)) | 289 | (when (and (> height 0) |
| 290 | (eq 0 (cdr tool-bar-lines)))) | 290 | (or (and lines |
| 291 | (set-frame-height | 291 | (or (null (cdr lines)) |
| 292 | frame-initial-frame (- (frame-text-height frame-initial-frame) | 292 | (eq 0 (cdr lines)))) |
| 293 | frame-initial-frame-tool-bar-height) | 293 | (not tool-bar-mode))) |
| 294 | nil t) | ||
| 295 | (let* ((initial-top | 294 | (let* ((initial-top |
| 296 | (cdr (assq 'top frame-initial-geometry-arguments))) | 295 | (cdr (assq 'top frame-initial-geometry-arguments))) |
| 297 | (top (frame-parameter frame-initial-frame 'top))) | 296 | (top (frame-parameter frame-initial-frame 'top))) |
| @@ -299,15 +298,19 @@ there (in decreasing order of priority)." | |||
| 299 | (let ((adjusted-top | 298 | (let ((adjusted-top |
| 300 | (cond | 299 | (cond |
| 301 | ((and (consp top) (eq '+ (car top))) | 300 | ((and (consp top) (eq '+ (car top))) |
| 302 | (list '+ (+ (cadr top) | 301 | (list '+ (+ (cadr top) height))) |
| 303 | frame-initial-frame-tool-bar-height))) | ||
| 304 | ((and (consp top) (eq '- (car top))) | 302 | ((and (consp top) (eq '- (car top))) |
| 305 | (list '- (- (cadr top) | 303 | (list '- (- (cadr top) height))) |
| 306 | frame-initial-frame-tool-bar-height))) | 304 | (t (+ top height))))) |
| 307 | (t (+ top frame-initial-frame-tool-bar-height))))) | ||
| 308 | (modify-frame-parameters | 305 | (modify-frame-parameters |
| 309 | frame-initial-frame `((top . ,adjusted-top)))))) | 306 | frame-initial-frame `((top . ,adjusted-top)))))) |
| 310 | (tool-bar-mode -1)))) | 307 | ;; Reset `tool-bar-mode' when zero tool bar lines have been |
| 308 | ;; requested for the window-system or default frame alists. | ||
| 309 | (when (and tool-bar-mode | ||
| 310 | (and other-lines | ||
| 311 | (or (null (cdr other-lines)) | ||
| 312 | (eq 0 (cdr other-lines))))) | ||
| 313 | (tool-bar-mode -1))))) | ||
| 311 | 314 | ||
| 312 | ;; The initial frame we create above always has a minibuffer. | 315 | ;; The initial frame we create above always has a minibuffer. |
| 313 | ;; If the user wants to remove it, or make it a minibuffer-only | 316 | ;; If the user wants to remove it, or make it a minibuffer-only |
| @@ -682,6 +685,9 @@ the new frame according to its own rules." | |||
| 682 | (push p params))) | 685 | (push p params))) |
| 683 | ;; Now make the frame. | 686 | ;; Now make the frame. |
| 684 | (run-hooks 'before-make-frame-hook) | 687 | (run-hooks 'before-make-frame-hook) |
| 688 | |||
| 689 | ;; (setq frame-adjust-size-history '(t)) | ||
| 690 | |||
| 685 | (setq frame | 691 | (setq frame |
| 686 | (funcall (gui-method frame-creation-function w) params)) | 692 | (funcall (gui-method frame-creation-function w) params)) |
| 687 | (normal-erase-is-backspace-setup-frame frame) | 693 | (normal-erase-is-backspace-setup-frame frame) |
| @@ -690,6 +696,12 @@ the new frame according to its own rules." | |||
| 690 | (unless (assq param parameters) ;Overridden by explicit parameters. | 696 | (unless (assq param parameters) ;Overridden by explicit parameters. |
| 691 | (let ((val (frame-parameter oldframe param))) | 697 | (let ((val (frame-parameter oldframe param))) |
| 692 | (when val (set-frame-parameter frame param val))))) | 698 | (when val (set-frame-parameter frame param val))))) |
| 699 | |||
| 700 | (when (eq (car frame-adjust-size-history) t) | ||
| 701 | (setq frame-adjust-size-history | ||
| 702 | (cons t (cons (list "Frame made") | ||
| 703 | (cdr frame-adjust-size-history))))) | ||
| 704 | |||
| 693 | (run-hook-with-args 'after-make-frame-functions frame) | 705 | (run-hook-with-args 'after-make-frame-functions frame) |
| 694 | frame)) | 706 | frame)) |
| 695 | 707 | ||
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 67cb3273d23..cd1a4d05b55 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el | |||
| @@ -381,7 +381,8 @@ | |||
| 381 | 381 | ||
| 382 | (bindings--define-key menu [xref-pop] | 382 | (bindings--define-key menu [xref-pop] |
| 383 | '(menu-item "Back" xref-pop-marker-stack | 383 | '(menu-item "Back" xref-pop-marker-stack |
| 384 | :visible (not (xref-marker-stack-empty-p)) | 384 | :visible (and (featurep 'xref) |
| 385 | (not (xref-marker-stack-empty-p))) | ||
| 385 | :help "Back to the position of the last search")) | 386 | :help "Back to the position of the last search")) |
| 386 | 387 | ||
| 387 | (bindings--define-key menu [xref-apropos] | 388 | (bindings--define-key menu [xref-apropos] |
diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 6a6da17d1ce..879eb53115e 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; eww.el --- Emacs Web Wowser | 1 | ;;; eww.el --- Emacs Web Wowser -*- lexical-binding:t -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2013-2015 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2013-2015 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -255,7 +255,9 @@ word(s) will be searched for via `eww-search-prefix'." | |||
| 255 | ((string-match-p "\\`ftp://" url) | 255 | ((string-match-p "\\`ftp://" url) |
| 256 | (user-error "FTP is not supported.")) | 256 | (user-error "FTP is not supported.")) |
| 257 | (t | 257 | (t |
| 258 | (if (or (string-match "\\`https?:" url) | 258 | ;; Anything that starts with something that vaguely looks |
| 259 | ;; like a protocol designator is interpreted as a full URL. | ||
| 260 | (if (or (string-match "\\`[A-Za-z]+:" url) | ||
| 259 | ;; Also try to match "naked" URLs like | 261 | ;; Also try to match "naked" URLs like |
| 260 | ;; en.wikipedia.org/wiki/Free software | 262 | ;; en.wikipedia.org/wiki/Free software |
| 261 | (string-match "\\`[A-Za-z_]+\\.[A-Za-z._]+/" url) | 263 | (string-match "\\`[A-Za-z_]+\\.[A-Za-z._]+/" url) |
| @@ -550,7 +552,7 @@ See the `eww-search-prefix' variable for the search engine used." | |||
| 550 | "Return URI of the Web page the current EWW buffer is visiting." | 552 | "Return URI of the Web page the current EWW buffer is visiting." |
| 551 | (plist-get eww-data :url)) | 553 | (plist-get eww-data :url)) |
| 552 | 554 | ||
| 553 | (defun eww-links-at-point (&optional pt) | 555 | (defun eww-links-at-point () |
| 554 | "Return list of URIs, if any, linked at point." | 556 | "Return list of URIs, if any, linked at point." |
| 555 | (remq nil | 557 | (remq nil |
| 556 | (list (get-text-property (point) 'shr-url) | 558 | (list (get-text-property (point) 'shr-url) |
| @@ -629,17 +631,13 @@ the like." | |||
| 629 | 631 | ||
| 630 | (defvar eww-mode-map | 632 | (defvar eww-mode-map |
| 631 | (let ((map (make-sparse-keymap))) | 633 | (let ((map (make-sparse-keymap))) |
| 632 | (suppress-keymap map) | 634 | (set-keymap-parent map special-mode-map) |
| 633 | (define-key map "q" 'quit-window) | 635 | (define-key map "g" 'eww-reload) ;FIXME: revert-buffer-function instead! |
| 634 | (define-key map "g" 'eww-reload) | ||
| 635 | (define-key map "G" 'eww) | 636 | (define-key map "G" 'eww) |
| 636 | (define-key map [?\t] 'shr-next-link) | 637 | (define-key map [?\t] 'shr-next-link) |
| 637 | (define-key map [?\M-\t] 'shr-previous-link) | 638 | (define-key map [?\M-\t] 'shr-previous-link) |
| 638 | (define-key map [backtab] 'shr-previous-link) | 639 | (define-key map [backtab] 'shr-previous-link) |
| 639 | (define-key map [delete] 'scroll-down-command) | 640 | (define-key map [delete] 'scroll-down-command) |
| 640 | (define-key map [?\S-\ ] 'scroll-down-command) | ||
| 641 | (define-key map "\177" 'scroll-down-command) | ||
| 642 | (define-key map " " 'scroll-up-command) | ||
| 643 | (define-key map "l" 'eww-back-url) | 641 | (define-key map "l" 'eww-back-url) |
| 644 | (define-key map "r" 'eww-forward-url) | 642 | (define-key map "r" 'eww-forward-url) |
| 645 | (define-key map "n" 'eww-next-url) | 643 | (define-key map "n" 'eww-next-url) |
| @@ -697,21 +695,19 @@ the like." | |||
| 697 | map) | 695 | map) |
| 698 | "Tool bar for `eww-mode'.") | 696 | "Tool bar for `eww-mode'.") |
| 699 | 697 | ||
| 700 | (define-derived-mode eww-mode nil "eww" | 698 | (define-derived-mode eww-mode special-mode "eww" |
| 701 | "Mode for browsing the web. | 699 | "Mode for browsing the web." |
| 702 | |||
| 703 | \\{eww-mode-map}" | ||
| 704 | (setq-local eww-data (list :title "")) | 700 | (setq-local eww-data (list :title "")) |
| 705 | (setq-local browse-url-browser-function 'eww-browse-url) | 701 | (setq-local browse-url-browser-function #'eww-browse-url) |
| 706 | (setq-local after-change-functions 'eww-process-text-input) | 702 | (add-hook 'after-change-functions #'eww-process-text-input nil t) |
| 707 | (setq-local eww-history nil) | 703 | (setq-local eww-history nil) |
| 708 | (setq-local eww-history-position 0) | 704 | (setq-local eww-history-position 0) |
| 709 | (when (boundp 'tool-bar-map) | 705 | (when (boundp 'tool-bar-map) |
| 710 | (setq-local tool-bar-map eww-tool-bar-map)) | 706 | (setq-local tool-bar-map eww-tool-bar-map)) |
| 711 | ;; desktop support | 707 | ;; desktop support |
| 712 | (setq-local desktop-save-buffer 'eww-desktop-misc-data) | 708 | (setq-local desktop-save-buffer #'eww-desktop-misc-data) |
| 713 | ;; multi-page isearch support | 709 | ;; multi-page isearch support |
| 714 | (setq-local multi-isearch-next-buffer-function 'eww-isearch-next-buffer) | 710 | (setq-local multi-isearch-next-buffer-function #'eww-isearch-next-buffer) |
| 715 | (setq truncate-lines t) | 711 | (setq truncate-lines t) |
| 716 | (buffer-disable-undo) | 712 | (buffer-disable-undo) |
| 717 | (setq buffer-read-only t)) | 713 | (setq buffer-read-only t)) |
| @@ -1054,7 +1050,7 @@ See URL `https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.") | |||
| 1054 | (insert value) | 1050 | (insert value) |
| 1055 | (shr-ensure-newline) | 1051 | (shr-ensure-newline) |
| 1056 | (when (< (count-lines start (point)) lines) | 1052 | (when (< (count-lines start (point)) lines) |
| 1057 | (dotimes (i (- lines (count-lines start (point)))) | 1053 | (dotimes (_ (- lines (count-lines start (point)))) |
| 1058 | (insert "\n"))) | 1054 | (insert "\n"))) |
| 1059 | (setq end (point-marker)) | 1055 | (setq end (point-marker)) |
| 1060 | (goto-char start) | 1056 | (goto-char start) |
| @@ -1846,7 +1842,7 @@ Also used when saving `eww-history'.") | |||
| 1846 | ;; . | 1842 | ;; . |
| 1847 | r)) | 1843 | r)) |
| 1848 | 1844 | ||
| 1849 | (defun eww-desktop-misc-data (directory) | 1845 | (defun eww-desktop-misc-data (_directory) |
| 1850 | "Return a property list with data used to restore eww buffers. | 1846 | "Return a property list with data used to restore eww buffers. |
| 1851 | This list will contain, as :history, the list, whose first element is | 1847 | This list will contain, as :history, the list, whose first element is |
| 1852 | the value of `eww-data', and the tail is `eww-history'. | 1848 | the value of `eww-data', and the tail is `eww-history'. |
| @@ -1894,7 +1890,7 @@ Otherwise, the restored buffer will contain a prompt to do so by using | |||
| 1894 | 1890 | ||
| 1895 | ;;; Isearch support | 1891 | ;;; Isearch support |
| 1896 | 1892 | ||
| 1897 | (defun eww-isearch-next-buffer (&optional buffer wrap) | 1893 | (defun eww-isearch-next-buffer (&optional _buffer wrap) |
| 1898 | "Go to the next page to search using `rel' attribute for navigation." | 1894 | "Go to the next page to search using `rel' attribute for navigation." |
| 1899 | (if wrap | 1895 | (if wrap |
| 1900 | (condition-case nil | 1896 | (condition-case nil |
diff --git a/lisp/progmodes/cc-bytecomp.el b/lisp/progmodes/cc-bytecomp.el index bf7803c85ca..b63eeb4c7a6 100644 --- a/lisp/progmodes/cc-bytecomp.el +++ b/lisp/progmodes/cc-bytecomp.el | |||
| @@ -89,13 +89,60 @@ | |||
| 89 | ;;`(message ,@args) | 89 | ;;`(message ,@args) |
| 90 | ) | 90 | ) |
| 91 | 91 | ||
| 92 | (defun cc-bytecomp-compiling-or-loading () | ||
| 93 | ;; Determine whether byte-compilation or loading is currently active, | ||
| 94 | ;; returning 'compiling, 'loading or nil. | ||
| 95 | ;; If both are active, the "innermost" activity counts. Note that | ||
| 96 | ;; compilation can trigger loading (various `require' type forms) | ||
| 97 | ;; and loading can trigger compilation (the package manager does | ||
| 98 | ;; this). We walk the lisp stack if necessary. | ||
| 99 | (cond | ||
| 100 | ((and load-in-progress | ||
| 101 | (boundp 'byte-compile-dest-file) | ||
| 102 | (stringp byte-compile-dest-file)) | ||
| 103 | (let ((n 0) elt) | ||
| 104 | (while (and | ||
| 105 | (setq elt (backtrace-frame n)) | ||
| 106 | (not (and (car elt) | ||
| 107 | (memq (cadr elt) | ||
| 108 | '(load require | ||
| 109 | byte-compile-file byte-recompile-directory | ||
| 110 | batch-byte-compile))))) | ||
| 111 | (setq n (1+ n))) | ||
| 112 | (cond | ||
| 113 | ((memq (cadr elt) '(load require)) | ||
| 114 | 'loading) | ||
| 115 | ((memq (cadr elt) '(byte-compile-file | ||
| 116 | byte-recompile-directory | ||
| 117 | batch-byte-compile)) | ||
| 118 | 'compiling) | ||
| 119 | (t ; Can't happen. | ||
| 120 | (message "cc-bytecomp-compiling-or-loading: System flags spuriously set") | ||
| 121 | nil)))) | ||
| 122 | (load-in-progress | ||
| 123 | ;; Being loaded. | ||
| 124 | 'loading) | ||
| 125 | ((and (boundp 'byte-compile-dest-file) | ||
| 126 | (stringp byte-compile-dest-file)) | ||
| 127 | ;; Being compiled. | ||
| 128 | 'compiling) | ||
| 129 | (t | ||
| 130 | ;; Being evaluated interactively. | ||
| 131 | nil))) | ||
| 132 | |||
| 133 | (defsubst cc-bytecomp-is-compiling () | ||
| 134 | "Return non-nil if eval'ed during compilation." | ||
| 135 | (eq (cc-bytecomp-compiling-or-loading) 'compiling)) | ||
| 136 | |||
| 137 | (defsubst cc-bytecomp-is-loading () | ||
| 138 | "Return non-nil if eval'ed during loading. | ||
| 139 | Nil will be returned if we're in a compilation triggered by the loading." | ||
| 140 | (eq (cc-bytecomp-compiling-or-loading) 'loading)) | ||
| 141 | |||
| 92 | (defun cc-bytecomp-setup-environment () | 142 | (defun cc-bytecomp-setup-environment () |
| 93 | ;; Eval'ed during compilation to setup variables, functions etc | 143 | ;; Eval'ed during compilation to setup variables, functions etc |
| 94 | ;; declared with `cc-bytecomp-defvar' et al. | 144 | ;; declared with `cc-bytecomp-defvar' et al. |
| 95 | (if (not load-in-progress) | 145 | (if (not (cc-bytecomp-is-loading)) |
| 96 | ;; Look at `load-in-progress' to tell whether we're called | ||
| 97 | ;; directly in the file being compiled or just from some file | ||
| 98 | ;; being loaded during compilation. | ||
| 99 | (let (p) | 146 | (let (p) |
| 100 | (if cc-bytecomp-environment-set | 147 | (if cc-bytecomp-environment-set |
| 101 | (error "Byte compilation environment already set - \ | 148 | (error "Byte compilation environment already set - \ |
| @@ -143,7 +190,7 @@ perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere")) | |||
| 143 | (defun cc-bytecomp-restore-environment () | 190 | (defun cc-bytecomp-restore-environment () |
| 144 | ;; Eval'ed during compilation to restore variables, functions etc | 191 | ;; Eval'ed during compilation to restore variables, functions etc |
| 145 | ;; declared with `cc-bytecomp-defvar' et al. | 192 | ;; declared with `cc-bytecomp-defvar' et al. |
| 146 | (if (not load-in-progress) | 193 | (if (not (cc-bytecomp-is-loading)) |
| 147 | (let (p) | 194 | (let (p) |
| 148 | (setq p cc-bytecomp-unbound-variables) | 195 | (setq p cc-bytecomp-unbound-variables) |
| 149 | (while p | 196 | (while p |
| @@ -287,8 +334,7 @@ use within `eval-when-compile'." | |||
| 287 | `(eval-when-compile | 334 | `(eval-when-compile |
| 288 | (if (and (fboundp 'cc-bytecomp-is-compiling) | 335 | (if (and (fboundp 'cc-bytecomp-is-compiling) |
| 289 | (cc-bytecomp-is-compiling)) | 336 | (cc-bytecomp-is-compiling)) |
| 290 | (if (or (not load-in-progress) | 337 | (if (not (featurep ,cc-part)) |
| 291 | (not (featurep ,cc-part))) | ||
| 292 | (cc-bytecomp-load (symbol-name ,cc-part))) | 338 | (cc-bytecomp-load (symbol-name ,cc-part))) |
| 293 | (require ,cc-part)))) | 339 | (require ,cc-part)))) |
| 294 | 340 | ||
| @@ -301,12 +347,6 @@ afterwards. Don't use within `eval-when-compile'." | |||
| 301 | (require ,feature) | 347 | (require ,feature) |
| 302 | (eval-when-compile (cc-bytecomp-setup-environment)))) | 348 | (eval-when-compile (cc-bytecomp-setup-environment)))) |
| 303 | 349 | ||
| 304 | (defun cc-bytecomp-is-compiling () | ||
| 305 | "Return non-nil if eval'ed during compilation. Don't use outside | ||
| 306 | `eval-when-compile'." | ||
| 307 | (and (boundp 'byte-compile-dest-file) | ||
| 308 | (stringp byte-compile-dest-file))) | ||
| 309 | |||
| 310 | (defmacro cc-bytecomp-defvar (var) | 350 | (defmacro cc-bytecomp-defvar (var) |
| 311 | "Binds the symbol as a variable during compilation of the file, | 351 | "Binds the symbol as a variable during compilation of the file, |
| 312 | to silence the byte compiler. Don't use within `eval-when-compile'." | 352 | to silence the byte compiler. Don't use within `eval-when-compile'." |
| @@ -320,8 +360,7 @@ to silence the byte compiler. Don't use within `eval-when-compile'." | |||
| 320 | "cc-bytecomp-defvar: Saving %s (as unbound)" ',var) | 360 | "cc-bytecomp-defvar: Saving %s (as unbound)" ',var) |
| 321 | (setq cc-bytecomp-unbound-variables | 361 | (setq cc-bytecomp-unbound-variables |
| 322 | (cons ',var cc-bytecomp-unbound-variables)))) | 362 | (cons ',var cc-bytecomp-unbound-variables)))) |
| 323 | (if (and (cc-bytecomp-is-compiling) | 363 | (if (cc-bytecomp-is-compiling) |
| 324 | (not load-in-progress)) | ||
| 325 | (progn | 364 | (progn |
| 326 | (defvar ,var) | 365 | (defvar ,var) |
| 327 | (set ',var (intern (concat "cc-bytecomp-ignore-var:" | 366 | (set ',var (intern (concat "cc-bytecomp-ignore-var:" |
| @@ -349,8 +388,7 @@ at compile time, e.g. for macros and inline functions." | |||
| 349 | (setq cc-bytecomp-original-functions | 388 | (setq cc-bytecomp-original-functions |
| 350 | (cons (list ',fun nil 'unbound) | 389 | (cons (list ',fun nil 'unbound) |
| 351 | cc-bytecomp-original-functions)))) | 390 | cc-bytecomp-original-functions)))) |
| 352 | (if (and (cc-bytecomp-is-compiling) | 391 | (if (cc-bytecomp-is-compiling) |
| 353 | (not load-in-progress)) | ||
| 354 | (progn | 392 | (progn |
| 355 | (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:" | 393 | (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:" |
| 356 | (symbol-name ',fun)))) | 394 | (symbol-name ',fun)))) |
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 2ea566a7a25..d0beab1d485 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el | |||
| @@ -1983,19 +1983,22 @@ system." | |||
| 1983 | 1983 | ||
| 1984 | (defvar c-lang-const-expansion nil) | 1984 | (defvar c-lang-const-expansion nil) |
| 1985 | 1985 | ||
| 1986 | ;; Ugly hack to pull in the definition of `cc-bytecomp-compiling-or-loading` | ||
| 1987 | ;; from cc-bytecomp to make it available at loadtime. This is the same | ||
| 1988 | ;; mechanism used in cc-mode.el for `c-populate-syntax-table'. | ||
| 1989 | (defalias 'cc-bytecomp-compiling-or-loading | ||
| 1990 | (cc-eval-when-compile | ||
| 1991 | (let ((f (symbol-function 'cc-bytecomp-compiling-or-loading))) | ||
| 1992 | (if (byte-code-function-p f) f (byte-compile f))))) | ||
| 1993 | |||
| 1986 | (defsubst c-get-current-file () | 1994 | (defsubst c-get-current-file () |
| 1987 | ;; Return the base name of the current file. | 1995 | ;; Return the base name of the current file. |
| 1988 | (let ((file (cond | 1996 | (let* ((c-or-l (cc-bytecomp-compiling-or-loading)) |
| 1989 | (load-in-progress | 1997 | (file |
| 1990 | ;; Being loaded. | 1998 | (cond |
| 1991 | load-file-name) | 1999 | ((eq c-or-l 'loading) load-file-name) |
| 1992 | ((and (boundp 'byte-compile-dest-file) | 2000 | ((eq c-or-l 'compiling) byte-compile-dest-file) |
| 1993 | (stringp byte-compile-dest-file)) | 2001 | ((null c-or-l) (buffer-file-name))))) |
| 1994 | ;; Being compiled. | ||
| 1995 | byte-compile-dest-file) | ||
| 1996 | (t | ||
| 1997 | ;; Being evaluated interactively. | ||
| 1998 | (buffer-file-name))))) | ||
| 1999 | (and file | 2002 | (and file |
| 2000 | (file-name-sans-extension | 2003 | (file-name-sans-extension |
| 2001 | (file-name-nondirectory file))))) | 2004 | (file-name-nondirectory file))))) |
| @@ -2062,6 +2065,9 @@ constant. A file is identified by its base name." | |||
| 2062 | ;; language constant source definitions.) | 2065 | ;; language constant source definitions.) |
| 2063 | (c-lang-const-expansion 'call) | 2066 | (c-lang-const-expansion 'call) |
| 2064 | (c-langs-are-parametric t) | 2067 | (c-langs-are-parametric t) |
| 2068 | (file (intern | ||
| 2069 | (or (c-get-current-file) | ||
| 2070 | (error "`c-lang-defconst' can only be used in a file")))) | ||
| 2065 | bindings | 2071 | bindings |
| 2066 | pre-files) | 2072 | pre-files) |
| 2067 | 2073 | ||
| @@ -2121,9 +2127,14 @@ constant. A file is identified by its base name." | |||
| 2121 | ;; definitions for this symbol, to make sure the order in the | 2127 | ;; definitions for this symbol, to make sure the order in the |
| 2122 | ;; `source' property is correct even when files are loaded out of | 2128 | ;; `source' property is correct even when files are loaded out of |
| 2123 | ;; order. | 2129 | ;; order. |
| 2124 | (setq pre-files (nreverse | 2130 | (setq pre-files (mapcar 'car (get sym 'source))) |
| 2125 | ;; Reverse to get the right load order. | 2131 | (if (memq file pre-files) |
| 2126 | (mapcar 'car (get sym 'source)))) | 2132 | ;; This can happen when the source file (e.g. cc-langs.el) is first |
| 2133 | ;; loaded as source, setting a 'source property entry, and then itself | ||
| 2134 | ;; being compiled. | ||
| 2135 | (setq pre-files (cdr (memq file pre-files)))) | ||
| 2136 | ;; Reverse to get the right load order. | ||
| 2137 | (setq pre-files (nreverse pre-files)) | ||
| 2127 | 2138 | ||
| 2128 | `(eval-and-compile | 2139 | `(eval-and-compile |
| 2129 | (c-define-lang-constant ',name ,bindings | 2140 | (c-define-lang-constant ',name ,bindings |
| @@ -2233,9 +2244,7 @@ quoted." | |||
| 2233 | (if (or (eq c-lang-const-expansion 'call) | 2244 | (if (or (eq c-lang-const-expansion 'call) |
| 2234 | (and (not c-lang-const-expansion) | 2245 | (and (not c-lang-const-expansion) |
| 2235 | (not mode)) | 2246 | (not mode)) |
| 2236 | load-in-progress | 2247 | (not (cc-bytecomp-is-compiling))) |
| 2237 | (not (boundp 'byte-compile-dest-file)) | ||
| 2238 | (not (stringp byte-compile-dest-file))) | ||
| 2239 | ;; Either a straight call is requested in the context, or | 2248 | ;; Either a straight call is requested in the context, or |
| 2240 | ;; we're in an "uncontrolled" context and got no language, | 2249 | ;; we're in an "uncontrolled" context and got no language, |
| 2241 | ;; or we're not being byte compiled so the compile time | 2250 | ;; or we're not being byte compiled so the compile time |
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 17d717e740f..4d16a9b9d33 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el | |||
| @@ -3260,10 +3260,7 @@ function it returns is byte compiled with all the evaluated results | |||
| 3260 | from the language constants. Use the `c-init-language-vars' macro to | 3260 | from the language constants. Use the `c-init-language-vars' macro to |
| 3261 | accomplish that conveniently." | 3261 | accomplish that conveniently." |
| 3262 | 3262 | ||
| 3263 | (if (and (not load-in-progress) | 3263 | (if (cc-bytecomp-is-compiling) |
| 3264 | (boundp 'byte-compile-dest-file) | ||
| 3265 | (stringp byte-compile-dest-file)) | ||
| 3266 | |||
| 3267 | ;; No need to byte compile this lambda since the byte compiler is | 3264 | ;; No need to byte compile this lambda since the byte compiler is |
| 3268 | ;; smart enough to detect the `funcall' construct in the | 3265 | ;; smart enough to detect the `funcall' construct in the |
| 3269 | ;; `c-init-language-vars' macro below and compile it all straight | 3266 | ;; `c-init-language-vars' macro below and compile it all straight |
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index b822619f783..7f77d218a48 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el | |||
| @@ -301,6 +301,7 @@ backward." | |||
| 301 | (let ((marker (ring-remove ring))) | 301 | (let ((marker (ring-remove ring))) |
| 302 | (set-marker marker nil nil))))) | 302 | (set-marker marker nil nil))))) |
| 303 | 303 | ||
| 304 | ;;;###autoload | ||
| 304 | (defun xref-marker-stack-empty-p () | 305 | (defun xref-marker-stack-empty-p () |
| 305 | "Return t if the marker stack is empty; nil otherwise." | 306 | "Return t if the marker stack is empty; nil otherwise." |
| 306 | (ring-empty-p xref--marker-ring)) | 307 | (ring-empty-p xref--marker-ring)) |