Switch panes with arrow keys + status display for current line
This commit is contained in:
parent
29f0e7a28b
commit
01d24e0733
|
|
@ -1,4 +1,5 @@
|
||||||
# by ChatGPT
|
# by ChatGPT
|
||||||
|
|
||||||
import curses
|
import curses
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -28,8 +29,15 @@ def main(stdscr, filename):
|
||||||
stdscr.clear()
|
stdscr.clear()
|
||||||
height, width = stdscr.getmaxyx()
|
height, width = stdscr.getmaxyx()
|
||||||
|
|
||||||
# Draw commit list on the left
|
# Fetch file content for selected commit
|
||||||
for i in range(min(len(commits), height)):
|
commit_hash = commits[selected_commit].split()[0]
|
||||||
|
file_lines = get_file_at_commit(commit_hash, filename)
|
||||||
|
max_scroll = max(0, len(file_lines) - (height - 1))
|
||||||
|
scroll_offset = min(scroll_offset, max_scroll)
|
||||||
|
visible_lines = file_lines[scroll_offset:scroll_offset + height - 1]
|
||||||
|
|
||||||
|
# Draw commit list
|
||||||
|
for i in range(min(len(commits), height - 1)):
|
||||||
line = commits[i]
|
line = commits[i]
|
||||||
if i == selected_commit and focus == "left":
|
if i == selected_commit and focus == "left":
|
||||||
stdscr.attron(curses.A_REVERSE)
|
stdscr.attron(curses.A_REVERSE)
|
||||||
|
|
@ -37,22 +45,22 @@ def main(stdscr, filename):
|
||||||
if i == selected_commit and focus == "left":
|
if i == selected_commit and focus == "left":
|
||||||
stdscr.attroff(curses.A_REVERSE)
|
stdscr.attroff(curses.A_REVERSE)
|
||||||
|
|
||||||
# Draw vertical divider with box-drawing character
|
# Vertical divider
|
||||||
for y in range(height):
|
for y in range(height):
|
||||||
stdscr.addch(y, divider_col, '│')
|
stdscr.addch(y, divider_col, '│')
|
||||||
|
|
||||||
# Draw file content on the right
|
# File content
|
||||||
if commits:
|
for i, line in enumerate(visible_lines):
|
||||||
commit_hash = commits[selected_commit].split()[0]
|
stdscr.addnstr(i, divider_col + 2, line, width - divider_col - 3)
|
||||||
file_lines = get_file_at_commit(commit_hash, filename)
|
|
||||||
visible_lines = file_lines[scroll_offset:scroll_offset + height]
|
# Status bar for right pane
|
||||||
for i, line in enumerate(visible_lines):
|
status = f"line {scroll_offset + 1}/{len(file_lines)}"
|
||||||
stdscr.addnstr(i, divider_col + 2, line, width - divider_col - 3)
|
stdscr.addnstr(height - 1, divider_col + 2, status, width - divider_col - 3, curses.A_DIM)
|
||||||
|
|
||||||
stdscr.refresh()
|
stdscr.refresh()
|
||||||
|
|
||||||
key = stdscr.getch()
|
key = stdscr.getch()
|
||||||
|
|
||||||
|
# Mouse click changes focus
|
||||||
if key == curses.KEY_MOUSE:
|
if key == curses.KEY_MOUSE:
|
||||||
try:
|
try:
|
||||||
_, mx, my, _, bstate = curses.getmouse()
|
_, mx, my, _, bstate = curses.getmouse()
|
||||||
|
|
@ -64,27 +72,35 @@ def main(stdscr, filename):
|
||||||
elif key in [ord('q'), 27]:
|
elif key in [ord('q'), 27]:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Left pane movement
|
||||||
elif focus == "left":
|
elif focus == "left":
|
||||||
if key in [curses.KEY_DOWN, ord('j')]:
|
if key in [curses.KEY_DOWN, ord('j')]:
|
||||||
if selected_commit < len(commits) - 1:
|
if selected_commit < len(commits) - 1:
|
||||||
selected_commit += 1
|
selected_commit += 1
|
||||||
scroll_offset = 0 # reset right pane scroll
|
scroll_offset = 0
|
||||||
elif key in [curses.KEY_UP, ord('k')]:
|
elif key in [curses.KEY_UP, ord('k')]:
|
||||||
if selected_commit > 0:
|
if selected_commit > 0:
|
||||||
selected_commit -= 1
|
selected_commit -= 1
|
||||||
scroll_offset = 0
|
scroll_offset = 0
|
||||||
|
|
||||||
|
# Right pane scrolling
|
||||||
elif focus == "right":
|
elif focus == "right":
|
||||||
if key == curses.KEY_DOWN or key == ord('j'):
|
if key in [curses.KEY_DOWN, ord('j')]:
|
||||||
if scroll_offset < max(0, len(file_lines) - height):
|
if scroll_offset < max_scroll:
|
||||||
scroll_offset += 1
|
scroll_offset += 1
|
||||||
elif key == curses.KEY_UP or key == ord('k'):
|
elif key in [curses.KEY_UP, ord('k')]:
|
||||||
if scroll_offset > 0:
|
if scroll_offset > 0:
|
||||||
scroll_offset -= 1
|
scroll_offset -= 1
|
||||||
elif key == curses.KEY_NPAGE: # Page Down
|
elif key == curses.KEY_NPAGE: # Page Down
|
||||||
scroll_offset = min(scroll_offset + height, max(0, len(file_lines) - height))
|
scroll_offset = min(scroll_offset + height - 1, max_scroll)
|
||||||
elif key == curses.KEY_PPAGE: # Page Up
|
elif key == curses.KEY_PPAGE: # Page Up
|
||||||
scroll_offset = max(0, scroll_offset - height)
|
scroll_offset = max(0, scroll_offset - (height - 1))
|
||||||
|
|
||||||
|
# Pane switching
|
||||||
|
if key in [curses.KEY_LEFT, ord('h')]:
|
||||||
|
focus = "left"
|
||||||
|
elif key in [curses.KEY_RIGHT, ord('l')]:
|
||||||
|
focus = "right"
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue