mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 09:08:59 +00:00
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.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
139 lines
4.3 KiB
Plaintext
139 lines
4.3 KiB
Plaintext
# Copyright (C) 2025 Free Software Foundation, Inc.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# This file is part of the GDB testsuite. It tests gdb.Color and how this
|
|
# interacts with GDB's pagination system. The test also tests gdb.Style
|
|
# because the tests are very similar.
|
|
|
|
load_lib gdb-python.exp
|
|
|
|
require allow_python_tests
|
|
require {!is_remote host}
|
|
|
|
standard_testfile
|
|
|
|
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
|
|
|
set str "<[string repeat - 78]>"
|
|
|
|
# These define all the default attributes for a style: background
|
|
# color, intensity, italics, and underlined.
|
|
set other_attr ";49;22;23;24;27"
|
|
|
|
# These colors set the foreground color only. Everything else is the
|
|
# default.
|
|
set black "(?:\033\\\[30${other_attr}m)"
|
|
set red "(?:\033\\\[31${other_attr}m)"
|
|
set green "(?:\033\\\[32${other_attr}m)"
|
|
set yellow "(?:\033\\\[33${other_attr}m)"
|
|
set blue "(?:\033\\\[34${other_attr}m)"
|
|
set magenta "(?:\033\\\[35${other_attr}m)"
|
|
set cyan "(?:\033\\\[36${other_attr}m)"
|
|
set white "(?:\033\\\[37${other_attr}m)"
|
|
|
|
set any_color "(?:${black}|${red}|${green}|${yellow}|${blue}|${magenta}|${cyan}|${white})"
|
|
|
|
# Run the command 'TYPE-fill MODE' which fills the screen with output and
|
|
# triggers the pagination prompt. Check that styling is applied correctly
|
|
# to the output.
|
|
proc test_pagination { type mode } {
|
|
|
|
# Start with a fresh GDB, but enable color support.
|
|
with_ansi_styling_terminal {
|
|
clean_restart
|
|
}
|
|
|
|
gdb_test_no_output "source $::pyfile" "source the script"
|
|
|
|
gdb_test_no_output "set width 80"
|
|
gdb_test_no_output "set height 15"
|
|
|
|
set saw_bad_color_handling false
|
|
set expected_restore_color ""
|
|
set last_color ""
|
|
gdb_test_multiple "$type-fill $mode" "" {
|
|
-re "^$type-fill $mode\r\n" {
|
|
exp_continue
|
|
}
|
|
|
|
-re "^(${::any_color})(${::any_color})$::str" {
|
|
# After a continuation prompt GDB will restore the previous
|
|
# color, and then we immediately switch to a new color.
|
|
set restored_color $expect_out(1,string)
|
|
if { $restored_color ne $expected_restore_color } {
|
|
set saw_bad_color_handling true
|
|
}
|
|
set last_color $expect_out(2,string)
|
|
exp_continue
|
|
}
|
|
|
|
-re "^(${::any_color})$::str" {
|
|
# This pattern matches printing STR in all cases that are not
|
|
# immediately after a pagination prompt. In this case there is
|
|
# a single escape sequence to set the color.
|
|
set last_color $expect_out(1,string)
|
|
exp_continue
|
|
}
|
|
|
|
-re "^\033\\\[${::decimal}m$::str" {
|
|
# This catches the case where the color's escape sequence has
|
|
# not been converted back into a full style. This indicates
|
|
# something went wrong in the pager_file::puts function.
|
|
set saw_bad_color_handling true
|
|
exp_continue
|
|
}
|
|
|
|
-re "^\033\\\[m$::pagination_prompt$" {
|
|
# After a pagination prompt we expect GDB to restore the last
|
|
# color.
|
|
set expected_restore_color $last_color
|
|
|
|
# Send '\n' to view more output.
|
|
send_gdb "\n"
|
|
exp_continue
|
|
}
|
|
|
|
-re "^$::pagination_prompt$" {
|
|
# After a pagination prompt we expect GDB to restore the last
|
|
# color.
|
|
set expected_restore_color $last_color
|
|
|
|
# If we didn't see a color reset sequence before the pagination
|
|
# prompt, then the prompt will have been printed in the wrong
|
|
# color, this is a GDB bug.
|
|
set saw_bad_color_handling true
|
|
|
|
# Send '\n' to view more output.
|
|
send_gdb "\n"
|
|
exp_continue
|
|
}
|
|
|
|
-re "^\r\n" {
|
|
# The matches the newline sent to the continuation prompt.
|
|
exp_continue
|
|
}
|
|
|
|
-re "^\033\\\[m\r\n$::gdb_prompt $" {
|
|
gdb_assert { !$saw_bad_color_handling } $gdb_test_name
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach_with_prefix type { color style } {
|
|
foreach_with_prefix mode { write print } {
|
|
test_pagination $type $mode
|
|
}
|
|
}
|