diff --git a/tui/gniza.tcss b/tui/gniza.tcss index 079f7e3..7bd23e0 100644 --- a/tui/gniza.tcss +++ b/tui/gniza.tcss @@ -154,6 +154,21 @@ Select { height: 1fr; } +#fp-new-row { + height: auto; + margin: 1 0 0 0; +} + +#fp-new-row Input { + width: 1fr; +} + +#fp-new-row Button { + width: auto; + min-width: 16; + margin: 0 0 0 1; +} + #fp-buttons { height: auto; margin: 1 0 0 0; diff --git a/tui/widgets/folder_picker.py b/tui/widgets/folder_picker.py index 69b5d32..d898497 100644 --- a/tui/widgets/folder_picker.py +++ b/tui/widgets/folder_picker.py @@ -1,8 +1,9 @@ +from pathlib import Path + from textual.app import ComposeResult from textual.screen import ModalScreen -from textual.widgets import DirectoryTree, Header, Footer, Static, Button +from textual.widgets import DirectoryTree, Static, Button, Input from textual.containers import Horizontal, Vertical -from pathlib import Path class _DirOnly(DirectoryTree): @@ -23,20 +24,49 @@ class FolderPicker(ModalScreen[str | None]): with Vertical(id="folder-picker"): yield Static(self._title, id="fp-title") yield _DirOnly(self._start, id="fp-tree") + with Horizontal(id="fp-new-row"): + yield Input(placeholder="New folder name", id="fp-new-name") + yield Button("Create Folder", id="fp-create") with Horizontal(id="fp-buttons"): yield Button("Select", variant="primary", id="fp-select") yield Button("Cancel", variant="default", id="fp-cancel") + def _get_selected_path(self) -> Path | None: + tree = self.query_one("#fp-tree", DirectoryTree) + node = tree.cursor_node + if node and node.data and node.data.path: + return node.data.path + return None + def on_button_pressed(self, event: Button.Pressed) -> None: if event.button.id == "fp-select": - tree = self.query_one("#fp-tree", DirectoryTree) - node = tree.cursor_node - if node and node.data and node.data.path: - self.dismiss(str(node.data.path)) - else: - self.dismiss(None) + path = self._get_selected_path() + self.dismiss(str(path) if path else None) + elif event.button.id == "fp-create": + self._create_folder() else: self.dismiss(None) + def _create_folder(self) -> None: + name = self.query_one("#fp-new-name", Input).value.strip() + if not name: + self.notify("Enter a folder name", severity="error") + return + if "/" in name or "\0" in name: + self.notify("Invalid folder name", severity="error") + return + parent = self._get_selected_path() + if not parent: + parent = Path(self._start) + new_dir = parent / name + try: + new_dir.mkdir(parents=True, exist_ok=True) + self.notify(f"Created: {new_dir}") + tree = self.query_one("#fp-tree", DirectoryTree) + tree.reload() + self.query_one("#fp-new-name", Input).value = "" + except OSError as e: + self.notify(f"Failed: {e}", severity="error") + def action_cancel(self) -> None: self.dismiss(None)