refactor: Improve diff parsing and display logic for deleted and added lines

This commit is contained in:
n loewen (aider) 2025-06-07 20:04:30 +01:00
parent 794f6d0716
commit 90a9f311fc
1 changed files with 56 additions and 45 deletions

101
gtm
View File

@ -24,49 +24,58 @@ def get_diff_info(current_commit, prev_commit, filename):
# For the first commit, we can't compare with a previous one # For the first commit, we can't compare with a previous one
return [], [] return [], []
# Get additions # Use a more detailed diff format to better understand the changes
cmd_additions = ['git', 'diff', '--unified=0', prev_commit, current_commit, '--', filename] cmd = ['git', 'diff', prev_commit, current_commit, '--', filename]
result_additions = subprocess.run(cmd_additions, capture_output=True, text=True) result = subprocess.run(cmd, capture_output=True, text=True)
# Parse the diff output to extract added and deleted lines
lines = result.stdout.splitlines()
# Store line changes with their positions
added_lines = [] added_lines = []
deleted_lines = [] deleted_lines = []
# Initialize variables outside the loop to avoid UnboundLocalError # Track the current position in the new file
start_line = 0 current_line_num = 0
del_start = 0 deletion_offset = 0
for line in result_additions.stdout.splitlines(): # Parse the diff output
# Parse the diff output to find line numbers of additions and deletions i = 0
while i < len(lines):
line = lines[i]
# Parse hunk headers to get line numbers
if line.startswith('@@'): if line.startswith('@@'):
# Parse the hunk header to get line numbers # Format is like @@ -a,b +c,d @@
parts = line.split() parts = line.split()
if len(parts) >= 3: if len(parts) >= 3:
# Format is like @@ -a,b +c,d @@ # Extract the starting line number in the new file
# We're interested in the +c,d part for additions
add_part = parts[2][1:] # Remove the + sign add_part = parts[2][1:] # Remove the + sign
if ',' in add_part: if ',' in add_part:
start_line, count = map(int, add_part.split(',')) current_line_num, _ = map(int, add_part.split(','))
else: else:
start_line, count = int(add_part), 1 current_line_num = int(add_part)
# For deletions, we look at the -a,b part # Reset deletion offset for this hunk
del_part = parts[1][1:] # Remove the - sign deletion_offset = 0
if ',' in del_part:
del_start, del_count = map(int, del_part.split(',')) # Process added lines
else:
del_start, del_count = int(del_part), 1
elif line.startswith('+') and not line.startswith('+++'): elif line.startswith('+') and not line.startswith('+++'):
# This is an added line added_lines.append((current_line_num, line[1:]))
added_lines.append((start_line, line[1:])) current_line_num += 1
start_line += 1
# Process deleted lines
elif line.startswith('-') and not line.startswith('---'): elif line.startswith('-') and not line.startswith('---'):
# This is a deleted line # Store deleted lines with the position where they would have been
deleted_lines.append((del_start, line[1:])) # in the new file (before the next line)
del_start += 1 deleted_lines.append((current_line_num, line[1:]))
deletion_offset += 1
# Process context lines
elif not line.startswith('+') and not line.startswith('-') and not line.startswith('@@'): elif not line.startswith('+') and not line.startswith('-') and not line.startswith('@@'):
# Context line, increment both counters current_line_num += 1
start_line += 1
del_start += 1 i += 1
return added_lines, deleted_lines return added_lines, deleted_lines
@ -167,12 +176,30 @@ def main(stdscr, filename, show_additions=False, show_deletions=False):
# Draw file content (right pane) - more efficiently # Draw file content (right pane) - more efficiently
right_width = width - divider_col - 3 right_width = width - divider_col - 3
# First, collect all lines to display (regular and deleted) # First, collect all lines to display (regular, added, and deleted)
display_lines = [] display_lines = []
# Create a map of line numbers to deleted lines for faster lookup
deleted_line_map = {}
if show_deletions:
for del_line_num, del_content in deleted_lines:
if del_line_num not in deleted_line_map:
deleted_line_map[del_line_num] = []
deleted_line_map[del_line_num].append(del_content)
# Process each visible line
for i, line in enumerate(visible_lines): for i, line in enumerate(visible_lines):
line_num = i + scroll_offset + 1 # 1-based line number line_num = i + scroll_offset + 1 # 1-based line number
# First add any deleted lines that come before this line
if 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,
'line_num': line_num
})
# Check if this is an added line # Check if this is an added line
is_added = False is_added = False
if show_additions: if show_additions:
@ -188,22 +215,6 @@ def main(stdscr, filename, show_additions=False, show_deletions=False):
'line_num': line_num 'line_num': line_num
}) })
# If showing deletions, check if there are deleted lines at this position
if show_deletions:
# Collect all deleted lines at this position
deleted_at_position = []
for del_line_num, del_line_content in deleted_lines:
if del_line_num == line_num:
deleted_at_position.append(del_line_content)
# Add all deleted lines together after the current line
for del_content in deleted_at_position:
display_lines.append({
'type': 'deleted',
'content': del_content,
'line_num': line_num
})
# Now display all lines # Now display all lines
display_row = 0 display_row = 0
for line_info in display_lines: for line_info in display_lines: