feat: Add line numbers with color-coded display and toggle option
This commit is contained in:
parent
cfa96a436f
commit
e4b65b98d1
47
gtm
47
gtm
|
|
@ -133,6 +133,9 @@ class AppState:
|
|||
# Line wrapping settings
|
||||
wrap_lines: bool = True
|
||||
|
||||
# Line numbers settings
|
||||
show_line_numbers: bool = False
|
||||
|
||||
# Change navigation
|
||||
change_blocks: List[Tuple[int, int]] = field(default_factory=list) # (start_line, end_line) of each change block
|
||||
current_change_idx: int = -1 # -1 means no change is selected
|
||||
|
|
@ -356,6 +359,18 @@ def jump_to_prev_change(state: AppState) -> AppState:
|
|||
def draw_right_pane(stdscr, state):
|
||||
# If sidebar is hidden, right pane starts at column 0
|
||||
right_start = 0 if not state.show_sidebar else state.divider_col + 2
|
||||
|
||||
# Calculate line number width if enabled
|
||||
line_num_width = 0
|
||||
if state.show_line_numbers:
|
||||
# Width based on the number of digits in the largest line number
|
||||
max_line_num = len(state.file_lines)
|
||||
line_num_width = len(str(max_line_num)) + 1 # +1 for spacing
|
||||
|
||||
# Adjust right pane start position and width for line numbers
|
||||
if state.show_line_numbers:
|
||||
right_start += line_num_width
|
||||
|
||||
right_width = state.width - right_start - 1
|
||||
|
||||
max_scroll = max(0, len(state.file_lines) - (state.height - 1))
|
||||
|
|
@ -375,7 +390,8 @@ def draw_right_pane(stdscr, state):
|
|||
line_num = i + state.right_scroll_offset + 1
|
||||
if (state.show_whole_diff or 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})
|
||||
# For deleted lines, use the same line number
|
||||
display_lines.append({'type': 'deleted', 'content': del_content, 'line_num': line_num})
|
||||
|
||||
is_added = False
|
||||
if state.show_whole_diff or state.show_additions:
|
||||
|
|
@ -384,7 +400,7 @@ def draw_right_pane(stdscr, state):
|
|||
is_added = True
|
||||
break
|
||||
|
||||
display_lines.append({'type': 'added' if is_added else 'regular', 'content': line})
|
||||
display_lines.append({'type': 'added' if is_added else 'regular', 'content': line, 'line_num': line_num})
|
||||
|
||||
display_row = 0
|
||||
for line_info in display_lines:
|
||||
|
|
@ -393,6 +409,20 @@ def draw_right_pane(stdscr, state):
|
|||
|
||||
line_type = line_info['type']
|
||||
content = line_info['content']
|
||||
line_num = line_info.get('line_num', 0)
|
||||
|
||||
# Draw line number if enabled
|
||||
if state.show_line_numbers:
|
||||
line_num_str = str(line_num).rjust(line_num_width - 1) + " "
|
||||
line_num_pos = (0 if not state.show_sidebar else state.divider_col + 2)
|
||||
|
||||
# Use different color for line numbers
|
||||
if line_type == 'added':
|
||||
stdscr.addstr(display_row, line_num_pos, line_num_str, curses.color_pair(5))
|
||||
elif line_type == 'deleted':
|
||||
stdscr.addstr(display_row, line_num_pos, line_num_str, curses.color_pair(6))
|
||||
else:
|
||||
stdscr.addstr(display_row, line_num_pos, line_num_str, curses.color_pair(7))
|
||||
|
||||
# Determine prefix based on line type and diff mode
|
||||
prefix = ""
|
||||
|
|
@ -528,13 +558,14 @@ def draw_status_bars(stdscr, state):
|
|||
if len(parts) >= 4:
|
||||
commit_message = parts[3]
|
||||
|
||||
# Add wrap indicator and change position to commit message
|
||||
# Add indicators to commit message
|
||||
wrap_indicator = "" if state.wrap_lines else "[NW] "
|
||||
line_num_indicator = "[LN] " if state.show_line_numbers else ""
|
||||
change_indicator = ""
|
||||
if state.change_blocks and state.current_change_idx != -1:
|
||||
change_indicator = f"[Change {state.current_change_idx + 1}/{len(state.change_blocks)}] "
|
||||
|
||||
commit_message = wrap_indicator + change_indicator + commit_message
|
||||
commit_message = wrap_indicator + line_num_indicator + change_indicator + commit_message
|
||||
|
||||
# Status bar percentages
|
||||
if len(state.file_lines) > 0:
|
||||
|
|
@ -814,6 +845,8 @@ def handle_keyboard_input(key, state: AppState) -> AppState:
|
|||
return toggle_sidebar(state)
|
||||
elif key == ord('w'):
|
||||
return replace(state, wrap_lines=not state.wrap_lines)
|
||||
elif key == ord('L'): # Capital L to toggle line numbers
|
||||
return replace(state, show_line_numbers=not state.show_line_numbers)
|
||||
elif key in [110, ord('n')]: # ASCII code for 'n'
|
||||
if state.show_whole_diff or state.show_additions or state.show_deletions:
|
||||
return jump_to_next_change(state)
|
||||
|
|
@ -864,6 +897,9 @@ def main(stdscr, filename, show_diff, show_add, show_del, mouse, wrap_lines=True
|
|||
curses.init_pair(2, curses.COLOR_WHITE, 0) # Inactive pane: white on black
|
||||
curses.init_pair(3, curses.COLOR_GREEN, -1) # Added lines
|
||||
curses.init_pair(4, curses.COLOR_RED, -1) # Deleted lines
|
||||
curses.init_pair(5, curses.COLOR_GREEN, -1) # Line numbers for added lines
|
||||
curses.init_pair(6, curses.COLOR_RED, -1) # Line numbers for deleted lines
|
||||
curses.init_pair(7, curses.COLOR_BLUE, -1) # Regular line numbers
|
||||
|
||||
height, width = stdscr.getmaxyx()
|
||||
state = AppState(
|
||||
|
|
@ -930,6 +966,7 @@ if __name__ == "__main__":
|
|||
parser.add_argument("--diff-deletions", action="store_true", help="Show deleted lines in red")
|
||||
parser.add_argument("--no-mouse", action="store_true", help="Disable mouse support")
|
||||
parser.add_argument("--no-wrap", action="store_true", help="Disable line wrapping")
|
||||
parser.add_argument("--line-numbers", action="store_true", help="Show line numbers")
|
||||
parser.add_argument("-v", "--version", action="store_true", help="Show version number")
|
||||
parser.add_argument("filename", nargs="?", help="File to view history for")
|
||||
|
||||
|
|
@ -956,4 +993,4 @@ if __name__ == "__main__":
|
|||
print(f" git commit -m 'Add {os.path.basename(filename)}'")
|
||||
sys.exit(1)
|
||||
|
||||
curses.wrapper(main, filename, args.diff, args.diff_additions, args.diff_deletions, not args.no_mouse, not args.no_wrap)
|
||||
curses.wrapper(main, filename, args.diff, args.diff_additions, args.diff_deletions, not args.no_mouse, not args.no_wrap, args.line_numbers)
|
||||
|
|
|
|||
Loading…
Reference in New Issue