Files
textual-serve/examples/dictionary.py
Will McGugan 5aecb6a072 resources
2024-06-17 12:53:20 +01:00

80 lines
2.6 KiB
Python

from __future__ import annotations
try:
import httpx
except ImportError:
raise ImportError("Please install httpx with 'pip install httpx' ")
from textual import work
from textual.app import App, ComposeResult
from textual.containers import VerticalScroll
from textual.widgets import Input, Markdown
class DictionaryApp(App):
"""Searches a dictionary API as-you-type."""
CSS_PATH = "dictionary.tcss"
def compose(self) -> ComposeResult:
yield Input(placeholder="Search for a word")
with VerticalScroll(id="results-container"):
yield Markdown(id="results")
def on_mount(self) -> None:
"""Called when app starts."""
# Give the input focus, so we can start typing straight away
self.query_one(Input).focus()
async def on_input_changed(self, message: Input.Changed) -> None:
"""A coroutine to handle a text changed message."""
if message.value:
self.lookup_word(message.value)
else:
# Clear the results
await self.query_one("#results", Markdown).update("")
@work(exclusive=True)
async def lookup_word(self, word: str) -> None:
"""Looks up a word."""
url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}"
async with httpx.AsyncClient() as client:
response = await client.get(url)
try:
results = response.json()
except Exception:
self.query_one("#results", Markdown).update(response.text)
return
if word == self.query_one(Input).value:
markdown = self.make_word_markdown(results)
self.query_one("#results", Markdown).update(markdown)
def make_word_markdown(self, results: object) -> str:
"""Convert the results in to markdown."""
lines = []
if isinstance(results, dict):
lines.append(f"# {results['title']}")
lines.append(results["message"])
elif isinstance(results, list):
for result in results:
lines.append(f"# {result['word']}")
lines.append("")
for meaning in result.get("meanings", []):
lines.append(f"_{meaning['partOfSpeech']}_")
lines.append("")
for definition in meaning.get("definitions", []):
lines.append(f" - {definition['definition']}")
lines.append("---")
return "\n".join(lines)
if __name__ == "__main__":
from textual_serve.server import Server
server = Server(DictionaryApp)
server.serve()