diff --git a/gtm b/gtm index a662e6a..15d88f2 100755 --- a/gtm +++ b/gtm @@ -123,6 +123,9 @@ class AppState: last_bstate: int = 0 mouse_x: int = -1 mouse_y: int = -1 + + # Line wrapping settings + wrap_lines: bool = True # --- Actions (Controller) --- @@ -272,21 +275,57 @@ def draw_right_pane(stdscr, state): line_type = line_info['type'] content = line_info['content'] + # Determine prefix based on line type and diff mode + prefix = "" if line_type == 'added': - stdscr.addstr(display_row, right_start, "+ ", curses.color_pair(3)) - stdscr.addnstr(display_row, right_start + 2, content, right_width - 2, curses.color_pair(3)) + prefix = "+ " + attr = curses.color_pair(3) elif line_type == 'deleted': - stdscr.addstr(display_row, right_start, "- ", curses.color_pair(4)) - stdscr.addnstr(display_row, right_start + 2, content, right_width - 2, curses.color_pair(4)) + prefix = "- " + attr = curses.color_pair(4) else: if state.show_whole_diff or state.show_additions or state.show_deletions: - stdscr.addstr(display_row, right_start, " ") - stdscr.addnstr(display_row, right_start + 2, content, right_width - 2) - else: - # No diff mode, so don't add the margin padding - stdscr.addnstr(display_row, right_start, content, right_width) + prefix = " " + attr = curses.A_NORMAL - 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): if not state.show_sidebar: @@ -364,6 +403,10 @@ def draw_status_bars(stdscr, state): if len(parts) >= 4: 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 if len(state.file_lines) > 0: 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) elif key == ord('s'): 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')]: if state.show_sidebar: return replace(state, focus="left") @@ -616,7 +661,7 @@ def handle_keyboard_input(key, state: AppState) -> AppState: # --- 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: curses.curs_set(0) except: @@ -637,7 +682,8 @@ def main(stdscr, filename, show_diff, show_add, show_del, mouse): filename=filename, width=width, height=height, show_whole_diff=show_diff, show_additions=show_add, show_deletions=show_del, enable_mouse=mouse, - commits=get_commits(filename) + commits=get_commits(filename), + wrap_lines=wrap_lines ) 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-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("-v", "--version", action="store_true", help="Show version number") 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") 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)