import os import sys from rich.console import RenderableType from rich.syntax import Syntax from rich.traceback import Traceback from textual.app import App from textual.widgets import Header, Footer, FileClick, ScrollView, DirectoryTree class MyApp(App): """An example of a very simple Textual App""" async def on_load(self) -> None: """Sent before going in to application mode.""" # Bind our basic keys await self.bind("b", "view.toggle('sidebar')", "Toggle sidebar") await self.bind("q", "quit", "Quit") # Get path to show try: self.path = sys.argv[1] except IndexError: self.path = os.path.abspath( os.path.join(os.path.basename(__file__), "../../") ) async def on_mount(self) -> None: """Call after terminal goes in to application mode""" # Create our widgets # In this a scroll view for the code and a directory tree self.body = ScrollView() self.directory = DirectoryTree(self.path, "Code") # Dock our widgets await self.view.dock(Header(), edge="top") await self.view.dock(Footer(), edge="bottom") # Note the directory is also in a scroll view await self.view.dock( ScrollView(self.directory), edge="left", size=48, name="sidebar" ) await self.view.dock(self.body, edge="top") async def handle_file_click(self, message: FileClick) -> None: """A message sent by the directory tree when a file is clicked.""" syntax: RenderableType try: # Construct a Syntax object for the path in the message syntax = Syntax.from_path( message.path, line_numbers=True, word_wrap=True, indent_guides=True, theme="monokai", ) except Exception: # Possibly a binary file # For demonstration purposes we will show the traceback syntax = Traceback(theme="monokai", width=None, show_locals=True) self.app.sub_title = os.path.basename(message.path) await self.body.update(syntax) # Run our app class MyApp.run(title="Code Viewer", log="textual.log")