feat: Implement line wrapping with toggle and CLI option

This commit is contained in:
n loewen (aider) 2025-06-08 01:49:10 +01:00
parent cc25765a41
commit a39c28c099
1 changed files with 60 additions and 13 deletions

73
gtm
View File

@ -123,6 +123,9 @@ class AppState:
last_bstate: int = 0 last_bstate: int = 0
mouse_x: int = -1 mouse_x: int = -1
mouse_y: int = -1 mouse_y: int = -1
# Line wrapping settings
wrap_lines: bool = True
# --- Actions (Controller) --- # --- Actions (Controller) ---
@ -272,21 +275,57 @@ def draw_right_pane(stdscr, state):
line_type = line_info['type'] line_type = line_info['type']
content = line_info['content'] content = line_info['content']
# Determine prefix based on line type and diff mode
prefix = ""
if line_type == 'added': if line_type == 'added':
stdscr.addstr(display_row, right_start, "+ ", curses.color_pair(3)) prefix = "+ "
stdscr.addnstr(display_row, right_start + 2, content, right_width - 2, curses.color_pair(3)) attr = curses.color_pair(3)
elif line_type == 'deleted': elif line_type == 'deleted':
stdscr.addstr(display_row, right_start, "- ", curses.color_pair(4)) prefix = "- "
stdscr.addnstr(display_row, right_start + 2, content, right_width - 2, curses.color_pair(4)) attr = curses.color_pair(4)
else: else:
if state.show_whole_diff or state.show_additions or state.show_deletions: if state.show_whole_diff or state.show_additions or state.show_deletions:
stdscr.addstr(display_row, right_start, " ") prefix = " "
stdscr.addnstr(display_row, right_start + 2, content, right_width - 2) attr = curses.A_NORMAL
else:
# No diff mode, so don't add the margin padding
stdscr.addnstr(display_row, right_start, content, right_width)
display_row += 1 # Calculate available width for content
content_start = right_start + len(prefix)
available_width = right_width - len(prefix)
# Handle line wrapping
if len(content) <= available_width:
# Line fits, no wrapping needed
if prefix:
stdscr.addstr(display_row, right_start, prefix, attr)
stdscr.addnstr(display_row, content_start, content, available_width, attr)
display_row += 1
else:
# Line needs wrapping
remaining = content
first_line = True
while remaining and display_row < state.height - 2:
# For first line, add the prefix
if first_line:
if prefix:
stdscr.addstr(display_row, right_start, prefix, attr)
chunk = remaining[:available_width]
stdscr.addnstr(display_row, content_start, chunk, available_width, attr)
remaining = remaining[available_width:]
first_line = False
else:
# For continuation lines, indent by 2 spaces
indent = " "
indent_start = right_start
content_start = indent_start + len(indent)
wrap_width = right_width - len(indent)
stdscr.addstr(display_row, indent_start, indent)
chunk = remaining[:wrap_width]
stdscr.addnstr(display_row, content_start, chunk, wrap_width, attr)
remaining = remaining[wrap_width:]
display_row += 1
def draw_divider(stdscr, state): def draw_divider(stdscr, state):
if not state.show_sidebar: if not state.show_sidebar:
@ -364,6 +403,10 @@ def draw_status_bars(stdscr, state):
if len(parts) >= 4: if len(parts) >= 4:
commit_message = parts[3] commit_message = parts[3]
# Add wrap indicator to commit message
wrap_indicator = " [W] " if state.wrap_lines else " [NW] "
commit_message = wrap_indicator + commit_message
# Status bar percentages # Status bar percentages
if len(state.file_lines) > 0: if len(state.file_lines) > 0:
last_visible_line = state.right_scroll_offset + visible_height last_visible_line = state.right_scroll_offset + visible_height
@ -587,6 +630,8 @@ def handle_keyboard_input(key, state: AppState) -> AppState:
return replace(state, should_exit=True) return replace(state, should_exit=True)
elif key == ord('s'): elif key == ord('s'):
return toggle_sidebar(state) return toggle_sidebar(state)
elif key == ord('w'):
return replace(state, wrap_lines=not state.wrap_lines)
elif key in [curses.KEY_LEFT, ord('h')]: elif key in [curses.KEY_LEFT, ord('h')]:
if state.show_sidebar: if state.show_sidebar:
return replace(state, focus="left") return replace(state, focus="left")
@ -616,7 +661,7 @@ def handle_keyboard_input(key, state: AppState) -> AppState:
# --- Main Application --- # --- Main Application ---
def main(stdscr, filename, show_diff, show_add, show_del, mouse): def main(stdscr, filename, show_diff, show_add, show_del, mouse, wrap_lines=True):
try: try:
curses.curs_set(0) curses.curs_set(0)
except: except:
@ -637,7 +682,8 @@ def main(stdscr, filename, show_diff, show_add, show_del, mouse):
filename=filename, width=width, height=height, filename=filename, width=width, height=height,
show_whole_diff=show_diff, show_additions=show_add, show_whole_diff=show_diff, show_additions=show_add,
show_deletions=show_del, enable_mouse=mouse, show_deletions=show_del, enable_mouse=mouse,
commits=get_commits(filename) commits=get_commits(filename),
wrap_lines=wrap_lines
) )
if state.enable_mouse: if state.enable_mouse:
@ -695,6 +741,7 @@ if __name__ == "__main__":
parser.add_argument("--diff-additions", action="store_true", help="Highlight newly added lines in green") parser.add_argument("--diff-additions", action="store_true", help="Highlight newly added lines in green")
parser.add_argument("--diff-deletions", action="store_true", help="Show deleted lines in red") 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-mouse", action="store_true", help="Disable mouse support")
parser.add_argument("--no-wrap", action="store_true", help="Disable line wrapping")
parser.add_argument("-v", "--version", action="store_true", help="Show version number") parser.add_argument("-v", "--version", action="store_true", help="Show version number")
parser.add_argument("filename", nargs="?", help="File to view history for") parser.add_argument("filename", nargs="?", help="File to view history for")
@ -713,4 +760,4 @@ if __name__ == "__main__":
print(f"Error: File '{filename}' does not exist") print(f"Error: File '{filename}' does not exist")
sys.exit(1) sys.exit(1)
curses.wrapper(main, filename, args.diff, args.diff_additions, args.diff_deletions, not args.no_mouse) curses.wrapper(main, filename, args.diff, args.diff_additions, args.diff_deletions, not args.no_mouse, not args.no_wrap)