From 90a9f311fcac66460c5a0a589e8a261eb5335c92 Mon Sep 17 00:00:00 2001 From: "n loewen (aider)" Date: Sat, 7 Jun 2025 20:04:30 +0100 Subject: [PATCH] refactor: Improve diff parsing and display logic for deleted and added lines --- gtm | 101 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/gtm b/gtm index 2416ce0..e9101af 100755 --- a/gtm +++ b/gtm @@ -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 return [], [] - # Get additions - cmd_additions = ['git', 'diff', '--unified=0', prev_commit, current_commit, '--', filename] - result_additions = subprocess.run(cmd_additions, capture_output=True, text=True) + # Use a more detailed diff format to better understand the changes + cmd = ['git', 'diff', prev_commit, current_commit, '--', filename] + 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 = [] deleted_lines = [] - # Initialize variables outside the loop to avoid UnboundLocalError - start_line = 0 - del_start = 0 + # Track the current position in the new file + current_line_num = 0 + deletion_offset = 0 - for line in result_additions.stdout.splitlines(): - # Parse the diff output to find line numbers of additions and deletions + # Parse the diff output + i = 0 + while i < len(lines): + line = lines[i] + + # Parse hunk headers to get line numbers if line.startswith('@@'): - # Parse the hunk header to get line numbers + # Format is like @@ -a,b +c,d @@ parts = line.split() if len(parts) >= 3: - # Format is like @@ -a,b +c,d @@ - # We're interested in the +c,d part for additions + # Extract the starting line number in the new file add_part = parts[2][1:] # Remove the + sign if ',' in add_part: - start_line, count = map(int, add_part.split(',')) + current_line_num, _ = map(int, add_part.split(',')) else: - start_line, count = int(add_part), 1 + current_line_num = int(add_part) - # For deletions, we look at the -a,b part - del_part = parts[1][1:] # Remove the - sign - if ',' in del_part: - del_start, del_count = map(int, del_part.split(',')) - else: - del_start, del_count = int(del_part), 1 + # Reset deletion offset for this hunk + deletion_offset = 0 + + # Process added lines elif line.startswith('+') and not line.startswith('+++'): - # This is an added line - added_lines.append((start_line, line[1:])) - start_line += 1 + added_lines.append((current_line_num, line[1:])) + current_line_num += 1 + + # Process deleted lines elif line.startswith('-') and not line.startswith('---'): - # This is a deleted line - deleted_lines.append((del_start, line[1:])) - del_start += 1 + # Store deleted lines with the position where they would have been + # in the new file (before the next line) + 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('@@'): - # Context line, increment both counters - start_line += 1 - del_start += 1 + current_line_num += 1 + + i += 1 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 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 = [] + # 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): 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 is_added = False if show_additions: @@ -187,22 +214,6 @@ def main(stdscr, filename, show_additions=False, show_deletions=False): 'content': line, '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 display_row = 0