SIGN IN SIGN UP
Textualize / textual UNCLAIMED

The lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser.

35092 0 0 Python
2022-09-20 15:56:32 +01:00
"""
Code browser example.
Run with:
python code_browser.py PATH
"""
from __future__ import annotations
2022-09-08 11:00:05 +01:00
import sys
from pathlib import Path
2022-09-08 11:00:05 +01:00
from rich.traceback import Traceback
2022-10-27 14:30:22 +01:00
2022-09-08 11:00:05 +01:00
from textual.app import App, ComposeResult
from textual.containers import Container, VerticalScroll
from textual.highlight import highlight
from textual.reactive import reactive, var
2022-09-08 11:00:05 +01:00
from textual.widgets import DirectoryTree, Footer, Header, Static
class CodeBrowser(App):
2022-09-08 21:11:05 +01:00
"""Textual code browser app."""
CSS_PATH = "code_browser.tcss"
2022-09-08 21:11:05 +01:00
BINDINGS = [
2022-09-09 15:54:16 +01:00
("f", "toggle_files", "Toggle Files"),
2022-09-08 21:11:05 +01:00
("q", "quit", "Quit"),
]
2022-09-08 11:00:05 +01:00
2022-09-09 17:52:08 +01:00
show_tree = var(True)
path: reactive[str | None] = reactive(None)
2022-09-08 11:00:05 +01:00
def watch_show_tree(self, show_tree: bool) -> None:
2022-09-08 21:11:05 +01:00
"""Called when show_tree is modified."""
2022-10-27 14:30:22 +01:00
self.set_class(show_tree, "-show-tree")
2022-09-08 11:00:05 +01:00
def compose(self) -> ComposeResult:
2022-09-08 21:11:05 +01:00
"""Compose our UI."""
2022-09-08 11:00:05 +01:00
path = "./" if len(sys.argv) < 2 else sys.argv[1]
yield Header()
2023-02-20 16:16:10 +00:00
with Container():
yield DirectoryTree(path, id="tree-view")
with VerticalScroll(id="code-view"):
2023-02-20 16:26:12 +00:00
yield Static(id="code", expand=True)
2022-09-08 11:00:05 +01:00
yield Footer()
def on_mount(self) -> None:
2022-10-27 14:30:22 +01:00
self.query_one(DirectoryTree).focus()
def theme_change(_signal) -> None:
"""Force the syntax to use a different theme."""
self.watch_path(self.path)
self.theme_changed_signal.subscribe(self, theme_change)
2022-11-19 17:21:23 +00:00
def on_directory_tree_file_selected(
self, event: DirectoryTree.FileSelected
) -> None:
2022-09-08 21:11:05 +01:00
"""Called when the user click a file in the directory tree."""
2022-11-19 17:21:23 +00:00
event.stop()
self.path = str(event.path)
def watch_path(self, path: str | None) -> None:
"""Called when path changes."""
2022-09-08 11:00:05 +01:00
code_view = self.query_one("#code", Static)
if path is None:
code_view.update("")
return
2022-09-08 11:00:05 +01:00
try:
code = Path(path).read_text(encoding="utf-8")
syntax = highlight(code, path=path)
2022-09-08 11:00:05 +01:00
except Exception:
2022-09-13 10:53:22 +01:00
code_view.update(Traceback(theme="github-dark", width=None))
2022-09-08 11:00:05 +01:00
self.sub_title = "ERROR"
else:
code_view.update(syntax)
self.query_one("#code-view").scroll_home(animate=False)
self.sub_title = path
2022-09-08 11:00:05 +01:00
2022-09-09 15:54:16 +01:00
def action_toggle_files(self) -> None:
2022-09-20 15:42:08 +01:00
"""Called in response to key binding."""
2022-09-08 11:00:05 +01:00
self.show_tree = not self.show_tree
if __name__ == "__main__":
2022-09-18 22:02:08 +01:00
CodeBrowser().run()