Verified Commit 79e302f6 authored by Jakob Moser's avatar Jakob Moser
Browse files

Add basic table of contents implementation

parent 3ded01f1
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
from __future__ import annotations

from dataclasses import dataclass, field
from math import inf


@dataclass
class Node[T]:
    level: int | float
    content: T | None

    parent: Node[T] | None = field(repr=False)
    children: list[Node[T]] = field(default_factory=list)

    _prime_possible_parent: Node[T] | None = field(default=None, init=False)

    def can_nurse_at(self, level: int) -> bool:
        """Return if the given level is greater than one's own level, i.e., if content with this level
        could be a child of this node.
        """
        return level > self.level

    def _nurse(self, level: int, content: T) -> Node[T]:
        """
        Append the given content with the given level as child of this node, without looking at the level.

        You probably want to use `append` instead, which takes care of inserting at the correct level
        (and doesn't just mindlessly append whatever you give it).
        """
        node = Node(level, content, self)
        self.children.append(node)
        return node

    def append(self, level: int | float, content: T) -> None:
        while True:
            if not self._prime_possible_parent:
                # Take care of the node myself, and note it down as next prime possible parent
                self._prime_possible_parent = self._nurse(level, content)
                return
            elif self._prime_possible_parent.can_nurse_at(level):
                # If the prime possible parent can nurse at this level, let it nurse the node,
                # and make the newly inserted node the next prime possible parent
                self._prime_possible_parent = self._prime_possible_parent._nurse(level, content)
                return
            else:
                # Go up once
                self._prime_possible_parent = self._prime_possible_parent.parent

    @classmethod
    def new_root(cls) -> Node[T]:
        return cls(-inf, None, None)
+0 −0

Empty file added.