aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1994-09-30 20:47:13 +0000
committerRichard M. Stallman1994-09-30 20:47:13 +0000
commit0e4d378b326194711ca81e445fd3d8b498be9c80 (patch)
tree5680280e72d0b91123e282d91b31246a3c5f5250
parent62476adc5590f2441e4f3b35834da7022f0363c7 (diff)
downloademacs-0e4d378b326194711ca81e445fd3d8b498be9c80.tar.gz
emacs-0e4d378b326194711ca81e445fd3d8b498be9c80.zip
(add-hook): Initialize default value and local value.
(run-hook-with-args-until-success): New function. (run-hook-with-args-until-failure): New function. (run-hooks): t as hook list element means run the global value of the variable as well as the local value. (run-hook-with-args): Likewise. (make-local-hook): New function. (add-hook, remove-hook): New arg LOCAL means modify local value. Test default-boundp as well as boundp.
-rw-r--r--lisp/subr.el173
1 files changed, 147 insertions, 26 deletions
diff --git a/lisp/subr.el b/lisp/subr.el
index 6b9768e0e60..a29d4e177a8 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -505,17 +505,26 @@ These symbols are processed in the order specified.
505If a hook symbol has a non-nil value, that value may be a function 505If a hook symbol has a non-nil value, that value may be a function
506or a list of functions to be called to run the hook. 506or a list of functions to be called to run the hook.
507If the value is a function, it is called with no arguments. 507If the value is a function, it is called with no arguments.
508If it is a list, the elements are called, in order, with no arguments." 508If it is a list, the elements are called, in order, with no arguments.
509
510To make a hook variable buffer-local, use `make-local-hook', not
511`make-local-variable'."
509 (while hooklist 512 (while hooklist
510 (let ((sym (car hooklist))) 513 (let ((sym (car hooklist)))
511 (and (boundp sym) 514 (and (boundp sym)
512 (symbol-value sym) 515 (symbol-value sym)
513 (let ((value (symbol-value sym))) 516 (let ((value (symbol-value sym)))
514 (if (and (listp value) (not (eq (car value) 'lambda))) 517 (if (and (listp value) (not (eq (car value) 'lambda)))
515 (let ((functions value)) 518 (while value
516 (while value 519 (if (eq (car value) t)
517 (funcall (car value)) 520 ;; t indicates this hook has a local binding;
518 (setq value (cdr value)))) 521 ;; it means to run the global binding too.
522 (let ((functions (default-value sym)))
523 (while functions
524 (funcall (car functions))
525 (setq functions (cdr functions))))
526 (funcall (car value)))
527 (setq value (cdr value)))
519 (funcall value))))) 528 (funcall value)))))
520 (setq hooklist (cdr hooklist)))) 529 (setq hooklist (cdr hooklist))))
521 530
@@ -528,59 +537,171 @@ the given arguments and its return value is returned. If it is a list
528of functions, those functions are called, in order, 537of functions, those functions are called, in order,
529with the given arguments ARGS. 538with the given arguments ARGS.
530It is best not to depend on the value return by `run-hook-with-args', 539It is best not to depend on the value return by `run-hook-with-args',
531as that may change." 540as that may change.
541
542To make a hook variable buffer-local, use `make-local-hook', not
543`make-local-variable'."
532 (and (boundp hook) 544 (and (boundp hook)
533 (symbol-value hook) 545 (symbol-value hook)
534 (let ((value (symbol-value hook))) 546 (let ((value (symbol-value hook)))
535 (if (and (listp value) (not (eq (car value) 'lambda))) 547 (if (and (listp value) (not (eq (car value) 'lambda)))
536 (mapcar '(lambda (foo) (apply foo args)) 548 (while value
537 value) 549 (if (eq (car value) t)
550 ;; t indicates this hook has a local binding;
551 ;; it means to run the global binding too.
552 (let ((functions (default-value hook)))
553 (while functions
554 (apply (car functions) args)
555 (setq functions (cdr functions))))
556 (apply (car value) args))
557 (setq value (cdr value)))
538 (apply value args))))) 558 (apply value args)))))
539 559
560(defun run-hook-with-args-until-success (hook &rest args)
561 "Run HOOK with the specified arguments ARGS.
562HOOK should be a symbol, a hook variable. Its value should
563be a list of functions. We call those functions, one by one,
564passing arguments ARGS to each of them, until one of them
565returns a non-nil value. Then we return that value.
566If all the functions return nil, we return nil.
567
568To make a hook variable buffer-local, use `make-local-hook', not
569`make-local-variable'."
570 (and (boundp hook)
571 (symbol-value hook)
572 (let ((value (symbol-value hook))
573 success)
574 (while (and value (not success))
575 (if (eq (car value) t)
576 ;; t indicates this hook has a local binding;
577 ;; it means to run the global binding too.
578 (let ((functions (default-value hook)))
579 (while (and functions (not success))
580 (setq success (apply (car functions) args))
581 (setq functions (cdr functions))))
582 (setq success (apply (car value) args)))
583 (setq value (cdr value)))
584 success)))
585
586(defun run-hook-with-args-until-failure (hook &rest args)
587 "Run HOOK with the specified arguments ARGS.
588HOOK should be a symbol, a hook variable. Its value should
589be a list of functions. We call those functions, one by one,
590passing arguments ARGS to each of them, until one of them
591returns nil. Then we return nil.
592If all the functions return non-nil, we return non-nil.
593
594To make a hook variable buffer-local, use `make-local-hook', not
595`make-local-variable'."
596 (and (boundp hook)
597 (symbol-value hook)
598 (let ((value (symbol-value hook))
599 (success t))
600 (while (and value success)
601 (if (eq (car value) t)
602 ;; t indicates this hook has a local binding;
603 ;; it means to run the global binding too.
604 (let ((functions (default-value hook)))
605 (while (and functions success)
606 (setq success (apply (car functions) args))
607 (setq functions (cdr functions))))
608 (setq success (apply (car value) args)))
609 (setq value (cdr value)))
610 success)))
611
540;; Tell C code how to call this function. 612;; Tell C code how to call this function.
541(defconst run-hooks 'run-hooks 613(defconst run-hooks 'run-hooks
542 "Variable by which C primitives find the function `run-hooks'. 614 "Variable by which C primitives find the function `run-hooks'.
543Don't change it.") 615Don't change it.")
544 616
545(defun add-hook (hook function &optional append) 617(defun make-local-hook (hook)
618 "Make the hook HOOK local to the current buffer.
619When a hook is local, its local and global values
620work in concert: running the hook actually runs all the hook
621functions listed in *either* the local value *or* the global value
622of the hook variable.
623
624This function does nothing if HOOK is already local in the current buffer.
625
626Do not use `make-local-variable' to make a hook variable buffer-local."
627 (if (local-variable-p hook)
628 nil
629 (or (boundp hook) (set hook nil))
630 (make-local-variable hook)
631 (set hook (list t))))
632
633(defun add-hook (hook function &optional append local)
546 "Add to the value of HOOK the function FUNCTION. 634 "Add to the value of HOOK the function FUNCTION.
547FUNCTION is not added if already present. 635FUNCTION is not added if already present.
548FUNCTION is added (if necessary) at the beginning of the hook list 636FUNCTION is added (if necessary) at the beginning of the hook list
549unless the optional argument APPEND is non-nil, in which case 637unless the optional argument APPEND is non-nil, in which case
550FUNCTION is added at the end. 638FUNCTION is added at the end.
551 639
640The optional fourth argument, LOCAL, if non-nil, says to modify
641the hook's buffer-local value rather than its default value.
642This makes no difference if the hook is not buffer-local.
643To make a hook variable buffer-local, always use
644`make-local-hook', not `make-local-variable'.
645
552HOOK should be a symbol, and FUNCTION may be any valid function. If 646HOOK should be a symbol, and FUNCTION may be any valid function. If
553HOOK is void, it is first set to nil. If HOOK's value is a single 647HOOK is void, it is first set to nil. If HOOK's value is a single
554function, it is changed to a list of functions." 648function, it is changed to a list of functions."
555 (or (boundp hook) (set hook nil)) 649 (or (boundp hook) (set hook nil))
650 (or (default-boundp hook) (set-default hook nil))
556 ;; If the hook value is a single function, turn it into a list. 651 ;; If the hook value is a single function, turn it into a list.
557 (let ((old (symbol-value hook))) 652 (let ((old (symbol-value hook)))
558 (if (or (not (listp old)) (eq (car old) 'lambda)) 653 (if (or (not (listp old)) (eq (car old) 'lambda))
559 (set hook (list old)))) 654 (set hook (list old))))
560 (or (if (consp function) 655 (if local
561 (member function (symbol-value hook)) 656 ;; Alter the local value only.
562 (memq function (symbol-value hook))) 657 (or (if (consp function)
563 (set hook 658 (member function (symbol-value hook))
564 (if append 659 (memq function (symbol-value hook)))
565 (append (symbol-value hook) (list function)) 660 (set hook
566 (cons function (symbol-value hook)))))) 661 (if append
567 662 (append (symbol-value hook) (list function))
568(defun remove-hook (hook function) 663 (cons function (symbol-value hook)))))
664 ;; Alter the global value (which is also the only value,
665 ;; if the hook doesn't have a local value).
666 (or (if (consp function)
667 (member function (default-value hook))
668 (memq function (default-value hook)))
669 (set-default hook
670 (if append
671 (append (default-value hook) (list function))
672 (cons function (default-value hook)))))))
673
674(defun remove-hook (hook function &optional local)
569 "Remove from the value of HOOK the function FUNCTION. 675 "Remove from the value of HOOK the function FUNCTION.
570HOOK should be a symbol, and FUNCTION may be any valid function. If 676HOOK should be a symbol, and FUNCTION may be any valid function. If
571FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the 677FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
572list of hooks to run in HOOK, then nothing is done. See `add-hook'." 678list of hooks to run in HOOK, then nothing is done. See `add-hook'.
679
680The optional third argument, LOCAL, if non-nil, says to modify
681the hook's buffer-local value rather than its default value.
682This makes no difference if the hook is not buffer-local.
683To make a hook variable buffer-local, always use
684`make-local-hook', not `make-local-variable'."
573 (if (or (not (boundp hook)) ;unbound symbol, or 685 (if (or (not (boundp hook)) ;unbound symbol, or
686 (not (default-boundp 'hook))
574 (null (symbol-value hook)) ;value is nil, or 687 (null (symbol-value hook)) ;value is nil, or
575 (null function)) ;function is nil, then 688 (null function)) ;function is nil, then
576 nil ;Do nothing. 689 nil ;Do nothing.
577 (let ((hook-value (symbol-value hook))) 690 (if local
578 (if (consp hook-value) 691 (let ((hook-value (symbol-value hook)))
579 (if (member function hook-value) 692 (if (consp hook-value)
580 (setq hook-value (delete function (copy-sequence hook-value)))) 693 (if (member function hook-value)
581 (if (equal hook-value function) 694 (setq hook-value (delete function (copy-sequence hook-value))))
582 (setq hook-value nil))) 695 (if (equal hook-value function)
583 (set hook hook-value)))) 696 (setq hook-value nil)))
697 (set hook hook-value))
698 (let ((hook-value (default-value hook)))
699 (if (consp hook-value)
700 (if (member function hook-value)
701 (setq hook-value (delete function (copy-sequence hook-value))))
702 (if (equal hook-value function)
703 (setq hook-value nil)))
704 (set-default hook hook-value)))))
584 705
585;;;; Specifying things to do after certain files are loaded. 706;;;; Specifying things to do after certain files are loaded.
586 707