| 1 | /* CLI colorizing |
| 2 | |
| 3 | Copyright (C) 2018-2019 Free Software Foundation, Inc. |
| 4 | |
| 5 | This file is part of GDB. |
| 6 | |
| 7 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 3 of the License, or |
| 10 | (at your option) any later version. |
| 11 | |
| 12 | This program is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 19 | |
| 20 | #include "defs.h" |
| 21 | #include "cli/cli-cmds.h" |
| 22 | #include "cli/cli-style.h" |
| 23 | #include "source-cache.h" |
| 24 | #include "observable.h" |
| 25 | |
| 26 | /* True if styling is enabled. */ |
| 27 | |
| 28 | #if defined (__MSDOS__) || defined (__CYGWIN__) |
| 29 | bool cli_styling = false; |
| 30 | #else |
| 31 | bool cli_styling = true; |
| 32 | #endif |
| 33 | |
| 34 | /* True if source styling is enabled. Note that this is only |
| 35 | consulted when cli_styling is true. */ |
| 36 | |
| 37 | bool source_styling = true; |
| 38 | |
| 39 | /* Name of colors; must correspond to ui_file_style::basic_color. */ |
| 40 | static const char * const cli_colors[] = { |
| 41 | "none", |
| 42 | "black", |
| 43 | "red", |
| 44 | "green", |
| 45 | "yellow", |
| 46 | "blue", |
| 47 | "magenta", |
| 48 | "cyan", |
| 49 | "white", |
| 50 | nullptr |
| 51 | }; |
| 52 | |
| 53 | /* Names of intensities; must correspond to |
| 54 | ui_file_style::intensity. */ |
| 55 | static const char * const cli_intensities[] = { |
| 56 | "normal", |
| 57 | "bold", |
| 58 | "dim", |
| 59 | nullptr |
| 60 | }; |
| 61 | |
| 62 | /* See cli-style.h. */ |
| 63 | |
| 64 | cli_style_option file_name_style ("filename", ui_file_style::GREEN); |
| 65 | |
| 66 | /* See cli-style.h. */ |
| 67 | |
| 68 | cli_style_option function_name_style ("function", ui_file_style::YELLOW); |
| 69 | |
| 70 | /* See cli-style.h. */ |
| 71 | |
| 72 | cli_style_option variable_name_style ("variable", ui_file_style::CYAN); |
| 73 | |
| 74 | /* See cli-style.h. */ |
| 75 | |
| 76 | cli_style_option address_style ("address", ui_file_style::BLUE); |
| 77 | |
| 78 | /* See cli-style.h. */ |
| 79 | |
| 80 | cli_style_option highlight_style ("highlight", ui_file_style::RED); |
| 81 | |
| 82 | /* See cli-style.h. */ |
| 83 | |
| 84 | cli_style_option title_style ("title", ui_file_style::BOLD); |
| 85 | |
| 86 | /* See cli-style.h. */ |
| 87 | |
| 88 | cli_style_option tui_border_style ("tui-border", ui_file_style::CYAN); |
| 89 | |
| 90 | /* See cli-style.h. */ |
| 91 | |
| 92 | cli_style_option tui_active_border_style ("tui-active-border", |
| 93 | ui_file_style::CYAN); |
| 94 | |
| 95 | /* See cli-style.h. */ |
| 96 | |
| 97 | cli_style_option metadata_style ("metadata", ui_file_style::DIM); |
| 98 | |
| 99 | /* See cli-style.h. */ |
| 100 | |
| 101 | cli_style_option::cli_style_option (const char *name, |
| 102 | ui_file_style::basic_color fg) |
| 103 | : changed (name), |
| 104 | m_name (name), |
| 105 | m_foreground (cli_colors[fg - ui_file_style::NONE]), |
| 106 | m_background (cli_colors[0]), |
| 107 | m_intensity (cli_intensities[ui_file_style::NORMAL]) |
| 108 | { |
| 109 | } |
| 110 | |
| 111 | /* See cli-style.h. */ |
| 112 | |
| 113 | cli_style_option::cli_style_option (const char *name, |
| 114 | ui_file_style::intensity i) |
| 115 | : changed (name), |
| 116 | m_name (name), |
| 117 | m_foreground (cli_colors[0]), |
| 118 | m_background (cli_colors[0]), |
| 119 | m_intensity (cli_intensities[i]) |
| 120 | { |
| 121 | } |
| 122 | |
| 123 | /* Return the color number corresponding to COLOR. */ |
| 124 | |
| 125 | static int |
| 126 | color_number (const char *color) |
| 127 | { |
| 128 | for (int i = 0; i < ARRAY_SIZE (cli_colors); ++i) |
| 129 | { |
| 130 | if (color == cli_colors[i]) |
| 131 | return i - 1; |
| 132 | } |
| 133 | gdb_assert_not_reached ("color not found"); |
| 134 | } |
| 135 | |
| 136 | /* See cli-style.h. */ |
| 137 | |
| 138 | ui_file_style |
| 139 | cli_style_option::style () const |
| 140 | { |
| 141 | int fg = color_number (m_foreground); |
| 142 | int bg = color_number (m_background); |
| 143 | ui_file_style::intensity intensity = ui_file_style::NORMAL; |
| 144 | |
| 145 | for (int i = 0; i < ARRAY_SIZE (cli_intensities); ++i) |
| 146 | { |
| 147 | if (m_intensity == cli_intensities[i]) |
| 148 | { |
| 149 | intensity = (ui_file_style::intensity) i; |
| 150 | break; |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | return ui_file_style (fg, bg, intensity); |
| 155 | } |
| 156 | |
| 157 | /* See cli-style.h. */ |
| 158 | |
| 159 | void |
| 160 | cli_style_option::do_set_value (const char *ignore, int from_tty, |
| 161 | struct cmd_list_element *cmd) |
| 162 | { |
| 163 | cli_style_option *cso = (cli_style_option *) get_cmd_context (cmd); |
| 164 | cso->changed.notify (); |
| 165 | } |
| 166 | |
| 167 | /* Implements the cli_style_option::do_show_* functions. |
| 168 | WHAT and VALUE are the property and value to show. |
| 169 | The style for which WHAT is shown is retrieved from CMD context. */ |
| 170 | |
| 171 | static void |
| 172 | do_show (const char *what, struct ui_file *file, |
| 173 | struct cmd_list_element *cmd, |
| 174 | const char *value) |
| 175 | { |
| 176 | cli_style_option *cso = (cli_style_option *) get_cmd_context (cmd); |
| 177 | fputs_filtered (_("The "), file); |
| 178 | fprintf_styled (file, cso->style (), _("\"%s\" style"), cso->name ()); |
| 179 | fprintf_filtered (file, _(" %s is: %s\n"), what, value); |
| 180 | } |
| 181 | |
| 182 | /* See cli-style.h. */ |
| 183 | |
| 184 | void |
| 185 | cli_style_option::do_show_foreground (struct ui_file *file, int from_tty, |
| 186 | struct cmd_list_element *cmd, |
| 187 | const char *value) |
| 188 | { |
| 189 | do_show (_("foreground color"), file, cmd, value); |
| 190 | } |
| 191 | |
| 192 | /* See cli-style.h. */ |
| 193 | |
| 194 | void |
| 195 | cli_style_option::do_show_background (struct ui_file *file, int from_tty, |
| 196 | struct cmd_list_element *cmd, |
| 197 | const char *value) |
| 198 | { |
| 199 | do_show (_("background color"), file, cmd, value); |
| 200 | } |
| 201 | |
| 202 | /* See cli-style.h. */ |
| 203 | |
| 204 | void |
| 205 | cli_style_option::do_show_intensity (struct ui_file *file, int from_tty, |
| 206 | struct cmd_list_element *cmd, |
| 207 | const char *value) |
| 208 | { |
| 209 | do_show (_("display intensity"), file, cmd, value); |
| 210 | } |
| 211 | |
| 212 | /* See cli-style.h. */ |
| 213 | |
| 214 | void |
| 215 | cli_style_option::add_setshow_commands (enum command_class theclass, |
| 216 | const char *prefix_doc, |
| 217 | struct cmd_list_element **set_list, |
| 218 | void (*do_set) (const char *args, |
| 219 | int from_tty), |
| 220 | struct cmd_list_element **show_list, |
| 221 | void (*do_show) (const char *args, |
| 222 | int from_tty), |
| 223 | bool skip_intensity) |
| 224 | { |
| 225 | m_set_prefix = std::string ("set style ") + m_name + " "; |
| 226 | m_show_prefix = std::string ("show style ") + m_name + " "; |
| 227 | |
| 228 | add_prefix_cmd (m_name, no_class, do_set, prefix_doc, &m_set_list, |
| 229 | m_set_prefix.c_str (), 0, set_list); |
| 230 | add_prefix_cmd (m_name, no_class, do_show, prefix_doc, &m_show_list, |
| 231 | m_show_prefix.c_str (), 0, show_list); |
| 232 | |
| 233 | add_setshow_enum_cmd ("foreground", theclass, cli_colors, |
| 234 | &m_foreground, |
| 235 | _("Set the foreground color for this property."), |
| 236 | _("Show the foreground color for this property."), |
| 237 | nullptr, |
| 238 | do_set_value, |
| 239 | do_show_foreground, |
| 240 | &m_set_list, &m_show_list, (void *) this); |
| 241 | add_setshow_enum_cmd ("background", theclass, cli_colors, |
| 242 | &m_background, |
| 243 | _("Set the background color for this property."), |
| 244 | _("Show the background color for this property."), |
| 245 | nullptr, |
| 246 | do_set_value, |
| 247 | do_show_background, |
| 248 | &m_set_list, &m_show_list, (void *) this); |
| 249 | if (!skip_intensity) |
| 250 | add_setshow_enum_cmd ("intensity", theclass, cli_intensities, |
| 251 | &m_intensity, |
| 252 | _("Set the display intensity for this property."), |
| 253 | _("Show the display intensity for this property."), |
| 254 | nullptr, |
| 255 | do_set_value, |
| 256 | do_show_intensity, |
| 257 | &m_set_list, &m_show_list, (void *) this); |
| 258 | } |
| 259 | |
| 260 | static cmd_list_element *style_set_list; |
| 261 | static cmd_list_element *style_show_list; |
| 262 | |
| 263 | static void |
| 264 | set_style (const char *arg, int from_tty) |
| 265 | { |
| 266 | printf_unfiltered (_("\"set style\" must be followed " |
| 267 | "by an appropriate subcommand.\n")); |
| 268 | help_list (style_set_list, "set style ", all_commands, gdb_stdout); |
| 269 | } |
| 270 | |
| 271 | static void |
| 272 | show_style (const char *arg, int from_tty) |
| 273 | { |
| 274 | cmd_show_list (style_show_list, from_tty, ""); |
| 275 | } |
| 276 | |
| 277 | static void |
| 278 | set_style_enabled (const char *args, int from_tty, struct cmd_list_element *c) |
| 279 | { |
| 280 | g_source_cache.clear (); |
| 281 | gdb::observers::source_styling_changed.notify (); |
| 282 | } |
| 283 | |
| 284 | static void |
| 285 | show_style_enabled (struct ui_file *file, int from_tty, |
| 286 | struct cmd_list_element *c, const char *value) |
| 287 | { |
| 288 | if (cli_styling) |
| 289 | fprintf_filtered (file, _("CLI output styling is enabled.\n")); |
| 290 | else |
| 291 | fprintf_filtered (file, _("CLI output styling is disabled.\n")); |
| 292 | } |
| 293 | |
| 294 | static void |
| 295 | show_style_sources (struct ui_file *file, int from_tty, |
| 296 | struct cmd_list_element *c, const char *value) |
| 297 | { |
| 298 | if (source_styling) |
| 299 | fprintf_filtered (file, _("Source code styling is enabled.\n")); |
| 300 | else |
| 301 | fprintf_filtered (file, _("Source code styling is disabled.\n")); |
| 302 | } |
| 303 | |
| 304 | /* Builds the "set style NAME " prefix. */ |
| 305 | |
| 306 | static std::string |
| 307 | set_style_name (const char *name) |
| 308 | { |
| 309 | std::string result ("set style "); |
| 310 | |
| 311 | result += name; |
| 312 | result += " "; |
| 313 | return result; |
| 314 | } |
| 315 | |
| 316 | void |
| 317 | _initialize_cli_style () |
| 318 | { |
| 319 | add_prefix_cmd ("style", no_class, set_style, _("\ |
| 320 | Style-specific settings.\n\ |
| 321 | Configure various style-related variables, such as colors"), |
| 322 | &style_set_list, "set style ", 0, &setlist); |
| 323 | add_prefix_cmd ("style", no_class, show_style, _("\ |
| 324 | Style-specific settings.\n\ |
| 325 | Configure various style-related variables, such as colors"), |
| 326 | &style_show_list, "show style ", 0, &showlist); |
| 327 | |
| 328 | add_setshow_boolean_cmd ("enabled", no_class, &cli_styling, _("\ |
| 329 | Set whether CLI styling is enabled."), _("\ |
| 330 | Show whether CLI is enabled."), _("\ |
| 331 | If enabled, output to the terminal is styled."), |
| 332 | set_style_enabled, show_style_enabled, |
| 333 | &style_set_list, &style_show_list); |
| 334 | |
| 335 | add_setshow_boolean_cmd ("sources", no_class, &source_styling, _("\ |
| 336 | Set whether source code styling is enabled."), _("\ |
| 337 | Show whether source code styling is enabled."), _("\ |
| 338 | If enabled, source code is styled.\n" |
| 339 | #ifdef HAVE_SOURCE_HIGHLIGHT |
| 340 | "Note that source styling only works if styling in general is enabled,\n\ |
| 341 | see \"show style enabled\"." |
| 342 | #else |
| 343 | "Source highlighting is disabled in this installation of gdb, because\n\ |
| 344 | it was not linked against GNU Source Highlight." |
| 345 | #endif |
| 346 | ), set_style_enabled, show_style_sources, |
| 347 | &style_set_list, &style_show_list); |
| 348 | |
| 349 | #define STYLE_ADD_SETSHOW_COMMANDS(STYLE, PREFIX_DOC, SKIP) \ |
| 350 | STYLE.add_setshow_commands (no_class, PREFIX_DOC, \ |
| 351 | &style_set_list, \ |
| 352 | [] (const char *args, int from_tty) \ |
| 353 | { \ |
| 354 | help_list \ |
| 355 | (STYLE.set_list (), \ |
| 356 | set_style_name (STYLE.name ()).c_str (), \ |
| 357 | all_commands, \ |
| 358 | gdb_stdout); \ |
| 359 | }, \ |
| 360 | &style_show_list, \ |
| 361 | [] (const char *args, int from_tty) \ |
| 362 | { \ |
| 363 | cmd_show_list \ |
| 364 | (STYLE.show_list (), \ |
| 365 | from_tty, \ |
| 366 | ""); \ |
| 367 | }, SKIP) |
| 368 | |
| 369 | STYLE_ADD_SETSHOW_COMMANDS (file_name_style, |
| 370 | _("\ |
| 371 | Filename display styling.\n\ |
| 372 | Configure filename colors and display intensity."), false); |
| 373 | |
| 374 | STYLE_ADD_SETSHOW_COMMANDS (function_name_style, |
| 375 | _("\ |
| 376 | Function name display styling.\n\ |
| 377 | Configure function name colors and display intensity"), false); |
| 378 | |
| 379 | STYLE_ADD_SETSHOW_COMMANDS (variable_name_style, |
| 380 | _("\ |
| 381 | Variable name display styling.\n\ |
| 382 | Configure variable name colors and display intensity"), false); |
| 383 | |
| 384 | STYLE_ADD_SETSHOW_COMMANDS (address_style, |
| 385 | _("\ |
| 386 | Address display styling.\n\ |
| 387 | Configure address colors and display intensity"), false); |
| 388 | |
| 389 | STYLE_ADD_SETSHOW_COMMANDS (title_style, |
| 390 | _("\ |
| 391 | Title display styling.\n\ |
| 392 | Configure title colors and display intensity\n\ |
| 393 | Some commands (such as \"apropos -v REGEXP\") use the title style to improve\n\ |
| 394 | readability."), false); |
| 395 | |
| 396 | STYLE_ADD_SETSHOW_COMMANDS (highlight_style, |
| 397 | _("\ |
| 398 | Highlight display styling.\n\ |
| 399 | Configure highlight colors and display intensity\n\ |
| 400 | Some commands use the highlight style to draw the attention to a part\n\ |
| 401 | of their output."), false); |
| 402 | |
| 403 | STYLE_ADD_SETSHOW_COMMANDS (metadata_style, |
| 404 | _("\ |
| 405 | Metadata display styling.\n\ |
| 406 | Configure metadata colors and display intensity\n\ |
| 407 | The \"metadata\" style is used when GDB displays information about\n\ |
| 408 | your data, for example \"<unavailable>\""), false); |
| 409 | |
| 410 | STYLE_ADD_SETSHOW_COMMANDS (tui_border_style, |
| 411 | _("\ |
| 412 | TUI border display styling.\n\ |
| 413 | Configure TUI border colors\n\ |
| 414 | The \"tui-border\" style is used when GDB displays the border of a\n\ |
| 415 | TUI window that does not have the focus."), true); |
| 416 | |
| 417 | STYLE_ADD_SETSHOW_COMMANDS (tui_active_border_style, |
| 418 | _("\ |
| 419 | TUI active border display styling.\n\ |
| 420 | Configure TUI active border colors\n\ |
| 421 | The \"tui-active-border\" style is used when GDB displays the border of a\n\ |
| 422 | TUI window that does have the focus."), true); |
| 423 | } |