Skip to content

Commit

Permalink
✨ Add table of content support
Browse files Browse the repository at this point in the history
Also tidy up how I work around
Textualize/textual#5488
  • Loading branch information
davep committed Feb 10, 2025
1 parent 3912064 commit 154e6aa
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 deletions.
22 changes: 21 additions & 1 deletion src/hike/screens/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from textual import on, work
from textual.app import ComposeResult
from textual.containers import Horizontal
from textual.widgets import Footer, Header
from textual.widgets import Footer, Header, Markdown

##############################################################################
# Textual enhanced imports.
Expand Down Expand Up @@ -130,6 +130,26 @@ def open_from_history(self, message: OpenFromHistory) -> None:
"""
self.query_one(Viewer).goto(message.location)

@on(Markdown.TableOfContentsUpdated)
def update_navigation_contents(
self, message: Markdown.TableOfContentsUpdated
) -> None:
"""Handle the table of contents being updated.
Args:
message: The message broadcasting that the ToC is updated.
"""
self.query_one(Navigation).table_of_contents = message.table_of_contents

@on(Markdown.TableOfContentsSelected)
def jump_to_content(self, message: Markdown.TableOfContentsSelected) -> None:
"""Jump to a specific location in the current document.
Args:
message: The message request the jump.
"""
self.query_one(Viewer).jump_to_content(message.block_id)

@on(Help)
def action_help_command(self) -> None:
"""Toggle the display of the help panel."""
Expand Down
1 change: 0 additions & 1 deletion src/hike/widgets/navigation/history_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ class HistoryView(EnhancedOptionList):
HistoryView {
height: 1fr;
border: none;
background: transparent;
&:focus {
border: none;
}
Expand Down
42 changes: 32 additions & 10 deletions src/hike/widgets/navigation/widget.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
"""Provides the navigation panel widget."""

##############################################################################
# Backward compatibility.
from __future__ import annotations

##############################################################################
# Textual imports.
from textual import on
from textual.app import ComposeResult
from textual.containers import Vertical
from textual.events import DescendantBlur, DescendantFocus
from textual.reactive import var
from textual.widgets import Placeholder, TabbedContent
from textual.widgets import Markdown, Placeholder, TabbedContent, Tree
from textual.widgets.markdown import MarkdownTableOfContents, TableOfContentsType

##############################################################################
# Local imports.
Expand All @@ -24,37 +28,55 @@ class Navigation(Vertical):
width: 27%;
dock: left;
background: transparent;
&.--dock-right {
dock: right;
}
#tabs-list {
background: $panel;
}
/* https://github.com/Textualize/textual/issues/5488 */
MarkdownTableOfContents, &:focus-within MarkdownTableOfContents {
background: transparent;
width: 1fr;
Tree {
background: transparent;
}
}
/* https://github.com/Textualize/textual/issues/5488 */
HistoryView, &:focus-within HistoryView {
background: transparent;
}
}
"""

dock_right: var[bool] = var(False)
"""Should the navigation dock to the right?"""

table_of_contents: var[TableOfContentsType | None] = var(None)

_history: var[HistoryView | None] = var(None)
"""The history display."""

@on(DescendantBlur)
@on(DescendantFocus)
def _textual_5488_workaround(self) -> None:
"""Workaround for https://github.com/Textualize/textual/issues/5488"""
for widget in self.query(HistoryView):
widget._refresh_lines()

def _watch_dock_right(self) -> None:
"""React to the dock toggle being changed."""
self.set_class(self.dock_right, "--dock-right")

def _watch_table_of_contents(self) -> None:
"""React to the table of content being updated."""
self.query_one(
MarkdownTableOfContents
).table_of_contents = self.table_of_contents
self.query_one("MarkdownTableOfContents Tree", Tree).cursor_line = 0

def compose(self) -> ComposeResult:
"""Compose the content of the widget."""
self._history = HistoryView()
with TabbedContent("Content", "Local", "Bookmarks", "History"):
yield Placeholder()
yield MarkdownTableOfContents(Markdown())
yield Placeholder()
yield Placeholder()
yield self._history
Expand Down
8 changes: 8 additions & 0 deletions src/hike/widgets/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,5 +248,13 @@ def forward(self) -> None:
if self.history.forward():
self._visit_from_history()

def jump_to_content(self, block_id: str) -> None:
"""Jump to some content in the current document.
Args:
block_id: The ID of the content to jump to.
"""
self.scroll_to_widget(self.query_one(f"#{block_id}"), top=True)


### viewer.py ends here

0 comments on commit 154e6aa

Please sign in to comment.