From fe4c0a4a58925d14f87e2ae8016e0dfc0d3e48e0 Mon Sep 17 00:00:00 2001 From: sHa Date: Sun, 28 Dec 2025 07:14:39 +0000 Subject: [PATCH] feat: Bump version to 0.3.1, update filename extraction logic, and enhance rename confirmation screen --- dist/renamer-0.3.1-py3-none-any.whl | Bin 0 -> 33952 bytes pyproject.toml | 2 +- renamer/app.py | 3 + renamer/extractors/filename_extractor.py | 12 ++- renamer/formatters/proposed_name_formatter.py | 2 +- renamer/screens.py | 86 +++++++++++++++--- ...atrical Cut] BDRemux [1080p,ukr,3eng].mkv" | 0 uv.lock | 2 +- 8 files changed, 86 insertions(+), 21 deletions(-) create mode 100644 dist/renamer-0.3.1-py3-none-any.whl create mode 100644 "renamer/test/filenames/Big Mommas. Like Father, Like Son (2011) \\[Theatrical Cut] BDRemux [1080p,ukr,3eng].mkv" diff --git a/dist/renamer-0.3.1-py3-none-any.whl b/dist/renamer-0.3.1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..1a53e57cf2a423227d50d3396e83f17013666d15 GIT binary patch literal 33952 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 1 else lang for lang, count in lang_counts.items()] - return ','.join(sorted(audio_langs)) + return ','.join(audio_langs) def extract_audio_tracks(self) -> list[dict]: """Extract audio track data from filename (simplified version with only language)""" diff --git a/renamer/formatters/proposed_name_formatter.py b/renamer/formatters/proposed_name_formatter.py index b768dc3..139e8ca 100644 --- a/renamer/formatters/proposed_name_formatter.py +++ b/renamer/formatters/proposed_name_formatter.py @@ -17,7 +17,7 @@ class ProposedNameFormatter: self.__frame_class = extractor.get("frame_class") or None self.__hdr = f",{extractor.get('hdr')}" if extractor.get("hdr") else "" self.__audio_langs = extractor.get("audio_langs") or None - self.__special_info = f" [{SpecialInfoFormatter.format_special_info(extractor.get('special_info'))}]" if extractor.get("special_info") else "" + self.__special_info = f" \[{SpecialInfoFormatter.format_special_info(extractor.get('special_info'))}]" if extractor.get("special_info") else "" self.__db_info = f" [{SpecialInfoFormatter.format_database_info(extractor.get('movie_db'))}]" if extractor.get("movie_db") else "" self.__extension = extractor.get("extension") or "ext" diff --git a/renamer/screens.py b/renamer/screens.py index 06cf3b5..5ffd3c9 100644 --- a/renamer/screens.py +++ b/renamer/screens.py @@ -1,7 +1,7 @@ from textual.screen import Screen from textual.widgets import Input, Button, Static from textual.containers import Vertical, Horizontal, Center, Container -from rich.markup import escape +from textual.markup import escape from pathlib import Path @@ -97,18 +97,30 @@ class RenameConfirmScreen(Screen): #confirm_content { text-align: center; } - Button { - background: $surface; - border: solid $surface; - } + # Button { + # background: $surface; + # border: solid $surface; + # } Button:focus { - background: $primary; - color: $text-primary; - border: solid $primary; + background: $primary; + # color: $text-primary; + # border: solid $primary; } #buttons { align: center middle; } + #new_name_input { + width: 100%; + margin: 1 0; + } + #new_name_display { + text-align: center; + margin-bottom: 1; + } + #warning_content { + text-align: center; + margin-bottom: 0; + } """ def __init__(self, old_path: Path, new_name: str): @@ -123,17 +135,25 @@ class RenameConfirmScreen(Screen): confirm_text = f""" {TextFormatter.bold(TextFormatter.red("RENAME CONFIRMATION"))} -Current name: {TextFormatter.cyan(escape(self.old_path.name))} -New name: {TextFormatter.green(escape(self.new_name))} +RAW name: {escape(self.old_path.name)} -{TextFormatter.yellow("This action cannot be undone!")} +Current name: {TextFormatter.cyan(escape(self.old_path.name))} +Proposed name: {TextFormatter.green(escape(self.new_name))} +{TextFormatter.yellow("Edit the new name below:")} + """.strip() + + warning_text = f""" +{TextFormatter.bold(TextFormatter.red("This action cannot be undone!"))} Do you want to proceed with renaming? """.strip() with Center(): with Vertical(): yield Static(confirm_text, id="confirm_content", markup=True) + yield Input(value=self.new_name, id="new_name_input", placeholder="New file name") + yield Static(f"{TextFormatter.green(escape(self.new_name))}", id="new_name_display", markup=True) + yield Static(warning_text, id="warning_content", markup=True) with Horizontal(id="buttons"): yield Button("Rename (y)", id="rename") yield Button("Cancel (n)", id="cancel") @@ -141,6 +161,15 @@ Do you want to proceed with renaming? def on_mount(self): self.set_focus(self.query_one("#rename")) + def on_input_changed(self, event): + if event.input.id == "new_name_input": + self.new_name = event.input.value + self.new_path = self.old_path.parent / self.new_name + # Update the display + from .formatters.text_formatter import TextFormatter + display = self.query_one("#new_name_display", Static) + display.update(f"{TextFormatter.green(escape(self.new_name))}") + def on_button_pressed(self, event): if event.button.id == "rename": try: @@ -156,10 +185,37 @@ Do you want to proceed with renaming? self.app.pop_screen() def on_key(self, event): - if event.key == "left": - self.set_focus(self.query_one("#rename")) - elif event.key == "right": - self.set_focus(self.query_one("#cancel")) + current = self.focused + if current and hasattr(current, 'id'): + if current.id == "new_name_input": + # When input is focused, let left/right move cursor, use up/down to change focus + if event.key == "up": + self.set_focus(self.query_one("#cancel")) + elif event.key == "down": + self.set_focus(self.query_one("#rename")) + elif current.id in ("rename", "cancel"): + if event.key == "left": + if current.id == "rename": + self.set_focus(self.query_one("#new_name_input")) + elif current.id == "cancel": + self.set_focus(self.query_one("#rename")) + elif event.key == "right": + if current.id == "new_name_input": + self.set_focus(self.query_one("#rename")) + elif current.id == "rename": + self.set_focus(self.query_one("#cancel")) + elif event.key == "up": + if current.id == "rename": + self.set_focus(self.query_one("#new_name_input")) + elif current.id == "cancel": + self.set_focus(self.query_one("#rename")) + elif event.key == "down": + if current.id == "new_name_input": + self.set_focus(self.query_one("#rename")) + elif current.id == "rename": + self.set_focus(self.query_one("#cancel")) + elif current.id == "cancel": + self.set_focus(self.query_one("#new_name_input")) elif event.key == "y": # Trigger rename try: diff --git "a/renamer/test/filenames/Big Mommas. Like Father, Like Son (2011) \\[Theatrical Cut] BDRemux [1080p,ukr,3eng].mkv" "b/renamer/test/filenames/Big Mommas. Like Father, Like Son (2011) \\[Theatrical Cut] BDRemux [1080p,ukr,3eng].mkv" new file mode 100644 index 0000000..e69de29 diff --git a/uv.lock b/uv.lock index a0c92fa..d5064b0 100644 --- a/uv.lock +++ b/uv.lock @@ -164,7 +164,7 @@ wheels = [ [[package]] name = "renamer" -version = "0.2.12" +version = "0.3.1" source = { editable = "." } dependencies = [ { name = "langcodes" },