fix: Update scan commands and key bindings for improved usability

This commit is contained in:
sHa
2026-01-04 14:33:31 +00:00
parent e4314f1587
commit cffd68c687
5 changed files with 50 additions and 13 deletions

BIN
dist/renamer-0.7.8-py3-none-any.whl vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "renamer" name = "renamer"
version = "0.7.7" version = "0.7.8"
description = "Terminal-based media file renamer and metadata viewer" description = "Terminal-based media file renamer and metadata viewer"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"

View File

@@ -66,14 +66,15 @@ class AppCommandProvider(Provider):
commands = [ commands = [
("open", "Open Directory", "Open a directory to browse media files (o)"), ("open", "Open Directory", "Open a directory to browse media files (o)"),
("scan", "Scan Directory", "Scan current directory for media files (s)"), ("scan_local", "Scan Node", "Scan current node's directory only (s)"),
("scan", "Scan Tree", "Scan entire directory tree (Ctrl+S)"),
("refresh", "Refresh File", "Refresh metadata for selected file (f)"), ("refresh", "Refresh File", "Refresh metadata for selected file (f)"),
("rename", "Rename File", "Rename the selected file (r)"), ("rename", "Rename File", "Rename the selected file (r)"),
("convert", "Convert to MKV", "Convert AVI/MPG/MPEG/WebM/MP4 file to MKV container with metadata (c)"), ("convert", "Convert to MKV", "Convert AVI/MPG/MPEG/WebM/MP4 file to MKV container with metadata (c)"),
("delete", "Delete File", "Delete the selected file (d)"), ("delete", "Delete File", "Delete the selected file (d)"),
("toggle_mode", "Toggle Display Mode", "Switch between technical and catalog view (m)"), ("toggle_mode", "Toggle Display Mode", "Switch between technical and catalog view (m)"),
("expand", "Toggle Tree Expansion", "Expand or collapse all tree nodes (p)"), ("expand", "Toggle Tree Expansion", "Expand or collapse all tree nodes (t)"),
("settings", "Settings", "Open settings screen (Ctrl+S)"), ("settings", "Settings", "Open settings screen (p)"),
("help", "Help", "Show keyboard shortcuts and help (h)"), ("help", "Help", "Show keyboard shortcuts and help (h)"),
] ]
@@ -102,15 +103,16 @@ class RenamerApp(App):
BINDINGS = [ BINDINGS = [
("q", "quit", "Quit"), ("q", "quit", "Quit"),
("o", "open", "Open directory"), ("o", "open", "Open directory"),
("s", "scan", "Scan"), ("s", "scan_local", "Scan Node"),
("ctrl+s", "scan", "Scan Tree"),
("f", "refresh", "Refresh"), ("f", "refresh", "Refresh"),
("r", "rename", "Rename"), ("r", "rename", "Rename"),
("c", "convert", "Convert to MKV"), ("c", "convert", "Convert to MKV"),
("d", "delete", "Delete"), ("d", "delete", "Delete"),
("p", "expand", "Toggle Tree"), ("t", "expand", "Toggle Tree"),
("m", "toggle_mode", "Toggle Mode"), ("m", "toggle_mode", "Toggle Mode"),
("h", "help", "Help"), ("h", "help", "Help"),
("ctrl+s", "settings", "Settings"), ("p", "settings", "Settings"),
] ]
# Command palette - extend built-in commands with cache and app commands # Command palette - extend built-in commands with cache and app commands
@@ -298,6 +300,36 @@ class RenamerApp(App):
if self.scan_dir: if self.scan_dir:
self.scan_files() self.scan_files()
async def action_scan_local(self):
"""Scan only the current node's directory (refresh node)."""
tree = self.query_one("#file_tree", Tree)
node = tree.cursor_node
if not node or not node.data:
self.notify("Please select a node first", severity="warning", timeout=3)
return
# Get the directory to scan
path = node.data
if path.is_file():
# If it's a file, scan its parent directory
path = path.parent
# Find the parent node in the tree
if node.parent:
node = node.parent
else:
self.notify("Cannot scan root level file", severity="warning", timeout=3)
return
# Clear the node and rescan
node.remove_children()
self.build_tree(path, node)
# Expand the node to show new content
node.expand()
self.notify(f"Rescanned: {path.name}", severity="information", timeout=2)
async def action_refresh(self): async def action_refresh(self):
tree = self.query_one("#file_tree", Tree) tree = self.query_one("#file_tree", Tree)
node = tree.cursor_node node = tree.cursor_node
@@ -384,10 +416,9 @@ By Category:"""
proposed_formatter = ProposedFilenameView(extractor) proposed_formatter = ProposedFilenameView(extractor)
new_name = str(proposed_formatter) new_name = str(proposed_formatter)
logging.info(f"Proposed new name: {new_name!r} for file: {node.data}") logging.info(f"Proposed new name: {new_name!r} for file: {node.data}")
if new_name and new_name != node.data.name: # Always open rename dialog, even if names are the same (user might want to manually edit)
if new_name:
self.push_screen(RenameConfirmScreen(node.data, new_name)) self.push_screen(RenameConfirmScreen(node.data, new_name))
else:
self.notify("Proposed name is the same as current name; no rename needed.", severity="information", timeout=3)
async def action_convert(self): async def action_convert(self):
"""Convert AVI/MPG/MPEG/WebM/MP4 file to MKV with metadata preservation.""" """Convert AVI/MPG/MPEG/WebM/MP4 file to MKV with metadata preservation."""

View File

@@ -180,6 +180,12 @@ Do you want to proceed with renaming?
def on_button_pressed(self, event): def on_button_pressed(self, event):
if event.button.id == "rename": if event.button.id == "rename":
# Check if new name is the same as old name
if self.new_name == self.old_path.name:
self.app.notify("Proposed name is the same as current name; no rename needed.", severity="information", timeout=3)
self.app.pop_screen()
return
try: try:
logging.info(f"Starting rename: old_path={self.old_path}, new_path={self.new_path}") logging.info(f"Starting rename: old_path={self.old_path}, new_path={self.new_path}")
logging.info(f"Old file name: {self.old_path.name}") logging.info(f"Old file name: {self.old_path.name}")
@@ -495,7 +501,7 @@ class ConvertConfirmScreen(Screen):
yield Static(details_text, id="conversion_details", markup=True) yield Static(details_text, id="conversion_details", markup=True)
yield Static(info_text, id="info_text", markup=True) yield Static(info_text, id="info_text", markup=True)
with Horizontal(id="buttons"): with Horizontal(id="buttons"):
yield Button("Convert Copy (c)", id="convert_copy", variant="success") yield Button("Convert Copy (y)", id="convert_copy", variant="success")
yield Button("Convert HEVC (e)", id="convert_hevc", variant="primary") yield Button("Convert HEVC (e)", id="convert_hevc", variant="primary")
yield Button("Cancel (n)", id="cancel", variant="error") yield Button("Cancel (n)", id="cancel", variant="error")
@@ -574,7 +580,7 @@ class ConvertConfirmScreen(Screen):
self.app.pop_screen() # type: ignore self.app.pop_screen() # type: ignore
def on_key(self, event): def on_key(self, event):
if event.key == "c": if event.key == "y":
# Copy mode # Copy mode
self._do_conversion(encode_hevc=False) self._do_conversion(encode_hevc=False)
elif event.key == "e": elif event.key == "e":

2
uv.lock generated
View File

@@ -462,7 +462,7 @@ wheels = [
[[package]] [[package]]
name = "renamer" name = "renamer"
version = "0.7.7" version = "0.7.8"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "langcodes" }, { name = "langcodes" },