feat: Add commit hash click-to-copy functionality with visual feedback

This commit is contained in:
n loewen (aider) 2025-06-08 10:06:47 +01:00
parent 7304451f3f
commit ecb452990b
1 changed files with 42 additions and 1 deletions

43
gtm
View File

@ -183,6 +183,10 @@ class AppState:
mouse_x: int = -1 mouse_x: int = -1
mouse_y: int = -1 mouse_y: int = -1
# Commit hash click tracking
commit_hash_clicked: bool = False
commit_hash_area: Optional[Tuple[int, int, int, int]] = None # (start_x, end_x, start_y, end_y)
# Line wrapping settings # Line wrapping settings
wrap_lines: bool = True wrap_lines: bool = True
@ -963,7 +967,18 @@ def draw_commit_details(stdscr, state: AppState, layout: StatusBarLayout):
# Draw the commit hash at the start # Draw the commit hash at the start
commit_info = f" {state.commit_hash} " commit_info = f" {state.commit_hash} "
stdscr.addstr(second_line, 0, commit_info, curses.A_REVERSE) # | curses.A_BOLD) hash_length = len(commit_info)
# Store the commit hash area for click detection
state.commit_hash_area = (0, hash_length - 1, second_line, second_line)
# Use different style when the hash is being clicked
if state.commit_hash_clicked:
# When clicked, show in normal video (not reversed)
stdscr.addstr(second_line, 0, commit_info, curses.A_BOLD)
else:
# Normal display: reverse video
stdscr.addstr(second_line, 0, commit_info, curses.A_REVERSE | curses.A_BOLD)
# Calculate the author and branch info, ensuring it always fits # Calculate the author and branch info, ensuring it always fits
author_branch_info = f" {state.commit_author} [{state.commit_branch}] " author_branch_info = f" {state.commit_author} [{state.commit_branch}] "
@ -1208,6 +1223,13 @@ def handle_mouse_input(stdscr, state: AppState) -> AppState:
# Handle mouse button press # Handle mouse button press
if bstate & curses.BUTTON1_PRESSED: if bstate & curses.BUTTON1_PRESSED:
# Check if click is on the commit hash
if state.commit_hash_area and state.commit_hash:
hash_start_x, hash_end_x, hash_start_y, hash_end_y = state.commit_hash_area
if hash_start_x <= mx <= hash_end_x and hash_start_y <= my <= hash_end_y:
# Clicked on commit hash
return replace(state, commit_hash_clicked=True)
if state.show_sidebar and abs(mx - state.divider_col) <= 1: if state.show_sidebar and abs(mx - state.divider_col) <= 1:
return replace(state, dragging_divider=True) return replace(state, dragging_divider=True)
elif my == status_bar_start: elif my == status_bar_start:
@ -1227,6 +1249,25 @@ def handle_mouse_input(stdscr, state: AppState) -> AppState:
# Handle mouse button release # Handle mouse button release
if bstate & curses.BUTTON1_RELEASED: if bstate & curses.BUTTON1_RELEASED:
if state.commit_hash_clicked:
# Copy commit hash to clipboard
if state.commit_hash:
try:
subprocess.run(['pbcopy'], input=state.commit_hash, text=True, check=True)
except (FileNotFoundError, subprocess.CalledProcessError):
try:
# Try xclip for Linux systems
subprocess.run(['xclip', '-selection', 'clipboard'], input=state.commit_hash, text=True, check=True)
except (FileNotFoundError, subprocess.CalledProcessError):
try:
# Try clip.exe for Windows
subprocess.run(['clip.exe'], input=state.commit_hash, text=True, check=True)
except (FileNotFoundError, subprocess.CalledProcessError):
pass # Silently fail if no clipboard command is available
# Reset the clicked state
return replace(state, commit_hash_clicked=False)
if state.dragging_divider: if state.dragging_divider:
return replace(state, dragging_divider=False) return replace(state, dragging_divider=False)
elif state.dragging_status_bar: elif state.dragging_status_bar: