Skip to content

Instantly share code, notes, and snippets.

@vadviktor
Last active January 20, 2024 10:41
Show Gist options
  • Save vadviktor/f30571147142577900313e76e823e6d3 to your computer and use it in GitHub Desktop.
Save vadviktor/f30571147142577900313e76e823e6d3 to your computer and use it in GitHub Desktop.
Traversing folders using Textual
from pathlib import Path
from textual import events, on
from textual.app import App, ComposeResult
from textual.containers import Container, Horizontal
from textual.screen import ModalScreen
from textual.widgets import Button, DataTable, Footer, Header, Label
from rich.text import Text
class FileInformation(ModalScreen):
def __init__(self, file_path: Path):
self.file_path = file_path
super().__init__()
def compose(self):
self.title = "File Information"
with Container():
yield Label(str(self.file_path))
yield Label(f"Size: {self.file_path.stat().st_size}")
with Horizontal():
yield Button("Close", id="close", variant="primary")
@on(Button.Pressed)
def close_modal(self, event):
if event.button.id == "close":
self.dismiss()
class NavigatorApp(App):
CSS_PATH = "main.tcss"
BINDINGS = [
("q", "quit", "Quit"),
("i", "show_file_information", "Show file information"),
]
table: DataTable
current_path: Path = Path.home()
def compose(self) -> ComposeResult:
yield Header()
yield Footer()
self.title = str(self.current_path)
self.table = DataTable(cursor_type="row")
self.table.add_column("", key="icon")
self.table.add_column("Name", key="name", width=20)
self.table.add_column("Type", key="type")
yield self.table
def on_mount(self) -> None:
self.list_directory()
def action_quit(self):
self.exit()
def action_show_file_information(self):
row_key, _ = self.table.coordinate_to_cell_key(self.table.cursor_coordinate)
entry_name = self.table.get_cell(row_key, "name")
file_path = self.current_path.joinpath(entry_name)
if file_path.is_dir():
return
self.push_screen(FileInformation(file_path=file_path))
def on_key(self, event: events.Key) -> None:
if event.key == "enter":
self.navigate_to_directory()
def navigate_to_directory(self):
# Get the keys for the row and column under the cursor.
row_key, _ = self.table.coordinate_to_cell_key(self.table.cursor_coordinate)
# Get the value of the first column of the row.
entry_name = self.table.get_cell(row_key, "name")
if entry_name == "..":
self.navigate_up()
self.table.clear()
self.list_directory()
elif self.current_path.joinpath(entry_name).is_dir():
self.navigate_down(entry_name)
self.table.clear()
self.list_directory()
def navigate_up(self):
self.current_path = self.current_path.parent
def navigate_down(self, entry_name):
self.current_path = self.current_path.joinpath(entry_name)
def list_directory(self):
self.title = str(self.current_path)
files_and_dirs = self.current_path.iterdir()
if self.current_path.parent == self.current_path:
self.table.add_row("", "-- no parent --", "Directory")
else:
self.table.add_row("", "..", "Directory")
for entry in files_and_dirs:
if entry.is_dir():
icon = "📁"
entry_type = "Directory"
else:
icon = "📄"
entry_type = "File"
self.table.add_row(icon, entry.name, entry_type)
if __name__ == "__main__":
NavigatorApp().run()
DataTable {
height: 100%;
}
FileInformation {
align: center middle;
}
FileInformation > Container {
height: auto;
width: auto;
padding: 1 2;
background: $panel;
}
FileInformation > Container > Horizontal {
height: auto;
width: auto;
}
FileInformation > Container > Horizontal > Button {
margin: 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment