Re: Colors in gdb

Matt Rice
2013-01-20T15:13:58Z

[-- Attachment #1: Type: text/plain, Size: 2950 bytes --]

On Tue, Jan 15, 2013 at 11:02 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Kevin" == Kevin Pouget <kevin.pouget@gmail.com> writes:
>
> Kevin> I have colors in my gdb Python prompt since quite a while, I wonder
> Kevin> what could be different in the context of prompt printing and pretty
> Kevin> printing ?
>
> For ordinary printing, there's just no place to hook into gdb.

its worth noting that the standard python print function works with
escape sequences,

> For printing via Python pretty-printers, strings are further processed
> by gdb before printing, and in particular the escape sequences are
> turned into plain text.

attached is a silly modification to the example pretty printer from the docs[1]:
it contains an additional method 'to_color_string', tested like:

py print gdb.default_visualizer(gdb.parse_and_eval("x")).to_color_string()

which could be easily shoved into a 'define'
or something (would be nice if it fell back to normal to_string method)

maybe i'm old in not liking the idea of making these work with the
standard 'print' command, because the escape sequences are terminal
type dependent, which is IMO fine for a prompt set by a gdbinit, but
less so for a pretty printer distributed with a library...
this opinion is only strengthened by considering a std::string
containing an escape sequence.

until there is a common cross platform escape sequence generator deal at least
(IIRC there is one, but it either requires a newer python, and/or is a
3rd party module not a standard python one)

so I probably should have included something like the 'color_dict'
from gaudy_prompt, as an argument to to_color_string, with a default
argument of a 'no_colors' dict, that way one could just implement
to_string() as calling to_color_string, there are some issues in that
the gaudy_prompt color dicts generate '\[ and \] as
\001 and \002 escape sequences to inform readline about non-printing
characters, these escape sequences get printed as junk since py print
doesn't grok them. I suppose they should be replaced with classes
(readline colors class subclassing a colors class)

i'm fairly steadfast that just having random escape sequences embedded
in pretty printers as i implemented it is entirely the wrong thing to
do, and we need some level of indirection that can be set in .gdbinit
that pretty printers can query

it would probably be a good idea to settle on a declaration for a
to_color_string method so it isn't done totally ad-hoc for each
pretty-printer that wants to do so.
I'll leave coming up with that declaration to someone actually
implementing one that is not a silly example...

FWIW running the pretty printers this way doesn't set the gdb numbered
convenience variable, like print does.

since the pretty printing API needs to remain compatible, please keep
us in the loop :)

[1] http://sourceware.org/gdb/current/onlinedocs/gdb/Writing-a-Pretty_002dPrinter.html#Writing-a-Pretty_002dPrinter

[-- Attachment #2: foo.py --]
[-- Type: application/octet-stream, Size: 1119 bytes --]

from curses import *

def colorize(str, color):
return tparm(tigetstr("setaf"), color) + str + tigetstr("sgr0")

class fooPrinter:
"""Print a foo object."""

def __init__(self, val):
self.val = val

def to_string(self):
return ("a=<" + str(self.val["a"]) +
"> b=<" + str(self.val["b"]) + ">")

def to_color_string(self):
return (colorize("a", COLOR_RED) + colorize("=", COLOR_BLUE) + colorize("<", COLOR_GREEN) + str(self.val["a"]) +
colorize(">", COLOR_GREEN) + "b=<" + str(self.val["b"]) + ">")

class barPrinter:
"""Print a bar object."""

def __init__(self, val):
self.val = val

def to_string(self):
return ("x=<" + str(self.val["x"]) +
"> y=<" + str(self.val["y"]) + ">")
import gdb.printing

def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter("my_library")
pp.add_printer('foo', '^foo$', fooPrinter)
pp.add_printer('bar', '^bar$', barPrinter)
return pp

gdb.printing.register_pretty_printer(gdb.current_objfile(),build_pretty_printer())
setupterm(None, 1);