Re: [PATCHv2 1/2] gdb/python: add gdb.Style class

Eli Zaretskii
2025-06-06T14:22:09Z

> From: Andrew Burgess <aburgess@redhat.com>
> Cc: Andrew Burgess <aburgess@redhat.com>
> Date: Fri, 6 Jun 2025 14:38:13 +0100
>
> This commit adds a new gdb.Style class. This class represents a
> complete style within GDB. A complete style is a collection of
> foreground color, background color, and an intensity.
>
> A gdb.Style comes in two flavours, named, and unnamed.
>
> A named style is one that is based on an existing style within GDB.
> For example, we have 'set style filename ...', the name of this style
> is 'filename'. We also have 'set style disassembler mnemonic ...',
> the name of this style is 'disassembler mnemonic'. A named style is
> created by passing the name of the style, like this:
>
> (gdb) python s1 = gdb.Style("filename")
> (gdb) python s2 = gdb.Style("disassembler mnemonic")
>
> The other type of style is an unnamed style. An unnamed style is
> created using a foreground and background color, along with an
> intensity. Colors are specified using gdb.Color objects. An example
> of creating an unnamed style is:
>
> (gdb) python s3 = gdb.Style(foreground=gdb.Color('red'),
> background=gdb.Color('green'),
> intensity=gdb.INTENSITY_BOLD)
>
> We can see here an example of the new intensity constants that have
> been added in this commit, there is gdb.INTENSITY_NORMAL,
> gdb.INTENSITY_BOLD, and gdb.INTENSITY_DIM. All of the arguments are
> optional, the default for the colors is gdb.Color(), which will apply
> the terminal default, and the default intensity is
> gdb.INTENSITY_NORMAL.
>
> Having created a gdb.Style object there are two ways that it can be
> used to style GDB's output. The Style.escape_sequence() method
> returns the escape sequence needed to apply this style, this can be
> used as in:
>
> (gdb) python print(s1.escape_sequence() + "Filename Style")
>
> The problem with this approach is that it is the users responsibility
> to restore the style to the default when they are done. In the above
> example, all output after the escape sequence is printed, including
> the next GDB prompt, will be in the s1 (filename) style. Which is why
> the Style.apply method exists. This method takes a string and returns
> the same string with escape sequences added before and after. The
> before sequence switches to the style, while the after escape sequence
> restores the terminal default style. This can be used like:
>
> (gdb) python print(s1.apply("Filename Style"))
>
> Now only the 'Filename Style' text will be styled. The next GDB
> prompt will be in the default terminal style. Personally, I think the
> apply method is the more useful, but having 'escape_sequence' matches
> what gdb.Color offers, though if/when this patch is merged, I might
> propose a similar 'apply' type method for the gdb.Color class.
>
> The gdb.Style class has 'foreground', 'background', and 'intensity'
> attributes which, when read, return the obvious values. These
> attributes can also be written too.
>
> When writing to an attribute of an unnamed Style object then the Style
> object itself is updated, as you might expect.
>
> When writing to an attribute of a named Style then the style setting
> itself is updated as the following example shows:
>
> (gdb) python s1 = gdb.Style("filename")
> (gdb) python print(s1.foreground)
> green
> (gdb) show style filename foreground
> The "filename" style foreground color is: green
> (gdb) python s1.foreground=gdb.Color("red")
> (gdb) python print(s1.foreground)
> red
> (gdb) show style filename foreground
> The "filename" style foreground color is: red
> (gdb)
>
> We can see that a gdb.Style object is connected to the underlying
> style settings, it doesn't take a copy of the style settings at
> creation time. And the relationship works both ways. Continuing the
> above example:
>
> (gdb) set style filename foreground blue
> (gdb) python print(s1.foreground)
> blue
> (gdb)
>
> Here we see that changing the setting value causes the gdb.Style
> object to update. And this is what you would want. I imagine this
> being used in a Python extension to GDB where a user might create
> global objects for some named styles, and then use these globals to
> format output from some custom commands. If a user of an extension
> changes a style setting then the extension wants to adapt to that
> change.
>
> Both the Style.escape_sequence and Style.apply methods take the global
> style enabled setting into consideration. If styling is disabled then
> Style.escape_sequence will return an empty string, and Style.apply
> will return an unmodified copy of the original string object (actually
> the input object with Py_INCREF applied).
>
> There is also support for representing a gdb.Style as a string:
>
> (gdb) python s1 = gdb.Style("filename")
> (gdb) python print(s1)
> <gdb.Style name='filename', fg=green, bg=none, intensity=normal>
> (gdb)
>
> Unnamed styles are similar, but don't have a 'name' field.
> ---
> gdb/Makefile.in | 1 +
> gdb/NEWS | 7 +
> gdb/doc/python.texi | 140 +++++
> gdb/python/py-style.c | 797 ++++++++++++++++++++++++++
> gdb/testsuite/gdb.python/py-style.exp | 339 +++++++++++
> gdb/ui-style.h | 6 +
> 6 files changed, 1290 insertions(+)
> create mode 100644 gdb/python/py-style.c
> create mode 100644 gdb/testsuite/gdb.python/py-style.exp

Thanks, the documentation parts are okay.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>