last commit

This commit is contained in:
rnsrk 2025-09-09 10:11:15 +02:00
parent 522298a6ec
commit 7ae62f426a

View file

@ -406,9 +406,19 @@ def draw_menu(stdscr, selector: ConfigSelector, selected_idx: int, view_mode: st
def add_prefix_dialog(stdscr): def add_prefix_dialog(stdscr):
"""Show dialog to add a new prefix.""" """Show dialog to add a new prefix."""
h, w = stdscr.getmaxyx() h, w = stdscr.getmaxyx()
dialog_h, dialog_w = 5, 50
dialog_y = (h - dialog_h) // 2 # Safety checks for minimum terminal size
dialog_x = (w - dialog_w) // 2 min_h, min_w = 7, 20
if h < min_h or w < min_w:
return "" # Terminal too small
dialog_h, dialog_w = min(5, h - 2), min(50, w - 4)
dialog_y = max(0, (h - dialog_h) // 2)
dialog_x = max(0, (w - dialog_w) // 2)
# Final safety check
if dialog_h <= 0 or dialog_w <= 0 or dialog_y < 0 or dialog_x < 0:
return ""
# Draw dialog box # Draw dialog box
dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x) dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
@ -416,8 +426,9 @@ def add_prefix_dialog(stdscr):
dialog_win.addstr(1, 2, "Enter new prefix (ESC or empty input to cancel):") dialog_win.addstr(1, 2, "Enter new prefix (ESC or empty input to cancel):")
dialog_win.refresh() dialog_win.refresh()
# Input field # Input field - ensure it fits within the dialog
input_win = curses.newwin(1, dialog_w - 6, dialog_y + 2, dialog_x + 3) input_w = max(1, dialog_w - 6)
input_win = curses.newwin(1, input_w, dialog_y + 2, dialog_x + 3)
input_win.clear() input_win.clear()
# Setup input mode # Setup input mode
@ -465,14 +476,29 @@ def add_prefix_dialog(stdscr):
def confirm_dialog(stdscr, message): def confirm_dialog(stdscr, message):
"""Show a confirmation dialog.""" """Show a confirmation dialog."""
h, w = stdscr.getmaxyx() h, w = stdscr.getmaxyx()
dialog_h, dialog_w = 5, 50
dialog_y = (h - dialog_h) // 2 # Safety checks for minimum terminal size
dialog_x = (w - dialog_w) // 2 min_h, min_w = 7, 20
if h < min_h or w < min_w:
return False # Terminal too small, default to cancel
dialog_h, dialog_w = min(5, h - 2), min(max(50, len(message) + 4), w - 4)
dialog_y = max(0, (h - dialog_h) // 2)
dialog_x = max(0, (w - dialog_w) // 2)
# Final safety check
if dialog_h <= 0 or dialog_w <= 0 or dialog_y < 0 or dialog_x < 0:
return False
# Draw dialog box # Draw dialog box
dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x) dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
dialog_win.box() dialog_win.box()
dialog_win.addstr(1, 2, message)
# Truncate message if it's too long for the dialog
max_msg_len = dialog_w - 4
display_message = message[:max_msg_len] if len(message) > max_msg_len else message
dialog_win.addstr(1, 2, display_message)
dialog_win.addstr(3, 2, "Press Y to confirm, any other key to cancel") dialog_win.addstr(3, 2, "Press Y to confirm, any other key to cancel")
dialog_win.refresh() dialog_win.refresh()
@ -488,19 +514,34 @@ def choose_prefix_dialog(stdscr, selector: ConfigSelector):
unmatched_prefixes = sorted(selector.unmatched_files.keys()) unmatched_prefixes = sorted(selector.unmatched_files.keys())
if not unmatched_prefixes: if not unmatched_prefixes:
# Show message if no unmatched prefixes # Show message if no unmatched prefixes - ensure minimum window size
message_win = curses.newwin(3, 40, (h - 3) // 2, (w - 40) // 2) msg_h = min(5, h - 2)
msg_w = min(40, w - 4)
if msg_h < 3 or msg_w < 10:
return None # Terminal too small
message_win = curses.newwin(msg_h, msg_w, max(0, (h - msg_h) // 2), max(0, (w - msg_w) // 2))
message_win.box() message_win.box()
message_win.addstr(1, 2, "No unmatched prefixes available.") message_win.addstr(1, 2, "No unmatched prefixes available.")
message_win.refresh() message_win.refresh()
message_win.getch() message_win.getch()
return None return None
# Calculate dialog dimensions # Calculate dialog dimensions with safety checks
dialog_h = min(15, len(unmatched_prefixes) + 4) # +4 for title, instructions, and border min_dialog_h = 6 # Minimum height for usable dialog
dialog_w = 60 min_dialog_w = 30 # Minimum width for usable dialog
dialog_y = (h - dialog_h) // 2
dialog_x = (w - dialog_w) // 2 # Ensure we have enough terminal space
if h < min_dialog_h + 2 or w < min_dialog_w + 4:
return None # Terminal too small
dialog_h = min(max(min_dialog_h, min(15, len(unmatched_prefixes) + 4)), h - 2) # +4 for title, instructions, and border
dialog_w = min(max(min_dialog_w, 60), w - 2)
dialog_y = max(0, (h - dialog_h) // 2)
dialog_x = max(0, (w - dialog_w) // 2)
# Final safety check
if dialog_h <= 0 or dialog_w <= 0 or dialog_y < 0 or dialog_x < 0:
return None
# Draw dialog box # Draw dialog box
dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x) dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
@ -580,8 +621,12 @@ def select_individual_files_dialog(stdscr, selector: ConfigSelector, prefix: str
action_text = "SPACE: Toggle selection | ENTER: Add selected | ESC: Cancel" action_text = "SPACE: Toggle selection | ENTER: Add selected | ESC: Cancel"
if not files: if not files:
# Show message if no files # Show message if no files - ensure minimum window size
message_win = curses.newwin(3, 40, (h - 3) // 2, (w - 40) // 2) msg_h = min(5, h - 2)
msg_w = min(40, w - 4)
if msg_h < 3 or msg_w < 10:
return [] # Terminal too small
message_win = curses.newwin(msg_h, msg_w, max(0, (h - msg_h) // 2), max(0, (w - msg_w) // 2))
message_win.box() message_win.box()
message_win.addstr(1, 2, "No files available.") message_win.addstr(1, 2, "No files available.")
message_win.refresh() message_win.refresh()
@ -594,11 +639,22 @@ def select_individual_files_dialog(stdscr, selector: ConfigSelector, prefix: str
# Track selected files # Track selected files
selected_files = set() selected_files = set()
# Calculate dialog dimensions # Calculate dialog dimensions with safety checks
dialog_h = min(20, len(files) + 5) # +5 for title, instructions, pagination, and border min_dialog_h = 8 # Minimum height for usable dialog
dialog_w = min(w - 4, 80) min_dialog_w = 30 # Minimum width for usable dialog
dialog_y = (h - dialog_h) // 2
dialog_x = (w - dialog_w) // 2 # Ensure we have enough terminal space
if h < min_dialog_h + 2 or w < min_dialog_w + 4:
return [] # Terminal too small
dialog_h = min(max(min_dialog_h, min(20, len(files) + 5)), h - 2) # +5 for title, instructions, pagination, and border
dialog_w = min(max(min_dialog_w, min(w - 4, 80)), w - 2)
dialog_y = max(0, (h - dialog_h) // 2)
dialog_x = max(0, (w - dialog_w) // 2)
# Final safety check
if dialog_h <= 0 or dialog_w <= 0 or dialog_y < 0 or dialog_x < 0:
return []
# Draw dialog box # Draw dialog box
dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x) dialog_win = curses.newwin(dialog_h, dialog_w, dialog_y, dialog_x)
@ -722,11 +778,20 @@ def preview_yaml_cleaning(stdscr, content):
"""Show a simplified schematic preview of the YAML cleaning process.""" """Show a simplified schematic preview of the YAML cleaning process."""
h, w = stdscr.getmaxyx() h, w = stdscr.getmaxyx()
# Safety checks for minimum terminal size
min_h, min_w = 10, 30
if h < min_h or w < min_w:
return # Terminal too small
# Calculate preview window size # Calculate preview window size
preview_h = min(12, h - 8) # Smaller height preview_h = min(max(8, min(12, h - 8)), h - 2) # Smaller height
preview_w = min(70, w - 4) preview_w = min(max(30, min(70, w - 4)), w - 2)
preview_y = (h - preview_h) // 2 preview_y = max(0, (h - preview_h) // 2)
preview_x = (w - preview_w) // 2 preview_x = max(0, (w - preview_w) // 2)
# Final safety check
if preview_h <= 0 or preview_w <= 0 or preview_y < 0 or preview_x < 0:
return
# Create window # Create window
preview_win = curses.newwin(preview_h, preview_w, preview_y, preview_x) preview_win = curses.newwin(preview_h, preview_w, preview_y, preview_x)
@ -797,11 +862,22 @@ def confirm_yaml_cleaning(stdscr, selector):
except Exception as e: except Exception as e:
# In case of error, just show a simple message # In case of error, just show a simple message
error_msg = f"Error reading sample file: {str(e)}" error_msg = f"Error reading sample file: {str(e)}"
message_win = curses.newwin(3, min(len(error_msg) + 4, w - 4), (h - 3) // 2, (w - min(len(error_msg) + 4, w - 4)) // 2) # Safety checks for window creation
message_win.box() if h >= 5 and w >= 20:
message_win.addstr(1, 2, error_msg[:w-8]) msg_h = min(3, h - 2)
message_win.refresh() msg_w = min(len(error_msg) + 4, w - 4)
message_win.getch() if msg_w < 10:
msg_w = min(20, w - 4)
msg_y = max(0, (h - msg_h) // 2)
msg_x = max(0, (w - msg_w) // 2)
if msg_h > 0 and msg_w > 0 and msg_y >= 0 and msg_x >= 0:
message_win = curses.newwin(msg_h, msg_w, msg_y, msg_x)
message_win.box()
display_msg = error_msg[:msg_w-4] if len(error_msg) > msg_w-4 else error_msg
message_win.addstr(1, 2, display_msg)
message_win.refresh()
message_win.getch()
return confirm_dialog(stdscr, "Copy all matched files to config directory and remove UUID and _core?") return confirm_dialog(stdscr, "Copy all matched files to config directory and remove UUID and _core?")
@ -995,11 +1071,21 @@ def main(stdscr):
else: else:
# Show message that you can only select files from complete prefixes # Show message that you can only select files from complete prefixes
h, w = stdscr.getmaxyx() h, w = stdscr.getmaxyx()
message_win = curses.newwin(3, 60, (h - 3) // 2, (w - 60) // 2) # Safety checks for window creation
message_win.box() if h >= 5 and w >= 30:
message_win.addstr(1, 2, "Can only select files from complete prefixes.") msg_h = min(3, h - 2)
message_win.refresh() msg_w = min(60, w - 4)
message_win.getch() if msg_w < 20:
msg_w = min(30, w - 4)
msg_y = max(0, (h - msg_h) // 2)
msg_x = max(0, (w - msg_w) // 2)
if msg_h > 0 and msg_w > 0 and msg_y >= 0 and msg_x >= 0:
message_win = curses.newwin(msg_h, msg_w, msg_y, msg_x)
message_win.box()
message_win.addstr(1, 2, "Can only select files from complete prefixes.")
message_win.refresh()
message_win.getch()
else: # Unmatched view else: # Unmatched view
# Find a matching prefix to add files to # Find a matching prefix to add files to
target_prefix = None target_prefix = None