First commit
This commit is contained in:
commit
58c7866468
|
|
@ -0,0 +1,67 @@
|
|||
# by ChatGPT
|
||||
|
||||
|
||||
import curses
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
def get_commits(filename):
|
||||
cmd = ['git', 'log', '--pretty=format:%h %ad %s', '--date=short', '--', filename]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
return result.stdout.splitlines()
|
||||
|
||||
def get_file_at_commit(commit_hash, filename):
|
||||
cmd = ['git', 'show', f'{commit_hash}:{filename}']
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
return result.stdout.splitlines()
|
||||
|
||||
def main(stdscr, filename):
|
||||
curses.curs_set(0)
|
||||
stdscr.keypad(True)
|
||||
|
||||
commits = get_commits(filename)
|
||||
selected = 0
|
||||
|
||||
while True:
|
||||
stdscr.clear()
|
||||
height, width = stdscr.getmaxyx()
|
||||
mid = width // 2
|
||||
|
||||
# Draw commit list on the left
|
||||
for i, line in enumerate(commits):
|
||||
if i >= height:
|
||||
break
|
||||
if i == selected:
|
||||
stdscr.attron(curses.A_REVERSE)
|
||||
stdscr.addnstr(i, 0, line, mid - 1)
|
||||
if i == selected:
|
||||
stdscr.attroff(curses.A_REVERSE)
|
||||
|
||||
# Show file content on the right
|
||||
if commits:
|
||||
commit_hash = commits[selected].split()[0]
|
||||
file_lines = get_file_at_commit(commit_hash, filename)
|
||||
for i, line in enumerate(file_lines):
|
||||
if i >= height:
|
||||
break
|
||||
stdscr.addnstr(i, mid + 1, line, width - mid - 2)
|
||||
|
||||
stdscr.refresh()
|
||||
|
||||
key = stdscr.getch()
|
||||
if key in [ord('q'), 27]: # q or ESC to quit
|
||||
break
|
||||
elif key in [curses.KEY_DOWN, ord('j')]:
|
||||
if selected < len(commits) - 1:
|
||||
selected += 1
|
||||
elif key in [curses.KEY_UP, ord('k')]:
|
||||
if selected > 0:
|
||||
selected -= 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python git_time_machine.py path/to/file")
|
||||
sys.exit(1)
|
||||
filename = sys.argv[1]
|
||||
curses.wrapper(main, filename)
|
||||
|
||||
Loading…
Reference in New Issue