fix: Improve text selection and clipboard handling
This commit is contained in:
parent
bc10b41059
commit
b8f49880f7
75
gtm
75
gtm
|
|
@ -351,7 +351,9 @@ def toggle_sidebar(state: AppState) -> AppState:
|
|||
def move_commit_selection(state: AppState, delta: int) -> AppState:
|
||||
new_idx = state.selected_commit_idx + delta
|
||||
if 0 <= new_idx < len(state.commits):
|
||||
new_state = replace(state, selected_commit_idx=new_idx)
|
||||
# Clear selection when changing commits
|
||||
new_state = replace(state, selected_commit_idx=new_idx, is_selecting=False,
|
||||
selection_start_coord=None, selection_end_coord=None, click_position=None)
|
||||
return load_commit_content(new_state)
|
||||
return state
|
||||
|
||||
|
|
@ -371,6 +373,11 @@ def scroll_right_pane(state: AppState, delta: int) -> AppState:
|
|||
new_offset = state.right_scroll_offset + delta
|
||||
new_offset = max(0, min(new_offset, max_scroll))
|
||||
|
||||
# Clear selection when scrolling
|
||||
if state.is_selecting:
|
||||
return replace(state, right_scroll_offset=new_offset, is_selecting=False,
|
||||
selection_start_coord=None, selection_end_coord=None, click_position=None)
|
||||
|
||||
return replace(state, right_scroll_offset=new_offset)
|
||||
|
||||
def page_right_pane(state: AppState, direction: int) -> AppState:
|
||||
|
|
@ -1152,13 +1159,13 @@ def copy_selection_to_clipboard(stdscr, state):
|
|||
line_num = i + state.right_scroll_offset + 1
|
||||
|
||||
# Add deleted lines if they should be shown
|
||||
if (state.show_whole_diff or state.show_deletions) and line_num in deleted_line_map:
|
||||
if state.show_deletions and line_num in deleted_line_map:
|
||||
for del_content in deleted_line_map[line_num]:
|
||||
display_lines.append({'type': 'deleted', 'content': del_content})
|
||||
|
||||
# Determine if this is an added line
|
||||
is_added = False
|
||||
if state.show_whole_diff or state.show_additions:
|
||||
if state.show_additions:
|
||||
for added_line_num, _ in state.added_lines:
|
||||
if added_line_num == line_num:
|
||||
is_added = True
|
||||
|
|
@ -1204,18 +1211,37 @@ def copy_selection_to_clipboard(stdscr, state):
|
|||
if selected_text_parts:
|
||||
text_to_copy = "\n".join(selected_text_parts)
|
||||
if text_to_copy.strip():
|
||||
# Log the text being copied for debugging
|
||||
with open("/tmp/gtm_clipboard.log", "w") as f:
|
||||
f.write(f"Copying to clipboard: {text_to_copy}\n")
|
||||
|
||||
# Try macOS pbcopy first (most likely on this system)
|
||||
try:
|
||||
subprocess.run(['pbcopy'], input=text_to_copy, text=True, check=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
try:
|
||||
# Try xclip for Linux systems
|
||||
subprocess.run(['xclip', '-selection', 'clipboard'], input=text_to_copy, text=True, check=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
try:
|
||||
# Try clip.exe for Windows
|
||||
subprocess.run(['clip.exe'], input=text_to_copy, text=True, check=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
pass # Silently fail if no clipboard command is available
|
||||
proc = subprocess.Popen(['pbcopy'], stdin=subprocess.PIPE)
|
||||
proc.communicate(text_to_copy.encode('utf-8'))
|
||||
proc.wait()
|
||||
return # Return early if successful
|
||||
except (FileNotFoundError, subprocess.SubprocessError):
|
||||
pass
|
||||
|
||||
# Try Linux xclip
|
||||
try:
|
||||
proc = subprocess.Popen(['xclip', '-selection', 'clipboard'], stdin=subprocess.PIPE)
|
||||
proc.communicate(text_to_copy.encode('utf-8'))
|
||||
proc.wait()
|
||||
return # Return early if successful
|
||||
except (FileNotFoundError, subprocess.SubprocessError):
|
||||
pass
|
||||
|
||||
# Try Windows clip.exe
|
||||
try:
|
||||
proc = subprocess.Popen(['clip.exe'], stdin=subprocess.PIPE)
|
||||
proc.communicate(text_to_copy.encode('utf-8'))
|
||||
proc.wait()
|
||||
except (FileNotFoundError, subprocess.SubprocessError):
|
||||
# Log failure
|
||||
with open("/tmp/gtm_clipboard.log", "a") as f:
|
||||
f.write("Failed to copy to clipboard - no clipboard command available\n")
|
||||
|
||||
def update_status_bar_height(state: AppState, my: int) -> AppState:
|
||||
"""Update the status bar height based on mouse position."""
|
||||
|
|
@ -1275,17 +1301,24 @@ def handle_mouse_input(stdscr, state: AppState) -> AppState:
|
|||
if state.commit_hash_clicked:
|
||||
# Copy commit hash to clipboard
|
||||
if state.commit_hash:
|
||||
# Try macOS pbcopy first (most likely on this system)
|
||||
try:
|
||||
subprocess.run(['pbcopy'], input=state.commit_hash, text=True, check=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
proc = subprocess.Popen(['pbcopy'], stdin=subprocess.PIPE)
|
||||
proc.communicate(state.commit_hash.encode('utf-8'))
|
||||
proc.wait()
|
||||
except (FileNotFoundError, subprocess.SubprocessError):
|
||||
try:
|
||||
# Try xclip for Linux systems
|
||||
subprocess.run(['xclip', '-selection', 'clipboard'], input=state.commit_hash, text=True, check=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
proc = subprocess.Popen(['xclip', '-selection', 'clipboard'], stdin=subprocess.PIPE)
|
||||
proc.communicate(state.commit_hash.encode('utf-8'))
|
||||
proc.wait()
|
||||
except (FileNotFoundError, subprocess.SubprocessError):
|
||||
try:
|
||||
# Try clip.exe for Windows
|
||||
subprocess.run(['clip.exe'], input=state.commit_hash, text=True, check=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
proc = subprocess.Popen(['clip.exe'], stdin=subprocess.PIPE)
|
||||
proc.communicate(state.commit_hash.encode('utf-8'))
|
||||
proc.wait()
|
||||
except (FileNotFoundError, subprocess.SubprocessError):
|
||||
pass # Silently fail if no clipboard command is available
|
||||
|
||||
# Reset the clicked state
|
||||
|
|
@ -1356,7 +1389,7 @@ def handle_keyboard_input(key, state: AppState) -> AppState:
|
|||
if state.search_mode:
|
||||
new_state = replace(new_state, search_mode=False)
|
||||
elif state.is_selecting:
|
||||
new_state = replace(new_state, is_selecting=False, selection_start_coord=None, selection_end_coord=None)
|
||||
new_state = replace(new_state, is_selecting=False, selection_start_coord=None, selection_end_coord=None, click_position=None)
|
||||
|
||||
# Return the updated state with all changes
|
||||
return new_state
|
||||
|
|
|
|||
Loading…
Reference in New Issue