diff options
| author | Stefan Monnier | 2023-11-08 11:32:27 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2023-11-08 22:42:16 -0500 |
| commit | 19445b6b7bb04e44e39ef2e39a620bd3eadb0acd (patch) | |
| tree | bd8b0f0a0a31556c11fd717264b5c0f89f6a3da5 | |
| parent | 21f36705266934d5a351d4d7f360734540132139 (diff) | |
| download | emacs-19445b6b7bb04e44e39ef2e39a620bd3eadb0acd.tar.gz emacs-19445b6b7bb04e44e39ef2e39a620bd3eadb0acd.zip | |
subr.el: Provide a functional API around `derived-mode-parent`
The `derived-mode-parent` property should be an implementation detail,
so we can change it more easily. To that end, add functions to set and
query it.
* lisp/subr.el (derived-mode-all-parents): New function.
(provided-mode-derived-p): Use it.
(derived-mode-set-parent): New function.
| -rw-r--r-- | lisp/subr.el | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index d4173b4daba..6a4c1abfb62 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -2678,20 +2678,27 @@ The variable list SPEC is the same as in `if-let*'." | |||
| 2678 | 2678 | ||
| 2679 | ;; PUBLIC: find if the current mode derives from another. | 2679 | ;; PUBLIC: find if the current mode derives from another. |
| 2680 | 2680 | ||
| 2681 | (defun derived-mode-all-parents (mode &optional known-children) | ||
| 2682 | "Return all the parents of MODE, starting with MODE. | ||
| 2683 | The returned list is not fresh, don't modify it. | ||
| 2684 | \n(fn MODE)" ;`known-children' is for internal use only. | ||
| 2685 | (if (memq mode known-children) | ||
| 2686 | (error "Cycle in the major mode hierarchy: %S" mode) | ||
| 2687 | (push mode known-children)) | ||
| 2688 | (let* ((parent (or (get mode 'derived-mode-parent) | ||
| 2689 | ;; If MODE is an alias, then follow the alias. | ||
| 2690 | (let ((alias (symbol-function mode))) | ||
| 2691 | (and (symbolp alias) alias))))) | ||
| 2692 | (cons mode (if parent (derived-mode-all-parents parent known-children))))) | ||
| 2693 | |||
| 2681 | (defun provided-mode-derived-p (mode &rest modes) | 2694 | (defun provided-mode-derived-p (mode &rest modes) |
| 2682 | "Non-nil if MODE is derived from one of MODES. | 2695 | "Non-nil if MODE is derived from one of MODES. |
| 2683 | Uses the `derived-mode-parent' property of the symbol to trace backwards. | ||
| 2684 | If you just want to check `major-mode', use `derived-mode-p'." | 2696 | If you just want to check `major-mode', use `derived-mode-p'." |
| 2685 | (declare (side-effect-free t)) | 2697 | (declare (side-effect-free t)) |
| 2686 | (while | 2698 | (let ((ps (derived-mode-all-parents mode))) |
| 2687 | (and | 2699 | (while (and ps (not (memq (car ps) modes))) |
| 2688 | (not (memq mode modes)) | 2700 | (setq ps (cdr ps))) |
| 2689 | (let* ((parent (get mode 'derived-mode-parent))) | 2701 | (car ps))) |
| 2690 | (setq mode (or parent | ||
| 2691 | ;; If MODE is an alias, then follow the alias. | ||
| 2692 | (let ((alias (symbol-function mode))) | ||
| 2693 | (and (symbolp alias) alias))))))) | ||
| 2694 | mode) | ||
| 2695 | 2702 | ||
| 2696 | (defun derived-mode-p (&rest modes) | 2703 | (defun derived-mode-p (&rest modes) |
| 2697 | "Non-nil if the current major mode is derived from one of MODES. | 2704 | "Non-nil if the current major mode is derived from one of MODES. |
| @@ -2699,6 +2706,10 @@ Uses the `derived-mode-parent' property of the symbol to trace backwards." | |||
| 2699 | (declare (side-effect-free t)) | 2706 | (declare (side-effect-free t)) |
| 2700 | (apply #'provided-mode-derived-p major-mode modes)) | 2707 | (apply #'provided-mode-derived-p major-mode modes)) |
| 2701 | 2708 | ||
| 2709 | (defun derived-mode-set-parent (mode parent) | ||
| 2710 | "Declare PARENT to be the parent of MODE." | ||
| 2711 | (put mode 'derived-mode-parent parent)) | ||
| 2712 | |||
| 2702 | (defvar-local major-mode--suspended nil) | 2713 | (defvar-local major-mode--suspended nil) |
| 2703 | (put 'major-mode--suspended 'permanent-local t) | 2714 | (put 'major-mode--suspended 'permanent-local t) |
| 2704 | 2715 | ||