mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Markdown and dictionary example
This commit is contained in:
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `App.batch_update`
|
- Added `App.batch_update`
|
||||||
|
- Added horizontal rule to Markdown
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#results {
|
#results {
|
||||||
width: auto;
|
width: 100%;
|
||||||
min-height: 100%;
|
height: auto;
|
||||||
padding: 0 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#results-container {
|
#results-container {
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError("Please install httpx with 'pip install httpx' ")
|
raise ImportError("Please install httpx with 'pip install httpx' ")
|
||||||
|
|
||||||
from rich.markdown import Markdown
|
|
||||||
|
|
||||||
from textual.app import App, ComposeResult
|
from textual.app import App, ComposeResult
|
||||||
from textual.containers import Content
|
from textual.containers import Content
|
||||||
from textual.widgets import Static, Input
|
from textual.widgets import Input, Markdown
|
||||||
|
|
||||||
|
|
||||||
class DictionaryApp(App):
|
class DictionaryApp(App):
|
||||||
@@ -21,7 +20,7 @@ class DictionaryApp(App):
|
|||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
yield Input(placeholder="Search for a word")
|
yield Input(placeholder="Search for a word")
|
||||||
yield Content(Static(id="results"), id="results-container")
|
yield Content(Markdown(id="results"), id="results-container")
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
def on_mount(self) -> None:
|
||||||
"""Called when app starts."""
|
"""Called when app starts."""
|
||||||
@@ -35,7 +34,7 @@ class DictionaryApp(App):
|
|||||||
asyncio.create_task(self.lookup_word(message.value))
|
asyncio.create_task(self.lookup_word(message.value))
|
||||||
else:
|
else:
|
||||||
# Clear the results
|
# Clear the results
|
||||||
self.query_one("#results", Static).update()
|
await self.query_one("#results", Markdown).update("")
|
||||||
|
|
||||||
async def lookup_word(self, word: str) -> None:
|
async def lookup_word(self, word: str) -> None:
|
||||||
"""Looks up a word."""
|
"""Looks up a word."""
|
||||||
@@ -45,7 +44,8 @@ class DictionaryApp(App):
|
|||||||
|
|
||||||
if word == self.query_one(Input).value:
|
if word == self.query_one(Input).value:
|
||||||
markdown = self.make_word_markdown(results)
|
markdown = self.make_word_markdown(results)
|
||||||
self.query_one("#results", Static).update(Markdown(markdown))
|
self.log(markdown)
|
||||||
|
await self.query_one("#results", Markdown).update(markdown)
|
||||||
|
|
||||||
def make_word_markdown(self, results: object) -> str:
|
def make_word_markdown(self, results: object) -> str:
|
||||||
"""Convert the results in to markdown."""
|
"""Convert the results in to markdown."""
|
||||||
|
|||||||
@@ -198,6 +198,18 @@ class MarkdownH6(MarkdownHeader):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownHorizontalRule(MarkdownBlock):
|
||||||
|
"""A horizontal rule."""
|
||||||
|
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
MarkdownHorizontalRule {
|
||||||
|
border-bottom: heavy $primary;
|
||||||
|
height: 1;
|
||||||
|
padding-top: 1;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class MarkdownParagraph(MarkdownBlock):
|
class MarkdownParagraph(MarkdownBlock):
|
||||||
"""A paragraph Markdown block."""
|
"""A paragraph Markdown block."""
|
||||||
|
|
||||||
@@ -501,7 +513,7 @@ class Markdown(Widget):
|
|||||||
markdown = path.read_text(encoding="utf-8")
|
markdown = path.read_text(encoding="utf-8")
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
await self.query("MarkdownBlock").remove()
|
|
||||||
await self.update(markdown)
|
await self.update(markdown)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -524,6 +536,8 @@ class Markdown(Widget):
|
|||||||
if token.type == "heading_open":
|
if token.type == "heading_open":
|
||||||
block_id += 1
|
block_id += 1
|
||||||
stack.append(HEADINGS[token.tag](id=f"block{block_id}"))
|
stack.append(HEADINGS[token.tag](id=f"block{block_id}"))
|
||||||
|
elif token.type == "hr":
|
||||||
|
output.append(MarkdownHorizontalRule())
|
||||||
elif token.type == "paragraph_open":
|
elif token.type == "paragraph_open":
|
||||||
stack.append(MarkdownParagraph())
|
stack.append(MarkdownParagraph())
|
||||||
elif token.type == "blockquote_open":
|
elif token.type == "blockquote_open":
|
||||||
@@ -627,7 +641,10 @@ class Markdown(Widget):
|
|||||||
await self.post_message(
|
await self.post_message(
|
||||||
Markdown.TableOfContentsUpdated(table_of_contents, sender=self)
|
Markdown.TableOfContentsUpdated(table_of_contents, sender=self)
|
||||||
)
|
)
|
||||||
await self.mount(*output)
|
with self.app.batch_update():
|
||||||
|
await self.query("MarkdownBlock").remove()
|
||||||
|
await self.mount(*output)
|
||||||
|
self.refresh(layout=True)
|
||||||
|
|
||||||
|
|
||||||
class MarkdownTableOfContents(Widget, can_focus_children=True):
|
class MarkdownTableOfContents(Widget, can_focus_children=True):
|
||||||
|
|||||||
Reference in New Issue
Block a user