mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
dictionary example
This commit is contained in:
@@ -19,7 +19,7 @@ class DictionaryApp(App):
|
|||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
yield TextInput(placeholder="Search for a word")
|
yield TextInput(placeholder="Search for a word")
|
||||||
yield Vertical(Static(id="results", fluid=False), id="results-container")
|
yield Vertical(Static(id="results"), id="results-container")
|
||||||
|
|
||||||
async def on_text_input_changed(self, message: TextInput.Changed) -> None:
|
async def on_text_input_changed(self, message: TextInput.Changed) -> None:
|
||||||
"""A coroutine to handle a text changed message."""
|
"""A coroutine to handle a text changed message."""
|
||||||
|
|||||||
@@ -18,9 +18,12 @@ CodeBrowser.-show-tree #tree-view {
|
|||||||
|
|
||||||
DirectoryTree {
|
DirectoryTree {
|
||||||
padding-right: 1;
|
padding-right: 1;
|
||||||
padding-right: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#code-view {
|
||||||
|
overflow: auto scroll;
|
||||||
|
|
||||||
|
}
|
||||||
#code {
|
#code {
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class CodeBrowser(App):
|
|||||||
yield Header()
|
yield Header()
|
||||||
yield Container(
|
yield Container(
|
||||||
Vertical(DirectoryTree(path), id="tree-view"),
|
Vertical(DirectoryTree(path), id="tree-view"),
|
||||||
Vertical(Static(id="code"), id="code-view"),
|
Vertical(Static(id="code", expand=True), id="code-view"),
|
||||||
)
|
)
|
||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ class CodeBrowser(App):
|
|||||||
syntax = Syntax.from_path(
|
syntax = Syntax.from_path(
|
||||||
event.path,
|
event.path,
|
||||||
line_numbers=True,
|
line_numbers=True,
|
||||||
word_wrap=True,
|
word_wrap=False,
|
||||||
indent_guides=True,
|
indent_guides=True,
|
||||||
theme="github-dark",
|
theme="github-dark",
|
||||||
)
|
)
|
||||||
@@ -54,6 +54,7 @@ class CodeBrowser(App):
|
|||||||
self.sub_title = event.path
|
self.sub_title = event.path
|
||||||
|
|
||||||
def action_toggle_files(self) -> None:
|
def action_toggle_files(self) -> None:
|
||||||
|
"""Called in response to key binding."""
|
||||||
self.show_tree = not self.show_tree
|
self.show_tree = not self.show_tree
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
31
examples/dictionary.css
Normal file
31
examples/dictionary.css
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
Screen {
|
||||||
|
background: $panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextInput {
|
||||||
|
dock: top;
|
||||||
|
border: tall $background;
|
||||||
|
width: 100%;
|
||||||
|
height: 1;
|
||||||
|
padding: 0 1;
|
||||||
|
margin: 1 1 0 1;
|
||||||
|
background: $boost;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextInput:focus {
|
||||||
|
border: tall $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#results {
|
||||||
|
width: auto;
|
||||||
|
min-height: 100%;
|
||||||
|
padding: 0 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#results-container {
|
||||||
|
background: $background 50%;
|
||||||
|
margin: 1 2;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden auto;
|
||||||
|
}
|
||||||
62
examples/dictionary.py
Normal file
62
examples/dictionary.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import asyncio
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
try:
|
||||||
|
import httpx
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError("Please install httpx with 'pip install httpx' ")
|
||||||
|
|
||||||
|
from rich.markdown import Markdown
|
||||||
|
|
||||||
|
from textual.app import App, ComposeResult
|
||||||
|
from textual.layout import Vertical
|
||||||
|
from textual.widgets import Static, TextInput
|
||||||
|
|
||||||
|
|
||||||
|
class DictionaryApp(App):
|
||||||
|
"""Searches ab dictionary API as-you-type."""
|
||||||
|
|
||||||
|
CSS_PATH = "dictionary.css"
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield TextInput(placeholder="Search for a word")
|
||||||
|
yield Vertical(Static(id="results"), id="results-container")
|
||||||
|
|
||||||
|
async def on_text_input_changed(self, message: TextInput.Changed) -> None:
|
||||||
|
"""A coroutine to handle a text changed message."""
|
||||||
|
if message.value:
|
||||||
|
# Look up the word in the background
|
||||||
|
asyncio.create_task(self.lookup_word(message.value))
|
||||||
|
else:
|
||||||
|
# Clear the results
|
||||||
|
self.query_one("#results", Static).update()
|
||||||
|
|
||||||
|
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:
|
||||||
|
results = (await client.get(url)).json()
|
||||||
|
|
||||||
|
if word == self.query_one(TextInput).value:
|
||||||
|
markdown = self.make_word_markdown(results)
|
||||||
|
self.query_one("#results", Static).update(Markdown(markdown))
|
||||||
|
|
||||||
|
def make_word_markdown(self, results: list[Any]) -> str:
|
||||||
|
"""Convert the results in to markdown."""
|
||||||
|
lines = []
|
||||||
|
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__":
|
||||||
|
app = DictionaryApp()
|
||||||
|
app.run()
|
||||||
101
poetry.lock
generated
101
poetry.lock
generated
@@ -74,7 +74,7 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "black"
|
name = "black"
|
||||||
version = "22.6.0"
|
version = "22.8.0"
|
||||||
description = "The uncompromising code formatter."
|
description = "The uncompromising code formatter."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -103,6 +103,14 @@ category = "dev"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "certifi"
|
||||||
|
version = "2022.9.14"
|
||||||
|
description = "Python package for providing Mozilla's CA Bundle."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfgv"
|
name = "cfgv"
|
||||||
version = "3.3.1"
|
version = "3.3.1"
|
||||||
@@ -166,7 +174,7 @@ toml = ["tomli"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "distlib"
|
name = "distlib"
|
||||||
version = "0.3.5"
|
version = "0.3.6"
|
||||||
description = "Distribution utilities"
|
description = "Distribution utilities"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -208,7 +216,7 @@ dev = ["twine", "markdown", "flake8", "wheel"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "griffe"
|
name = "griffe"
|
||||||
version = "0.22.0"
|
version = "0.22.1"
|
||||||
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
|
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -222,7 +230,7 @@ async = ["aiofiles (>=0.7,<1.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "identify"
|
name = "identify"
|
||||||
version = "2.5.3"
|
version = "2.5.5"
|
||||||
description = "File identification library for Python"
|
description = "File identification library for Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -233,7 +241,7 @@ license = ["ukkonen"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.3"
|
version = "3.4"
|
||||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -345,7 +353,7 @@ mkdocs = ">=1.1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocs-material"
|
name = "mkdocs-material"
|
||||||
version = "8.4.2"
|
version = "8.5.3"
|
||||||
description = "Documentation that simply works"
|
description = "Documentation that simply works"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -358,6 +366,7 @@ mkdocs = ">=1.3.0"
|
|||||||
mkdocs-material-extensions = ">=1.0.3"
|
mkdocs-material-extensions = ">=1.0.3"
|
||||||
pygments = ">=2.12"
|
pygments = ">=2.12"
|
||||||
pymdown-extensions = ">=9.4"
|
pymdown-extensions = ">=9.4"
|
||||||
|
requests = ">=2.26"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocs-material-extensions"
|
name = "mkdocs-material-extensions"
|
||||||
@@ -473,11 +482,11 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathspec"
|
name = "pathspec"
|
||||||
version = "0.9.0"
|
version = "0.10.1"
|
||||||
description = "Utility library for gitignore style pattern matching of file paths."
|
description = "Utility library for gitignore style pattern matching of file paths."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
@@ -663,9 +672,27 @@ python-versions = ">=3.6"
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pyyaml = "*"
|
pyyaml = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests"
|
||||||
|
version = "2.28.1"
|
||||||
|
description = "Python HTTP for Humans."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7, <4"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
certifi = ">=2017.4.17"
|
||||||
|
charset-normalizer = ">=2,<3"
|
||||||
|
idna = ">=2.5,<4"
|
||||||
|
urllib3 = ">=1.21.1,<1.27"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||||
|
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rich"
|
name = "rich"
|
||||||
version = "12.5.1"
|
version = "12.6.0a1"
|
||||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -730,9 +757,22 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urllib3"
|
||||||
|
version = "1.26.12"
|
||||||
|
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
|
||||||
|
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"]
|
||||||
|
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtualenv"
|
name = "virtualenv"
|
||||||
version = "20.16.3"
|
version = "20.16.5"
|
||||||
description = "Virtual Python Environment builder"
|
description = "Virtual Python Environment builder"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -790,7 +830,7 @@ dev = ["aiohttp", "click", "msgpack"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.7"
|
python-versions = "^3.7"
|
||||||
content-hash = "61db56567f708cd9ca1c27f0e4a4b4aa3dd808fc8411f80967a90995d7fdd8c8"
|
content-hash = "675b2fee0c6462eb36040dfbb19cf2c72451c73dfd619b1e830962c5f21ad529"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
aiohttp = [
|
aiohttp = [
|
||||||
@@ -881,35 +921,12 @@ asynctest = [
|
|||||||
]
|
]
|
||||||
atomicwrites = []
|
atomicwrites = []
|
||||||
attrs = []
|
attrs = []
|
||||||
black = [
|
black = []
|
||||||
{file = "black-22.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69"},
|
|
||||||
{file = "black-22.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807"},
|
|
||||||
{file = "black-22.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e"},
|
|
||||||
{file = "black-22.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def"},
|
|
||||||
{file = "black-22.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666"},
|
|
||||||
{file = "black-22.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d"},
|
|
||||||
{file = "black-22.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256"},
|
|
||||||
{file = "black-22.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78"},
|
|
||||||
{file = "black-22.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849"},
|
|
||||||
{file = "black-22.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c"},
|
|
||||||
{file = "black-22.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90"},
|
|
||||||
{file = "black-22.6.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f"},
|
|
||||||
{file = "black-22.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e"},
|
|
||||||
{file = "black-22.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6"},
|
|
||||||
{file = "black-22.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad"},
|
|
||||||
{file = "black-22.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf"},
|
|
||||||
{file = "black-22.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c"},
|
|
||||||
{file = "black-22.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2"},
|
|
||||||
{file = "black-22.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee"},
|
|
||||||
{file = "black-22.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b"},
|
|
||||||
{file = "black-22.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4"},
|
|
||||||
{file = "black-22.6.0-py3-none-any.whl", hash = "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c"},
|
|
||||||
{file = "black-22.6.0.tar.gz", hash = "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9"},
|
|
||||||
]
|
|
||||||
cached-property = [
|
cached-property = [
|
||||||
{file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"},
|
{file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"},
|
||||||
{file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"},
|
{file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"},
|
||||||
]
|
]
|
||||||
|
certifi = []
|
||||||
cfgv = [
|
cfgv = [
|
||||||
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
|
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
|
||||||
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
|
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
|
||||||
@@ -937,10 +954,7 @@ ghp-import = [
|
|||||||
]
|
]
|
||||||
griffe = []
|
griffe = []
|
||||||
identify = []
|
identify = []
|
||||||
idna = [
|
idna = []
|
||||||
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
|
|
||||||
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
|
|
||||||
]
|
|
||||||
importlib-metadata = [
|
importlib-metadata = [
|
||||||
{file = "importlib_metadata-4.12.0-py3-none-any.whl", hash = "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"},
|
{file = "importlib_metadata-4.12.0-py3-none-any.whl", hash = "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"},
|
||||||
{file = "importlib_metadata-4.12.0.tar.gz", hash = "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670"},
|
{file = "importlib_metadata-4.12.0.tar.gz", hash = "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670"},
|
||||||
@@ -1174,10 +1188,7 @@ packaging = [
|
|||||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
||||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
||||||
]
|
]
|
||||||
pathspec = [
|
pathspec = []
|
||||||
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
|
|
||||||
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
|
|
||||||
]
|
|
||||||
platformdirs = [
|
platformdirs = [
|
||||||
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
|
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
|
||||||
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
|
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
|
||||||
@@ -1256,6 +1267,7 @@ pyyaml-env-tag = [
|
|||||||
{file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
|
{file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
|
||||||
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
|
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
|
||||||
]
|
]
|
||||||
|
requests = []
|
||||||
rich = []
|
rich = []
|
||||||
six = [
|
six = [
|
||||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
@@ -1297,6 +1309,7 @@ typed-ast = [
|
|||||||
{file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"},
|
{file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"},
|
||||||
]
|
]
|
||||||
typing-extensions = []
|
typing-extensions = []
|
||||||
|
urllib3 = []
|
||||||
virtualenv = []
|
virtualenv = []
|
||||||
watchdog = [
|
watchdog = [
|
||||||
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"},
|
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"},
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ textual = "textual.cli.cli:run"
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.7"
|
python = "^3.7"
|
||||||
rich = "^12.5.0"
|
rich = "^12.6.0a1"
|
||||||
#rich = {path="../rich", develop=true}
|
#rich = {path="../rich", develop=true}
|
||||||
importlib-metadata = "^4.11.3"
|
importlib-metadata = "^4.11.3"
|
||||||
typing-extensions = { version = "^4.0.0", python = "<3.8" }
|
typing-extensions = { version = "^4.0.0", python = "<3.8" }
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ App > Screen {
|
|||||||
layers: base sidebar;
|
layers: base sidebar;
|
||||||
layout: vertical;
|
layout: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#tree-container {
|
#tree-container {
|
||||||
|
|||||||
@@ -104,9 +104,11 @@ class Success(Static):
|
|||||||
return Text("This is a success message", justify="center")
|
return Text("This is a success message", justify="center")
|
||||||
|
|
||||||
|
|
||||||
class BasicApp(App, css_path="basic.css"):
|
class BasicApp(App):
|
||||||
"""A basic app demonstrating CSS"""
|
"""A basic app demonstrating CSS"""
|
||||||
|
|
||||||
|
CSS_PATH = "basic.css"
|
||||||
|
|
||||||
def on_load(self):
|
def on_load(self):
|
||||||
"""Bind keys here."""
|
"""Bind keys here."""
|
||||||
self.bind("s", "toggle_class('#sidebar', '-active')", description="Sidebar")
|
self.bind("s", "toggle_class('#sidebar', '-active')", description="Sidebar")
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ def measure(console: Console, renderable: RenderableType, default: int) -> int:
|
|||||||
Returns:
|
Returns:
|
||||||
int: Width in cells
|
int: Width in cells
|
||||||
"""
|
"""
|
||||||
|
width = default
|
||||||
renderable = rich_cast(renderable)
|
renderable = rich_cast(renderable)
|
||||||
get_console_width = getattr(renderable, "__rich_measure__", None)
|
get_console_width = getattr(renderable, "__rich_measure__", None)
|
||||||
if get_console_width is not None:
|
if get_console_width is not None:
|
||||||
render_width = get_console_width(console, console.options).normalize().maximum
|
render_width = get_console_width(console, console.options).maximum
|
||||||
return max(0, render_width)
|
width = max(0, render_width)
|
||||||
return default
|
return width
|
||||||
|
|||||||
@@ -87,8 +87,13 @@ class Widget(DOMNode):
|
|||||||
COMPONENT_CLASSES: ClassVar[set[str]] = set()
|
COMPONENT_CLASSES: ClassVar[set[str]] = set()
|
||||||
|
|
||||||
can_focus: bool = False
|
can_focus: bool = False
|
||||||
|
"""Widget may receive focus."""
|
||||||
can_focus_children: bool = True
|
can_focus_children: bool = True
|
||||||
fluid = Reactive(True)
|
"""Widget's children may receive focus."""
|
||||||
|
expand = Reactive(True)
|
||||||
|
"""Rich renderable may expand."""
|
||||||
|
shrink = Reactive(True)
|
||||||
|
"""Rich renderable may shrink."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -237,26 +242,6 @@ class Widget(DOMNode):
|
|||||||
"""Clear arrangement cache, forcing a new arrange operation."""
|
"""Clear arrangement cache, forcing a new arrange operation."""
|
||||||
self._arrangement = None
|
self._arrangement = None
|
||||||
|
|
||||||
def watch_show_horizontal_scrollbar(self, value: bool) -> None:
|
|
||||||
"""Watch function for show_horizontal_scrollbar attribute.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (bool): Show horizontal scrollbar flag.
|
|
||||||
"""
|
|
||||||
if not value:
|
|
||||||
# reset the scroll position if the scrollbar is hidden.
|
|
||||||
self.scroll_to(0, 0, animate=False)
|
|
||||||
|
|
||||||
def watch_show_vertical_scrollbar(self, value: bool) -> None:
|
|
||||||
"""Watch function for show_vertical_scrollbar attribute.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (bool): Show vertical scrollbar flag.
|
|
||||||
"""
|
|
||||||
if not value:
|
|
||||||
# reset the scroll position if the scrollbar is hidden.
|
|
||||||
self.scroll_to(0, 0, animate=False)
|
|
||||||
|
|
||||||
def mount(self, *anon_widgets: Widget, **widgets: Widget) -> None:
|
def mount(self, *anon_widgets: Widget, **widgets: Widget) -> None:
|
||||||
"""Mount child widgets (making this widget a container).
|
"""Mount child widgets (making this widget a container).
|
||||||
|
|
||||||
@@ -350,7 +335,9 @@ class Widget(DOMNode):
|
|||||||
renderable = self._render()
|
renderable = self._render()
|
||||||
|
|
||||||
width = measure(console, renderable, container.width)
|
width = measure(console, renderable, container.width)
|
||||||
if self.fluid:
|
if self.expand:
|
||||||
|
width = max(container.width, width)
|
||||||
|
if self.shrink:
|
||||||
width = min(width, container.width)
|
width = min(width, container.width)
|
||||||
|
|
||||||
self._content_width_cache = (cache_key, width)
|
self._content_width_cache = (cache_key, width)
|
||||||
@@ -514,6 +501,11 @@ class Widget(DOMNode):
|
|||||||
elif overflow_y == "auto":
|
elif overflow_y == "auto":
|
||||||
show_vertical = self.virtual_size.height > height
|
show_vertical = self.virtual_size.height > height
|
||||||
|
|
||||||
|
if overflow_x == "auto" and show_vertical and not show_horizontal:
|
||||||
|
show_horizontal = (
|
||||||
|
self.virtual_size.width + styles.scrollbar_size_vertical > width
|
||||||
|
)
|
||||||
|
|
||||||
self.show_horizontal_scrollbar = show_horizontal
|
self.show_horizontal_scrollbar = show_horizontal
|
||||||
self.show_vertical_scrollbar = show_vertical
|
self.show_vertical_scrollbar = show_vertical
|
||||||
self.horizontal_scrollbar.display = show_horizontal
|
self.horizontal_scrollbar.display = show_horizontal
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ class Static(Widget):
|
|||||||
Args:
|
Args:
|
||||||
renderable (RenderableType, optional): A Rich renderable, or string containing console markup.
|
renderable (RenderableType, optional): A Rich renderable, or string containing console markup.
|
||||||
Defaults to "".
|
Defaults to "".
|
||||||
fluid (bool, optional): Enable fluid content (adapts to size of window). Defaults to True.
|
expand (bool, optional): Rich renderable may expand beyond optimal. Defaults to False.
|
||||||
|
shrink (bool, optional): Rich renderable may shrink below optional. Defaults to False.
|
||||||
name (str | None, optional): Name of widget. Defaults to None.
|
name (str | None, optional): Name of widget. Defaults to None.
|
||||||
id (str | None, optional): ID of Widget. Defaults to None.
|
id (str | None, optional): ID of Widget. Defaults to None.
|
||||||
classes (str | None, optional): Space separated list of class names. Defaults to None.
|
classes (str | None, optional): Space separated list of class names. Defaults to None.
|
||||||
@@ -43,14 +44,16 @@ class Static(Widget):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
fluid = reactive(True, layout=True)
|
expand = reactive(False)
|
||||||
|
shrink = reactive(False)
|
||||||
_renderable: RenderableType
|
_renderable: RenderableType
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
renderable: RenderableType = "",
|
renderable: RenderableType = "",
|
||||||
*,
|
*,
|
||||||
fluid: bool = True,
|
expand: bool = False,
|
||||||
|
shrink: bool = False,
|
||||||
markup: bool = True,
|
markup: bool = True,
|
||||||
name: str | None = None,
|
name: str | None = None,
|
||||||
id: str | None = None,
|
id: str | None = None,
|
||||||
@@ -58,7 +61,8 @@ class Static(Widget):
|
|||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
super().__init__(name=name, id=id, classes=classes)
|
super().__init__(name=name, id=id, classes=classes)
|
||||||
self.fluid = fluid
|
self.expand = expand
|
||||||
|
self.shrink = shrink
|
||||||
self.markup = markup
|
self.markup = markup
|
||||||
self.renderable = renderable
|
self.renderable = renderable
|
||||||
_check_renderable(renderable)
|
_check_renderable(renderable)
|
||||||
|
|||||||
Reference in New Issue
Block a user