aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorStefan Monnier2013-08-04 16:18:11 -0400
committerStefan Monnier2013-08-04 16:18:11 -0400
commit671d5c16547d16bef2efa056705bd35b5feacc29 (patch)
tree4bc2c3774ce9914f21508d0e2a83e25504dbc1db /lisp
parente443729d658ee2b9e0f55bbbb90241819bf516a6 (diff)
downloademacs-671d5c16547d16bef2efa056705bd35b5feacc29.tar.gz
emacs-671d5c16547d16bef2efa056705bd35b5feacc29.zip
* lisp/subr.el (macrop): New function.
(text-clone--maintaining): New var. (text-clone--maintain): Rename from text-clone-maintain. Use it instead of inhibit-modification-hooks. * lisp/emacs-lisp/nadvice.el (advice--normalize): For aliases to macros, use a proxy, so as handle autoloads and redefinitions of the target. (advice--defalias-fset, advice-remove): Use advice--symbol-function. * lisp/emacs-lisp/pcase.el (pcase-mutually-exclusive-predicates): Remove bogus (arrayp . stringp) pair. Add entries for `vectorp'. (pcase--mutually-exclusive-p): New function. (pcase--split-consp): Use it. (pcase--split-pred): Use it. Optimize the case where `pat' is a qpat mutually exclusive with the current predicate. * test/automated/advice-tests.el (advice-tests-nadvice): Test removal before definition. (advice-tests-macroaliases): New test. * lisp/emacs-lisp/edebug.el (edebug-lookup-function): Remove function. (edebug-macrop): Remove. Use `macrop' instead. * lisp/emacs-lisp/advice.el (ad-subr-p): Remove. Use `subrp' instead. (ad-macro-p): * lisp/eshell/esh-cmd.el (eshell-macrop): * lisp/apropos.el (apropos-macrop): Remove. Use `macrop' instead.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog25
-rw-r--r--lisp/apropos.el13
-rw-r--r--lisp/emacs-lisp/advice.el30
-rw-r--r--lisp/emacs-lisp/edebug.el15
-rw-r--r--lisp/emacs-lisp/nadvice.el23
-rw-r--r--lisp/emacs-lisp/pcase.el31
-rw-r--r--lisp/eshell/esh-cmd.el10
-rw-r--r--lisp/subr.el24
8 files changed, 82 insertions, 89 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index dc1fa09b316..66bf7422b0d 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,30 @@
12013-08-04 Stefan Monnier <monnier@iro.umontreal.ca> 12013-08-04 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * subr.el (macrop): New function.
4 (text-clone--maintaining): New var.
5 (text-clone--maintain): Rename from text-clone-maintain. Use it
6 instead of inhibit-modification-hooks.
7
8 * emacs-lisp/nadvice.el (advice--normalize): For aliases to macros, use
9 a proxy, so as handle autoloads and redefinitions of the target.
10 (advice--defalias-fset, advice-remove): Use advice--symbol-function.
11
12 * emacs-lisp/pcase.el (pcase-mutually-exclusive-predicates):
13 Remove bogus (arrayp . stringp) pair. Add entries for `vectorp'.
14 (pcase--mutually-exclusive-p): New function.
15 (pcase--split-consp): Use it.
16 (pcase--split-pred): Use it. Optimize the case where `pat' is a qpat
17 mutually exclusive with the current predicate.
18
19 * emacs-lisp/edebug.el (edebug-lookup-function): Remove function.
20 (edebug-macrop): Remove. Use `macrop' instead.
21 * emacs-lisp/advice.el (ad-subr-p): Remove. Use `subrp' instead.
22 (ad-macro-p):
23 * eshell/esh-cmd.el (eshell-macrop):
24 * apropos.el (apropos-macrop): Remove. Use `macrop' instead.
25
262013-08-04 Stefan Monnier <monnier@iro.umontreal.ca>
27
3 * emacs-lisp/nadvice.el (advice-function-mapc): Rename from advice-mapc. 28 * emacs-lisp/nadvice.el (advice-function-mapc): Rename from advice-mapc.
4 (advice-mapc): New function, using it. 29 (advice-mapc): New function, using it.
5 (advice-function-member-p): New function. 30 (advice-function-member-p): New function.
diff --git a/lisp/apropos.el b/lisp/apropos.el
index 000d2d87d05..7a1a6f6a75a 100644
--- a/lisp/apropos.el
+++ b/lisp/apropos.el
@@ -1121,7 +1121,7 @@ If non-nil TEXT is a string that will be printed as a heading."
1121 (apropos-print-doc 2 1121 (apropos-print-doc 2
1122 (if (commandp symbol) 1122 (if (commandp symbol)
1123 'apropos-command 1123 'apropos-command
1124 (if (apropos-macrop symbol) 1124 (if (macrop symbol)
1125 'apropos-macro 1125 'apropos-macro
1126 'apropos-function)) 1126 'apropos-function))
1127 (not nosubst)) 1127 (not nosubst))
@@ -1139,17 +1139,6 @@ If non-nil TEXT is a string that will be printed as a heading."
1139 (prog1 apropos-accumulator 1139 (prog1 apropos-accumulator
1140 (setq apropos-accumulator ()))) ; permit gc 1140 (setq apropos-accumulator ()))) ; permit gc
1141 1141
1142(defun apropos-macrop (symbol)
1143 "Return t if SYMBOL is a Lisp macro."
1144 (and (fboundp symbol)
1145 (consp (setq symbol
1146 (symbol-function symbol)))
1147 (or (eq (car symbol) 'macro)
1148 (if (autoloadp symbol)
1149 (memq (nth 4 symbol)
1150 '(macro t))))))
1151
1152
1153(defun apropos-print-doc (i type do-keys) 1142(defun apropos-print-doc (i type do-keys)
1154 (let ((doc (nth i apropos-item))) 1143 (let ((doc (nth i apropos-item)))
1155 (when (stringp doc) 1144 (when (stringp doc)
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el
index eb1d63e788b..861054e777f 100644
--- a/lisp/emacs-lisp/advice.el
+++ b/lisp/emacs-lisp/advice.el
@@ -2140,14 +2140,6 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
2140 "Take a macro function DEFINITION and make a lambda out of it." 2140 "Take a macro function DEFINITION and make a lambda out of it."
2141 `(cdr ,definition)) 2141 `(cdr ,definition))
2142 2142
2143(defmacro ad-subr-p (definition)
2144 ;;"non-nil if DEFINITION is a subr."
2145 (list 'subrp definition))
2146
2147(defmacro ad-macro-p (definition)
2148 ;;"non-nil if DEFINITION is a macro."
2149 `(eq (car-safe ,definition) 'macro))
2150
2151(defmacro ad-lambda-p (definition) 2143(defmacro ad-lambda-p (definition)
2152 ;;"non-nil if DEFINITION is a lambda expression." 2144 ;;"non-nil if DEFINITION is a lambda expression."
2153 `(eq (car-safe ,definition) 'lambda)) 2145 `(eq (car-safe ,definition) 'lambda))
@@ -2160,12 +2152,12 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
2160(defmacro ad-compiled-p (definition) 2152(defmacro ad-compiled-p (definition)
2161 "Return non-nil if DEFINITION is a compiled byte-code object." 2153 "Return non-nil if DEFINITION is a compiled byte-code object."
2162 `(or (byte-code-function-p ,definition) 2154 `(or (byte-code-function-p ,definition)
2163 (and (ad-macro-p ,definition) 2155 (and (macrop ,definition)
2164 (byte-code-function-p (ad-lambdafy ,definition))))) 2156 (byte-code-function-p (ad-lambdafy ,definition)))))
2165 2157
2166(defmacro ad-compiled-code (compiled-definition) 2158(defmacro ad-compiled-code (compiled-definition)
2167 "Return the byte-code object of a COMPILED-DEFINITION." 2159 "Return the byte-code object of a COMPILED-DEFINITION."
2168 `(if (ad-macro-p ,compiled-definition) 2160 `(if (macrop ,compiled-definition)
2169 (ad-lambdafy ,compiled-definition) 2161 (ad-lambdafy ,compiled-definition)
2170 ,compiled-definition)) 2162 ,compiled-definition))
2171 2163
@@ -2173,7 +2165,7 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
2173 "Return the lambda expression of a function/macro/advice DEFINITION." 2165 "Return the lambda expression of a function/macro/advice DEFINITION."
2174 (cond ((ad-lambda-p definition) 2166 (cond ((ad-lambda-p definition)
2175 definition) 2167 definition)
2176 ((ad-macro-p definition) 2168 ((macrop definition)
2177 (ad-lambdafy definition)) 2169 (ad-lambdafy definition))
2178 ((ad-advice-p definition) 2170 ((ad-advice-p definition)
2179 (cdr definition)) 2171 (cdr definition))
@@ -2183,7 +2175,7 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
2183 "Return the argument list of DEFINITION." 2175 "Return the argument list of DEFINITION."
2184 (require 'help-fns) 2176 (require 'help-fns)
2185 (help-function-arglist 2177 (help-function-arglist
2186 (if (or (ad-macro-p definition) (ad-advice-p definition)) 2178 (if (or (macrop definition) (ad-advice-p definition))
2187 (cdr definition) 2179 (cdr definition)
2188 definition) 2180 definition)
2189 'preserve-names)) 2181 'preserve-names))
@@ -2229,7 +2221,7 @@ definition (see the code for `documentation')."
2229(defun ad-advised-definition-p (definition) 2221(defun ad-advised-definition-p (definition)
2230 "Return non-nil if DEFINITION was generated from advice information." 2222 "Return non-nil if DEFINITION was generated from advice information."
2231 (if (or (ad-lambda-p definition) 2223 (if (or (ad-lambda-p definition)
2232 (ad-macro-p definition) 2224 (macrop definition)
2233 (ad-compiled-p definition)) 2225 (ad-compiled-p definition))
2234 (let ((docstring (ad-docstring definition))) 2226 (let ((docstring (ad-docstring definition)))
2235 (and (stringp docstring) 2227 (and (stringp docstring)
@@ -2242,8 +2234,8 @@ definition (see the code for `documentation')."
2242 ;; representations, so cache entries preactivated with version 2234 ;; representations, so cache entries preactivated with version
2243 ;; 1 can't be used. 2235 ;; 1 can't be used.
2244 (cond 2236 (cond
2245 ((ad-macro-p definition) 'macro2) 2237 ((macrop definition) 'macro2)
2246 ((ad-subr-p definition) 'subr2) 2238 ((subrp definition) 'subr2)
2247 ((or (ad-lambda-p definition) (ad-compiled-p definition)) 'fun2) 2239 ((or (ad-lambda-p definition) (ad-compiled-p definition)) 'fun2)
2248 ((ad-advice-p definition) 'advice2))) ;; FIXME: Can this ever happen? 2240 ((ad-advice-p definition) 'advice2))) ;; FIXME: Can this ever happen?
2249 2241
@@ -2273,7 +2265,7 @@ For that it has to be fbound with a non-autoload definition."
2273 "True if FUNCTION has an interpreted definition that can be compiled." 2265 "True if FUNCTION has an interpreted definition that can be compiled."
2274 (and (ad-has-proper-definition function) 2266 (and (ad-has-proper-definition function)
2275 (or (ad-lambda-p (symbol-function function)) 2267 (or (ad-lambda-p (symbol-function function))
2276 (ad-macro-p (symbol-function function))) 2268 (macrop (symbol-function function)))
2277 (not (ad-compiled-p (symbol-function function))))) 2269 (not (ad-compiled-p (symbol-function function)))))
2278 2270
2279(defvar warning-suppress-types) ;From warnings.el. 2271(defvar warning-suppress-types) ;From warnings.el.
@@ -2902,7 +2894,7 @@ If COMPILE is nil then the result depends on the value of
2902 ((eq ad-default-compilation-action 'never) nil) 2894 ((eq ad-default-compilation-action 'never) nil)
2903 ((eq ad-default-compilation-action 'always) t) 2895 ((eq ad-default-compilation-action 'always) t)
2904 ((eq ad-default-compilation-action 'like-original) 2896 ((eq ad-default-compilation-action 'like-original)
2905 (or (ad-subr-p (ad-get-orig-definition function)) 2897 (or (subrp (ad-get-orig-definition function))
2906 (ad-compiled-p (ad-get-orig-definition function)))) 2898 (ad-compiled-p (ad-get-orig-definition function))))
2907 ;; everything else means `maybe': 2899 ;; everything else means `maybe':
2908 (t (featurep 'byte-compile)))) 2900 (t (featurep 'byte-compile))))
@@ -3249,7 +3241,7 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
3249 `((ad-set-cache 3241 `((ad-set-cache
3250 ',function 3242 ',function
3251 ;; the function will get compiled: 3243 ;; the function will get compiled:
3252 ,(cond ((ad-macro-p (car preactivation)) 3244 ,(cond ((macrop (car preactivation))
3253 `(ad-macrofy 3245 `(ad-macrofy
3254 (function 3246 (function
3255 ,(ad-lambdafy 3247 ,(ad-lambdafy
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index ae20e5270e1..ac7e5f12a18 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -295,19 +295,6 @@ A lambda list keyword is a symbol that starts with `&'."
295 (eq (selected-window) 295 (eq (selected-window)
296 (next-window (next-window (selected-window)))))) 296 (next-window (next-window (selected-window))))))
297 297
298(defsubst edebug-lookup-function (object)
299 (while (and (symbolp object) (fboundp object))
300 (setq object (symbol-function object)))
301 object)
302
303(defun edebug-macrop (object)
304 "Return the macro named by OBJECT, or nil if it is not a macro."
305 (setq object (edebug-lookup-function object))
306 (if (and (listp object)
307 (eq 'macro (car object))
308 (functionp (cdr object)))
309 object))
310
311(defun edebug-sort-alist (alist function) 298(defun edebug-sort-alist (alist function)
312 ;; Return the ALIST sorted with comparison function FUNCTION. 299 ;; Return the ALIST sorted with comparison function FUNCTION.
313 ;; This uses 'sort so the sorting is destructive. 300 ;; This uses 'sort so the sorting is destructive.
@@ -1416,7 +1403,7 @@ expressions; a `progn' form will be returned enclosing these forms."
1416 ; but leave it in for compatibility. 1403 ; but leave it in for compatibility.
1417 )) 1404 ))
1418 ;; No edebug-form-spec provided. 1405 ;; No edebug-form-spec provided.
1419 ((edebug-macrop head) 1406 ((macrop head)
1420 (if edebug-eval-macro-args 1407 (if edebug-eval-macro-args
1421 (edebug-forms cursor) 1408 (edebug-forms cursor)
1422 (edebug-sexps cursor))) 1409 (edebug-sexps cursor)))
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index 660eb0365ae..576e72088e9 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -314,9 +314,8 @@ of the piece of advice."
314 ((special-form-p def) 314 ((special-form-p def)
315 ;; Not worth the trouble trying to handle this, I think. 315 ;; Not worth the trouble trying to handle this, I think.
316 (error "Advice impossible: %S is a special form" symbol)) 316 (error "Advice impossible: %S is a special form" symbol))
317 ((and (symbolp def) 317 ((and (symbolp def) (macrop def))
318 (eq 'macro (car-safe (ignore-errors (indirect-function def))))) 318 (let ((newval `(macro . ,(lambda (&rest r) (macroexpand `(,def . ,r))))))
319 (let ((newval (cons 'macro (cdr (indirect-function def)))))
320 (put symbol 'advice--saved-rewrite (cons def (cdr newval))) 319 (put symbol 'advice--saved-rewrite (cons def (cdr newval)))
321 newval)) 320 newval))
322 ;; `f' might be a pure (hence read-only) cons! 321 ;; `f' might be a pure (hence read-only) cons!
@@ -351,19 +350,7 @@ of the piece of advice."
351 (when (get symbol 'advice--saved-rewrite) 350 (when (get symbol 'advice--saved-rewrite)
352 (put symbol 'advice--saved-rewrite nil)) 351 (put symbol 'advice--saved-rewrite nil))
353 (setq newdef (advice--normalize symbol newdef)) 352 (setq newdef (advice--normalize symbol newdef))
354 (let* ((olddef (advice--strip-macro (symbol-function symbol))) 353 (let ((oldadv (advice--symbol-function symbol)))
355 (oldadv
356 (cond
357 ((null (get symbol 'advice--pending))
358 (or olddef
359 (progn
360 (message "Delayed advice activation failed for %s: no data"
361 symbol)
362 nil)))
363 ((or (not olddef) (autoloadp olddef))
364 (get symbol 'advice--pending))
365 (t (message "Dropping left-over advice--pending for %s" symbol)
366 olddef))))
367 (if (and newdef (not (autoloadp newdef))) 354 (if (and newdef (not (autoloadp newdef)))
368 (let* ((snewdef (advice--strip-macro newdef)) 355 (let* ((snewdef (advice--strip-macro newdef))
369 (snewadv (advice--subst-main oldadv snewdef))) 356 (snewadv (advice--subst-main oldadv snewdef)))
@@ -383,7 +370,6 @@ is defined as a macro, alias, command, ..."
383 ;; TODO: 370 ;; TODO:
384 ;; - record the advice location, to display in describe-function. 371 ;; - record the advice location, to display in describe-function.
385 ;; - change all defadvice in lisp/**/*.el. 372 ;; - change all defadvice in lisp/**/*.el.
386 ;; - rewrite advice.el on top of this.
387 ;; - obsolete advice.el. 373 ;; - obsolete advice.el.
388 (let* ((f (symbol-function symbol)) 374 (let* ((f (symbol-function symbol))
389 (nf (advice--normalize symbol f))) 375 (nf (advice--normalize symbol f)))
@@ -420,8 +406,7 @@ of the piece of advice."
420 ((eq (car-safe f) 'macro) (cdr f)) 406 ((eq (car-safe f) 'macro) (cdr f))
421 (t (symbol-function symbol))) 407 (t (symbol-function symbol)))
422 function) 408 function)
423 (unless (advice--p 409 (unless (advice--p (advice--symbol-function symbol))
424 (if (eq (car-safe f) 'macro) (cdr f) (symbol-function symbol)))
425 ;; Not advised any more. 410 ;; Not advised any more.
426 (remove-function (get symbol 'defalias-fset-function) 411 (remove-function (get symbol 'defalias-fset-function)
427 #'advice--defalias-fset) 412 #'advice--defalias-fset)
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 50c92518b02..eb2c7f002e8 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -353,23 +353,34 @@ MATCH is the pattern that needs to be matched, of the form:
353 (symbolp . numberp) 353 (symbolp . numberp)
354 (symbolp . consp) 354 (symbolp . consp)
355 (symbolp . arrayp) 355 (symbolp . arrayp)
356 (symbolp . vectorp)
356 (symbolp . stringp) 357 (symbolp . stringp)
357 (symbolp . byte-code-function-p) 358 (symbolp . byte-code-function-p)
358 (integerp . consp) 359 (integerp . consp)
359 (integerp . arrayp) 360 (integerp . arrayp)
361 (integerp . vectorp)
360 (integerp . stringp) 362 (integerp . stringp)
361 (integerp . byte-code-function-p) 363 (integerp . byte-code-function-p)
362 (numberp . consp) 364 (numberp . consp)
363 (numberp . arrayp) 365 (numberp . arrayp)
366 (numberp . vectorp)
364 (numberp . stringp) 367 (numberp . stringp)
365 (numberp . byte-code-function-p) 368 (numberp . byte-code-function-p)
366 (consp . arrayp) 369 (consp . arrayp)
370 (consp . vectorp)
367 (consp . stringp) 371 (consp . stringp)
368 (consp . byte-code-function-p) 372 (consp . byte-code-function-p)
369 (arrayp . stringp)
370 (arrayp . byte-code-function-p) 373 (arrayp . byte-code-function-p)
374 (vectorp . byte-code-function-p)
375 (stringp . vectorp)
371 (stringp . byte-code-function-p))) 376 (stringp . byte-code-function-p)))
372 377
378(defun pcase--mutually-exclusive-p (pred1 pred2)
379 (or (member (cons pred1 pred2)
380 pcase-mutually-exclusive-predicates)
381 (member (cons pred2 pred1)
382 pcase-mutually-exclusive-predicates)))
383
373(defun pcase--split-match (sym splitter match) 384(defun pcase--split-match (sym splitter match)
374 (cond 385 (cond
375 ((eq (car match) 'match) 386 ((eq (car match) 'match)
@@ -433,10 +444,7 @@ MATCH is the pattern that needs to be matched, of the form:
433 ;; A QPattern but not for a cons, can only go to the `else' side. 444 ;; A QPattern but not for a cons, can only go to the `else' side.
434 ((eq (car-safe pat) '\`) '(:pcase--fail . nil)) 445 ((eq (car-safe pat) '\`) '(:pcase--fail . nil))
435 ((and (eq (car-safe pat) 'pred) 446 ((and (eq (car-safe pat) 'pred)
436 (or (member (cons 'consp (cadr pat)) 447 (pcase--mutually-exclusive-p #'consp (cadr pat)))
437 pcase-mutually-exclusive-predicates)
438 (member (cons (cadr pat) 'consp)
439 pcase-mutually-exclusive-predicates)))
440 '(:pcase--fail . nil)))) 448 '(:pcase--fail . nil))))
441 449
442(defun pcase--split-equal (elem pat) 450(defun pcase--split-equal (elem pat)
@@ -496,11 +504,14 @@ MATCH is the pattern that needs to be matched, of the form:
496 (not (pcase--fgrep (mapcar #'car vars) (cadr upat))))) 504 (not (pcase--fgrep (mapcar #'car vars) (cadr upat)))))
497 '(:pcase--succeed . :pcase--fail)) 505 '(:pcase--succeed . :pcase--fail))
498 ((and (eq 'pred (car upat)) 506 ((and (eq 'pred (car upat))
499 (eq 'pred (car-safe pat)) 507 (let ((otherpred
500 (or (member (cons (cadr upat) (cadr pat)) 508 (cond ((eq 'pred (car-safe pat)) (cadr pat))
501 pcase-mutually-exclusive-predicates) 509 ((not (eq '\` (car-safe pat))) nil)
502 (member (cons (cadr pat) (cadr upat)) 510 ((consp (cadr pat)) #'consp)
503 pcase-mutually-exclusive-predicates))) 511 ((vectorp (cadr pat)) #'vectorp)
512 ((byte-code-function-p (cadr pat))
513 #'byte-code-function-p))))
514 (pcase--mutually-exclusive-p (cadr upat) otherpred)))
504 '(:pcase--fail . nil)) 515 '(:pcase--fail . nil))
505 ((and (eq 'pred (car upat)) 516 ((and (eq 'pred (car upat))
506 (eq '\` (car-safe pat)) 517 (eq '\` (car-safe pat))
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 69dc6c76b41..ef8a53f3c0b 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -993,14 +993,6 @@ at the moment are:
993 ,@commands 993 ,@commands
994 (eshell-debug-command ,(concat "done " (eval tag)) form)))) 994 (eshell-debug-command ,(concat "done " (eval tag)) form))))
995 995
996(defsubst eshell-macrop (object)
997 "Return t if OBJECT is a macro or nil otherwise."
998 (and (symbolp object) (fboundp object)
999 (setq object (indirect-function object))
1000 (listp object)
1001 (eq 'macro (car object))
1002 (functionp (cdr object))))
1003
1004(defun eshell-do-eval (form &optional synchronous-p) 996(defun eshell-do-eval (form &optional synchronous-p)
1005 "Evaluate form, simplifying it as we go. 997 "Evaluate form, simplifying it as we go.
1006Unless SYNCHRONOUS-P is non-nil, throws `eshell-defer' if it needs to 998Unless SYNCHRONOUS-P is non-nil, throws `eshell-defer' if it needs to
@@ -1016,7 +1008,7 @@ be finished later after the completion of an asynchronous subprocess."
1016 (setq form (cadr (cadr form)))) 1008 (setq form (cadr (cadr form))))
1017 ;; expand any macros directly into the form. This is done so that 1009 ;; expand any macros directly into the form. This is done so that
1018 ;; we can modify any `let' forms to evaluate only once. 1010 ;; we can modify any `let' forms to evaluate only once.
1019 (if (eshell-macrop (car form)) 1011 (if (macrop (car form))
1020 (let ((exp (eshell-copy-tree (macroexpand form)))) 1012 (let ((exp (eshell-copy-tree (macroexpand form))))
1021 (eshell-manipulate (format "expanding macro `%s'" 1013 (eshell-manipulate (format "expanding macro `%s'"
1022 (symbol-name (car form))) 1014 (symbol-name (car form)))
diff --git a/lisp/subr.el b/lisp/subr.el
index 3b85a9bedb0..bdeee677471 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2750,6 +2750,13 @@ Otherwise, return nil."
2750 (setq object (indirect-function object t))) 2750 (setq object (indirect-function object t)))
2751 (and (subrp object) (eq (cdr (subr-arity object)) 'unevalled))) 2751 (and (subrp object) (eq (cdr (subr-arity object)) 'unevalled)))
2752 2752
2753(defun macrop (object)
2754 "Non-nil if and only if OBJECT is a macro."
2755 (let ((def (indirect-function object t)))
2756 (when (consp def)
2757 (or (eq 'macro (car def))
2758 (and (eq 'autoload (car def)) (memq (nth 4 def) '(macro t)))))))
2759
2753(defun field-at-pos (pos) 2760(defun field-at-pos (pos)
2754 "Return the field at position POS, taking stickiness etc into account." 2761 "Return the field at position POS, taking stickiness etc into account."
2755 (let ((raw-field (get-char-property (field-beginning pos) 'field))) 2762 (let ((raw-field (get-char-property (field-beginning pos) 'field)))
@@ -4050,10 +4057,14 @@ backwards ARG times if negative."
4050 4057
4051;;;; Text clones 4058;;;; Text clones
4052 4059
4053(defun text-clone-maintain (ol1 after beg end &optional _len) 4060(defvar text-clone--maintaining nil)
4061
4062(defun text-clone--maintain (ol1 after beg end &optional _len)
4054 "Propagate the changes made under the overlay OL1 to the other clones. 4063 "Propagate the changes made under the overlay OL1 to the other clones.
4055This is used on the `modification-hooks' property of text clones." 4064This is used on the `modification-hooks' property of text clones."
4056 (when (and after (not undo-in-progress) (overlay-start ol1)) 4065 (when (and after (not undo-in-progress)
4066 (not text-clone--maintaining)
4067 (overlay-start ol1))
4057 (let ((margin (if (overlay-get ol1 'text-clone-spreadp) 1 0))) 4068 (let ((margin (if (overlay-get ol1 'text-clone-spreadp) 1 0)))
4058 (setq beg (max beg (+ (overlay-start ol1) margin))) 4069 (setq beg (max beg (+ (overlay-start ol1) margin)))
4059 (setq end (min end (- (overlay-end ol1) margin))) 4070 (setq end (min end (- (overlay-end ol1) margin)))
@@ -4084,7 +4095,7 @@ This is used on the `modification-hooks' property of text clones."
4084 (tail (- (overlay-end ol1) end)) 4095 (tail (- (overlay-end ol1) end))
4085 (str (buffer-substring beg end)) 4096 (str (buffer-substring beg end))
4086 (nothing-left t) 4097 (nothing-left t)
4087 (inhibit-modification-hooks t)) 4098 (text-clone--maintaining t))
4088 (dolist (ol2 (overlay-get ol1 'text-clones)) 4099 (dolist (ol2 (overlay-get ol1 'text-clones))
4089 (let ((oe (overlay-end ol2))) 4100 (let ((oe (overlay-end ol2)))
4090 (unless (or (eq ol1 ol2) (null oe)) 4101 (unless (or (eq ol1 ol2) (null oe))
@@ -4095,7 +4106,7 @@ This is used on the `modification-hooks' property of text clones."
4095 (unless (> mod-beg (point)) 4106 (unless (> mod-beg (point))
4096 (save-excursion (insert str)) 4107 (save-excursion (insert str))
4097 (delete-region mod-beg (point))) 4108 (delete-region mod-beg (point)))
4098 ;;(overlay-put ol2 'modification-hooks '(text-clone-maintain)) 4109 ;;(overlay-put ol2 'modification-hooks '(text-clone--maintain))
4099 )))) 4110 ))))
4100 (if nothing-left (delete-overlay ol1)))))))) 4111 (if nothing-left (delete-overlay ol1))))))))
4101 4112
@@ -4126,17 +4137,18 @@ clone should be incorporated in the clone."
4126 (>= pt-end (point-max)) 4137 (>= pt-end (point-max))
4127 (>= start (point-max))) 4138 (>= start (point-max)))
4128 0 1)) 4139 0 1))
4140 ;; FIXME: Reuse overlays at point to extend dups!
4129 (ol1 (make-overlay (- start start-margin) (+ end end-margin) nil t)) 4141 (ol1 (make-overlay (- start start-margin) (+ end end-margin) nil t))
4130 (ol2 (make-overlay (- (point) start-margin) (+ pt-end end-margin) nil t)) 4142 (ol2 (make-overlay (- (point) start-margin) (+ pt-end end-margin) nil t))
4131 (dups (list ol1 ol2))) 4143 (dups (list ol1 ol2)))
4132 (overlay-put ol1 'modification-hooks '(text-clone-maintain)) 4144 (overlay-put ol1 'modification-hooks '(text-clone--maintain))
4133 (when spreadp (overlay-put ol1 'text-clone-spreadp t)) 4145 (when spreadp (overlay-put ol1 'text-clone-spreadp t))
4134 (when syntax (overlay-put ol1 'text-clone-syntax syntax)) 4146 (when syntax (overlay-put ol1 'text-clone-syntax syntax))
4135 ;;(overlay-put ol1 'face 'underline) 4147 ;;(overlay-put ol1 'face 'underline)
4136 (overlay-put ol1 'evaporate t) 4148 (overlay-put ol1 'evaporate t)
4137 (overlay-put ol1 'text-clones dups) 4149 (overlay-put ol1 'text-clones dups)
4138 ;; 4150 ;;
4139 (overlay-put ol2 'modification-hooks '(text-clone-maintain)) 4151 (overlay-put ol2 'modification-hooks '(text-clone--maintain))
4140 (when spreadp (overlay-put ol2 'text-clone-spreadp t)) 4152 (when spreadp (overlay-put ol2 'text-clone-spreadp t))
4141 (when syntax (overlay-put ol2 'text-clone-syntax syntax)) 4153 (when syntax (overlay-put ol2 'text-clone-syntax syntax))
4142 ;;(overlay-put ol2 'face 'underline) 4154 ;;(overlay-put ol2 'face 'underline)