diff --git a/gtm b/gtm index fffd13e..a4945bb 100755 --- a/gtm +++ b/gtm @@ -183,6 +183,10 @@ class AppState: mouse_x: 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 wrap_lines: bool = True @@ -963,7 +967,18 @@ def draw_commit_details(stdscr, state: AppState, layout: StatusBarLayout): # Draw the commit hash at the start 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 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 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: return replace(state, dragging_divider=True) elif my == status_bar_start: @@ -1227,6 +1249,25 @@ def handle_mouse_input(stdscr, state: AppState) -> AppState: # Handle mouse button release 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: return replace(state, dragging_divider=False) elif state.dragging_status_bar: