v0.3.1: q/Escape beenden wieder, Rename-Crash und ".."-Aktionen gefixt
- Screen-Bindings lösen Actions im Screen-Namespace auf. "quit" traf daher ins Leere, weil Screen.action_quit nicht existiert – die Taste wurde still verworfen. Bindings auf "app.quit" umgestellt (q im Browser, Escape im Verbindungsdialog). - RenameScreen._ok rief do_rename() auf sich selbst statt auf den darunter liegenden BrowserScreen (AttributeError). Reihenfolge korrigiert: erst pop_screen(), dann do_rename(). - RenameScreen mit Escape abbrechbar. - Neuer Helfer _selected_entry() blendet den ".."-Navigationseintrag aus. Download, Upload, Löschen und Umbenennen operierten sonst auf "↑ ..".
This commit is contained in:
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
"""ftptui - Interaktiver FTP/SFTP-Client als Terminal-User-Interface."""
|
"""ftptui - Interaktiver FTP/SFTP-Client als Terminal-User-Interface."""
|
||||||
|
|
||||||
__version__ = "0.3.0"
|
__version__ = "0.3.1"
|
||||||
|
|||||||
+19
-7
@@ -92,7 +92,7 @@ class FileTable(DataTable):
|
|||||||
class ConnectionScreen(Screen):
|
class ConnectionScreen(Screen):
|
||||||
"""Startbildschirm zur Eingabe der Verbindungsdaten (Terminal-Look)."""
|
"""Startbildschirm zur Eingabe der Verbindungsdaten (Terminal-Look)."""
|
||||||
|
|
||||||
BINDINGS = [Binding("escape", "quit", "Beenden")]
|
BINDINGS = [Binding("escape", "app.quit", "Beenden")]
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
yield Header(show_clock=True)
|
yield Header(show_clock=True)
|
||||||
@@ -205,7 +205,7 @@ class BrowserScreen(Screen):
|
|||||||
"""Total-Commander-artiger Datei-Browser zwischen lokal & entfernt."""
|
"""Total-Commander-artiger Datei-Browser zwischen lokal & entfernt."""
|
||||||
|
|
||||||
BINDINGS = [
|
BINDINGS = [
|
||||||
Binding("q", "quit", "Beenden"),
|
Binding("q", "app.quit", "Beenden"),
|
||||||
Binding("enter", "open", "Öffnen"),
|
Binding("enter", "open", "Öffnen"),
|
||||||
Binding("tab", "focus_next", "Panele wechseln"),
|
Binding("tab", "focus_next", "Panele wechseln"),
|
||||||
Binding("l", "download", "Herunterladen"),
|
Binding("l", "download", "Herunterladen"),
|
||||||
@@ -356,6 +356,13 @@ class BrowserScreen(Screen):
|
|||||||
cell = table.get_row_at(row)[0]
|
cell = table.get_row_at(row)[0]
|
||||||
return cell.plain if isinstance(cell, Text) else str(cell)
|
return cell.plain if isinstance(cell, Text) else str(cell)
|
||||||
|
|
||||||
|
def _selected_entry(self, table: FileTable) -> str | None:
|
||||||
|
"""Wie `_selected`, ignoriert aber den ``..``-Navigationseintrag."""
|
||||||
|
sel = self._selected(table)
|
||||||
|
if not sel or sel.startswith("↑"):
|
||||||
|
return None
|
||||||
|
return sel
|
||||||
|
|
||||||
@on(DataTable.RowSelected, "#local_table")
|
@on(DataTable.RowSelected, "#local_table")
|
||||||
def _local_selected(self, event: DataTable.RowSelected) -> None:
|
def _local_selected(self, event: DataTable.RowSelected) -> None:
|
||||||
self._open("local")
|
self._open("local")
|
||||||
@@ -404,7 +411,7 @@ class BrowserScreen(Screen):
|
|||||||
self._update_info()
|
self._update_info()
|
||||||
|
|
||||||
def action_download(self) -> None:
|
def action_download(self) -> None:
|
||||||
sel = self._selected(self.table_remote)
|
sel = self._selected_entry(self.table_remote)
|
||||||
if not sel:
|
if not sel:
|
||||||
return
|
return
|
||||||
name = sel[:-1] if sel.endswith("/") else sel
|
name = sel[:-1] if sel.endswith("/") else sel
|
||||||
@@ -420,7 +427,7 @@ class BrowserScreen(Screen):
|
|||||||
self._refresh_local()
|
self._refresh_local()
|
||||||
|
|
||||||
def action_upload(self) -> None:
|
def action_upload(self) -> None:
|
||||||
sel = self._selected(self.table_local)
|
sel = self._selected_entry(self.table_local)
|
||||||
if not sel:
|
if not sel:
|
||||||
return
|
return
|
||||||
name = sel[:-1] if sel.endswith("/") else sel
|
name = sel[:-1] if sel.endswith("/") else sel
|
||||||
@@ -479,7 +486,7 @@ class BrowserScreen(Screen):
|
|||||||
|
|
||||||
def action_delete(self) -> None:
|
def action_delete(self) -> None:
|
||||||
table = self._focused_table()
|
table = self._focused_table()
|
||||||
sel = self._selected(table)
|
sel = self._selected_entry(table)
|
||||||
if not sel:
|
if not sel:
|
||||||
return
|
return
|
||||||
remote = table is not self.table_local
|
remote = table is not self.table_local
|
||||||
@@ -504,7 +511,7 @@ class BrowserScreen(Screen):
|
|||||||
|
|
||||||
def action_rename(self) -> None:
|
def action_rename(self) -> None:
|
||||||
table = self._focused_table()
|
table = self._focused_table()
|
||||||
sel = self._selected(table)
|
sel = self._selected_entry(table)
|
||||||
if not sel:
|
if not sel:
|
||||||
return
|
return
|
||||||
self._rename_target = sel
|
self._rename_target = sel
|
||||||
@@ -535,6 +542,11 @@ class BrowserScreen(Screen):
|
|||||||
class RenameScreen(Screen):
|
class RenameScreen(Screen):
|
||||||
"""Eingabebildschirm zum Umbenennen."""
|
"""Eingabebildschirm zum Umbenennen."""
|
||||||
|
|
||||||
|
BINDINGS = [Binding("escape", "cancel", "Abbrechen")]
|
||||||
|
|
||||||
|
def action_cancel(self) -> None:
|
||||||
|
self.app.pop_screen()
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
yield Static("Neuer Name:", classes="field")
|
yield Static("Neuer Name:", classes="field")
|
||||||
yield Input(id="newname", placeholder="neuer-name", classes="input")
|
yield Input(id="newname", placeholder="neuer-name", classes="input")
|
||||||
@@ -547,8 +559,8 @@ class RenameScreen(Screen):
|
|||||||
@on(Button.Pressed, "#ok")
|
@on(Button.Pressed, "#ok")
|
||||||
def _ok(self) -> None:
|
def _ok(self) -> None:
|
||||||
name = self.query_one("#newname", Input).value.strip()
|
name = self.query_one("#newname", Input).value.strip()
|
||||||
self.app.screen.do_rename(name if name else "unbenannt")
|
|
||||||
self.app.pop_screen()
|
self.app.pop_screen()
|
||||||
|
self.app.screen.do_rename(name if name else "unbenannt")
|
||||||
|
|
||||||
@on(Button.Pressed, "#cancel")
|
@on(Button.Pressed, "#cancel")
|
||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "ftptui"
|
name = "ftptui"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
description = "Interaktiver FTP/SFTP-Client als Terminal-User-Interface in Python"
|
description = "Interaktiver FTP/SFTP-Client als Terminal-User-Interface in Python"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
|||||||
Reference in New Issue
Block a user