Color pass-through in urwid or curses

浪尽此生 提交于 2020-01-25 07:29:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!