问题
I would like to write a wrapper around git log
, somewhat similar to gitk
but on a terminal.
I thought this should be easy because git log
already formats the output, all I need to do is put it in a list view where I can select a commit.
However, both urwid and curses mess up the color codes which git log
is using.
I tried to implement a custom urwid widget hoping it might leave the color codes alone but it does not behave any different.
I considered to move the coloring of the output from git log
to my wrapper but that's not possible with the --graph
option.
A direct pass through of colors works with a normal print statement but I don't want to reinvent window management, input handling, recognition of resizing and I don't know what else.
How can I stop urwid or curses to touch the color codes?
desired output:
achieved output:
MWE:
model.py
:
#!/usr/bin/env python
import subprocess
class LogModel():
encoding = "utf-8"
cmd = ["git", "log", "--color", "--graph", "--pretty=format:%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset", "--abbrev-commit"]
def get_lines(self):
p = subprocess.run(self.cmd, stdout=subprocess.PIPE, check=True, encoding=self.encoding)
out = p.stdout
return out.splitlines()
if __name__ == '__main__':
log = LogModel()
for ln in log.get_lines():
print(ln)
(credit for the git log format goes here)
main_urwid.py
:
#!/usr/bin/env python
import urwid
import model
class MyText(urwid.Widget):
_sizing = frozenset(['flow'])
def __init__(self, text):
super().__init__()
self.text = text.encode("utf-8")
def render(self, size, focus=False):
(maxcol,) = size
return urwid.TextCanvas([self.text], maxcol=maxcol, check_width=False)
def rows(self, size, focus=False):
return 1
class LogView(urwid.ListBox):
def __init__(self, log_model):
widgets = [self.create_line_widget(ln) for ln in log_model.get_lines()]
body = urwid.SimpleFocusListWalker(widgets)
super().__init__(body)
def create_line_widget(self, ln):
#return urwid.Text(ln, wrap=urwid.CLIP)
return MyText(ln)
class App():
palette = []
def __init__(self):
self.view = LogView(model.LogModel())
def run(self):
self.loop = urwid.MainLoop(self.view, self.palette,
unhandled_input=self.unhandled_input)
self.loop.run()
def unhandled_input(self, k):
if k == "q":
raise urwid.ExitMainLoop()
if __name__ == '__main__':
a = App()
a.run()
main_curses.py
:
#!/usr/bin/env python
import curses
import model
def main(stdscr):
log_model = model.LogModel()
curses.use_default_colors()
stdscr.clear()
col = 0
for row, ln in enumerate(log_model.get_lines()):
stdscr.addstr(row, col, ln)
stdscr.refresh()
stdscr.getkey()
if __name__ == '__main__':
curses.wrapper(main)
来源:https://stackoverflow.com/questions/59338591/color-pass-through-in-urwid-or-curses