mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-09 17:12:54 +00:00
Add an option with a color type.
Colors can be specified as "none" for terminal's default color, as a name of one of the eight standard colors of ISO/IEC 6429 "black", "red", "green", etc., as an RGB hexadecimal tripplet #RRGGBB for 24-bit TrueColor, or as an integer from 0 to 255. Integers 0 to 7 are the synonyms for the standard colors. Integers 8-15 are used for the so-called bright colors from the aixterm extended 16-color palette. Integers 16-255 are the indexes into xterm extended 256-color palette (usually 6x6x6 cube plus gray ramp). In general, 256-color palette is terminal dependent and sometimes can be changed with OSC 4 sequences, e.g. "\033]4;1;rgb:00/FF/00\033\\". It is the responsibility of the user to verify that the terminal supports the specified colors. PATCH v5 changes: documentation fixed. PATCH v6 changes: documentation fixed. PATCH v7 changes: rebase onto master and fixes after review. PATCH v8 changes: fixes after review.
This commit is contained in:
@@ -359,6 +359,7 @@ SUBDIR_GUILE_SRCS = \
|
||||
guile/scm-block.c \
|
||||
guile/scm-breakpoint.c \
|
||||
guile/scm-cmd.c \
|
||||
guile/scm-color.c \
|
||||
guile/scm-disasm.c \
|
||||
guile/scm-exception.c \
|
||||
guile/scm-frame.c \
|
||||
@@ -395,6 +396,7 @@ SUBDIR_PYTHON_SRCS = \
|
||||
python/py-bpevent.c \
|
||||
python/py-breakpoint.c \
|
||||
python/py-cmd.c \
|
||||
python/py-color.c \
|
||||
python/py-connection.c \
|
||||
python/py-continueevent.c \
|
||||
python/py-dap.c \
|
||||
|
||||
33
gdb/NEWS
33
gdb/NEWS
@@ -3,6 +3,25 @@
|
||||
|
||||
*** Changes since GDB 16
|
||||
|
||||
* "set style" commands now supports numeric format for basic colors
|
||||
from 0 to 255 and #RRGGBB format for TrueColor.
|
||||
|
||||
* New built-in convenience variable $_colorsupport provides comma-separated
|
||||
list of color space names supported by terminal. Each color space name is one
|
||||
of monochrome, ansi_8color, aixterm_16color, xterm_256color or rgb_24bit.
|
||||
It is handy for conditionally using styling colors based on terminal features.
|
||||
For example:
|
||||
|
||||
(gdb) if $_regex ($_colorsupport, ".*(^|,)rgb_24bit($|,).*")
|
||||
>set style filename background #FACADE
|
||||
>else
|
||||
>if $_regex ($_colorsupport, ".*(^|,)xterm_256color($|,).*")
|
||||
>set style filename background 224
|
||||
>else
|
||||
>set style filename background red
|
||||
>end
|
||||
>end
|
||||
|
||||
* New commands
|
||||
|
||||
maintenance check psymtabs
|
||||
@@ -11,6 +30,20 @@ maintenance check psymtabs
|
||||
maintenance check symtabs
|
||||
Renamed from maintenance check-symtabs
|
||||
|
||||
* Python API
|
||||
|
||||
** New class gdb.Color for dealing with colors.
|
||||
|
||||
** New constant gdb.PARAM_COLOR represents color type of a
|
||||
gdb.Parameter.value. Parameter's value is gdb.Color instance.
|
||||
|
||||
* Guile API
|
||||
|
||||
** New type <gdb:color> for dealing with colors.
|
||||
|
||||
** New constant PARAM_COLOR represents color type of a value
|
||||
of a <gdb:parameter> object. Parameter's value is <gdb::color> instance.
|
||||
|
||||
*** Changes in GDB 16
|
||||
|
||||
* Support for Nios II targets has been removed as this architecture
|
||||
|
||||
@@ -2398,6 +2398,11 @@ value_from_setting (const setting &var, struct gdbarch *gdbarch)
|
||||
|
||||
return current_language->value_string (gdbarch, value, len);
|
||||
}
|
||||
case var_color:
|
||||
{
|
||||
std::string s = var.get<ui_file_style::color> ().to_string ();
|
||||
return current_language->value_string (gdbarch, s.c_str (), s.size ());
|
||||
}
|
||||
default:
|
||||
gdb_assert_not_reached ("bad var_type");
|
||||
}
|
||||
@@ -2445,6 +2450,7 @@ str_value_from_setting (const setting &var, struct gdbarch *gdbarch)
|
||||
case var_pinteger:
|
||||
case var_boolean:
|
||||
case var_auto_boolean:
|
||||
case var_color:
|
||||
{
|
||||
std::string cmd_val = get_setshow_command_value_string (var);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "cli/cli-cmds.h"
|
||||
#include "cli/cli-decode.h"
|
||||
#include "cli/cli-style.h"
|
||||
#include "cli/cli-utils.h"
|
||||
#include <optional>
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
@@ -739,6 +740,87 @@ add_setshow_enum_cmd (const char *name, command_class theclass,
|
||||
return cmds;
|
||||
}
|
||||
|
||||
/* See cli-decode.h. */
|
||||
|
||||
void
|
||||
complete_on_color (completion_tracker &tracker,
|
||||
const char *text, const char *word)
|
||||
{
|
||||
complete_on_enum (tracker, ui_file_style::basic_color_enums.data (),
|
||||
text, word);
|
||||
if (*text == '\0')
|
||||
{
|
||||
/* Convenience to let the user know what the option
|
||||
can accept. Note there's no common prefix between
|
||||
the strings on purpose, so that complete_on_enum doesn't do
|
||||
a partial match. */
|
||||
tracker.add_completion (make_unique_xstrdup ("NUMBER"));
|
||||
tracker.add_completion (make_unique_xstrdup ("#RRGGBB"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Completer used in color commands. */
|
||||
|
||||
static void
|
||||
color_completer (struct cmd_list_element *ignore,
|
||||
completion_tracker &tracker,
|
||||
const char *text, const char *word)
|
||||
{
|
||||
complete_on_color (tracker, text, word);
|
||||
}
|
||||
|
||||
|
||||
/* Add element named NAME to command list LIST (the list for set or
|
||||
some sublist thereof). CLASS is as in add_cmd. VAR is address
|
||||
of the variable which will contain the color. */
|
||||
|
||||
set_show_commands
|
||||
add_setshow_color_cmd (const char *name,
|
||||
enum command_class theclass,
|
||||
ui_file_style::color *var,
|
||||
const char *set_doc,
|
||||
const char *show_doc,
|
||||
const char *help_doc,
|
||||
cmd_func_ftype *set_func,
|
||||
show_value_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list)
|
||||
{
|
||||
set_show_commands commands = add_setshow_cmd_full<ui_file_style::color>
|
||||
(name, theclass, var_color, var,
|
||||
set_doc, show_doc, help_doc,
|
||||
nullptr, nullptr, set_func, show_func,
|
||||
set_list, show_list);
|
||||
|
||||
set_cmd_completer (commands.set, color_completer);
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
/* Same as above but using a getter and a setter function instead of a pointer
|
||||
to a global storage buffer. */
|
||||
|
||||
set_show_commands
|
||||
add_setshow_color_cmd (const char *name, command_class theclass,
|
||||
const char *set_doc, const char *show_doc,
|
||||
const char *help_doc,
|
||||
setting_func_types<ui_file_style::color>::set set_func,
|
||||
setting_func_types<ui_file_style::color>::get get_func,
|
||||
show_value_ftype *show_func,
|
||||
cmd_list_element **set_list,
|
||||
cmd_list_element **show_list)
|
||||
{
|
||||
auto cmds = add_setshow_cmd_full<ui_file_style::color>
|
||||
(name, theclass, var_color, nullptr,
|
||||
set_doc, show_doc, help_doc,
|
||||
set_func, get_func, nullptr, show_func,
|
||||
set_list, show_list);
|
||||
|
||||
set_cmd_completer (cmds.set, color_completer);
|
||||
|
||||
return cmds;
|
||||
}
|
||||
|
||||
/* See cli-decode.h. */
|
||||
const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL };
|
||||
|
||||
@@ -2756,3 +2838,95 @@ cli_user_command_p (struct cmd_list_element *cmd)
|
||||
{
|
||||
return cmd->theclass == class_user && cmd->func == do_simple_func;
|
||||
}
|
||||
|
||||
/* See cli-decode.h. */
|
||||
|
||||
ui_file_style::color
|
||||
parse_cli_var_color (const char **args)
|
||||
{
|
||||
/* Do a "set" command. ARG is nullptr if no argument, or the
|
||||
text of the argument. */
|
||||
|
||||
if (args == nullptr || *args == nullptr || **args == '\0')
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
for (size_t i = 0; ui_file_style::basic_color_enums[i]; ++i)
|
||||
{
|
||||
msg.append ("\"");
|
||||
msg.append (ui_file_style::basic_color_enums[i]);
|
||||
msg.append ("\", ");
|
||||
}
|
||||
|
||||
error (_("Requires an argument. Valid arguments are %sinteger from -1 "
|
||||
"to 255 or an RGB hex triplet in a format #RRGGBB"),
|
||||
msg.c_str ());
|
||||
}
|
||||
|
||||
const char *p = skip_to_space (*args);
|
||||
size_t len = p - *args;
|
||||
|
||||
int nmatches = 0;
|
||||
ui_file_style::basic_color match = ui_file_style::NONE;
|
||||
for (int i = 0; ui_file_style::basic_color_enums[i]; ++i)
|
||||
if (strncmp (*args, ui_file_style::basic_color_enums[i], len) == 0)
|
||||
{
|
||||
match = static_cast<ui_file_style::basic_color> (i - 1);
|
||||
if (ui_file_style::basic_color_enums[i][len] == '\0')
|
||||
{
|
||||
nmatches = 1;
|
||||
break; /* Exact match. */
|
||||
}
|
||||
else
|
||||
nmatches++;
|
||||
}
|
||||
|
||||
if (nmatches == 1)
|
||||
{
|
||||
*args += len;
|
||||
return ui_file_style::color (match);
|
||||
}
|
||||
|
||||
if (nmatches > 1)
|
||||
error (_("Ambiguous item \"%.*s\"."), (int) len, *args);
|
||||
|
||||
if (**args != '#')
|
||||
{
|
||||
ULONGEST num = get_ulongest (args);
|
||||
if (num > 255)
|
||||
error (_("integer %s out of range"), pulongest (num));
|
||||
return ui_file_style::color (color_space::XTERM_256COLOR,
|
||||
static_cast<int> (num));
|
||||
}
|
||||
|
||||
/* Try to parse #RRGGBB string. */
|
||||
if (len != 7)
|
||||
error_no_arg (_("invalid RGB hex triplet format"));
|
||||
|
||||
uint8_t r, g, b;
|
||||
int scanned_chars = 0;
|
||||
int parsed_args = sscanf (*args, "#%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%n",
|
||||
&r, &g, &b, &scanned_chars);
|
||||
|
||||
if (parsed_args != 3 || scanned_chars != 7)
|
||||
error_no_arg (_("invalid RGB hex triplet format"));
|
||||
|
||||
*args += len;
|
||||
return ui_file_style::color (r, g, b);
|
||||
}
|
||||
|
||||
/* See cli-decode.h. */
|
||||
|
||||
ui_file_style::color
|
||||
parse_var_color (const char *arg)
|
||||
{
|
||||
const char *end_arg = arg;
|
||||
ui_file_style::color color = parse_cli_var_color (&end_arg);
|
||||
|
||||
int len = end_arg - arg;
|
||||
const char *after = skip_spaces (end_arg);
|
||||
if (*after != '\0')
|
||||
error (_("Junk after item \"%.*s\": %s"), len, arg, after);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -309,6 +309,27 @@ extern const char * const boolean_enums[];
|
||||
/* The enums of auto-boolean commands. */
|
||||
extern const char * const auto_boolean_enums[];
|
||||
|
||||
/* Add the different possible completions of TEXT with color.
|
||||
|
||||
WORD points in the same buffer as TEXT, and completions should be
|
||||
returned relative to this position. For example, suppose TEXT is "foo"
|
||||
and we want to complete to "foobar". If WORD is "oo", return
|
||||
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
|
||||
|
||||
extern void complete_on_color (completion_tracker &tracker,
|
||||
const char *text, const char *word);
|
||||
|
||||
/* Parse ARGS, an option to a var_color variable.
|
||||
*
|
||||
Either returns the parsed value on success or throws an error. ARGS may be
|
||||
one of strings {none, black, red, green, yellow, blue, magenta,
|
||||
cyan, white}, or color number from 0 to 255, or RGB hex triplet #RRGGBB.
|
||||
*/
|
||||
extern ui_file_style::color parse_cli_var_color (const char **args);
|
||||
|
||||
/* Same as above but additionally check that there is no junk in the end. */
|
||||
extern ui_file_style::color parse_var_color (const char *arg);
|
||||
|
||||
/* Verify whether a given cmd_list_element is a user-defined command.
|
||||
Return 1 if it is user-defined. Return 0 otherwise. */
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ union option_value
|
||||
|
||||
/* For var_string and var_filename options. This is allocated with new. */
|
||||
std::string *string;
|
||||
|
||||
/* For var_color options. */
|
||||
ui_file_style::color color = ui_file_style::NONE;
|
||||
};
|
||||
|
||||
/* Holds an options definition and its value. */
|
||||
@@ -433,6 +436,35 @@ parse_option (gdb::array_view<const option_def_group> options_group,
|
||||
val.enumeration = parse_cli_var_enum (args, match->enums);
|
||||
return option_def_and_value {*match, match_ctx, val};
|
||||
}
|
||||
case var_color:
|
||||
{
|
||||
if (completion != nullptr)
|
||||
{
|
||||
const char *after_arg = skip_to_space (*args);
|
||||
if (*after_arg == '\0')
|
||||
{
|
||||
complete_on_color (completion->tracker, *args, *args);
|
||||
|
||||
if (completion->tracker.have_completions ())
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (check_for_argument (args, "--"))
|
||||
{
|
||||
/* Treat e.g., "backtrace -entry-values --" as if there
|
||||
was no argument after "-entry-values". This makes
|
||||
parse_cli_var_color throw an error with a suggestion of
|
||||
what are the valid options. */
|
||||
args = nullptr;
|
||||
}
|
||||
|
||||
option_value val;
|
||||
ui_file_style::color color = parse_cli_var_color (args);
|
||||
ui_file_style::color approx_color = color.approximate (colorsupport ());
|
||||
val.color = approx_color;
|
||||
return option_def_and_value {*match, match_ctx, val};
|
||||
}
|
||||
case var_string:
|
||||
{
|
||||
if (check_for_argument (args, "--"))
|
||||
@@ -683,6 +715,10 @@ save_option_value_in_ctx (std::optional<option_def_and_value> &ov)
|
||||
*ov->option.var_address.enumeration (ov->option, ov->ctx)
|
||||
= ov->value->enumeration;
|
||||
break;
|
||||
case var_color:
|
||||
*ov->option.var_address.color (ov->option, ov->ctx)
|
||||
= ov->value->color;
|
||||
break;
|
||||
case var_string:
|
||||
case var_filename:
|
||||
*ov->option.var_address.string (ov->option, ov->ctx)
|
||||
@@ -789,6 +825,12 @@ append_val_type_str (std::string &help, const option_def &opt,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case var_color:
|
||||
help += ' ';
|
||||
for (size_t i = 0; ui_file_style::basic_color_enums[i]; ++i)
|
||||
help.append (ui_file_style::basic_color_enums[i]).append ("|");
|
||||
help += "NUMBER|#RRGGBB";
|
||||
break;
|
||||
case var_string:
|
||||
help += "STRING";
|
||||
break;
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
int *(*integer) (const option_def &, void *ctx);
|
||||
const char **(*enumeration) (const option_def &, void *ctx);
|
||||
std::string *(*string) (const option_def &, void *ctx);
|
||||
ui_file_style::color *(*color) (const option_def &, void *ctx);
|
||||
}
|
||||
var_address;
|
||||
|
||||
@@ -328,6 +329,26 @@ struct filename_option_def : option_def
|
||||
}
|
||||
};
|
||||
|
||||
/* A var_color command line option. */
|
||||
|
||||
template<typename Context>
|
||||
struct color_option_def : option_def
|
||||
{
|
||||
color_option_def (const char *long_option_,
|
||||
ui_file_style::color *(*get_var_address_cb_) (Context *),
|
||||
show_value_ftype *show_cmd_cb_,
|
||||
const char *set_doc_,
|
||||
const char *show_doc_ = nullptr,
|
||||
const char *help_doc_ = nullptr)
|
||||
: option_def (long_option_, var_color,
|
||||
(erased_get_var_address_ftype *) get_var_address_cb_,
|
||||
show_cmd_cb_,
|
||||
set_doc_, show_doc_, help_doc_)
|
||||
{
|
||||
var_address.color = detail::get_var_address<ui_file_style::color, Context>;
|
||||
}
|
||||
};
|
||||
|
||||
/* A group of options that all share the same context pointer to pass
|
||||
to the options' get-current-value callbacks. */
|
||||
struct option_def_group
|
||||
|
||||
@@ -443,6 +443,13 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
option_changed = c->var->set<const char *> (match);
|
||||
}
|
||||
break;
|
||||
case var_color:
|
||||
{
|
||||
ui_file_style::color color = parse_var_color (arg);
|
||||
ui_file_style::color approx_color = color.approximate (colorsupport ());
|
||||
option_changed = c->var->set<ui_file_style::color> (approx_color);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error (_("gdb internal error: bad var_type in do_setshow_command"));
|
||||
}
|
||||
@@ -520,6 +527,14 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
|
||||
interps_notify_param_changed
|
||||
(name, c->var->get<const char *> ());
|
||||
break;
|
||||
case var_color:
|
||||
{
|
||||
const ui_file_style::color &color
|
||||
= c->var->get<ui_file_style::color> ();
|
||||
interps_notify_param_changed
|
||||
(name, color.to_string ().c_str ());
|
||||
}
|
||||
break;
|
||||
case var_boolean:
|
||||
{
|
||||
const char *opt = c->var->get<bool> () ? "on" : "off";
|
||||
@@ -585,6 +600,12 @@ get_setshow_command_value_string (const setting &var)
|
||||
stb.puts (value);
|
||||
}
|
||||
break;
|
||||
case var_color:
|
||||
{
|
||||
const ui_file_style::color &value = var.get<ui_file_style::color> ();
|
||||
stb.puts (value.to_string ().c_str ());
|
||||
}
|
||||
break;
|
||||
case var_boolean:
|
||||
stb.puts (var.get<bool> () ? "on" : "off");
|
||||
break;
|
||||
|
||||
@@ -42,20 +42,6 @@ bool source_styling = true;
|
||||
|
||||
bool disassembler_styling = true;
|
||||
|
||||
/* Name of colors; must correspond to ui_file_style::basic_color. */
|
||||
static const char * const cli_colors[] = {
|
||||
"none",
|
||||
"black",
|
||||
"red",
|
||||
"green",
|
||||
"yellow",
|
||||
"blue",
|
||||
"magenta",
|
||||
"cyan",
|
||||
"white",
|
||||
nullptr
|
||||
};
|
||||
|
||||
/* Names of intensities; must correspond to
|
||||
ui_file_style::intensity. */
|
||||
static const char * const cli_intensities[] = {
|
||||
@@ -139,8 +125,8 @@ cli_style_option::cli_style_option (const char *name,
|
||||
ui_file_style::intensity intensity)
|
||||
: changed (name),
|
||||
m_name (name),
|
||||
m_foreground (cli_colors[fg - ui_file_style::NONE]),
|
||||
m_background (cli_colors[0]),
|
||||
m_foreground (fg),
|
||||
m_background (ui_file_style::NONE),
|
||||
m_intensity (cli_intensities[intensity])
|
||||
{
|
||||
}
|
||||
@@ -151,32 +137,17 @@ cli_style_option::cli_style_option (const char *name,
|
||||
ui_file_style::intensity i)
|
||||
: changed (name),
|
||||
m_name (name),
|
||||
m_foreground (cli_colors[0]),
|
||||
m_background (cli_colors[0]),
|
||||
m_foreground (ui_file_style::NONE),
|
||||
m_background (ui_file_style::NONE),
|
||||
m_intensity (cli_intensities[i])
|
||||
{
|
||||
}
|
||||
|
||||
/* Return the color number corresponding to COLOR. */
|
||||
|
||||
static int
|
||||
color_number (const char *color)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE (cli_colors); ++i)
|
||||
{
|
||||
if (color == cli_colors[i])
|
||||
return i - 1;
|
||||
}
|
||||
gdb_assert_not_reached ("color not found");
|
||||
}
|
||||
|
||||
/* See cli-style.h. */
|
||||
|
||||
ui_file_style
|
||||
cli_style_option::style () const
|
||||
{
|
||||
int fg = color_number (m_foreground);
|
||||
int bg = color_number (m_background);
|
||||
ui_file_style::intensity intensity = ui_file_style::NORMAL;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE (cli_intensities); ++i)
|
||||
@@ -188,7 +159,7 @@ cli_style_option::style () const
|
||||
}
|
||||
}
|
||||
|
||||
return ui_file_style (fg, bg, intensity);
|
||||
return ui_file_style (m_foreground, m_background, intensity);
|
||||
}
|
||||
|
||||
/* See cli-style.h. */
|
||||
@@ -261,9 +232,8 @@ cli_style_option::add_setshow_commands (enum command_class theclass,
|
||||
|
||||
set_show_commands commands;
|
||||
|
||||
commands = add_setshow_enum_cmd
|
||||
("foreground", theclass, cli_colors,
|
||||
&m_foreground,
|
||||
commands = add_setshow_color_cmd
|
||||
("foreground", theclass, &m_foreground,
|
||||
_("Set the foreground color for this property."),
|
||||
_("Show the foreground color for this property."),
|
||||
nullptr,
|
||||
@@ -273,9 +243,8 @@ cli_style_option::add_setshow_commands (enum command_class theclass,
|
||||
commands.set->set_context (this);
|
||||
commands.show->set_context (this);
|
||||
|
||||
commands = add_setshow_enum_cmd
|
||||
("background", theclass, cli_colors,
|
||||
&m_background,
|
||||
commands = add_setshow_color_cmd
|
||||
("background", theclass, &m_background,
|
||||
_("Set the background color for this property."),
|
||||
_("Show the background color for this property."),
|
||||
nullptr,
|
||||
|
||||
@@ -67,9 +67,9 @@ private:
|
||||
const char *m_name;
|
||||
|
||||
/* The foreground. */
|
||||
const char *m_foreground;
|
||||
ui_file_style::color m_foreground;
|
||||
/* The background. */
|
||||
const char *m_background;
|
||||
ui_file_style::color m_background;
|
||||
/* The intensity. */
|
||||
const char *m_intensity;
|
||||
|
||||
|
||||
@@ -110,7 +110,9 @@ enum var_types
|
||||
/* Enumerated type. Can only have one of the specified values.
|
||||
*VAR is a char pointer to the name of the element that we
|
||||
find. */
|
||||
var_enum
|
||||
var_enum,
|
||||
/* Color type. *VAR is a ui_file_style::color structure. */
|
||||
var_color
|
||||
};
|
||||
|
||||
/* A structure describing an extra literal accepted and shown in place
|
||||
@@ -184,6 +186,14 @@ inline bool var_type_uses<const char *> (var_types t)
|
||||
return t == var_enum;
|
||||
}
|
||||
|
||||
/* Return true if a setting of type T is backed by an ui_file_style::color
|
||||
variable. */
|
||||
template<>
|
||||
inline bool var_type_uses<ui_file_style::color> (var_types t)
|
||||
{
|
||||
return t == var_color;
|
||||
}
|
||||
|
||||
template<bool is_scalar, typename T> struct setting_func_types_1;
|
||||
|
||||
template<typename T>
|
||||
@@ -680,6 +690,20 @@ extern set_show_commands add_setshow_enum_cmd
|
||||
setting_func_types<const char *>::get get_func, show_value_ftype *show_func,
|
||||
cmd_list_element **set_list, cmd_list_element **show_list);
|
||||
|
||||
extern set_show_commands add_setshow_color_cmd
|
||||
(const char *name, command_class theclass, ui_file_style::color *var,
|
||||
const char *set_doc, const char *show_doc, const char *help_doc,
|
||||
cmd_func_ftype *set_func, show_value_ftype *show_func,
|
||||
cmd_list_element **set_list, cmd_list_element **show_list);
|
||||
|
||||
extern set_show_commands add_setshow_color_cmd
|
||||
(const char *name, command_class theclass,
|
||||
const char *set_doc, const char *show_doc, const char *help_doc,
|
||||
setting_func_types<ui_file_style::color>::set set_func,
|
||||
setting_func_types<ui_file_style::color>::get get_func,
|
||||
show_value_ftype *show_func, cmd_list_element **set_list,
|
||||
cmd_list_element **show_list);
|
||||
|
||||
extern set_show_commands add_setshow_auto_boolean_cmd
|
||||
(const char *name, command_class theclass, auto_boolean *var,
|
||||
const char *set_doc, const char *show_doc, const char *help_doc,
|
||||
|
||||
@@ -13009,6 +13009,20 @@ and @code{$_shell_exitsignal} according to the exit status of the last
|
||||
launched command. These variables are set and used similarly to
|
||||
the variables @code{$_exitcode} and @code{$_exitsignal}.
|
||||
|
||||
@item $_colorsupport
|
||||
@vindex $_colorsupport@r{, convenience variable}
|
||||
@cindex color space
|
||||
Comma-separated list of @dfn{color space} names supported by terminal. Names
|
||||
could be any of @samp{monochrome}, @samp{ansi_8color}, @samp{aixterm_16color},
|
||||
@samp{xterm_256color}, @samp{rgb_24bit}. E.g., for plain linux terminal the
|
||||
value could be @samp{monochrome,ansi_8color} and for terminal with truecolor
|
||||
support it could be
|
||||
@samp{monochrome,ansi_8color,aixterm_16color,xterm_256color,rgb_24bit}.
|
||||
@samp{rgb_24bit} availability is determined by the @env{COLORTERM} environment
|
||||
variable which may be @samp{truecolor} or @samp{24bit}. Other color spaces are
|
||||
determined by the "Co" termcap which in turn depends on the @env{TERM}
|
||||
environment variable.
|
||||
|
||||
@end table
|
||||
|
||||
@node Convenience Funs
|
||||
@@ -27871,16 +27885,32 @@ For example, the style of file names can be controlled using the
|
||||
|
||||
@table @code
|
||||
@item set style filename background @var{color}
|
||||
Set the background to @var{color}. Valid colors are @samp{none}
|
||||
(meaning the terminal's default color), @samp{black}, @samp{red},
|
||||
@samp{green}, @samp{yellow}, @samp{blue}, @samp{magenta}, @samp{cyan},
|
||||
and@samp{white}.
|
||||
Set the background to @var{color}. @var{color} can be @samp{none}
|
||||
(meaning the terminal's default color), a name of one of the eight standard
|
||||
colors of ISO/IEC 6429, index from 0 to 255 into terminal's color
|
||||
palette or a hexadecimal RGB triplet in @samp{#RRGGBB} format for
|
||||
24-bit TrueColor.
|
||||
|
||||
Valid color names are @samp{black}, @samp{red}, @samp{green},
|
||||
@samp{yellow}, @samp{blue}, @samp{magenta}, @samp{cyan}, and
|
||||
@samp{white}.
|
||||
|
||||
Integers 0 to 7 are the synonyms for the standard colors. Integers 8-15 are
|
||||
used for the so-called bright colors from the aixterm extended 16-color
|
||||
palette. Integers 16-255 are the indexes into xterm extended 256-color palette
|
||||
(usually 6x6x6 cube plus gray ramp). In general, 256-color palette is terminal
|
||||
dependent and sometimes can be changed with OSC 4 sequences, e.g.
|
||||
"\033]4;1;rgb:00/FF/00\033\\". A hexadecimal 24-bit TrueColor is specified in
|
||||
the format @samp{#RRGGBB} where RR, GG and BB are the 2-digit hexadecimal
|
||||
integers specifiing the intensity of the red, green and blue color components,
|
||||
respectively.
|
||||
|
||||
It is the responsibility of the user to verify that the terminal supports
|
||||
the specified colors.
|
||||
|
||||
@item set style filename foreground @var{color}
|
||||
Set the foreground to @var{color}. Valid colors are @samp{none}
|
||||
(meaning the terminal's default color), @samp{black}, @samp{red},
|
||||
@samp{green}, @samp{yellow}, @samp{blue}, @samp{magenta}, @samp{cyan},
|
||||
and@samp{white}.
|
||||
Set the foreground to @var{color}. @var{color} can be given in the same ways
|
||||
as for the background.
|
||||
|
||||
@item set style filename intensity @var{value}
|
||||
Set the intensity to @var{value}. Valid intensities are @samp{normal}
|
||||
|
||||
@@ -155,6 +155,7 @@ from the Guile interactive prompt.
|
||||
* I/O Ports in Guile:: GDB I/O ports
|
||||
* Memory Ports in Guile:: Accessing memory through ports and bytevectors
|
||||
* Iterators In Guile:: Basic iterator support
|
||||
* Colors In Guile:: Colorize output with Guile
|
||||
@end menu
|
||||
|
||||
@node Basic Guile
|
||||
@@ -408,6 +409,9 @@ as a symbol.
|
||||
|
||||
@item <gdb:value>
|
||||
@xref{Values From Inferior In Guile}.
|
||||
|
||||
@item <gdb:color>
|
||||
@xref{Colors In Guile}.
|
||||
@end table
|
||||
|
||||
The following @value{GDBN} objects are managed internally so that the
|
||||
@@ -2184,6 +2188,14 @@ The value is a filename. This is just like
|
||||
@item PARAM_ENUM
|
||||
The value is a string, which must be one of a collection of string
|
||||
constants provided when the parameter is created.
|
||||
|
||||
@item PARAM_COLOR
|
||||
The value is either a string or an unsigned integer. Integer from 0 to 255
|
||||
means index into terminal's color palette. String can be a hex RGB triplet in
|
||||
@samp{#RRGGBB} format or one of the following color names:
|
||||
@samp{none} (meaning the terminal's default color), @samp{black}, @samp{red},
|
||||
@samp{green}, @samp{yellow}, @samp{blue}, @samp{magenta}, @samp{cyan},
|
||||
or @samp{white}.
|
||||
@end vtable
|
||||
|
||||
@node Progspaces In Guile
|
||||
@@ -3820,6 +3832,98 @@ Run @var{iterator} until the result of @code{(pred element)} is true
|
||||
and return that as the result. Otherwise return @code{#f}.
|
||||
@end deffn
|
||||
|
||||
@node Colors In Guile
|
||||
@subsubsection Colors In Guile
|
||||
|
||||
@cindex guile colors
|
||||
@tindex <gdb:color>
|
||||
You can assign instance of @code{<gdb:color>} to the value of
|
||||
a @code{<gdb:parameter>} object created with @code{PARAM_COLOR}.
|
||||
|
||||
@code{<gdb:color>} may refer to an index from color palette or contain
|
||||
components of a color from some colorspace.
|
||||
|
||||
@deffn {Scheme Procedure} make-color @w{@r{[}value} @
|
||||
@w{@r{[}#:color-space color-space@r{]}@r{]}}
|
||||
|
||||
@var{value} is an integer index of a color in palette, tuple with color
|
||||
components or a string. String can be a hex RGB triplet in @samp{#RRGGBB}
|
||||
format or one of the following color names:
|
||||
@samp{none} (meaning the terminal's default color), @samp{black}, @samp{red},
|
||||
@samp{green}, @samp{yellow}, @samp{blue}, @samp{magenta}, @samp{cyan},
|
||||
or @samp{white}.
|
||||
|
||||
@var{color-space} should be one of the @samp{COLORSPACE_} constants. This
|
||||
argument tells @value{GDBN} which color space @var{value} belongs.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color? object
|
||||
Return @code{#t} if @var{object} is a @code{<gdb:color>} object.
|
||||
Otherwise return @code{#f}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-none? color
|
||||
Return @code{#t} if @var{color} is terminal's default.
|
||||
Otherwise return @code{#f}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-indexed? color
|
||||
Return @code{#t} if @var{color} is indexed, i.e. belongs to some palette.
|
||||
Otherwise return @code{#f}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-direct? color
|
||||
Return @code{#t} if @var{color} is direct in the sense of ISO/IEC 8613-6.
|
||||
Otherwise return @code{#f}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-string color
|
||||
Return the textual representation of a @code{<gdb:color>} object.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-colorspace color
|
||||
Return the color space of a @code{<gdb:color>} object.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-index color
|
||||
Return index of the color of a @code{<gdb:color>} object in a palette.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-components color
|
||||
Return components of the direct @code{<gdb:color>} object.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} color-escape-sequence color is_foreground
|
||||
Return string to change terminal's color to this.
|
||||
|
||||
If @var{is_foreground} is @code{#t}, then the returned sequence will change
|
||||
foreground color. Otherwise, the returned sequence will change background
|
||||
color.
|
||||
@end deffn
|
||||
|
||||
When color is initialized, its color space must be specified. The
|
||||
available color spaces are represented by constants defined in the @code{gdb}
|
||||
module:
|
||||
|
||||
@vtable @code
|
||||
@item COLORSPACE_MONOCHROME
|
||||
Palette with only terminal's default color.
|
||||
|
||||
@item COLORSPACE_ANSI_8COLOR
|
||||
Palette with eight standard colors of ISO/IEC 6429 "black", "red", "green", etc.
|
||||
|
||||
@item COLORSPACE_AIXTERM_16COLOR
|
||||
Palette with 16 colors. First eight are standard colors of ISO/IEC 6429
|
||||
"black", "red", "green", etc. Next eight are their bright version.
|
||||
|
||||
@item COLORSPACE_XTERM_256COLOR
|
||||
Palette with 256 colors. First 16 are from COLORSPACE_AIXTERM_16COLOR. Next
|
||||
216 colors are 6x6x6 RGB cube. And last 24 colors form grayscale ramp.
|
||||
|
||||
@item COLORSPACE_RGB_24BIT
|
||||
Direct 24-bit RGB colors.
|
||||
@end vtable
|
||||
|
||||
@node Guile Auto-loading
|
||||
@subsection Guile Auto-loading
|
||||
@cindex guile auto-loading
|
||||
|
||||
@@ -225,6 +225,7 @@ optional arguments while skipping others. Example:
|
||||
* Finish Breakpoints in Python:: Setting Breakpoints on function return
|
||||
using Python.
|
||||
* Lazy Strings In Python:: Python representation of lazy strings.
|
||||
* Colors In Python:: Python representation of colors.
|
||||
* Architectures In Python:: Python representation of architectures.
|
||||
* Registers In Python:: Python representation of registers.
|
||||
* Connections In Python:: Python representation of connections.
|
||||
@@ -5242,6 +5243,11 @@ except the special value -1 is returned for the setting of ``unlimited''.
|
||||
@item gdb.PARAM_ENUM
|
||||
The value is a string, which must be one of a collection string
|
||||
constants provided when the parameter is created.
|
||||
|
||||
@findex PARAM_COLOR
|
||||
@findex gdb.PARAM_COLOR
|
||||
@item gdb.PARAM_COLOR
|
||||
The value is @code{gdb.Color} instance.
|
||||
@end table
|
||||
|
||||
@node Functions In Python
|
||||
@@ -7020,6 +7026,98 @@ resolve this to the lazy string's character type, use the type's
|
||||
writable.
|
||||
@end defvar
|
||||
|
||||
@node Colors In Python
|
||||
@subsubsection Python representation of colors
|
||||
|
||||
@cindex colors in python
|
||||
@tindex gdb.Color
|
||||
You can assign instance of @code{Color} to the @code{value} of
|
||||
a @code{Parameter} instance created with @code{PARAM_COLOR}.
|
||||
|
||||
@code{Color} may refer to an index from color palette or contain components
|
||||
of a color from some colorspace.
|
||||
|
||||
@defun Color.__init__ (@r{[}@var{value} @r{[}, @var{color-space}@r{]}@r{]})
|
||||
|
||||
@var{value} is @code{None} (meaning the terminal's default color),
|
||||
an integer index of a color in palette, tuple with color components
|
||||
or a string. String can be a hex RGB triplet in @samp{#RRGGBB} format
|
||||
or one of the following color names:
|
||||
@samp{none} (meaning the terminal's default color), @samp{black}, @samp{red},
|
||||
@samp{green}, @samp{yellow}, @samp{blue}, @samp{magenta}, @samp{cyan},
|
||||
or @samp{white}.
|
||||
|
||||
@var{color-space} should be one of the @samp{COLORSPACE_} constants. This
|
||||
argument tells @value{GDBN} which color space @var{value} belongs.
|
||||
@end defun
|
||||
|
||||
@defvar Color.is_none
|
||||
This atribute is boolean. If its value is @code{True} then color is terminal's
|
||||
default.
|
||||
@end defvar
|
||||
|
||||
@defvar Color.is_indexed
|
||||
This atribute is boolean. If its value is @code{True} then color is indexed,
|
||||
i.e. belongs to some palette.
|
||||
@end defvar
|
||||
|
||||
@defvar Color.is_direct
|
||||
This atribute is boolean. If its value is @code{True} then this object
|
||||
describes direct colour in the sense of ISO/IEC 8613-6.
|
||||
@end defvar
|
||||
|
||||
@defvar Color.index
|
||||
This attribute exist if @code{is_indexed} is @code{True}. Its integer value is
|
||||
index of a color in a palette.
|
||||
@end defvar
|
||||
|
||||
@defvar Color.components
|
||||
This attribute exist if @code{is_direct} is @code{True}. Its value is tuple
|
||||
with integer components of a color.
|
||||
@end defvar
|
||||
|
||||
@defun Color.escape_sequence (@var{self}, @var{is_foreground})
|
||||
Returns string to change terminal's color to this.
|
||||
|
||||
If @var{is_foreground} is @code{True}, then the returned sequence will change
|
||||
foreground color. Otherwise, the returned sequence will change background
|
||||
color.
|
||||
@end defun
|
||||
|
||||
When color is initialized, its color space must be specified. The
|
||||
available color spaces are represented by constants defined in the @code{gdb}
|
||||
module:
|
||||
|
||||
@table @code
|
||||
@findex COLORSPACE_MONOCHROME
|
||||
@findex gdb.COLORSPACE_MONOCHROME
|
||||
@item gdb.COLORSPACE_MONOCHROME
|
||||
Palette with only terminal's default color.
|
||||
|
||||
@findex COLORSPACE_ANSI_8COLOR
|
||||
@findex gdb.COLORSPACE_ANSI_8COLOR
|
||||
@item gdb.COLORSPACE_ANSI_8COLOR
|
||||
Palette with eight standard colors of ISO/IEC 6429 "black", "red", "green", etc.
|
||||
|
||||
@findex COLORSPACE_AIXTERM_16COLOR
|
||||
@findex gdb.COLORSPACE_AIXTERM_16COLOR
|
||||
@item gdb.COLORSPACE_AIXTERM_16COLOR
|
||||
Palette with 16 colors. First eight are standard colors of ISO/IEC 6429
|
||||
"black", "red", "green", etc. Next eight are their bright version.
|
||||
|
||||
@findex COLORSPACE_XTERM_256COLOR
|
||||
@findex gdb.COLORSPACE_XTERM_256COLOR
|
||||
@item gdb.COLORSPACE_XTERM_256COLOR
|
||||
Palette with 256 colors. First 16 are from COLORSPACE_AIXTERM_16COLOR. Next
|
||||
216 colors are 6x6x6 RGB cube. And last 24 colors form grayscale ramp.
|
||||
|
||||
@findex COLORSPACE_RGB_24BIT
|
||||
@findex gdb.COLORSPACE_RGB_24BIT
|
||||
@item gdb.COLORSPACE_RGB_24BIT
|
||||
Direct 24-bit RGB colors.
|
||||
|
||||
@end table
|
||||
|
||||
@node Architectures In Python
|
||||
@subsubsection Python representation of architectures
|
||||
@cindex Python architectures
|
||||
|
||||
@@ -452,6 +452,14 @@ extern int gdbscm_valid_command_class_p (int command_class);
|
||||
extern char *gdbscm_canonicalize_command_name (const char *name,
|
||||
int want_trailing_space);
|
||||
|
||||
/* scm-color.c */
|
||||
|
||||
extern SCM coscm_scm_from_color (const ui_file_style::color &color);
|
||||
|
||||
extern int coscm_is_color (SCM scm);
|
||||
|
||||
extern const ui_file_style::color & coscm_get_color (SCM color_scm);
|
||||
|
||||
/* scm-frame.c */
|
||||
|
||||
struct frame_smob;
|
||||
@@ -630,6 +638,7 @@ extern void gdbscm_initialize_arches (void);
|
||||
extern void gdbscm_initialize_auto_load (void);
|
||||
extern void gdbscm_initialize_blocks (void);
|
||||
extern void gdbscm_initialize_breakpoints (void);
|
||||
extern void gdbscm_initialize_colors (void);
|
||||
extern void gdbscm_initialize_commands (void);
|
||||
extern void gdbscm_initialize_disasm (void);
|
||||
extern void gdbscm_initialize_exceptions (void);
|
||||
|
||||
@@ -594,6 +594,7 @@ initialize_gdb_module (void *data)
|
||||
gdbscm_initialize_auto_load ();
|
||||
gdbscm_initialize_blocks ();
|
||||
gdbscm_initialize_breakpoints ();
|
||||
gdbscm_initialize_colors ();
|
||||
gdbscm_initialize_commands ();
|
||||
gdbscm_initialize_disasm ();
|
||||
gdbscm_initialize_frames ();
|
||||
|
||||
427
gdb/guile/scm-color.c
Normal file
427
gdb/guile/scm-color.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/* GDB parameters implemented in Guile.
|
||||
|
||||
Copyright (C) 2008-2024 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/>. */
|
||||
|
||||
#include "value.h"
|
||||
#include "charset.h"
|
||||
#include "cli/cli-decode.h"
|
||||
#include "completer.h"
|
||||
#include "language.h"
|
||||
#include "arch-utils.h"
|
||||
#include "guile-internal.h"
|
||||
|
||||
/* A GDB color. */
|
||||
|
||||
struct color_smob
|
||||
{
|
||||
/* This always appears first. */
|
||||
gdb_smob base;
|
||||
|
||||
/* Underlying value. */
|
||||
ui_file_style::color color;
|
||||
};
|
||||
|
||||
static const char color_smob_name[] = "gdb:color";
|
||||
|
||||
/* The tag Guile knows the color smob by. */
|
||||
static scm_t_bits color_smob_tag;
|
||||
|
||||
/* Keywords used by make-color. */
|
||||
static SCM colorspace_keyword;
|
||||
|
||||
static const char *coscm_colorspace_name (color_space colorspace);
|
||||
|
||||
/* Administrivia for color smobs. */
|
||||
|
||||
static int
|
||||
coscm_print_color_smob (SCM self, SCM port, scm_print_state *pstate)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
|
||||
gdbscm_printf (port, "#<%s", color_smob_name);
|
||||
|
||||
gdbscm_printf (port, " %s", color.to_string ().c_str ());
|
||||
gdbscm_printf (port, " %s", coscm_colorspace_name (color.colorspace ()));
|
||||
scm_puts (">", port);
|
||||
|
||||
scm_remember_upto_here_1 (self);
|
||||
|
||||
/* Non-zero means success. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create an empty (uninitialized) color. */
|
||||
|
||||
static SCM
|
||||
coscm_make_color_smob (void)
|
||||
{
|
||||
color_smob *c_smob = (color_smob *)
|
||||
scm_gc_calloc (sizeof (color_smob), color_smob_name);
|
||||
SCM c_scm;
|
||||
|
||||
c_smob->color = ui_file_style::color (ui_file_style::NONE);
|
||||
c_scm = scm_new_smob (color_smob_tag, (scm_t_bits) c_smob);
|
||||
gdbscm_init_gsmob (&c_smob->base);
|
||||
|
||||
return c_scm;
|
||||
}
|
||||
|
||||
/* Return the <gdb:color> object that encapsulates COLOR. */
|
||||
|
||||
SCM
|
||||
coscm_scm_from_color (const ui_file_style::color &color)
|
||||
{
|
||||
SCM c_scm = coscm_make_color_smob ();
|
||||
color_smob *c_smob = (color_smob *) SCM_SMOB_DATA (c_scm);
|
||||
c_smob->color = color;
|
||||
return c_scm;
|
||||
}
|
||||
|
||||
/* Return the color field of color_smob. */
|
||||
|
||||
const ui_file_style::color &
|
||||
coscm_get_color (SCM color_scm)
|
||||
{
|
||||
SCM_ASSERT_TYPE (coscm_is_color (color_scm), color_scm, SCM_ARG1, FUNC_NAME,
|
||||
_("<gdb:color>"));
|
||||
|
||||
color_smob *c_smob = (color_smob *) SCM_SMOB_DATA (color_scm);
|
||||
return c_smob->color;
|
||||
|
||||
}
|
||||
|
||||
/* Returns non-zero if SCM is a <gdb:color> object. */
|
||||
|
||||
int
|
||||
coscm_is_color (SCM scm)
|
||||
{
|
||||
return SCM_SMOB_PREDICATE (color_smob_tag, scm);
|
||||
}
|
||||
|
||||
/* (gdb:color? scm) -> boolean */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_p (SCM scm)
|
||||
{
|
||||
return scm_from_bool (coscm_is_color (scm));
|
||||
}
|
||||
|
||||
static const scheme_integer_constant colorspaces[] =
|
||||
{
|
||||
{ "COLORSPACE_MONOCHROME", (int) color_space::MONOCHROME },
|
||||
{ "COLORSPACE_ANSI_8COLOR", (int) color_space::ANSI_8COLOR },
|
||||
{ "COLORSPACE_AIXTERM_16COLOR", (int) color_space::AIXTERM_16COLOR },
|
||||
{ "COLORSPACE_XTERM_256COLOR", (int) color_space::XTERM_256COLOR },
|
||||
{ "COLORSPACE_RGB_24BIT", (int) color_space::RGB_24BIT },
|
||||
|
||||
END_INTEGER_CONSTANTS
|
||||
};
|
||||
|
||||
/* Return COLORSPACE as a string. */
|
||||
|
||||
static const char *
|
||||
coscm_colorspace_name (color_space colorspace)
|
||||
{
|
||||
for (int i = 0; colorspaces[i].name != nullptr; ++i)
|
||||
{
|
||||
if (colorspaces[i].value == static_cast<int> (colorspace))
|
||||
return colorspaces[i].name;
|
||||
}
|
||||
|
||||
gdb_assert_not_reached ("bad color space");
|
||||
}
|
||||
|
||||
/* Free function for a color_smob. */
|
||||
static size_t
|
||||
coscm_free_color_smob (SCM self)
|
||||
{
|
||||
(void) self;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Color Scheme functions. */
|
||||
|
||||
/* (make-color [value
|
||||
[#:color-space colorspace]]) -> <gdb:color>
|
||||
|
||||
VALUE is the value of the color. It may be SCM_UNDEFINED, string, number
|
||||
or list.
|
||||
|
||||
COLORSPACE is the color space of the VALUE. It should be one of the
|
||||
COLORSPACE_* constants defined in the gdb module.
|
||||
|
||||
The result is the <gdb:color> Scheme object. */
|
||||
|
||||
static SCM
|
||||
gdbscm_make_color (SCM value_scm, SCM rest)
|
||||
{
|
||||
SCM colorspace_arg = SCM_UNDEFINED;
|
||||
color_space colorspace = color_space::MONOCHROME;
|
||||
|
||||
scm_c_bind_keyword_arguments (FUNC_NAME, rest,
|
||||
static_cast<scm_t_keyword_arguments_flags> (0),
|
||||
colorspace_keyword, &colorspace_arg,
|
||||
SCM_UNDEFINED);
|
||||
|
||||
if (!SCM_UNBNDP (colorspace_arg))
|
||||
{
|
||||
SCM_ASSERT_TYPE (scm_is_integer (colorspace_arg), colorspace_arg,
|
||||
SCM_ARG2, FUNC_NAME, _("int"));
|
||||
int colorspace_int = scm_to_int (colorspace_arg);
|
||||
if (!color_space_safe_cast (&colorspace, colorspace_int))
|
||||
gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2,
|
||||
scm_from_int (colorspace_int),
|
||||
_("invalid colorspace argument"));
|
||||
}
|
||||
|
||||
ui_file_style::color color = ui_file_style::NONE;
|
||||
gdbscm_gdb_exception exc {};
|
||||
|
||||
try
|
||||
{
|
||||
if (SCM_UNBNDP (value_scm) || scm_is_integer (value_scm))
|
||||
{
|
||||
int i = -1;
|
||||
if (scm_is_integer (value_scm))
|
||||
{
|
||||
i = scm_to_int (value_scm);
|
||||
if (i < 0)
|
||||
gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, value_scm,
|
||||
_("negative color index"));
|
||||
}
|
||||
|
||||
if (SCM_UNBNDP (colorspace_arg))
|
||||
color = ui_file_style::color (i);
|
||||
else
|
||||
color = ui_file_style::color (colorspace, i);
|
||||
}
|
||||
else if (gdbscm_is_true (scm_list_p (value_scm)))
|
||||
{
|
||||
if (SCM_UNBNDP (colorspace_arg)
|
||||
|| colorspace != color_space::RGB_24BIT)
|
||||
error (_("colorspace must be COLORSPACE_RGB_24BIT with "
|
||||
"value of list type."));
|
||||
|
||||
if (scm_ilength (value_scm) != 3)
|
||||
error (_("List value with RGB must be of size 3."));
|
||||
|
||||
uint8_t rgb[3] = {};
|
||||
int i = 0;
|
||||
for (; i < 3 && !scm_is_eq (value_scm, SCM_EOL); ++i)
|
||||
{
|
||||
SCM item = scm_car (value_scm);
|
||||
|
||||
SCM_ASSERT_TYPE (scm_is_integer (item), item, SCM_ARG1, FUNC_NAME,
|
||||
_("int"));
|
||||
int component = scm_to_int (item);
|
||||
if (component < 0 || component > UINT8_MAX)
|
||||
gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, item,
|
||||
_("invalid rgb component"));
|
||||
rgb[i] = static_cast<uint8_t> (component);
|
||||
|
||||
value_scm = scm_cdr (value_scm);
|
||||
}
|
||||
|
||||
gdb_assert (i == 3);
|
||||
|
||||
color = ui_file_style::color (rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else if (scm_is_string (value_scm))
|
||||
{
|
||||
SCM exception;
|
||||
|
||||
gdb::unique_xmalloc_ptr<char> string
|
||||
= gdbscm_scm_to_host_string (value_scm, nullptr, &exception);
|
||||
if (string == nullptr)
|
||||
gdbscm_throw (exception);
|
||||
|
||||
color = parse_var_color (string.get ());
|
||||
|
||||
if (!SCM_UNBNDP (colorspace_arg) && colorspace != color.colorspace ())
|
||||
error (_("colorspace doesn't match to the value."));
|
||||
|
||||
}
|
||||
else
|
||||
scm_wrong_type_arg_msg (FUNC_NAME, SCM_ARG1, value_scm,
|
||||
"integer, string or list");
|
||||
}
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
exc = unpack (except);
|
||||
}
|
||||
|
||||
GDBSCM_HANDLE_GDB_EXCEPTION (exc);
|
||||
|
||||
return coscm_scm_from_color (color);
|
||||
}
|
||||
|
||||
/* (color-string <gdb:color>) -> value */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_string (SCM self)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
std::string s = color.to_string ();
|
||||
return gdbscm_scm_from_host_string (s.c_str (), s.size ());
|
||||
}
|
||||
|
||||
/* (color-colorspace <gdb:color>) -> value */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_colorspace (SCM self)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
return scm_from_int (static_cast<int> (color.colorspace ()));
|
||||
}
|
||||
|
||||
/* (color-none? scm) -> boolean */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_none_p (SCM self)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
return scm_from_bool (color.is_none ());
|
||||
}
|
||||
|
||||
/* (color-indexed? scm) -> boolean */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_indexed_p (SCM self)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
return scm_from_bool (color.is_indexed ());
|
||||
}
|
||||
|
||||
/* (color-direct? scm) -> boolean */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_direct_p (SCM self)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
return scm_from_bool (color.is_direct ());
|
||||
}
|
||||
|
||||
/* (color-index <gdb:color>) -> value */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_index (SCM self)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
|
||||
if (!color.is_indexed ())
|
||||
gdbscm_misc_error (FUNC_NAME, SCM_ARG1, self, "color is not indexed");
|
||||
return scm_from_int (color.get_value ());
|
||||
}
|
||||
|
||||
/* (color-components <gdb:color>) -> value */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_components (SCM self)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
|
||||
if (!color.is_direct ())
|
||||
gdbscm_misc_error (FUNC_NAME, SCM_ARG1, self, "color is not direct");
|
||||
|
||||
uint8_t rgb[3] = {};
|
||||
color.get_rgb (rgb);
|
||||
SCM red = scm_from_uint8 (rgb[0]);
|
||||
SCM green = scm_from_uint8 (rgb[1]);
|
||||
SCM blue = scm_from_uint8 (rgb[2]);
|
||||
return scm_list_3 (red, green, blue);
|
||||
}
|
||||
|
||||
/* (color-escape-sequence <gdb:color> is_fg) -> value */
|
||||
|
||||
static SCM
|
||||
gdbscm_color_escape_sequence (SCM self, SCM is_fg_scm)
|
||||
{
|
||||
const ui_file_style::color &color = coscm_get_color (self);
|
||||
SCM_ASSERT_TYPE (gdbscm_is_bool (is_fg_scm), is_fg_scm, SCM_ARG2, FUNC_NAME,
|
||||
_("boolean"));
|
||||
bool is_fg = gdbscm_is_true (is_fg_scm);
|
||||
std::string s = color.to_ansi (is_fg);
|
||||
return gdbscm_scm_from_host_string (s.c_str (), s.size ());
|
||||
}
|
||||
|
||||
/* Initialize the Scheme color support. */
|
||||
|
||||
static const scheme_function color_functions[] =
|
||||
{
|
||||
{ "make-color", 0, 1, 1, as_a_scm_t_subr (gdbscm_make_color),
|
||||
"\
|
||||
Make a GDB color object.\n\
|
||||
\n\
|
||||
Arguments: [value\n\
|
||||
[#:color-space <colorspace>]]\n\
|
||||
value: The name of the color. It may be string, number with color index\n\
|
||||
or list with RGB components.\n\
|
||||
colorspace: The color space of the color, one of COLORSPACE_*." },
|
||||
|
||||
{ "color?", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_p),
|
||||
"\
|
||||
Return #t if the object is a <gdb:color> object." },
|
||||
|
||||
{ "color-none?", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_none_p),
|
||||
"\
|
||||
Return #t if the <gdb:color> object has default color." },
|
||||
|
||||
{ "color-indexed?", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_indexed_p),
|
||||
"\
|
||||
Return #t if the <gdb:color> object is from indexed color space." },
|
||||
|
||||
{ "color-direct?", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_direct_p),
|
||||
"\
|
||||
Return #t if the <gdb:color> object has direct color (e.g. RGB, CMY, CMYK)." },
|
||||
|
||||
{ "color-string", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_string),
|
||||
"\
|
||||
Return the textual representation of a <gdb:color> object." },
|
||||
|
||||
{ "color-colorspace", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_colorspace),
|
||||
"\
|
||||
Return the color space of a <gdb:color> object." },
|
||||
|
||||
{ "color-index", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_index),
|
||||
"\
|
||||
Return index of the color of a <gdb:color> object in a palette." },
|
||||
|
||||
{ "color-components", 1, 0, 0, as_a_scm_t_subr (gdbscm_color_components),
|
||||
"\
|
||||
Return components of the direct <gdb:color> object." },
|
||||
|
||||
{ "color-escape-sequence", 2, 0, 0,
|
||||
as_a_scm_t_subr (gdbscm_color_escape_sequence),
|
||||
"\
|
||||
Return string to change terminal's color to this." },
|
||||
|
||||
END_FUNCTIONS
|
||||
};
|
||||
|
||||
void
|
||||
gdbscm_initialize_colors (void)
|
||||
{
|
||||
color_smob_tag = gdbscm_make_smob_type (color_smob_name, sizeof (color_smob));
|
||||
scm_set_smob_free (color_smob_tag, coscm_free_color_smob);
|
||||
scm_set_smob_print (color_smob_tag, coscm_print_color_smob);
|
||||
|
||||
gdbscm_define_integer_constants (colorspaces, 1);
|
||||
gdbscm_define_functions (color_functions, 1);
|
||||
|
||||
colorspace_keyword = scm_from_latin1_keyword ("color-space");
|
||||
}
|
||||
@@ -47,6 +47,9 @@ union pascm_variable
|
||||
|
||||
/* Hold a string, for enums. */
|
||||
const char *cstringval;
|
||||
|
||||
/* Hold a color. */
|
||||
ui_file_style::color color;
|
||||
};
|
||||
|
||||
/* A GDB parameter.
|
||||
@@ -130,6 +133,7 @@ enum scm_param_types
|
||||
param_optional_filename,
|
||||
param_filename,
|
||||
param_enum,
|
||||
param_color,
|
||||
};
|
||||
|
||||
/* Translation from Guile parameters to GDB variable types. Keep in the
|
||||
@@ -155,7 +159,8 @@ param_to_var[] =
|
||||
{ var_string_noescape },
|
||||
{ var_optional_filename },
|
||||
{ var_filename },
|
||||
{ var_enum }
|
||||
{ var_enum },
|
||||
{ var_color }
|
||||
};
|
||||
|
||||
/* Wraps a setting around an existing param_smob. This abstraction
|
||||
@@ -179,6 +184,8 @@ make_setting (param_smob *s)
|
||||
return setting (type, s->value.stringval);
|
||||
else if (var_type_uses<const char *> (type))
|
||||
return setting (type, &s->value.cstringval);
|
||||
else if (var_type_uses<ui_file_style::color> (s->type))
|
||||
return setting (s->type, &s->value.color);
|
||||
else
|
||||
gdb_assert_not_reached ("unhandled var type");
|
||||
}
|
||||
@@ -239,10 +246,9 @@ static SCM
|
||||
pascm_make_param_smob (void)
|
||||
{
|
||||
param_smob *p_smob = (param_smob *)
|
||||
scm_gc_malloc (sizeof (param_smob), param_smob_name);
|
||||
scm_gc_calloc (sizeof (param_smob), param_smob_name);
|
||||
SCM p_scm;
|
||||
|
||||
memset (p_smob, 0, sizeof (*p_smob));
|
||||
p_smob->cmd_class = no_class;
|
||||
p_smob->type = var_boolean; /* ARI: var_boolean */
|
||||
p_smob->set_func = SCM_BOOL_F;
|
||||
@@ -511,6 +517,13 @@ add_setshow_generic (enum var_types param_type,
|
||||
set_list, show_list);
|
||||
break;
|
||||
|
||||
case var_color:
|
||||
commands = add_setshow_color_cmd (cmd_name, cmd_class, &self->value.color,
|
||||
set_doc, show_doc, help_doc,
|
||||
set_func, show_func,
|
||||
set_list, show_list);
|
||||
break;
|
||||
|
||||
default:
|
||||
gdb_assert_not_reached ("bad param_type value");
|
||||
}
|
||||
@@ -588,6 +601,7 @@ static const scheme_integer_constant parameter_types[] =
|
||||
{ "PARAM_OPTIONAL_FILENAME", param_optional_filename },
|
||||
{ "PARAM_FILENAME", param_filename },
|
||||
{ "PARAM_ENUM", param_enum },
|
||||
{ "PARAM_COLOR", param_color },
|
||||
|
||||
END_INTEGER_CONSTANTS
|
||||
};
|
||||
@@ -650,6 +664,11 @@ pascm_param_value (const setting &var, int arg_pos, const char *func_name)
|
||||
return gdbscm_scm_from_host_string (str, strlen (str));
|
||||
}
|
||||
|
||||
case var_color:
|
||||
{
|
||||
return coscm_scm_from_color (var.get<ui_file_style::color> ());
|
||||
}
|
||||
|
||||
case var_boolean:
|
||||
{
|
||||
if (var.get<bool> ())
|
||||
@@ -764,6 +783,12 @@ pascm_set_param_value_x (param_smob *p_smob,
|
||||
break;
|
||||
}
|
||||
|
||||
case var_color:
|
||||
SCM_ASSERT_TYPE (coscm_is_color (value), value, arg_pos, func_name,
|
||||
_("<gdb:color>"));
|
||||
var.set<ui_file_style::color> (coscm_get_color (value));
|
||||
break;
|
||||
|
||||
case var_boolean:
|
||||
SCM_ASSERT_TYPE (gdbscm_is_bool (value), value, arg_pos, func_name,
|
||||
_("boolean"));
|
||||
@@ -1050,6 +1075,8 @@ gdbscm_make_parameter (SCM name_scm, SCM rest)
|
||||
scm_set_smob_free (parameter_smob_tag, pascm_free_parameter_smob);
|
||||
if (var_type_uses<std::string> (p_smob->type))
|
||||
p_smob->value.stringval = new std::string;
|
||||
else if (var_type_uses<ui_file_style::color> (p_smob->type))
|
||||
p_smob->value.color = ui_file_style::NONE;
|
||||
|
||||
if (initial_value_arg_pos > 0)
|
||||
{
|
||||
|
||||
336
gdb/python/py-color.c
Normal file
336
gdb/python/py-color.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* Python interface to ui_file_style::color objects.
|
||||
|
||||
Copyright (C) 2008-2024 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/>. */
|
||||
|
||||
|
||||
#include "python-internal.h"
|
||||
#include "py-color.h"
|
||||
#include "cli/cli-decode.h"
|
||||
|
||||
/* Colorspace constants and their values. */
|
||||
static struct {
|
||||
const char *name;
|
||||
color_space value;
|
||||
} colorspace_constants[] =
|
||||
{
|
||||
{ "COLORSPACE_MONOCHROME", color_space::MONOCHROME },
|
||||
{ "COLORSPACE_ANSI_8COLOR", color_space::ANSI_8COLOR },
|
||||
{ "COLORSPACE_AIXTERM_16COLOR", color_space::AIXTERM_16COLOR },
|
||||
{ "COLORSPACE_XTERM_256COLOR", color_space::XTERM_256COLOR },
|
||||
{ "COLORSPACE_RGB_24BIT", color_space::RGB_24BIT },
|
||||
};
|
||||
|
||||
/* A color. */
|
||||
struct colorpy_object
|
||||
{
|
||||
PyObject_HEAD
|
||||
|
||||
/* Underlying value. */
|
||||
ui_file_style::color color;
|
||||
};
|
||||
|
||||
extern PyTypeObject colorpy_object_type;
|
||||
|
||||
/* See py-color.h. */
|
||||
gdbpy_ref<>
|
||||
create_color_object (const ui_file_style::color &color)
|
||||
{
|
||||
gdbpy_ref<colorpy_object> color_obj (PyObject_New (colorpy_object,
|
||||
&colorpy_object_type));
|
||||
|
||||
if (color_obj == nullptr)
|
||||
return nullptr;
|
||||
|
||||
color_obj->color = color;
|
||||
return gdbpy_ref<> ((PyObject *) color_obj.release ());
|
||||
}
|
||||
|
||||
/* See py-color.h. */
|
||||
bool
|
||||
gdbpy_is_color (PyObject *obj)
|
||||
{
|
||||
return PyObject_IsInstance (obj, (PyObject *) &colorpy_object_type);
|
||||
}
|
||||
|
||||
/* See py-color.h. */
|
||||
const ui_file_style::color &
|
||||
gdbpy_get_color (PyObject *obj)
|
||||
{
|
||||
gdb_assert (gdbpy_is_color (obj));
|
||||
colorpy_object *self = (colorpy_object *) obj;
|
||||
return self->color;
|
||||
}
|
||||
|
||||
/* Get an attribute. */
|
||||
static PyObject *
|
||||
get_attr (PyObject *obj, PyObject *attr_name)
|
||||
{
|
||||
if (! PyUnicode_Check (attr_name))
|
||||
return PyObject_GenericGetAttr (obj, attr_name);
|
||||
|
||||
colorpy_object *self = (colorpy_object *) obj;
|
||||
const ui_file_style::color &color = self->color;
|
||||
|
||||
if (! PyUnicode_CompareWithASCIIString (attr_name, "colorspace"))
|
||||
{
|
||||
int value = static_cast<int> (color.colorspace ());
|
||||
return gdb_py_object_from_longest (value).release ();
|
||||
}
|
||||
|
||||
if (! PyUnicode_CompareWithASCIIString (attr_name, "is_none"))
|
||||
return PyBool_FromLong (color.is_none ());
|
||||
|
||||
if (! PyUnicode_CompareWithASCIIString (attr_name, "is_indexed"))
|
||||
return PyBool_FromLong (color.is_indexed ());
|
||||
|
||||
if (! PyUnicode_CompareWithASCIIString (attr_name, "is_direct"))
|
||||
return PyBool_FromLong (color.is_direct ());
|
||||
|
||||
if (color.is_indexed ()
|
||||
&& ! PyUnicode_CompareWithASCIIString (attr_name, "index"))
|
||||
return gdb_py_object_from_longest (color.get_value ()).release ();
|
||||
|
||||
if (color.is_direct ()
|
||||
&& ! PyUnicode_CompareWithASCIIString (attr_name, "components"))
|
||||
{
|
||||
uint8_t rgb[3];
|
||||
color.get_rgb (rgb);
|
||||
|
||||
gdbpy_ref<> rgb_objects[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
rgb_objects[i] = gdb_py_object_from_ulongest (rgb[i]);
|
||||
if (rgb_objects[i] == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject *comp = PyTuple_New (3);
|
||||
if (comp == nullptr)
|
||||
return nullptr;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
PyTuple_SET_ITEM (comp, i, rgb_objects[i].release ());
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
return PyObject_GenericGetAttr (obj, attr_name);
|
||||
}
|
||||
|
||||
/* Implementation of Color.escape_sequence (self, is_fg) -> str. */
|
||||
|
||||
static PyObject *
|
||||
colorpy_escape_sequence (PyObject *self, PyObject *is_fg_obj)
|
||||
{
|
||||
if (!gdbpy_is_color (self))
|
||||
{
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("Object is not gdb.Color."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (! PyBool_Check (is_fg_obj))
|
||||
{
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("A boolean argument is required."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool is_fg = is_fg_obj == Py_True;
|
||||
std::string s = gdbpy_get_color (self).to_ansi (is_fg);
|
||||
|
||||
return host_string_to_python_string (s.c_str ()).release ();
|
||||
}
|
||||
|
||||
/* Object initializer; fills color with value.
|
||||
|
||||
Use: __init__(VALUE = None, COLORSPACE = None)
|
||||
|
||||
VALUE is a string, integer, RGB-tuple or None.
|
||||
|
||||
COLORSPACE is the color space index.
|
||||
|
||||
Returns -1 on error, with a python exception set. */
|
||||
|
||||
static int
|
||||
colorpy_init (PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
colorpy_object *obj = (colorpy_object *) self;
|
||||
PyObject *value_obj = nullptr;
|
||||
PyObject *colorspace_obj = nullptr;
|
||||
color_space colorspace = color_space::MONOCHROME;
|
||||
|
||||
if (! PyArg_ParseTuple (args, "|OO", &value_obj, &colorspace_obj))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
if (colorspace_obj)
|
||||
{
|
||||
if (PyLong_Check (colorspace_obj))
|
||||
{
|
||||
long colorspace_id = -1;
|
||||
if (! gdb_py_int_as_long (colorspace_obj, &colorspace_id))
|
||||
return -1;
|
||||
if (!color_space_safe_cast (&colorspace, colorspace_id))
|
||||
error (_("colorspace %ld is out of range."), colorspace_id);
|
||||
}
|
||||
else if (colorspace_obj == Py_None)
|
||||
colorspace_obj = nullptr;
|
||||
else
|
||||
error (_("colorspace must be None or integer"));
|
||||
}
|
||||
|
||||
if (value_obj == nullptr || value_obj == Py_None)
|
||||
obj->color = ui_file_style::color (colorspace, -1);
|
||||
else if (PyLong_Check (value_obj))
|
||||
{
|
||||
long value = -1;
|
||||
if (! gdb_py_int_as_long (value_obj, &value))
|
||||
return -1;
|
||||
if (value < 0 || value > INT_MAX)
|
||||
error (_("value %ld is out of range."), value);
|
||||
if (colorspace_obj)
|
||||
obj->color = ui_file_style::color (colorspace, value);
|
||||
else
|
||||
obj->color = ui_file_style::color (value);
|
||||
}
|
||||
else if (PyTuple_Check (value_obj))
|
||||
{
|
||||
if (colorspace_obj == nullptr || colorspace != color_space::RGB_24BIT)
|
||||
error (_("colorspace must be gdb.COLORSPACE_RGB_24BIT with "
|
||||
"value of tuple type."));
|
||||
Py_ssize_t tuple_size = PyTuple_Size (value_obj);
|
||||
if (tuple_size < 0)
|
||||
return -1;
|
||||
if (tuple_size != 3)
|
||||
error (_("Tuple value with RGB must be of size 3."));
|
||||
uint8_t rgb[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
PyObject *item = PyTuple_GetItem (value_obj, i);
|
||||
if (!PyLong_Check (item))
|
||||
error (_("Item %d of an RGB tuple must be integer."), i);
|
||||
long item_value = -1;
|
||||
if (!gdb_py_int_as_long (item, &item_value))
|
||||
return -1;
|
||||
if (item_value < 0 || item_value > UINT8_MAX)
|
||||
error (_("RGB item %ld is out of byte range."), item_value);
|
||||
rgb[i] = static_cast<uint8_t> (item_value);
|
||||
}
|
||||
|
||||
obj->color = ui_file_style::color (rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else if (PyUnicode_Check (value_obj))
|
||||
{
|
||||
gdb::unique_xmalloc_ptr<char>
|
||||
str (python_string_to_host_string (value_obj));
|
||||
if (str == nullptr)
|
||||
return -1;
|
||||
obj->color = parse_var_color (str.get());
|
||||
|
||||
if (colorspace_obj != nullptr
|
||||
&& colorspace != obj->color.colorspace ())
|
||||
error (_("colorspace doesn't match to the value."));
|
||||
}
|
||||
else
|
||||
error (_("value must be one of None, integer, tuple or str."));
|
||||
}
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
return gdbpy_handle_gdb_exception (-1, except);
|
||||
}
|
||||
|
||||
Py_INCREF (self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
colorpy_str (PyObject *self)
|
||||
{
|
||||
colorpy_object *obj = reinterpret_cast<colorpy_object *> (self);
|
||||
|
||||
return PyUnicode_FromString (obj->color.to_string ().c_str ());
|
||||
}
|
||||
|
||||
/* Initialize the 'color' module. */
|
||||
static int
|
||||
gdbpy_initialize_color (void)
|
||||
{
|
||||
for (auto & pair : colorspace_constants)
|
||||
if (PyModule_AddIntConstant (gdb_module, pair.name,
|
||||
static_cast<long> (pair.value)) < 0)
|
||||
return -1;
|
||||
|
||||
colorpy_object_type.tp_new = PyType_GenericNew;
|
||||
return gdbpy_type_ready (&colorpy_object_type, gdb_module);
|
||||
}
|
||||
|
||||
/* Color methods. */
|
||||
|
||||
static PyMethodDef color_methods[] =
|
||||
{
|
||||
{ "escape_sequence", colorpy_escape_sequence, METH_O,
|
||||
"escape_sequence (is_foreground) -> str.\n\
|
||||
Return the ANSI escape sequence for this color.\n\
|
||||
IS_FOREGROUND indicates whether this is a foreground or background color."},
|
||||
{nullptr}
|
||||
};
|
||||
|
||||
PyTypeObject colorpy_object_type =
|
||||
{
|
||||
PyVarObject_HEAD_INIT (nullptr, 0)
|
||||
"gdb.Color", /*tp_name*/
|
||||
sizeof (colorpy_object), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
0, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
0, /*tp_call*/
|
||||
colorpy_str, /*tp_str*/
|
||||
get_attr, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||
"GDB color object", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
color_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
colorpy_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
};
|
||||
|
||||
GDBPY_INITIALIZE_FILE (gdbpy_initialize_color);
|
||||
35
gdb/python/py-color.h
Normal file
35
gdb/python/py-color.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Python interface to ui_file_style::color objects.
|
||||
|
||||
Copyright (C) 2009-2024 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 PYTHON_PY_COLOR_H
|
||||
#define PYTHON_PY_COLOR_H
|
||||
|
||||
#include "python-internal.h"
|
||||
#include "ui-style.h"
|
||||
|
||||
/* Create a new gdb.Color object from COLOR. */
|
||||
extern gdbpy_ref<> create_color_object (const ui_file_style::color &color);
|
||||
|
||||
/* Check if OBJ is instance of a gdb.Color type. */
|
||||
extern bool gdbpy_is_color (PyObject *obj);
|
||||
|
||||
/* Extracts value from OBJ object of gdb.Color type. */
|
||||
extern const ui_file_style::color &gdbpy_get_color (PyObject *obj);
|
||||
|
||||
#endif /* PYTHON_PY_COLOR_H */
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "completer.h"
|
||||
#include "language.h"
|
||||
#include "arch-utils.h"
|
||||
#include "py-color.h"
|
||||
|
||||
/* Python parameter types as in PARM_CONSTANTS below. */
|
||||
|
||||
@@ -43,6 +44,7 @@ enum py_param_types
|
||||
param_zuinteger,
|
||||
param_zuinteger_unlimited,
|
||||
param_enum,
|
||||
param_color,
|
||||
};
|
||||
|
||||
/* Translation from Python parameters to GDB variable types. Keep in the
|
||||
@@ -69,7 +71,8 @@ param_to_var[] =
|
||||
{ var_integer },
|
||||
{ var_uinteger },
|
||||
{ var_pinteger, pinteger_unlimited_literals },
|
||||
{ var_enum }
|
||||
{ var_enum },
|
||||
{ var_color }
|
||||
};
|
||||
|
||||
/* Parameter constants and their values. */
|
||||
@@ -90,6 +93,7 @@ static struct {
|
||||
{ "PARAM_ZUINTEGER", param_zuinteger },
|
||||
{ "PARAM_ZUINTEGER_UNLIMITED", param_zuinteger_unlimited },
|
||||
{ "PARAM_ENUM", param_enum },
|
||||
{ "PARAM_COLOR", param_color },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -114,6 +118,9 @@ union parmpy_variable
|
||||
|
||||
/* Hold a string, for enums. */
|
||||
const char *cstringval;
|
||||
|
||||
/* Hold a color. */
|
||||
ui_file_style::color color;
|
||||
};
|
||||
|
||||
/* A GDB parameter. */
|
||||
@@ -157,6 +164,8 @@ make_setting (parmpy_object *s)
|
||||
return setting (type, s->value.stringval);
|
||||
else if (var_type_uses<const char *> (type))
|
||||
return setting (type, &s->value.cstringval);
|
||||
else if (var_type_uses<ui_file_style::color> (s->type))
|
||||
return setting (s->type, &s->value.color);
|
||||
else
|
||||
gdb_assert_not_reached ("unhandled var type");
|
||||
}
|
||||
@@ -248,6 +257,19 @@ set_parameter_value (parmpy_object *self, PyObject *value)
|
||||
break;
|
||||
}
|
||||
|
||||
case var_color:
|
||||
{
|
||||
if (gdbpy_is_color (value))
|
||||
self->value.color = gdbpy_get_color (value);
|
||||
else
|
||||
{
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("color argument must be a gdb.Color object."));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case var_boolean:
|
||||
if (! PyBool_Check (value))
|
||||
{
|
||||
@@ -707,6 +729,15 @@ add_setshow_generic (enum var_types type, const literal_def *extra_literals,
|
||||
get_show_value, set_list, show_list);
|
||||
break;
|
||||
|
||||
case var_color:
|
||||
/* Initialize the value, just in case. */
|
||||
self->value.color = ui_file_style::NONE;
|
||||
commands = add_setshow_color_cmd (cmd_name.get (), cmdclass,
|
||||
&self->value.color, set_doc,
|
||||
show_doc, help_doc, get_set_value,
|
||||
get_show_value, set_list, show_list);
|
||||
break;
|
||||
|
||||
default:
|
||||
gdb_assert_not_reached ("Unhandled parameter class.");
|
||||
}
|
||||
@@ -830,7 +861,8 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
|
||||
&& parmclass != param_string && parmclass != param_string_noescape
|
||||
&& parmclass != param_optional_filename && parmclass != param_filename
|
||||
&& parmclass != param_zinteger && parmclass != param_zuinteger
|
||||
&& parmclass != param_zuinteger_unlimited && parmclass != param_enum)
|
||||
&& parmclass != param_zuinteger_unlimited && parmclass != param_enum
|
||||
&& parmclass != param_color)
|
||||
{
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("Invalid parameter class argument."));
|
||||
@@ -854,7 +886,7 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
|
||||
extra_literals = param_to_var[parmclass].extra_literals;
|
||||
obj->type = type;
|
||||
obj->extra_literals = extra_literals;
|
||||
memset (&obj->value, 0, sizeof (obj->value));
|
||||
obj->value = {}; /* zeros initialization */
|
||||
|
||||
if (var_type_uses<std::string> (obj->type))
|
||||
obj->value.stringval = new std::string;
|
||||
@@ -900,6 +932,8 @@ parmpy_dealloc (PyObject *obj)
|
||||
|
||||
if (var_type_uses<std::string> (parm_obj->type))
|
||||
delete parm_obj->value.stringval;
|
||||
else if (var_type_uses<ui_file_style::color> (parm_obj->type))
|
||||
parm_obj->value.color.~color();
|
||||
}
|
||||
|
||||
/* Initialize the 'parameters' module. */
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "run-on-main-thread.h"
|
||||
#include "observable.h"
|
||||
#include "build-id.h"
|
||||
#include "py-color.h"
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
#include "gdbsupport/selftest.h"
|
||||
@@ -511,6 +512,12 @@ gdbpy_parameter_value (const setting &var)
|
||||
return host_string_to_python_string (str).release ();
|
||||
}
|
||||
|
||||
case var_color:
|
||||
{
|
||||
const ui_file_style::color &color = var.get<ui_file_style::color> ();
|
||||
return create_color_object (color).release ();
|
||||
}
|
||||
|
||||
case var_boolean:
|
||||
{
|
||||
if (var.get<bool> ())
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
|
||||
# Start with a fresh gdb
|
||||
|
||||
gdb_exit
|
||||
gdb_start
|
||||
with_ansi_styling_terminal {
|
||||
setenv TERM dumb
|
||||
gdb_exit
|
||||
gdb_start
|
||||
}
|
||||
|
||||
set prev_timeout $timeout
|
||||
set timeout 60
|
||||
@@ -684,6 +687,7 @@ set show_conv_list \
|
||||
{$_probe_arg10 = <error: No frame selected>} \
|
||||
{$_probe_arg11 = <error: No frame selected>} \
|
||||
{$_cimag = <internal function _cimag>} \
|
||||
{$_colorsupport = "monochrome"} \
|
||||
{$_creal = <internal function _creal>} \
|
||||
{$_isvoid = <internal function _isvoid>} \
|
||||
{$_shell = <internal function _shell>} \
|
||||
|
||||
@@ -70,6 +70,9 @@ proc run_style_tests { } {
|
||||
global currently_disabled_style decimal hex
|
||||
|
||||
with_ansi_styling_terminal {
|
||||
setenv TERM xterm-256color
|
||||
setenv COLORTERM truecolor
|
||||
|
||||
# Restart GDB with the correct TERM variable setting, this
|
||||
# means that GDB will enable styling.
|
||||
clean_restart_and_disable "restart 1" ${binfile}
|
||||
@@ -311,6 +314,21 @@ proc run_style_tests { } {
|
||||
set url [limited_style "http:.*html" file]
|
||||
gdb_test "show version" "${vers}.*<$url>.*" \
|
||||
"'show version' is styled"
|
||||
|
||||
if { $currently_disabled_style != "version" } {
|
||||
# Check that colors in styling can be set as integer and as RGB hex
|
||||
# triplet. Check that the version string is styled in the output of
|
||||
# 'show version' according to the set colors.
|
||||
gdb_test_no_output "set style version intensity normal"
|
||||
gdb_test_no_output "set style version background 255"
|
||||
gdb_test_no_output "set style version foreground #FED210"
|
||||
gdb_test "show style version background" \
|
||||
"The \033\\\[38;2;254;210;16;48;5;255;22;27m.*\".*version.*\".*style.*\033\\\[m background color is: 255" \
|
||||
"Version's 256-color background style"
|
||||
gdb_test "show style version foreground" \
|
||||
"The \033\\\[38;2;254;210;16;48;5;255;22;27m.*\".*version.*\".*style.*\033\\\[m foreground color is: #FED210" \
|
||||
"Version's TrueColor foreground style"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,6 +505,179 @@ proc test_startup_version_string { } {
|
||||
gdb_test "" "${vers}.*" "version is styled at startup"
|
||||
}
|
||||
|
||||
# Color support is disabled when TERM=dumb and COLORTERM="".
|
||||
# All colors are approximated to none when set.
|
||||
proc test_colorsupport_monochrome { } {
|
||||
with_test_prefix "colorsupport_monochrome" {
|
||||
with_ansi_styling_terminal {
|
||||
setenv TERM dumb
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_test "print \$_colorsupport" \
|
||||
"\\\$1 = \"monochrome\"" \
|
||||
"color support is monochrome"
|
||||
gdb_test_no_output "set style enabled off"
|
||||
gdb_test_no_output "set style filename foreground none"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: none" \
|
||||
"none without approximation"
|
||||
gdb_test_no_output "set style filename foreground blue"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: none" \
|
||||
"blue approximated to none"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Color support is limited by 8 colors when TERM=ansi and COLORTERM="".
|
||||
# All colors are approximated to basic colors when set.
|
||||
proc test_colorsupport_8color { } {
|
||||
with_test_prefix "colorsupport_8color" {
|
||||
with_ansi_styling_terminal {
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_test "print \$_colorsupport" \
|
||||
"\033\\\[.*m\\\$1\033\\\[m = \"monochrome,ansi_8color\"" \
|
||||
"color support is 8 color"
|
||||
gdb_test_no_output "set style enabled off"
|
||||
gdb_test_no_output "set style filename foreground none"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: none" \
|
||||
"none without approximation"
|
||||
gdb_test_no_output "set style filename foreground yellow"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: yellow" \
|
||||
"yellow without approximation"
|
||||
gdb_test_no_output "set style filename foreground 9"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: red" \
|
||||
"9 approximated to red"
|
||||
gdb_test_no_output "set style filename foreground 118"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: green" \
|
||||
"118 approximated to green"
|
||||
gdb_test_no_output "set style filename foreground #000ABC"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: blue" \
|
||||
"#000ABC approximated to blue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Color support is limited by 256 colors when TERM=xterm-256color and
|
||||
# COLORTERM="". All colors are approximated by 256 color palette when set.
|
||||
proc test_colorsupport_256color { } {
|
||||
with_test_prefix "colorsupport_256color" {
|
||||
with_ansi_styling_terminal {
|
||||
setenv TERM xterm-256color
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_test "print \$_colorsupport" \
|
||||
"\033\\\[.*m\\\$1\033\\\[m = \"monochrome,ansi_8color,aixterm_16color,xterm_256color\"" \
|
||||
"color support is 256 color"
|
||||
gdb_test_no_output "set style enabled off"
|
||||
gdb_test_no_output "set style filename foreground none"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: none" \
|
||||
"none without approximation"
|
||||
gdb_test_no_output "set style filename foreground red"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: red" \
|
||||
"red without approximation"
|
||||
gdb_test_no_output "set style filename foreground 9"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: 9" \
|
||||
"9 without approximation"
|
||||
gdb_test_no_output "set style filename foreground 118"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: 118" \
|
||||
"118 without approximation"
|
||||
gdb_test_no_output "set style filename foreground #CD00CD"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: 5" \
|
||||
"#CD00CD approximated to 5"
|
||||
gdb_test_no_output "set style filename foreground #FFAF12"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: 214" \
|
||||
"#FFAF12 approximated to 214"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Color support is limited by 16777216 colors when TERM=xterm-256color and
|
||||
# COLORTERM="truecolor". No approximation needed.
|
||||
proc test_colorsupport_truecolor { } {
|
||||
with_test_prefix "colorsupport_truecolor" {
|
||||
with_ansi_styling_terminal {
|
||||
setenv TERM xterm-256color
|
||||
setenv COLORTERM truecolor
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_test "print \$_colorsupport" \
|
||||
"\033\\\[.*m\\\$1\033\\\[m = \"monochrome,ansi_8color,aixterm_16color,xterm_256color,rgb_24bit\"" \
|
||||
"color support is truecolor"
|
||||
gdb_test_no_output "set style enabled off"
|
||||
gdb_test_no_output "set style filename foreground none"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: none" \
|
||||
"none without approximation"
|
||||
gdb_test_no_output "set style filename foreground red"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: red" \
|
||||
"red without approximation"
|
||||
gdb_test_no_output "set style filename foreground 9"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: 9" \
|
||||
"9 without approximation"
|
||||
gdb_test_no_output "set style filename foreground 118"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: 118" \
|
||||
"118 without approximation"
|
||||
gdb_test_no_output "set style filename foreground #CD00CD"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: #CD00CD" \
|
||||
"#CD00CD without approximation"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Color support is limited by 16777216 colors when TERM=dumb and
|
||||
# COLORTERM=24bit. No approximation needed. Basic colors replaced with RGB.
|
||||
proc test_colorsupport_truecolor_only { } {
|
||||
with_test_prefix "colorsupport_truecolor_only" {
|
||||
with_ansi_styling_terminal {
|
||||
setenv TERM dumb
|
||||
setenv COLORTERM truecolor
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_test "print \$_colorsupport" \
|
||||
"\\\$1 = \"monochrome,rgb_24bit\"" \
|
||||
"color support is truecolor only"
|
||||
gdb_test_no_output "set style enabled off"
|
||||
gdb_test_no_output "set style filename foreground none"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: none" \
|
||||
"none without approximation"
|
||||
gdb_test_no_output "set style filename foreground red"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: #DE382B" \
|
||||
"red replaced by #DE382B"
|
||||
gdb_test_no_output "set style filename foreground 9"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: #FF0000" \
|
||||
"9 replaced by #FF0000"
|
||||
gdb_test_no_output "set style filename foreground 118"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: #87FF00" \
|
||||
"118 replaced by #87FF00"
|
||||
gdb_test_no_output "set style filename foreground #CD00CD"
|
||||
gdb_test "show style filename foreground" \
|
||||
"The \"filename\" style foreground color is: #CD00CD" \
|
||||
"#CD00CD without approximation"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check to see if the Python styling of disassembler output is
|
||||
# expected or not, this styling requires Python support in GDB, and
|
||||
# the Python pygments module to be available.
|
||||
@@ -521,3 +712,9 @@ test_disassembler_error_handling
|
||||
|
||||
# Finally, check the styling of the version string during startup.
|
||||
test_startup_version_string
|
||||
|
||||
test_colorsupport_monochrome
|
||||
test_colorsupport_8color
|
||||
test_colorsupport_256color
|
||||
test_colorsupport_truecolor
|
||||
test_colorsupport_truecolor_only
|
||||
|
||||
110
gdb/testsuite/gdb.guile/scm-color.exp
Normal file
110
gdb/testsuite/gdb.guile/scm-color.exp
Normal file
@@ -0,0 +1,110 @@
|
||||
# Copyright (C) 2010-2024 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 parameter support in Guile.
|
||||
|
||||
load_lib gdb-guile.exp
|
||||
|
||||
require allow_guile_tests
|
||||
|
||||
clean_restart
|
||||
|
||||
gdb_install_guile_utils
|
||||
gdb_install_guile_module
|
||||
|
||||
gdb_test_no_output [concat "guile (define (print_color_attrs c) " \
|
||||
"(display (color-string c)) (display \" \") " \
|
||||
"(display (color-colorspace c)) (display \" \") " \
|
||||
"(display (color-none? c)) (display \" \") " \
|
||||
"(display (color-indexed? c)) (display \" \") " \
|
||||
"(display (color-direct? c)) (newline))"] \
|
||||
"print_color_attrs helper"
|
||||
|
||||
gdb_test "guile (print_color_attrs (make-color))" \
|
||||
"none 0 #t #f #f" \
|
||||
"print attrs of a color without params"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color \"green\"))" \
|
||||
"create color from basic name string"
|
||||
gdb_test "guile (print_color_attrs c)" "green 1 #f #t #f" \
|
||||
"print attrs of a basic color name"
|
||||
gdb_test "guile (print (color-index c))" "2" \
|
||||
"print index of a basic color name"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color 2))" \
|
||||
"create color from basic index"
|
||||
gdb_test "guile (print_color_attrs c)" "green 1 #f #t #f" \
|
||||
"print attrs of a basic color"
|
||||
gdb_test "guile (print (color-index c))" "2" \
|
||||
"print index of a basic color"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color 14))" \
|
||||
"create color from integer 14"
|
||||
gdb_test "guile (print_color_attrs c)" "14 2 #f #t #f" \
|
||||
"print attrs of an color 14"
|
||||
gdb_test "guile (print (color-index c))" "14" \
|
||||
"print index of color 14"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color 2 #:color-space COLORSPACE_ANSI_8COLOR))" \
|
||||
"create color from basic index and ansi colorspace"
|
||||
gdb_test "guile (print_color_attrs c)" "green 1 #f #t #f" \
|
||||
"print attrs of a basic color with ansi colorspace"
|
||||
gdb_test "guile (print (color-index c))" "2" \
|
||||
"print index of a basic color with ansi colorspace"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color 2 #:color-space COLORSPACE_XTERM_256COLOR))" \
|
||||
"create color from basic index and xterm256 colorspace"
|
||||
gdb_test "guile (print_color_attrs c)" "2 3 #f #t #f" \
|
||||
"print attrs of a basic color with xterm256 colorspace"
|
||||
gdb_test "guile (print (color-index c))" "2" \
|
||||
"print index of a basic color with xterm256 colorspace"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color '(171 205 239) #:color-space COLORSPACE_RGB_24BIT))" \
|
||||
"create color from rgb components"
|
||||
gdb_test "guile (print_color_attrs c)" "#ABCDEF 4 #f #f #t" \
|
||||
"print attrs of an RGB color"
|
||||
gdb_test "guile (print (color-components c))" "\\(171 205 239\\)" \
|
||||
"print components of an RGB color"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color \"none\"))" \
|
||||
"create color from string none"
|
||||
gdb_test "guile (print_color_attrs c)" "none 0 #t #f #f" \
|
||||
"print attrs of a color none"
|
||||
|
||||
gdb_test_no_output "guile (define c (make-color \"254\"))" \
|
||||
"create color from string 254"
|
||||
gdb_test "guile (print_color_attrs c)" "254 3 #f #t #f" \
|
||||
"print attrs of an color 254"
|
||||
gdb_test "guile (print (color-index c))" "254" \
|
||||
"print index of color 254"
|
||||
|
||||
gdb_test_no_output "guile (define c_none (make-color \"none\"))" \
|
||||
"save default color"
|
||||
gdb_test_no_output "guile (define c_red (make-color \"red\"))" \
|
||||
"save blue color"
|
||||
gdb_test_no_output "guile (define c_green (make-color \"green\"))" \
|
||||
"save yellow color"
|
||||
gdb_test [concat "guile " \
|
||||
"(display (color-escape-sequence c_red #t)) " \
|
||||
"(display (color-escape-sequence c_green #f)) " \
|
||||
"(display \"red on green\") " \
|
||||
"(display (color-escape-sequence c_none #f)) " \
|
||||
"(display \" red on default\") " \
|
||||
"(display (color-escape-sequence c_none #t)) " \
|
||||
"(newline)"] \
|
||||
"\033\\\[31m\033\\\[42mred on green\033\\\[49m red on default\033\\\[39m" \
|
||||
"escape sequences"
|
||||
|
||||
@@ -389,3 +389,50 @@ with_test_prefix "previously-ambiguous" {
|
||||
}
|
||||
|
||||
rename scm_param_test_maybe_no_output ""
|
||||
|
||||
# Test a color parameter.
|
||||
|
||||
with_ansi_styling_terminal {
|
||||
# This enables 256 colors support and disables colors approximation.
|
||||
setenv TERM xterm-256color
|
||||
setenv COLORTERM truecolor
|
||||
|
||||
# Start with a fresh gdb.
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
|
||||
gdb_install_guile_utils
|
||||
gdb_install_guile_module
|
||||
|
||||
# We use "." here instead of ":" so that this works on win32 too.
|
||||
set escaped_directory [string_to_regexp "$srcdir/$subdir"]
|
||||
|
||||
gdb_test_multiline "color gdb parameter" \
|
||||
"guile" "" \
|
||||
"(define test-color-param" "" \
|
||||
" (make-parameter \"print test-color-param\"" "" \
|
||||
" #:command-class COMMAND_DATA" "" \
|
||||
" #:parameter-type PARAM_COLOR" "" \
|
||||
" #:doc \"When set, test param does something useful. When disabled, does nothing.\"" "" \
|
||||
" #:show-doc \"Show the state of the test-color-param.\"" "" \
|
||||
" #:set-doc \"Set the state of the test-color-param.\"" "" \
|
||||
" #:show-func (lambda (self value)" "" \
|
||||
" (format #f \"The state of the test-color-param is ~a.\" value))" "" \
|
||||
" #:initial-value (make-color \"green\")))" "" \
|
||||
"(register-parameter! test-color-param)" "" \
|
||||
"end"
|
||||
|
||||
with_test_prefix "test-color-param" {
|
||||
with_test_prefix "initial-value" {
|
||||
gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color green COLORSPACE_ANSI_8COLOR>" "color parameter value (green)"
|
||||
gdb_test "show print test-color-param" "The state of the test-color-param is green." "show initial value"
|
||||
gdb_test_no_output "set print test-color-param 255"
|
||||
}
|
||||
with_test_prefix "new-value" {
|
||||
gdb_test "show print test-color-param" "The state of the test-color-param is 255." "show new value"
|
||||
gdb_test "guile (print (parameter-value test-color-param))" "= #<gdb:color 255 COLORSPACE_XTERM_256COLOR>" "color parameter value (255)"
|
||||
gdb_test "set print test-color-param 256" "integer 256 out of range.*" "set invalid color parameter"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
100
gdb/testsuite/gdb.python/py-color.exp
Normal file
100
gdb/testsuite/gdb.python/py-color.exp
Normal file
@@ -0,0 +1,100 @@
|
||||
# Copyright (C) 2010-2024 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.parameter and gdb.Parameter.
|
||||
|
||||
load_lib gdb-python.exp
|
||||
|
||||
require allow_python_tests
|
||||
|
||||
# Start with a fresh gdb.
|
||||
clean_restart
|
||||
|
||||
gdb_test_no_output "python print_color_attrs = lambda c: print (c, c.colorspace, c.is_none, c.is_indexed, c.is_direct)" \
|
||||
"print_color_attrs helper"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color ()" \
|
||||
"create color without params"
|
||||
gdb_test "python print_color_attrs (c)" "none 0 True False False" \
|
||||
"print attrs of a color without params"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color ('green')" \
|
||||
"create color from basic name string"
|
||||
gdb_test "python print_color_attrs (c)" "green 1 False True False" \
|
||||
"print attrs of a basic color name"
|
||||
gdb_test "python print (c.index)" "2" \
|
||||
"print index of a basic color name"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color (2)" \
|
||||
"create color from basic index"
|
||||
gdb_test "python print_color_attrs (c)" "green 1 False True False" \
|
||||
"print attrs of a basic color"
|
||||
gdb_test "python print (c.index)" "2" \
|
||||
"print index of a basic color"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color (14)" \
|
||||
"create color from integer 14"
|
||||
gdb_test "python print_color_attrs (c)" "14 2 False True False" \
|
||||
"print attrs of an color 14"
|
||||
gdb_test "python print (c.index)" "14" \
|
||||
"print index of color 14"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color (2, gdb.COLORSPACE_ANSI_8COLOR)" \
|
||||
"create color from basic index and ansi colorspace"
|
||||
gdb_test "python print_color_attrs (c)" "green 1 False True False" \
|
||||
"print attrs of a basic color with ansi colorspace"
|
||||
gdb_test "python print (c.index)" "2" \
|
||||
"print index of a basic color with ansi colorspace"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color (2, gdb.COLORSPACE_XTERM_256COLOR)" \
|
||||
"create color from basic index and xterm256 colorspace"
|
||||
gdb_test "python print_color_attrs (c)" "2 3 False True False" \
|
||||
"print attrs of a basic color with xterm256 colorspace"
|
||||
gdb_test "python print (c.index)" "2" \
|
||||
"print index of a basic color with xterm256 colorspace"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color ((171, 205, 239), gdb.COLORSPACE_RGB_24BIT)" \
|
||||
"create color from rgb components"
|
||||
gdb_test "python print_color_attrs (c)" "#ABCDEF 4 False False True" \
|
||||
"print attrs of an RGB color"
|
||||
gdb_test "python print (c.components)" "\\(171, 205, 239\\)" \
|
||||
"print components of an RGB color"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color ('none')" \
|
||||
"create color from string none"
|
||||
gdb_test "python print_color_attrs (c)" "none 0 True False False" \
|
||||
"print attrs of a color none"
|
||||
|
||||
gdb_test_no_output "python c = gdb.Color ('254')" \
|
||||
"create color from string 254"
|
||||
gdb_test "python print_color_attrs (c)" "254 3 False True False" \
|
||||
"print attrs of an color 254"
|
||||
gdb_test "python print (c.index)" "254" \
|
||||
"print index of color 254"
|
||||
|
||||
gdb_test_no_output "python c_none = gdb.Color ('none')" \
|
||||
"save default color"
|
||||
gdb_test_no_output "python c_red = gdb.Color ('red')" \
|
||||
"save blue color"
|
||||
gdb_test_no_output "python c_green = gdb.Color ('green')" \
|
||||
"save yellow color"
|
||||
gdb_test [concat "python print (c_red.escape_sequence (True) + " \
|
||||
"c_green.escape_sequence (False) + 'red on green' + " \
|
||||
"c_none.escape_sequence (False) + ' red on default' + " \
|
||||
"c_none.escape_sequence (True))"] \
|
||||
"\033\\\[31m\033\\\[42mred on green\033\\\[49m red on default\033\\\[39m" \
|
||||
"escape sequences"
|
||||
|
||||
@@ -185,6 +185,58 @@ proc_with_prefix test_enum_parameter { } {
|
||||
"Undefined item: \"three\".*" "set invalid enum parameter"
|
||||
}
|
||||
|
||||
# Test an color parameter.
|
||||
proc_with_prefix test_color_parameter { } {
|
||||
global env
|
||||
with_ansi_styling_terminal {
|
||||
# This enables 256 colors support and disables colors approximation.
|
||||
setenv TERM xterm-256color
|
||||
setenv COLORTERM truecolor
|
||||
|
||||
clean_restart
|
||||
|
||||
gdb_test_multiline "color gdb parameter" \
|
||||
"python" "" \
|
||||
"class TestColorParam (gdb.Parameter):" "" \
|
||||
" \"\"\"When set, test param does something useful. When disabled, does nothing.\"\"\"" "" \
|
||||
" show_doc = \"Show the state of the color\"" ""\
|
||||
" set_doc = \"Set the state of the color\"" "" \
|
||||
" def get_show_string (self, pvalue):" ""\
|
||||
" return \"The state of the color is \" + str(pvalue)" ""\
|
||||
" def get_set_string (self):" ""\
|
||||
" return \"The state of the color has been set to \" + str(self.value)" ""\
|
||||
" def __init__ (self, name):" "" \
|
||||
" super (TestColorParam, self).__init__ (name, gdb.COMMAND_DATA, gdb.PARAM_COLOR)" "" \
|
||||
" self.value = gdb.Color(\"green\")" "" \
|
||||
"test_color_param = TestColorParam ('print test-color-param')" ""\
|
||||
"end"
|
||||
|
||||
gdb_test "python print (test_color_param.value)" "green" \
|
||||
"test color parameter value is green"
|
||||
gdb_test "show print test-color-param" \
|
||||
"The state of the color is green.*" \
|
||||
"show parameter is initial value"
|
||||
gdb_test "set print test-color-param 255" \
|
||||
"The state of the color has been set to 255" "set color to 255"
|
||||
gdb_test "show print test-color-param" \
|
||||
"The state of the color is 255.*" "show parameter is new value"
|
||||
gdb_test "python print (test_color_param.value)" "255" \
|
||||
"test color parameter value is 255"
|
||||
gdb_test_no_output "python test_color_param.value = gdb.Color(254)" \
|
||||
"assign test_color_param.value to 254"
|
||||
gdb_test "python print (test_color_param.value)" "254" \
|
||||
"test color parameter value is integer"
|
||||
gdb_test_no_output "python test_color_param.value = gdb.Color('#FED210')" \
|
||||
"assign test_color_param.value to #FED210"
|
||||
gdb_test "python print (test_color_param.value.components)" "\\(254, 210, 16\\)" \
|
||||
"test color parameter components from RGB hex tripple value"
|
||||
gdb_test "set print test-color-param 256" \
|
||||
"integer 256 out of range.*" "set invalid color parameter"
|
||||
gdb_test "python test_color_param.value = gdb.Color(256)" \
|
||||
".*Error occurred in Python: Palette color index 256 is out of range.*" "set invalid color value"
|
||||
}
|
||||
}
|
||||
|
||||
# Test a file parameter.
|
||||
proc_with_prefix test_file_parameter { } {
|
||||
clean_restart
|
||||
@@ -623,6 +675,7 @@ test_directories
|
||||
test_data_directory
|
||||
test_boolean_parameter
|
||||
test_enum_parameter
|
||||
test_color_parameter
|
||||
test_file_parameter
|
||||
test_undocumented_parameter
|
||||
test_really_undocumented_parameter
|
||||
|
||||
@@ -67,20 +67,24 @@ proc string_list_to_regexp { args } {
|
||||
# "function", "variable", "address", etc.
|
||||
|
||||
proc style {str style} {
|
||||
set fg 39
|
||||
set bg 49
|
||||
set intensity 22
|
||||
set reverse 27
|
||||
switch -exact -- $style {
|
||||
title { set style 1 }
|
||||
command { set style 1 }
|
||||
file { set style 32 }
|
||||
function { set style 33 }
|
||||
highlight { set style 31 }
|
||||
variable { set style 36 }
|
||||
address { set style 34 }
|
||||
metadata { set style 2 }
|
||||
version { set style "35;1" }
|
||||
line-number { set style 2 }
|
||||
title { set intensity 1 }
|
||||
command { set intensity 1 }
|
||||
file { set fg 32 }
|
||||
function { set fg 33 }
|
||||
highlight { set fg 31 }
|
||||
variable { set fg 36 }
|
||||
address { set fg 34 }
|
||||
metadata { set intensity 2 }
|
||||
version { set fg 35; set intensity 1 }
|
||||
line-number { set intensity 2 }
|
||||
none { return $str }
|
||||
}
|
||||
return "\033\\\[${style}m${str}\033\\\[m"
|
||||
return "\033\\\[${fg};${bg};${intensity};${reverse}m${str}\033\\\[m"
|
||||
}
|
||||
|
||||
# gdb_get_bp_addr num
|
||||
|
||||
@@ -10265,10 +10265,11 @@ proc with_override { name override body } {
|
||||
# Run BODY after setting the TERM environment variable to 'ansi', and
|
||||
# unsetting the NO_COLOR environment variable.
|
||||
proc with_ansi_styling_terminal { body } {
|
||||
save_vars { ::env(TERM) ::env(NO_COLOR) } {
|
||||
save_vars { ::env(TERM) ::env(NO_COLOR) ::env(COLORTERM) } {
|
||||
# Set environment variables to allow styling.
|
||||
setenv TERM ansi
|
||||
unset -nocomplain ::env(NO_COLOR)
|
||||
unset -nocomplain ::env(COLORTERM)
|
||||
|
||||
set code [catch {uplevel 1 $body} result]
|
||||
}
|
||||
|
||||
14
gdb/top.c
14
gdb/top.c
@@ -2129,6 +2129,17 @@ show_startup_quiet (struct ui_file *file, int from_tty,
|
||||
value);
|
||||
}
|
||||
|
||||
static void
|
||||
init_colorsupport_var ()
|
||||
{
|
||||
const std::vector<color_space> &cs = colorsupport ();
|
||||
std::string s;
|
||||
for (color_space c : cs)
|
||||
s.append (s.empty () ? "" : ",").append (color_space_name (c));
|
||||
struct internalvar *colorsupport_var = create_internalvar ("_colorsupport");
|
||||
set_internalvar_string (colorsupport_var, s.c_str ());
|
||||
}
|
||||
|
||||
static void
|
||||
init_main (void)
|
||||
{
|
||||
@@ -2333,6 +2344,9 @@ gdb_init ()
|
||||
during startup. */
|
||||
set_language (language_c);
|
||||
expected_language = current_language; /* Don't warn about the change. */
|
||||
|
||||
/* Create $_colorsupport convenience variable. */
|
||||
init_colorsupport_var ();
|
||||
}
|
||||
|
||||
void _initialize_top ();
|
||||
|
||||
353
gdb/ui-style.c
353
gdb/ui-style.c
@@ -17,6 +17,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "ui-style.h"
|
||||
#include "gdb_curses.h"
|
||||
#include "gdbsupport/gdb_regex.h"
|
||||
|
||||
/* A regular expression that is used for matching ANSI terminal escape
|
||||
@@ -46,48 +47,118 @@ static const char ansi_regex_text[] =
|
||||
|
||||
static regex_t ansi_regex;
|
||||
|
||||
/* This maps bright colors to RGB triples. The index is the bright
|
||||
color index, starting with bright black. The values come from
|
||||
xterm. */
|
||||
/* This maps 8-color palette to RGB triples. The values come from
|
||||
plain linux terminal. */
|
||||
|
||||
static const uint8_t bright_colors[][3] = {
|
||||
{ 127, 127, 127 }, /* Black. */
|
||||
{ 255, 0, 0 }, /* Red. */
|
||||
{ 0, 255, 0 }, /* Green. */
|
||||
{ 255, 255, 0 }, /* Yellow. */
|
||||
{ 92, 92, 255 }, /* Blue. */
|
||||
{ 255, 0, 255 }, /* Magenta. */
|
||||
{ 0, 255, 255 }, /* Cyan. */
|
||||
{ 255, 255, 255 } /* White. */
|
||||
static const uint8_t palette_8colors[][3] = {
|
||||
{ 1, 1, 1 }, /* Black. */
|
||||
{ 222, 56, 43 }, /* Red. */
|
||||
{ 57, 181, 74 }, /* Green. */
|
||||
{ 255, 199, 6 }, /* Yellow. */
|
||||
{ 0, 111, 184 }, /* Blue. */
|
||||
{ 118, 38, 113 }, /* Magenta. */
|
||||
{ 44, 181, 233 }, /* Cyan. */
|
||||
{ 204, 204, 204 }, /* White. */
|
||||
};
|
||||
|
||||
/* This maps 16-color palette to RGB triples. The values come from xterm. */
|
||||
|
||||
static const uint8_t palette_16colors[][3] = {
|
||||
{ 0, 0, 0 }, /* Black. */
|
||||
{ 205, 0, 0 }, /* Red. */
|
||||
{ 0, 205, 0 }, /* Green. */
|
||||
{ 205, 205, 0 }, /* Yellow. */
|
||||
{ 0, 0, 238 }, /* Blue. */
|
||||
{ 205, 0, 205 }, /* Magenta. */
|
||||
{ 0, 205, 205 }, /* Cyan. */
|
||||
{ 229, 229, 229 }, /* White. */
|
||||
{ 127, 127, 127 }, /* Bright Black. */
|
||||
{ 255, 0, 0 }, /* Bright Red. */
|
||||
{ 0, 255, 0 }, /* Bright Green. */
|
||||
{ 255, 255, 0 }, /* Bright Yellow. */
|
||||
{ 92, 92, 255 }, /* Bright Blue. */
|
||||
{ 255, 0, 255 }, /* Bright Magenta. */
|
||||
{ 0, 255, 255 }, /* Bright Cyan. */
|
||||
{ 255, 255, 255 } /* Bright White. */
|
||||
};
|
||||
|
||||
/* See ui-style.h. */
|
||||
/* Must correspond to ui_file_style::basic_color. */
|
||||
const std::vector<const char *> ui_file_style::basic_color_enums = {
|
||||
"none",
|
||||
"black",
|
||||
"red",
|
||||
"green",
|
||||
"yellow",
|
||||
"blue",
|
||||
"magenta",
|
||||
"cyan",
|
||||
"white",
|
||||
nullptr
|
||||
};
|
||||
|
||||
bool
|
||||
/* Returns text representation of a basic COLOR. */
|
||||
|
||||
static const char *
|
||||
basic_color_name (int color)
|
||||
{
|
||||
int pos = color - ui_file_style::NONE;
|
||||
if (0 <= pos && pos < ui_file_style::basic_color_enums.size ())
|
||||
if (const char *s = ui_file_style::basic_color_enums[pos])
|
||||
return s;
|
||||
error (_("Basic color %d has no name."), color);
|
||||
}
|
||||
|
||||
/* See ui-style.h. */
|
||||
|
||||
void
|
||||
ui_file_style::color::append_ansi (bool is_fg, std::string *str) const
|
||||
{
|
||||
if (m_simple)
|
||||
{
|
||||
if (m_value >= BLACK && m_value <= WHITE)
|
||||
str->append (std::to_string (m_value + (is_fg ? 30 : 40)));
|
||||
else if (m_value > WHITE && m_value <= WHITE + 8)
|
||||
str->append (std::to_string (m_value - WHITE + (is_fg ? 90 : 100)));
|
||||
else if (m_value != -1)
|
||||
{
|
||||
str->append (is_fg ? "38;5;" : "48;5;");
|
||||
str->append (std::to_string (m_value));
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (m_color_space == color_space::MONOCHROME)
|
||||
str->append (is_fg ? "39" : "49");
|
||||
else if (is_basic ())
|
||||
str->append (std::to_string (m_value + (is_fg ? 30 : 40)));
|
||||
else if (m_color_space == color_space::AIXTERM_16COLOR)
|
||||
str->append (std::to_string (m_value - WHITE - 1 + (is_fg ? 90 : 100)));
|
||||
else if (m_color_space == color_space::XTERM_256COLOR)
|
||||
str->append (is_fg ? "38;5;" : "48;5;").append (std::to_string (m_value));
|
||||
else if (m_color_space == color_space::RGB_24BIT)
|
||||
{
|
||||
// See ISO/IEC 8613-6 (or ITU T.416) 13.1.8 Select Graphic Rendition (SGR)
|
||||
str->append (is_fg ? "38;2;" : "48;2;");
|
||||
str->append (std::to_string (m_red)
|
||||
+ ";" + std::to_string (m_green)
|
||||
+ ";" + std::to_string (m_blue));
|
||||
}
|
||||
return true;
|
||||
else
|
||||
gdb_assert_not_reached ("no valid ansi representation of the color");
|
||||
}
|
||||
|
||||
/* See ui-style.h. */
|
||||
std::string
|
||||
ui_file_style::color::to_ansi (bool is_fg) const
|
||||
{
|
||||
std::string s = "\033[";
|
||||
append_ansi (is_fg, &s);
|
||||
s.push_back ('m');
|
||||
return s;
|
||||
}
|
||||
|
||||
/* See ui-style.h. */
|
||||
|
||||
std::string
|
||||
ui_file_style::color::to_string () const
|
||||
{
|
||||
if (m_color_space == color_space::RGB_24BIT)
|
||||
{
|
||||
char s[64];
|
||||
snprintf (s, sizeof s, "#%02X%02X%02X", m_red, m_green, m_blue);
|
||||
return s;
|
||||
}
|
||||
else if (is_none () || is_basic ())
|
||||
return basic_color_name (m_value);
|
||||
else
|
||||
return std::to_string (get_value ());
|
||||
}
|
||||
|
||||
/* See ui-style.h. */
|
||||
@@ -95,42 +166,108 @@ ui_file_style::color::append_ansi (bool is_fg, std::string *str) const
|
||||
void
|
||||
ui_file_style::color::get_rgb (uint8_t *rgb) const
|
||||
{
|
||||
if (m_simple)
|
||||
{
|
||||
/* Can't call this for a basic color or NONE -- those will end
|
||||
up in the assert below. */
|
||||
if (m_value >= 8 && m_value <= 15)
|
||||
memcpy (rgb, bright_colors[m_value - 8], 3 * sizeof (uint8_t));
|
||||
else if (m_value >= 16 && m_value <= 231)
|
||||
{
|
||||
int value = m_value;
|
||||
value -= 16;
|
||||
/* This obscure formula seems to be what terminals actually
|
||||
do. */
|
||||
int component = value / 36;
|
||||
rgb[0] = component == 0 ? 0 : (55 + component * 40);
|
||||
value %= 36;
|
||||
component = value / 6;
|
||||
rgb[1] = component == 0 ? 0 : (55 + component * 40);
|
||||
value %= 6;
|
||||
rgb[2] = value == 0 ? 0 : (55 + value * 40);
|
||||
}
|
||||
else if (m_value >= 232)
|
||||
{
|
||||
uint8_t v = (m_value - 232) * 10 + 8;
|
||||
rgb[0] = v;
|
||||
rgb[1] = v;
|
||||
rgb[2] = v;
|
||||
}
|
||||
else
|
||||
gdb_assert_not_reached ("get_rgb called on invalid color");
|
||||
}
|
||||
else
|
||||
if (m_color_space == color_space::RGB_24BIT)
|
||||
{
|
||||
rgb[0] = m_red;
|
||||
rgb[1] = m_green;
|
||||
rgb[2] = m_blue;
|
||||
}
|
||||
else if (m_color_space == color_space::ANSI_8COLOR
|
||||
&& 0 <= m_value && m_value <= 7)
|
||||
memcpy (rgb, palette_8colors[m_value], 3 * sizeof (uint8_t));
|
||||
else if (m_color_space == color_space::AIXTERM_16COLOR
|
||||
&& 0 <= m_value && m_value <= 15)
|
||||
memcpy (rgb, palette_16colors[m_value], 3 * sizeof (uint8_t));
|
||||
else if (m_color_space != color_space::XTERM_256COLOR)
|
||||
gdb_assert_not_reached ("get_rgb called on invalid color");
|
||||
else if (0 <= m_value && m_value <= 15)
|
||||
memcpy (rgb, palette_16colors[m_value], 3 * sizeof (uint8_t));
|
||||
else if (m_value >= 16 && m_value <= 231)
|
||||
{
|
||||
int value = m_value;
|
||||
value -= 16;
|
||||
/* This obscure formula seems to be what terminals actually
|
||||
do. */
|
||||
int component = value / 36;
|
||||
rgb[0] = component == 0 ? 0 : (55 + component * 40);
|
||||
value %= 36;
|
||||
component = value / 6;
|
||||
rgb[1] = component == 0 ? 0 : (55 + component * 40);
|
||||
value %= 6;
|
||||
rgb[2] = value == 0 ? 0 : (55 + value * 40);
|
||||
}
|
||||
else if (232 <= m_value && m_value <= 255)
|
||||
{
|
||||
uint8_t v = (m_value - 232) * 10 + 8;
|
||||
rgb[0] = v;
|
||||
rgb[1] = v;
|
||||
rgb[2] = v;
|
||||
}
|
||||
else
|
||||
gdb_assert_not_reached ("get_rgb called on invalid color");
|
||||
}
|
||||
|
||||
/* See ui-style.h. */
|
||||
|
||||
ui_file_style::color
|
||||
ui_file_style::color::approximate (const std::vector<color_space> &spaces) const
|
||||
{
|
||||
if (spaces.empty () || is_none ())
|
||||
return NONE;
|
||||
|
||||
color_space target_space = color_space::MONOCHROME;
|
||||
for (color_space sp : spaces)
|
||||
if (sp == m_color_space)
|
||||
return *this;
|
||||
else if (sp > target_space)
|
||||
target_space = sp;
|
||||
|
||||
if (target_space == color_space::RGB_24BIT)
|
||||
{
|
||||
uint8_t rgb[3];
|
||||
get_rgb (rgb);
|
||||
return color (rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
int target_size = 0;
|
||||
switch (target_space)
|
||||
{
|
||||
case color_space::ANSI_8COLOR:
|
||||
target_size = 8;
|
||||
break;
|
||||
case color_space::AIXTERM_16COLOR:
|
||||
target_size = 16;
|
||||
break;
|
||||
case color_space::XTERM_256COLOR:
|
||||
target_size = 256;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_simple() && m_value < target_size)
|
||||
return color (target_space, m_value);
|
||||
|
||||
color result = NONE;
|
||||
int best_distance = std::numeric_limits<int>::max ();
|
||||
uint8_t rgb[3];
|
||||
get_rgb (rgb);
|
||||
|
||||
for (int i = 0; i < target_size; ++i)
|
||||
{
|
||||
uint8_t c_rgb[3];
|
||||
color c (target_space, i);
|
||||
c.get_rgb (c_rgb);
|
||||
int d_red = std::abs (rgb[0] - c_rgb[0]);
|
||||
int d_green = std::abs (rgb[1] - c_rgb[1]);
|
||||
int d_blue = std::abs (rgb[2] - c_rgb[2]);
|
||||
int dist = d_red * d_red + d_green * d_green + d_blue * d_blue;
|
||||
if (dist < best_distance)
|
||||
{
|
||||
best_distance = dist;
|
||||
result = c;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* See ui-style.h. */
|
||||
@@ -139,26 +276,21 @@ std::string
|
||||
ui_file_style::to_ansi () const
|
||||
{
|
||||
std::string result ("\033[");
|
||||
bool need_semi = m_foreground.append_ansi (true, &result);
|
||||
if (!m_background.is_none ())
|
||||
if (!is_default ())
|
||||
{
|
||||
if (need_semi)
|
||||
result.push_back (';');
|
||||
m_foreground.append_ansi (true, &result);
|
||||
result.push_back (';');
|
||||
m_background.append_ansi (false, &result);
|
||||
need_semi = true;
|
||||
}
|
||||
if (m_intensity != NORMAL)
|
||||
{
|
||||
if (need_semi)
|
||||
result.push_back (';');
|
||||
result.append (std::to_string (m_intensity));
|
||||
need_semi = true;
|
||||
}
|
||||
if (m_reverse)
|
||||
{
|
||||
if (need_semi)
|
||||
result.push_back (';');
|
||||
result.push_back ('7');
|
||||
result.push_back (';');
|
||||
if (m_intensity == NORMAL)
|
||||
result.append ("22");
|
||||
else
|
||||
result.append (std::to_string (m_intensity));
|
||||
result.push_back (';');
|
||||
if (m_reverse)
|
||||
result.push_back ('7');
|
||||
else
|
||||
result.append ("27");
|
||||
}
|
||||
result.push_back ('m');
|
||||
return result;
|
||||
@@ -315,9 +447,11 @@ ui_file_style::parse (const char *buf, size_t *n_read)
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
m_foreground = color (value - 30);
|
||||
break;
|
||||
/* Note: not 38. */
|
||||
case 39:
|
||||
m_foreground = color (value - 30);
|
||||
m_foreground = NONE;
|
||||
break;
|
||||
|
||||
case 40:
|
||||
@@ -328,9 +462,11 @@ ui_file_style::parse (const char *buf, size_t *n_read)
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
m_background = color (value - 40);
|
||||
break;
|
||||
/* Note: not 48. */
|
||||
case 49:
|
||||
m_background = color (value - 40);
|
||||
m_background = NONE;
|
||||
break;
|
||||
|
||||
case 90:
|
||||
@@ -412,3 +548,60 @@ _initialize_ui_style ()
|
||||
error. */
|
||||
gdb_assert (code == 0);
|
||||
}
|
||||
|
||||
/* See ui-style.h. */
|
||||
|
||||
const std::vector<color_space> &
|
||||
colorsupport ()
|
||||
{
|
||||
static const std::vector<color_space> value = []
|
||||
{
|
||||
std::vector<color_space> result = {color_space::MONOCHROME};
|
||||
|
||||
int colors = tgetnum ("Co");
|
||||
if (colors >= 8)
|
||||
result.push_back (color_space::ANSI_8COLOR);
|
||||
if (colors >= 16)
|
||||
result.push_back (color_space::AIXTERM_16COLOR);
|
||||
if (colors >= 256)
|
||||
result.push_back (color_space::XTERM_256COLOR);
|
||||
|
||||
const char *colorterm = getenv ("COLORTERM");
|
||||
if (colorterm != nullptr && (!strcmp (colorterm, "truecolor")
|
||||
|| !strcmp (colorterm, "24bit")))
|
||||
result.push_back (color_space::RGB_24BIT);
|
||||
|
||||
return result;
|
||||
} ();
|
||||
return value;
|
||||
}
|
||||
|
||||
const char *
|
||||
color_space_name (color_space c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case color_space::MONOCHROME: return "monochrome";
|
||||
case color_space::ANSI_8COLOR: return "ansi_8color";
|
||||
case color_space::AIXTERM_16COLOR: return "aixterm_16color";
|
||||
case color_space::XTERM_256COLOR: return "xterm_256color";
|
||||
case color_space::RGB_24BIT: return "rgb_24bit";
|
||||
}
|
||||
gdb_assert_not_reached ("color_space_name called on invalid color");
|
||||
}
|
||||
|
||||
bool
|
||||
color_space_safe_cast (color_space *result, long c)
|
||||
{
|
||||
switch (static_cast<color_space>(c))
|
||||
{
|
||||
case color_space::MONOCHROME:
|
||||
case color_space::ANSI_8COLOR:
|
||||
case color_space::AIXTERM_16COLOR:
|
||||
case color_space::XTERM_256COLOR:
|
||||
case color_space::RGB_24BIT:
|
||||
*result = static_cast<color_space>(c);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
157
gdb/ui-style.h
157
gdb/ui-style.h
@@ -19,6 +19,38 @@
|
||||
#ifndef GDB_UI_STYLE_H
|
||||
#define GDB_UI_STYLE_H
|
||||
|
||||
/* One of the color spaces that usually supported by terminals. */
|
||||
enum class color_space
|
||||
{
|
||||
/* one default terminal color */
|
||||
MONOCHROME,
|
||||
|
||||
/* foreground colors \e[30m ... \e[37m,
|
||||
background colors \e[40m ... \e[47m */
|
||||
ANSI_8COLOR,
|
||||
|
||||
/* foreground colors \e[30m ... \e[37m, \e[90m ... \e[97m
|
||||
background colors \e[40m ... \e[47m, \e[100m ... \e107m */
|
||||
AIXTERM_16COLOR,
|
||||
|
||||
/* foreground colors \e[38;5;0m ... \e[38;5;255m
|
||||
background colors \e[48;5;0m ... \e[48;5;255m */
|
||||
XTERM_256COLOR,
|
||||
|
||||
/* foreground colors \e[38;2;0;0;0m ... \e[38;2;255;255;255m
|
||||
background colors \e[48;2;0;0;0m ... \e[48;2;255;255;255m */
|
||||
RGB_24BIT
|
||||
};
|
||||
|
||||
/* Color spaces supported by terminal. */
|
||||
extern const std::vector<color_space> & colorsupport ();
|
||||
|
||||
/* Textual representation of C. */
|
||||
extern const char * color_space_name (color_space c);
|
||||
|
||||
/* Cast C to RESULT and return true if it's value is valid; false otherwise. */
|
||||
extern bool color_space_safe_cast (color_space *result, long c);
|
||||
|
||||
/* Styles that can be applied to a ui_file. */
|
||||
struct ui_file_style
|
||||
{
|
||||
@@ -43,20 +75,61 @@ struct ui_file_style
|
||||
public:
|
||||
|
||||
color (basic_color c)
|
||||
: m_simple (true),
|
||||
: m_color_space (c == NONE ? color_space::MONOCHROME
|
||||
: color_space::ANSI_8COLOR),
|
||||
m_value (c)
|
||||
{
|
||||
}
|
||||
|
||||
color (int c)
|
||||
: m_simple (true),
|
||||
: m_value (c)
|
||||
{
|
||||
if (c < -1 || c > 255)
|
||||
error (_("Palette color index %d is out of range."), c);
|
||||
if (c == -1)
|
||||
m_color_space = color_space::MONOCHROME;
|
||||
else if (c <= 7)
|
||||
m_color_space = color_space::ANSI_8COLOR;
|
||||
else if (c <= 15)
|
||||
m_color_space = color_space::AIXTERM_16COLOR;
|
||||
else
|
||||
m_color_space = color_space::XTERM_256COLOR;
|
||||
}
|
||||
|
||||
color (color_space cs, int c)
|
||||
: m_color_space (cs),
|
||||
m_value (c)
|
||||
{
|
||||
gdb_assert (c >= -1 && c <= 255);
|
||||
if (c < -1 || c > 255)
|
||||
error (_("Palette color index %d is out of range."), c);
|
||||
|
||||
std::pair<int, int> range;
|
||||
switch (cs)
|
||||
{
|
||||
case color_space::MONOCHROME:
|
||||
range = {-1, -1};
|
||||
break;
|
||||
case color_space::ANSI_8COLOR:
|
||||
range = {0, 7};
|
||||
break;
|
||||
case color_space::AIXTERM_16COLOR:
|
||||
range = {0, 15};
|
||||
break;
|
||||
case color_space::XTERM_256COLOR:
|
||||
range = {0, 255};
|
||||
break;
|
||||
default:
|
||||
error (_("Color space %d is incompatible with indexed colors."),
|
||||
static_cast<int> (cs));
|
||||
}
|
||||
|
||||
if (c < range.first || c > range.second)
|
||||
error (_("Color %d is out of range [%d, %d] of color space %d."),
|
||||
c, range.first, range.second, static_cast<int> (cs));
|
||||
}
|
||||
|
||||
color (uint8_t r, uint8_t g, uint8_t b)
|
||||
: m_simple (false),
|
||||
: m_color_space (color_space::RGB_24BIT),
|
||||
m_red (r),
|
||||
m_green (g),
|
||||
m_blue (b)
|
||||
@@ -65,19 +138,24 @@ struct ui_file_style
|
||||
|
||||
bool operator== (const color &other) const
|
||||
{
|
||||
if (m_simple != other.m_simple)
|
||||
if (m_color_space != other.m_color_space)
|
||||
return false;
|
||||
if (m_simple)
|
||||
if (is_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
|
||||
{
|
||||
return ! (*this == other);
|
||||
}
|
||||
|
||||
bool operator< (const color &other) const
|
||||
{
|
||||
if (m_simple != other.m_simple)
|
||||
return m_simple < other.m_simple;
|
||||
if (m_simple)
|
||||
if (m_color_space != other.m_color_space)
|
||||
return m_color_space < other.m_color_space;
|
||||
if (is_simple ())
|
||||
return m_value < other.m_value;
|
||||
if (m_red < other.m_red)
|
||||
return true;
|
||||
@@ -91,23 +169,54 @@ struct ui_file_style
|
||||
return false;
|
||||
}
|
||||
|
||||
color_space colorspace () const
|
||||
{
|
||||
return m_color_space;
|
||||
}
|
||||
|
||||
/* Return true if this is the "NONE" color, false otherwise. */
|
||||
bool is_none () const
|
||||
{
|
||||
return m_simple && m_value == NONE;
|
||||
return m_color_space == color_space::MONOCHROME && 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;
|
||||
if (m_color_space == color_space::ANSI_8COLOR
|
||||
|| m_color_space == color_space::AIXTERM_16COLOR)
|
||||
return BLACK <= m_value && m_value <= WHITE;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return the value of a basic color. */
|
||||
/* Return true if this is one of the colors, stored as int, false
|
||||
otherwise. */
|
||||
bool is_simple () const
|
||||
{
|
||||
return m_color_space != color_space::RGB_24BIT;
|
||||
}
|
||||
|
||||
/* Return true if this is one of the indexed colors, false
|
||||
otherwise. */
|
||||
bool is_indexed () const
|
||||
{
|
||||
return m_color_space != color_space::RGB_24BIT
|
||||
&& m_color_space != color_space::MONOCHROME;
|
||||
}
|
||||
|
||||
/* Return true if this is one of the direct colors (RGB, CMY, CMYK), false
|
||||
otherwise. */
|
||||
bool is_direct () const
|
||||
{
|
||||
return m_color_space == color_space::RGB_24BIT;
|
||||
}
|
||||
|
||||
/* Return the value of a simple color. */
|
||||
int get_value () const
|
||||
{
|
||||
gdb_assert (is_basic ());
|
||||
gdb_assert (is_simple ());
|
||||
return m_value;
|
||||
}
|
||||
|
||||
@@ -118,14 +227,23 @@ struct ui_file_style
|
||||
|
||||
/* 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;
|
||||
color. */
|
||||
void append_ansi (bool is_fg, std::string *str) const;
|
||||
|
||||
/* Return the ANSI escape sequence for this color.
|
||||
IS_FG indicates whether this is a foreground or background color. */
|
||||
std::string to_ansi (bool is_fg) const;
|
||||
|
||||
/* Returns text representation of this object.
|
||||
It is "none", name of a basic color, number or a #RRGGBB hex triplet. */
|
||||
std::string to_string () const;
|
||||
|
||||
/* Approximates THIS color by closest one from SPACES. */
|
||||
color approximate (const std::vector<color_space> &spaces) const;
|
||||
|
||||
private:
|
||||
|
||||
bool m_simple;
|
||||
color_space m_color_space;
|
||||
union
|
||||
{
|
||||
int m_value;
|
||||
@@ -235,6 +353,9 @@ struct ui_file_style
|
||||
return this;
|
||||
}
|
||||
|
||||
/* nullptr-terminated list of names corresponding to enum basic_color. */
|
||||
static const std::vector<const char *> basic_color_enums;
|
||||
|
||||
private:
|
||||
|
||||
color m_foreground = NONE;
|
||||
|
||||
@@ -58,7 +58,7 @@ run_tests ()
|
||||
SELF_CHECK (style.get_background ().is_none ());
|
||||
SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
|
||||
SELF_CHECK (style.is_reverse ());
|
||||
SELF_CHECK (style.to_ansi () == "\033[7m");
|
||||
SELF_CHECK (style.to_ansi () == "\033[39;49;22;7m");
|
||||
|
||||
style = ui_file_style ();
|
||||
SELF_CHECK (style.parse ("\033[32;1m", &n_read));
|
||||
@@ -68,7 +68,7 @@ run_tests ()
|
||||
SELF_CHECK (style.get_background ().is_none ());
|
||||
SELF_CHECK (style.get_intensity () == ui_file_style::BOLD);
|
||||
SELF_CHECK (!style.is_reverse ());
|
||||
SELF_CHECK (style.to_ansi () == "\033[32;1m");
|
||||
SELF_CHECK (style.to_ansi () == "\033[32;49;1;27m");
|
||||
|
||||
style = ui_file_style ();
|
||||
SELF_CHECK (style.parse ("\033[38;5;112;48;5;249m", &n_read));
|
||||
@@ -81,7 +81,7 @@ run_tests ()
|
||||
CHECK_RGB (0xb2, 0xb2, 0xb2);
|
||||
SELF_CHECK (style.get_intensity () == ui_file_style::NORMAL);
|
||||
SELF_CHECK (!style.is_reverse ());
|
||||
SELF_CHECK (style.to_ansi () == "\033[38;5;112;48;5;249m");
|
||||
SELF_CHECK (style.to_ansi () == "\033[38;5;112;48;5;249;22;27m");
|
||||
|
||||
style = ui_file_style ();
|
||||
SELF_CHECK (style.parse ("\033[38;2;83;84;85;48;2;0;1;254;2;7m", &n_read));
|
||||
|
||||
Reference in New Issue
Block a user