Add 'Create Folder' to folder picker dialog

Adds an input field and button to create a new folder inside the
currently selected directory, then refreshes the tree.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shuki
2026-03-06 02:13:36 +02:00
parent 4bd9df3b5e
commit 5ecb9537b7
2 changed files with 53 additions and 8 deletions

View File

@@ -154,6 +154,21 @@ Select {
height: 1fr; 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 { #fp-buttons {
height: auto; height: auto;
margin: 1 0 0 0; margin: 1 0 0 0;

View File

@@ -1,8 +1,9 @@
from pathlib import Path
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.screen import ModalScreen 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 textual.containers import Horizontal, Vertical
from pathlib import Path
class _DirOnly(DirectoryTree): class _DirOnly(DirectoryTree):
@@ -23,20 +24,49 @@ class FolderPicker(ModalScreen[str | None]):
with Vertical(id="folder-picker"): with Vertical(id="folder-picker"):
yield Static(self._title, id="fp-title") yield Static(self._title, id="fp-title")
yield _DirOnly(self._start, id="fp-tree") 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"): with Horizontal(id="fp-buttons"):
yield Button("Select", variant="primary", id="fp-select") yield Button("Select", variant="primary", id="fp-select")
yield Button("Cancel", variant="default", id="fp-cancel") yield Button("Cancel", variant="default", id="fp-cancel")
def on_button_pressed(self, event: Button.Pressed) -> None: def _get_selected_path(self) -> Path | None:
if event.button.id == "fp-select":
tree = self.query_one("#fp-tree", DirectoryTree) tree = self.query_one("#fp-tree", DirectoryTree)
node = tree.cursor_node node = tree.cursor_node
if node and node.data and node.data.path: if node and node.data and node.data.path:
self.dismiss(str(node.data.path)) return node.data.path
else: return None
self.dismiss(None)
def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "fp-select":
path = self._get_selected_path()
self.dismiss(str(path) if path else None)
elif event.button.id == "fp-create":
self._create_folder()
else: else:
self.dismiss(None) 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: def action_cancel(self) -> None:
self.dismiss(None) self.dismiss(None)