Function: derived-mode-all-parents

derived-mode-all-parents is a byte-compiled function defined in subr.el.gz.

Signature

(derived-mode-all-parents MODE)

Documentation

Return all the parents of MODE, starting with MODE.

This includes the parents set by define-derived-mode and additional ones set by derived-mode-add-parents. The returned list is not fresh, don't modify it.

View in manual

Probably introduced at or before Emacs version 30.1.

Aliases

mode-local-equivalent-mode-p (obsolete since 30.1)

Source Code

;; Defined in /usr/src/emacs/lisp/subr.el.gz
(defun derived-mode-all-parents (mode &optional known-children)
  "Return all the parents of MODE, starting with MODE.
This includes the parents set by `define-derived-mode' and additional
ones set by `derived-mode-add-parents'.
The returned list is not fresh, don't modify it.
\n(fn MODE)"               ;`known-children' is for internal use only.
  ;; Can't use `with-memoization' :-(
  (let ((ps (get mode 'derived-mode--all-parents)))
    (cond
     (ps ps)
     ((memq mode known-children)
      ;; These things happen, better not get all worked up about it.
      ;;(error "Cycle in the major mode hierarchy: %S" mode)
      ;; But do try to return something meaningful.
      (memq mode (reverse known-children)))
     (t
      ;; The mode hierarchy (or DAG, actually), is very static, but we
      ;; need to react to changes because `parent' may not be defined
      ;; yet (e.g. it's still just an autoload), so the recursive call
      ;; to `derived-mode-all-parents' may return an
      ;; invalid/incomplete result which we'll need to update when the
      ;; mode actually gets loaded.
      (let* ((new-children (cons mode known-children))
             (get-all-parents
              (lambda (parent)
                ;; Can't use `cl-lib' here (nor `gv') :-(
                ;;(cl-assert (not (equal parent mode)))
                ;;(cl-pushnew mode (get parent 'derived-mode--followers))
                (let ((followers (get parent 'derived-mode--followers)))
                  (unless (memq mode followers)
                    (put parent 'derived-mode--followers
                         (cons mode followers))))
                (derived-mode-all-parents parent new-children)))
             (parent (or (get mode 'derived-mode-parent)
                         ;; If MODE is an alias, then follow the alias.
                         (let ((alias (symbol-function mode)))
                           (and (symbolp alias) alias))))
             (extras (get mode 'derived-mode-extra-parents))
             (all-parents
              (merge-ordered-lists
               (cons (if (and parent (not (memq parent extras)))
                         (funcall get-all-parents parent))
                     (mapcar get-all-parents extras)))))
        ;; Cache the result unless it was affected by `known-children'
        ;; because of a cycle.
        (if (and (memq mode all-parents) known-children)
            (cons mode (remq mode all-parents))
          (put mode 'derived-mode--all-parents (cons mode all-parents))))))))