2a3c1174c3
This introduces a few gdb-specific %p format suffixes. This is useful for emitting gdb-specific output in an ergonomic way. It also yields code that is more i18n-friendly. The comment before ui_out::message explains the details. Note that the tests had to change a little. When using one of the gdb printf functions with styling, there can be spurious style changes emitted to the output. This did not seem worthwhile to fix, as the low-level output functions are rather spaghetti-ish already, and I didn't want to make them even worse. This change also necessitated adding support for "*" as precision and width in format_pieces. These are used in various spots in gdb, and it seemed better to me to implement them than to remove the uses. gdb/ChangeLog 2019-10-01 Pedro Alves <palves@redhat.com> Tom Tromey <tom@tromey.com> * unittests/format_pieces-selftests.c: Add gdb_format parameter. (test_gdb_formats): New function. (run_tests): Call it. (test_format_specifier): Update. * utils.h (fputs_filtered): Update comment. (vfprintf_styled, vfprintf_styled_no_gdbfmt) (fputs_styled_unfiltered): Declare. * utils.c (fputs_styled_unfiltered): New function. (vfprintf_maybe_filtered): Add gdbfmt parameter. (vfprintf_filtered): Update. (vfprintf_unfiltered, vprintf_filtered): Update. (vfprintf_styled, vfprintf_styled_no_gdbfmt): New functions. * ui-out.h (enum ui_out_flag) <unfiltered_output, disallow_ui_out_field>: New constants. (enum class field_kind): New. (struct base_field_s, struct signed_field_s): New. (signed_field): New function. (struct string_field_s): New. (string_field): New function. (struct styled_string_s): New. (styled_string): New function. (class ui_out) <message>: Add comment. <vmessage, call_do_message>: New methods. <do_message>: Add style parameter. * ui-out.c (ui_out::call_do_message, ui_out::vmessage): New methods. (ui_out::message): Rewrite. * mi/mi-out.h (class mi_ui_out) <do_message>: Add style parameter. * mi/mi-out.c (mi_ui_out::do_message): Add style parameter. * gdbsupport/format.h (class format_pieces) <format_pieces>: Add gdb_extensions parameter. (class format_piece): Add parameter to constructor. (n_int_args): New field. * gdbsupport/format.c (format_pieces::format_pieces): Add gdb_extensions parameter. Handle '*'. * cli-out.h (class cli_ui_out) <do_message>: Add style parameter. * cli-out.c (cli_ui_out::do_message): Add style parameter. Call vfprintf_styled_no_gdbfmt. (cli_ui_out::do_field_string, cli_ui_out::do_spaces) (cli_ui_out::do_text, cli_ui_out::field_separator): Allow unfiltered output. * ui-style.h (struct ui_file_style) <ptr>: New method. gdb/testsuite/ChangeLog 2019-10-01 Tom Tromey <tom@tromey.com> * gdb.base/style.exp: Update tests.
248 lines
5.8 KiB
C++
248 lines
5.8 KiB
C++
/* Styling for ui_file
|
|
Copyright (C) 2018-2019 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
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/>. */
|
|
|
|
#ifndef UI_STYLE_H
|
|
#define UI_STYLE_H
|
|
|
|
/* Styles that can be applied to a ui_file. */
|
|
struct ui_file_style
|
|
{
|
|
/* One of the basic colors that can be handled by ANSI
|
|
terminals. */
|
|
enum basic_color
|
|
{
|
|
NONE = -1,
|
|
BLACK,
|
|
RED,
|
|
GREEN,
|
|
YELLOW,
|
|
BLUE,
|
|
MAGENTA,
|
|
CYAN,
|
|
WHITE
|
|
};
|
|
|
|
/* Representation of a terminal color. */
|
|
class color
|
|
{
|
|
public:
|
|
|
|
color (basic_color c)
|
|
: m_simple (true),
|
|
m_value (c)
|
|
{
|
|
}
|
|
|
|
color (int c)
|
|
: m_simple (true),
|
|
m_value (c)
|
|
{
|
|
gdb_assert (c >= -1 && c <= 255);
|
|
}
|
|
|
|
color (uint8_t r, uint8_t g, uint8_t b)
|
|
: m_simple (false),
|
|
m_red (r),
|
|
m_green (g),
|
|
m_blue (b)
|
|
{
|
|
}
|
|
|
|
bool operator== (const color &other) const
|
|
{
|
|
if (m_simple != other.m_simple)
|
|
return false;
|
|
if (m_simple)
|
|
return m_value == other.m_value;
|
|
return (m_red == other.m_red && m_green == other.m_green
|
|
&& m_blue == other.m_blue);
|
|
}
|
|
|
|
bool operator< (const color &other) const
|
|
{
|
|
if (m_simple != other.m_simple)
|
|
return m_simple < other.m_simple;
|
|
if (m_simple)
|
|
return m_value < other.m_value;
|
|
if (m_red < other.m_red)
|
|
return true;
|
|
if (m_red == other.m_red)
|
|
{
|
|
if (m_green < other.m_green)
|
|
return true;
|
|
if (m_green == other.m_green)
|
|
return m_blue < other.m_blue;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* Return true if this is the "NONE" color, false otherwise. */
|
|
bool is_none () const
|
|
{
|
|
return m_simple && m_value == NONE;
|
|
}
|
|
|
|
/* Return true if this is one of the basic colors, false
|
|
otherwise. */
|
|
bool is_basic () const
|
|
{
|
|
return m_simple && m_value >= BLACK && m_value <= WHITE;
|
|
}
|
|
|
|
/* Return the value of a basic color. */
|
|
int get_value () const
|
|
{
|
|
gdb_assert (is_basic ());
|
|
return m_value;
|
|
}
|
|
|
|
/* Fill in RGB with the red/green/blue values for this color.
|
|
This may not be called for basic colors or for the "NONE"
|
|
color. */
|
|
void get_rgb (uint8_t *rgb) const;
|
|
|
|
/* Append the ANSI terminal escape sequence for this color to STR.
|
|
IS_FG indicates whether this is a foreground or background
|
|
color. Returns true if any characters were written; returns
|
|
false otherwise (which can only happen for the "NONE"
|
|
color). */
|
|
bool append_ansi (bool is_fg, std::string *str) const;
|
|
|
|
private:
|
|
|
|
bool m_simple;
|
|
int m_value;
|
|
uint8_t m_red, m_green, m_blue;
|
|
};
|
|
|
|
/* Intensity settings that are available. */
|
|
enum intensity
|
|
{
|
|
NORMAL = 0,
|
|
BOLD,
|
|
DIM
|
|
};
|
|
|
|
ui_file_style () = default;
|
|
|
|
ui_file_style (color f, color b, intensity i = NORMAL)
|
|
: m_foreground (f),
|
|
m_background (b),
|
|
m_intensity (i)
|
|
{
|
|
}
|
|
|
|
bool operator== (const ui_file_style &other) const
|
|
{
|
|
return (m_foreground == other.m_foreground
|
|
&& m_background == other.m_background
|
|
&& m_intensity == other.m_intensity
|
|
&& m_reverse == other.m_reverse);
|
|
}
|
|
|
|
bool operator!= (const ui_file_style &other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
/* Return the ANSI escape sequence for this style. */
|
|
std::string to_ansi () const;
|
|
|
|
/* Return true if this style is the default style; false
|
|
otherwise. */
|
|
bool is_default () const
|
|
{
|
|
return (m_foreground == NONE
|
|
&& m_background == NONE
|
|
&& m_intensity == NORMAL
|
|
&& !m_reverse);
|
|
}
|
|
|
|
/* Return true if this style specified reverse display; false
|
|
otherwise. */
|
|
bool is_reverse () const
|
|
{
|
|
return m_reverse;
|
|
}
|
|
|
|
/* Set/clear the reverse display flag. */
|
|
void set_reverse (bool reverse)
|
|
{
|
|
m_reverse = reverse;
|
|
}
|
|
|
|
/* Return the foreground color of this style. */
|
|
const color &get_foreground () const
|
|
{
|
|
return m_foreground;
|
|
}
|
|
|
|
/* Set the foreground color of this style. */
|
|
void set_fg (color c)
|
|
{
|
|
m_foreground = c;
|
|
}
|
|
|
|
/* Return the background color of this style. */
|
|
const color &get_background () const
|
|
{
|
|
return m_background;
|
|
}
|
|
|
|
/* Set the background color of this style. */
|
|
void set_bg (color c)
|
|
{
|
|
m_background = c;
|
|
}
|
|
|
|
/* Return the intensity of this style. */
|
|
intensity get_intensity () const
|
|
{
|
|
return m_intensity;
|
|
}
|
|
|
|
/* Parse an ANSI escape sequence in BUF, modifying this style. BUF
|
|
must begin with an ESC character. Return true if an escape
|
|
sequence was successfully parsed; false otherwise. In either
|
|
case, N_READ is updated to reflect the number of chars read from
|
|
BUF. */
|
|
bool parse (const char *buf, size_t *n_read);
|
|
|
|
/* We need this because we can't pass a reference via va_args. */
|
|
const ui_file_style *ptr () const
|
|
{
|
|
return this;
|
|
}
|
|
|
|
private:
|
|
|
|
color m_foreground = NONE;
|
|
color m_background = NONE;
|
|
intensity m_intensity = NORMAL;
|
|
bool m_reverse = false;
|
|
};
|
|
|
|
/* Skip an ANSI escape sequence in BUF. BUF must begin with an ESC
|
|
character. Return true if an escape sequence was successfully
|
|
skipped; false otherwise. If an escape sequence was skipped,
|
|
N_READ is updated to reflect the number of chars read from BUF. */
|
|
|
|
extern bool skip_ansi_escape (const char *buf, int *n_read);
|
|
|
|
#endif /* UI_STYLE_H */
|