From bd27d0432d77b3562cd453e2b05c9d29e340ad58 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 19 May 2024 20:07:24 +0100 Subject: [PATCH] Added dyanmic bindings to Markdown --- CHANGELOG.md | 6 ++++++ examples/markdown.py | 10 ++++++++++ src/textual/widgets/_markdown.py | 16 ++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db97673569..4cdf692da8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.62.0] - Unrelease + +### Added + +- Added `start` and `end` properties to Markdown Navigator + ## [0.61.1] - 2024-05-19 ### Fixed diff --git a/examples/markdown.py b/examples/markdown.py index a6d26cb190..3fd7bad883 100644 --- a/examples/markdown.py +++ b/examples/markdown.py @@ -31,6 +31,9 @@ async def on_mount(self) -> None: except FileNotFoundError: self.exit(message=f"Unable to load {self.path!r}") + def on_markdown_viewer_navigator_updated(self) -> None: + self.refresh_bindings() + def action_toggle_table_of_contents(self) -> None: self.markdown_viewer.show_table_of_contents = ( not self.markdown_viewer.show_table_of_contents @@ -42,6 +45,13 @@ async def action_back(self) -> None: async def action_forward(self) -> None: await self.markdown_viewer.forward() + def check_action(self, action: str, parameters: tuple[object, ...]) -> bool | None: + if action == "forward" and self.markdown_viewer.navigator.end: + return None + if action == "back" and self.markdown_viewer.navigator.start: + return None + return True + if __name__ == "__main__": app = MarkdownApp() diff --git a/src/textual/widgets/_markdown.py b/src/textual/widgets/_markdown.py index 6a05259642..dc2a9f35d1 100644 --- a/src/textual/widgets/_markdown.py +++ b/src/textual/widgets/_markdown.py @@ -48,6 +48,16 @@ def location(self) -> Path: return Path(".") return self.stack[self.index] + @property + def start(self) -> bool: + """Is the current location at the start of the stack?""" + return self.index == 0 + + @property + def end(self) -> bool: + """Is the current location at the end of the stack?""" + return self.index >= len(self.stack) - 1 + def go(self, path: str | PurePath) -> Path: """Go to a new document. @@ -1066,6 +1076,9 @@ class MarkdownViewer(VerticalScroll, can_focus=True, can_focus_children=True): navigator: var[Navigator] = var(Navigator) + class NavigatorUpdated(Message): + """Navigator has been changed (clicked link etc).""" + def __init__( self, markdown: str | None = None, @@ -1114,16 +1127,19 @@ async def go(self, location: str | PurePath) -> None: else: # We've been asked to go to a file, optionally with an anchor. await self.document.load(self.navigator.go(location)) + self.post_message(self.NavigatorUpdated()) async def back(self) -> None: """Go back one level in the history.""" if self.navigator.back(): await self.document.load(self.navigator.location) + self.post_message(self.NavigatorUpdated()) async def forward(self) -> None: """Go forward one level in the history.""" if self.navigator.forward(): await self.document.load(self.navigator.location) + self.post_message(self.NavigatorUpdated()) async def _on_markdown_link_clicked(self, message: Markdown.LinkClicked) -> None: message.stop()