diff options
| author | Richard M. Stallman | 1994-09-30 20:47:13 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1994-09-30 20:47:13 +0000 |
| commit | 0e4d378b326194711ca81e445fd3d8b498be9c80 (patch) | |
| tree | 5680280e72d0b91123e282d91b31246a3c5f5250 | |
| parent | 62476adc5590f2441e4f3b35834da7022f0363c7 (diff) | |
| download | emacs-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.el | 173 |
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. | |||
| 505 | If a hook symbol has a non-nil value, that value may be a function | 505 | If a hook symbol has a non-nil value, that value may be a function |
| 506 | or a list of functions to be called to run the hook. | 506 | or a list of functions to be called to run the hook. |
| 507 | If the value is a function, it is called with no arguments. | 507 | If the value is a function, it is called with no arguments. |
| 508 | If it is a list, the elements are called, in order, with no arguments." | 508 | If it is a list, the elements are called, in order, with no arguments. |
| 509 | |||
| 510 | To 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 | |||
| 528 | of functions, those functions are called, in order, | 537 | of functions, those functions are called, in order, |
| 529 | with the given arguments ARGS. | 538 | with the given arguments ARGS. |
| 530 | It is best not to depend on the value return by `run-hook-with-args', | 539 | It is best not to depend on the value return by `run-hook-with-args', |
| 531 | as that may change." | 540 | as that may change. |
| 541 | |||
| 542 | To 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. | ||
| 562 | HOOK should be a symbol, a hook variable. Its value should | ||
| 563 | be a list of functions. We call those functions, one by one, | ||
| 564 | passing arguments ARGS to each of them, until one of them | ||
| 565 | returns a non-nil value. Then we return that value. | ||
| 566 | If all the functions return nil, we return nil. | ||
| 567 | |||
| 568 | To 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. | ||
| 588 | HOOK should be a symbol, a hook variable. Its value should | ||
| 589 | be a list of functions. We call those functions, one by one, | ||
| 590 | passing arguments ARGS to each of them, until one of them | ||
| 591 | returns nil. Then we return nil. | ||
| 592 | If all the functions return non-nil, we return non-nil. | ||
| 593 | |||
| 594 | To 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'. |
| 543 | Don't change it.") | 615 | Don'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. | ||
| 619 | When a hook is local, its local and global values | ||
| 620 | work in concert: running the hook actually runs all the hook | ||
| 621 | functions listed in *either* the local value *or* the global value | ||
| 622 | of the hook variable. | ||
| 623 | |||
| 624 | This function does nothing if HOOK is already local in the current buffer. | ||
| 625 | |||
| 626 | Do 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. |
| 547 | FUNCTION is not added if already present. | 635 | FUNCTION is not added if already present. |
| 548 | FUNCTION is added (if necessary) at the beginning of the hook list | 636 | FUNCTION is added (if necessary) at the beginning of the hook list |
| 549 | unless the optional argument APPEND is non-nil, in which case | 637 | unless the optional argument APPEND is non-nil, in which case |
| 550 | FUNCTION is added at the end. | 638 | FUNCTION is added at the end. |
| 551 | 639 | ||
| 640 | The optional fourth argument, LOCAL, if non-nil, says to modify | ||
| 641 | the hook's buffer-local value rather than its default value. | ||
| 642 | This makes no difference if the hook is not buffer-local. | ||
| 643 | To make a hook variable buffer-local, always use | ||
| 644 | `make-local-hook', not `make-local-variable'. | ||
| 645 | |||
| 552 | HOOK should be a symbol, and FUNCTION may be any valid function. If | 646 | HOOK should be a symbol, and FUNCTION may be any valid function. If |
| 553 | HOOK is void, it is first set to nil. If HOOK's value is a single | 647 | HOOK is void, it is first set to nil. If HOOK's value is a single |
| 554 | function, it is changed to a list of functions." | 648 | function, 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. |
| 570 | HOOK should be a symbol, and FUNCTION may be any valid function. If | 676 | HOOK should be a symbol, and FUNCTION may be any valid function. If |
| 571 | FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the | 677 | FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the |
| 572 | list of hooks to run in HOOK, then nothing is done. See `add-hook'." | 678 | list of hooks to run in HOOK, then nothing is done. See `add-hook'. |
| 679 | |||
| 680 | The optional third argument, LOCAL, if non-nil, says to modify | ||
| 681 | the hook's buffer-local value rather than its default value. | ||
| 682 | This makes no difference if the hook is not buffer-local. | ||
| 683 | To 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 | ||