Home | History | Annotate | Line # | Download | only in cli
cli-style.c revision 1.1.1.3
      1 /* CLI colorizing
      2 
      3    Copyright (C) 2018-2023 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-decode.h"
     23 #include "cli/cli-setshow.h"
     24 #include "cli/cli-style.h"
     25 #include "source-cache.h"
     26 #include "observable.h"
     27 
     28 /* True if styling is enabled.  */
     29 
     30 #if defined (__MSDOS__)
     31 bool cli_styling = false;
     32 #else
     33 bool cli_styling = true;
     34 #endif
     35 
     36 /* True if source styling is enabled.  Note that this is only
     37    consulted when cli_styling is true.  */
     38 
     39 bool source_styling = true;
     40 
     41 /* True if disassembler styling is enabled.  Note that this is only
     42    consulted when cli_styling is true.  */
     43 
     44 bool disassembler_styling = true;
     45 
     46 /* Name of colors; must correspond to ui_file_style::basic_color.  */
     47 static const char * const cli_colors[] = {
     48   "none",
     49   "black",
     50   "red",
     51   "green",
     52   "yellow",
     53   "blue",
     54   "magenta",
     55   "cyan",
     56   "white",
     57   nullptr
     58 };
     59 
     60 /* Names of intensities; must correspond to
     61    ui_file_style::intensity.  */
     62 static const char * const cli_intensities[] = {
     63   "normal",
     64   "bold",
     65   "dim",
     66   nullptr
     67 };
     68 
     69 /* See cli-style.h.  */
     70 
     71 cli_style_option file_name_style ("filename", ui_file_style::GREEN);
     72 
     73 /* See cli-style.h.  */
     74 
     75 cli_style_option function_name_style ("function", ui_file_style::YELLOW);
     76 
     77 /* See cli-style.h.  */
     78 
     79 cli_style_option variable_name_style ("variable", ui_file_style::CYAN);
     80 
     81 /* See cli-style.h.  */
     82 
     83 cli_style_option address_style ("address", ui_file_style::BLUE);
     84 
     85 /* See cli-style.h.  */
     86 
     87 cli_style_option highlight_style ("highlight", ui_file_style::RED);
     88 
     89 /* See cli-style.h.  */
     90 
     91 cli_style_option title_style ("title", ui_file_style::BOLD);
     92 
     93 /* See cli-style.h.  */
     94 
     95 cli_style_option tui_border_style ("tui-border", ui_file_style::CYAN);
     96 
     97 /* See cli-style.h.  */
     98 
     99 cli_style_option tui_active_border_style ("tui-active-border",
    100 					  ui_file_style::CYAN);
    101 
    102 /* See cli-style.h.  */
    103 
    104 cli_style_option metadata_style ("metadata", ui_file_style::DIM);
    105 
    106 /* See cli-style.h.  */
    107 
    108 cli_style_option version_style ("version", ui_file_style::MAGENTA,
    109 				ui_file_style::BOLD);
    110 
    111 /* See cli-style.h.  */
    112 
    113 cli_style_option disasm_mnemonic_style ("mnemonic", ui_file_style::GREEN);
    114 
    115 /* See cli-style.h.  */
    116 
    117 cli_style_option disasm_register_style ("register", ui_file_style::RED);
    118 
    119 /* See cli-style.h.  */
    120 
    121 cli_style_option disasm_immediate_style ("immediate", ui_file_style::BLUE);
    122 
    123 /* See cli-style.h.  */
    124 
    125 cli_style_option disasm_comment_style ("comment", ui_file_style::WHITE,
    126 				       ui_file_style::DIM);
    127 
    128 /* See cli-style.h.  */
    129 
    130 cli_style_option::cli_style_option (const char *name,
    131 				    ui_file_style::basic_color fg,
    132 				    ui_file_style::intensity intensity)
    133   : changed (name),
    134     m_name (name),
    135     m_foreground (cli_colors[fg - ui_file_style::NONE]),
    136     m_background (cli_colors[0]),
    137     m_intensity (cli_intensities[intensity])
    138 {
    139 }
    140 
    141 /* See cli-style.h.  */
    142 
    143 cli_style_option::cli_style_option (const char *name,
    144 				    ui_file_style::intensity i)
    145   : changed (name),
    146     m_name (name),
    147     m_foreground (cli_colors[0]),
    148     m_background (cli_colors[0]),
    149     m_intensity (cli_intensities[i])
    150 {
    151 }
    152 
    153 /* Return the color number corresponding to COLOR.  */
    154 
    155 static int
    156 color_number (const char *color)
    157 {
    158   for (int i = 0; i < ARRAY_SIZE (cli_colors); ++i)
    159     {
    160       if (color == cli_colors[i])
    161 	return i - 1;
    162     }
    163   gdb_assert_not_reached ("color not found");
    164 }
    165 
    166 /* See cli-style.h.  */
    167 
    168 ui_file_style
    169 cli_style_option::style () const
    170 {
    171   int fg = color_number (m_foreground);
    172   int bg = color_number (m_background);
    173   ui_file_style::intensity intensity = ui_file_style::NORMAL;
    174 
    175   for (int i = 0; i < ARRAY_SIZE (cli_intensities); ++i)
    176     {
    177       if (m_intensity == cli_intensities[i])
    178 	{
    179 	  intensity = (ui_file_style::intensity) i;
    180 	  break;
    181 	}
    182     }
    183 
    184   return ui_file_style (fg, bg, intensity);
    185 }
    186 
    187 /* See cli-style.h.  */
    188 
    189 void
    190 cli_style_option::do_set_value (const char *ignore, int from_tty,
    191 				struct cmd_list_element *cmd)
    192 {
    193   cli_style_option *cso = (cli_style_option *) cmd->context ();
    194   cso->changed.notify ();
    195 }
    196 
    197 /* Implements the cli_style_option::do_show_* functions.
    198    WHAT and VALUE are the property and value to show.
    199    The style for which WHAT is shown is retrieved from CMD context.  */
    200 
    201 static void
    202 do_show (const char *what, struct ui_file *file,
    203 	 struct cmd_list_element *cmd,
    204 	 const char *value)
    205 {
    206   cli_style_option *cso = (cli_style_option *) cmd->context ();
    207   gdb_puts (_("The "), file);
    208   fprintf_styled (file, cso->style (), _("\"%s\" style"), cso->name ());
    209   gdb_printf (file, _(" %s is: %s\n"), what, value);
    210 }
    211 
    212 /* See cli-style.h.  */
    213 
    214 void
    215 cli_style_option::do_show_foreground (struct ui_file *file, int from_tty,
    216 				      struct cmd_list_element *cmd,
    217 				      const char *value)
    218 {
    219   do_show (_("foreground color"), file, cmd, value);
    220 }
    221 
    222 /* See cli-style.h.  */
    223 
    224 void
    225 cli_style_option::do_show_background (struct ui_file *file, int from_tty,
    226 				      struct cmd_list_element *cmd,
    227 				      const char *value)
    228 {
    229   do_show (_("background color"), file, cmd, value);
    230 }
    231 
    232 /* See cli-style.h.  */
    233 
    234 void
    235 cli_style_option::do_show_intensity (struct ui_file *file, int from_tty,
    236 				     struct cmd_list_element *cmd,
    237 				     const char *value)
    238 {
    239   do_show (_("display intensity"), file, cmd, value);
    240 }
    241 
    242 /* See cli-style.h.  */
    243 
    244 set_show_commands
    245 cli_style_option::add_setshow_commands (enum command_class theclass,
    246 					const char *prefix_doc,
    247 					struct cmd_list_element **set_list,
    248 					struct cmd_list_element **show_list,
    249 					bool skip_intensity)
    250 {
    251   set_show_commands prefix_cmds
    252     = add_setshow_prefix_cmd (m_name, theclass, prefix_doc, prefix_doc,
    253 			      &m_set_list, &m_show_list, set_list, show_list);
    254 
    255   set_show_commands commands;
    256 
    257   commands = add_setshow_enum_cmd
    258     ("foreground", theclass, cli_colors,
    259      &m_foreground,
    260      _("Set the foreground color for this property."),
    261      _("Show the foreground color for this property."),
    262      nullptr,
    263      do_set_value,
    264      do_show_foreground,
    265      &m_set_list, &m_show_list);
    266   commands.set->set_context (this);
    267   commands.show->set_context (this);
    268 
    269   commands = add_setshow_enum_cmd
    270     ("background", theclass, cli_colors,
    271      &m_background,
    272      _("Set the background color for this property."),
    273      _("Show the background color for this property."),
    274      nullptr,
    275      do_set_value,
    276      do_show_background,
    277      &m_set_list, &m_show_list);
    278   commands.set->set_context (this);
    279   commands.show->set_context (this);
    280 
    281   if (!skip_intensity)
    282     {
    283       commands = add_setshow_enum_cmd
    284 	("intensity", theclass, cli_intensities,
    285 	 &m_intensity,
    286 	 _("Set the display intensity for this property."),
    287 	 _("Show the display intensity for this property."),
    288 	 nullptr,
    289 	 do_set_value,
    290 	 do_show_intensity,
    291 	 &m_set_list, &m_show_list);
    292       commands.set->set_context (this);
    293       commands.show->set_context (this);
    294     }
    295 
    296   return prefix_cmds;
    297 }
    298 
    299 cmd_list_element *style_set_list;
    300 cmd_list_element *style_show_list;
    301 
    302 /* The command list for 'set style disassembler'.  */
    303 
    304 static cmd_list_element *style_disasm_set_list;
    305 
    306 /* The command list for 'show style disassembler'.  */
    307 
    308 static cmd_list_element *style_disasm_show_list;
    309 
    310 static void
    311 set_style_enabled  (const char *args, int from_tty, struct cmd_list_element *c)
    312 {
    313   g_source_cache.clear ();
    314   gdb::observers::styling_changed.notify ();
    315 }
    316 
    317 static void
    318 show_style_enabled (struct ui_file *file, int from_tty,
    319 		    struct cmd_list_element *c, const char *value)
    320 {
    321   if (cli_styling)
    322     gdb_printf (file, _("CLI output styling is enabled.\n"));
    323   else
    324     gdb_printf (file, _("CLI output styling is disabled.\n"));
    325 }
    326 
    327 static void
    328 show_style_sources (struct ui_file *file, int from_tty,
    329 		    struct cmd_list_element *c, const char *value)
    330 {
    331   if (source_styling)
    332     gdb_printf (file, _("Source code styling is enabled.\n"));
    333   else
    334     gdb_printf (file, _("Source code styling is disabled.\n"));
    335 }
    336 
    337 /* Implement 'show style disassembler'.  */
    338 
    339 static void
    340 show_style_disassembler (struct ui_file *file, int from_tty,
    341 			 struct cmd_list_element *c, const char *value)
    342 {
    343   if (disassembler_styling)
    344     gdb_printf (file, _("Disassembler output styling is enabled.\n"));
    345   else
    346     gdb_printf (file, _("Disassembler output styling is disabled.\n"));
    347 }
    348 
    349 void _initialize_cli_style ();
    350 void
    351 _initialize_cli_style ()
    352 {
    353   add_setshow_prefix_cmd ("style", no_class,
    354 			  _("\
    355 Style-specific settings.\n\
    356 Configure various style-related variables, such as colors"),
    357 			  _("\
    358 Style-specific settings.\n\
    359 Configure various style-related variables, such as colors"),
    360 			  &style_set_list, &style_show_list,
    361 			  &setlist, &showlist);
    362 
    363   add_setshow_boolean_cmd ("enabled", no_class, &cli_styling, _("\
    364 Set whether CLI styling is enabled."), _("\
    365 Show whether CLI is enabled."), _("\
    366 If enabled, output to the terminal is styled."),
    367 			   set_style_enabled, show_style_enabled,
    368 			   &style_set_list, &style_show_list);
    369 
    370   add_setshow_boolean_cmd ("sources", no_class, &source_styling, _("\
    371 Set whether source code styling is enabled."), _("\
    372 Show whether source code styling is enabled."), _("\
    373 If enabled, source code is styled.\n"
    374 #ifdef HAVE_SOURCE_HIGHLIGHT
    375 "Note that source styling only works if styling in general is enabled,\n\
    376 see \"show style enabled\"."
    377 #else
    378 "Source highlighting may be disabled in this installation of gdb, because\n\
    379 it was not linked against GNU Source Highlight.  However, it might still be\n\
    380 available if the appropriate extension is available at runtime."
    381 #endif
    382 			   ), set_style_enabled, show_style_sources,
    383 			   &style_set_list, &style_show_list);
    384 
    385   add_setshow_prefix_cmd ("disassembler", no_class,
    386 			  _("\
    387 Style-specific settings for the disassembler.\n\
    388 Configure various disassembler style-related variables."),
    389 			  _("\
    390 Style-specific settings for the disassembler.\n\
    391 Configure various disassembler style-related variables."),
    392 			  &style_disasm_set_list, &style_disasm_show_list,
    393 			  &style_set_list, &style_show_list);
    394 
    395   add_setshow_boolean_cmd ("enabled", no_class, &disassembler_styling, _("\
    396 Set whether disassembler output styling is enabled."), _("\
    397 Show whether disassembler output styling is enabled."), _("\
    398 If enabled, disassembler output is styled.  Disassembler highlighting\n\
    399 requires the Python Pygments library, if this library is not available\n\
    400 then disassembler highlighting will not be possible."
    401 			   ), set_style_enabled, show_style_disassembler,
    402 			   &style_disasm_set_list, &style_disasm_show_list);
    403 
    404   file_name_style.add_setshow_commands (no_class, _("\
    405 Filename display styling.\n\
    406 Configure filename colors and display intensity."),
    407 					&style_set_list, &style_show_list,
    408 					false);
    409 
    410   set_show_commands function_prefix_cmds
    411     = function_name_style.add_setshow_commands (no_class, _("\
    412 Function name display styling.\n\
    413 Configure function name colors and display intensity"),
    414 						&style_set_list,
    415 						&style_show_list,
    416 						false);
    417 
    418   variable_name_style.add_setshow_commands (no_class, _("\
    419 Variable name display styling.\n\
    420 Configure variable name colors and display intensity"),
    421 					    &style_set_list, &style_show_list,
    422 					    false);
    423 
    424   set_show_commands address_prefix_cmds
    425     = address_style.add_setshow_commands (no_class, _("\
    426 Address display styling.\n\
    427 Configure address colors and display intensity"),
    428 					  &style_set_list, &style_show_list,
    429 					  false);
    430 
    431   title_style.add_setshow_commands (no_class, _("\
    432 Title display styling.\n\
    433 Configure title colors and display intensity\n\
    434 Some commands (such as \"apropos -v REGEXP\") use the title style to improve\n\
    435 readability."),
    436 				    &style_set_list, &style_show_list,
    437 				    false);
    438 
    439   highlight_style.add_setshow_commands (no_class, _("\
    440 Highlight display styling.\n\
    441 Configure highlight colors and display intensity\n\
    442 Some commands use the highlight style to draw the attention to a part\n\
    443 of their output."),
    444 					&style_set_list, &style_show_list,
    445 					false);
    446 
    447   metadata_style.add_setshow_commands (no_class, _("\
    448 Metadata display styling.\n\
    449 Configure metadata colors and display intensity\n\
    450 The \"metadata\" style is used when GDB displays information about\n\
    451 your data, for example \"<unavailable>\""),
    452 				       &style_set_list, &style_show_list,
    453 				       false);
    454 
    455   tui_border_style.add_setshow_commands (no_class, _("\
    456 TUI border display styling.\n\
    457 Configure TUI border colors\n\
    458 The \"tui-border\" style is used when GDB displays the border of a\n\
    459 TUI window that does not have the focus."),
    460 					 &style_set_list, &style_show_list,
    461 					 true);
    462 
    463   tui_active_border_style.add_setshow_commands (no_class, _("\
    464 TUI active border display styling.\n\
    465 Configure TUI active border colors\n\
    466 The \"tui-active-border\" style is used when GDB displays the border of a\n\
    467 TUI window that does have the focus."),
    468 						&style_set_list,
    469 						&style_show_list,
    470 						true);
    471 
    472   version_style.add_setshow_commands (no_class, _("\
    473 Version string display styling.\n\
    474 Configure colors used to display the GDB version string."),
    475 				      &style_set_list, &style_show_list,
    476 				      false);
    477 
    478   disasm_mnemonic_style.add_setshow_commands (no_class, _("\
    479 Disassembler mnemonic display styling.\n\
    480 Configure the colors and display intensity for instruction mnemonics\n\
    481 in the disassembler output.  The \"disassembler mnemonic\" style is\n\
    482 used to display instruction mnemonics as well as any assembler\n\
    483 directives, e.g. \".byte\", \".word\", etc.\n\
    484 \n\
    485 This style will only be used for targets that support libopcodes based\n\
    486 disassembler styling.  When Python Pygments based styling is used\n\
    487 then this style has no effect."),
    488 					      &style_disasm_set_list,
    489 					      &style_disasm_show_list,
    490 					      false);
    491 
    492   disasm_register_style.add_setshow_commands (no_class, _("\
    493 Disassembler register display styling.\n\
    494 Configure the colors and display intensity for registers in the\n\
    495 disassembler output.\n\
    496 \n\
    497 This style will only be used for targets that support libopcodes based\n\
    498 disassembler styling.  When Python Pygments based styling is used\n\
    499 then this style has no effect."),
    500 					      &style_disasm_set_list,
    501 					      &style_disasm_show_list,
    502 					      false);
    503 
    504   disasm_immediate_style.add_setshow_commands (no_class, _("\
    505 Disassembler immediate display styling.\n\
    506 Configure the colors and display intensity for immediates in the\n\
    507 disassembler output.  The \"disassembler immediate\" style is used for\n\
    508 any number that is not an address, this includes constants in arithmetic\n\
    509 instructions, as well as address offsets in memory access instructions.\n\
    510 \n\
    511 This style will only be used for targets that support libopcodes based\n\
    512 disassembler styling.  When Python Pygments based styling is used\n\
    513 then this style has no effect."),
    514 					       &style_disasm_set_list,
    515 					       &style_disasm_show_list,
    516 					       false);
    517 
    518   disasm_comment_style.add_setshow_commands (no_class, _("\
    519 Disassembler comment display styling.\n\
    520 Configure the colors and display intensity for comments in the\n\
    521 disassembler output.  The \"disassembler comment\" style is used for\n\
    522 the comment character, and everything after the comment character up to\n\
    523 the end of the line.  The comment style overrides any other styling,\n\
    524 e.g. a register name in a comment will use the comment styling.\n\
    525 \n\
    526 This style will only be used for targets that support libopcodes based\n\
    527 disassembler styling.  When Python Pygments based styling is used\n\
    528 then this style has no effect."),
    529 					     &style_disasm_set_list,
    530 					     &style_disasm_show_list,
    531 					     false);
    532 
    533   /* Setup 'disassembler address' style and 'disassembler symbol' style,
    534      these are aliases for 'address' and 'function' styles respectively.  */
    535   add_alias_cmd ("address", address_prefix_cmds.set, no_class, 0,
    536 		 &style_disasm_set_list);
    537   add_alias_cmd ("address", address_prefix_cmds.show, no_class, 0,
    538 		 &style_disasm_show_list);
    539   add_alias_cmd ("symbol", function_prefix_cmds.set, no_class, 0,
    540 		 &style_disasm_set_list);
    541   add_alias_cmd ("symbol", function_prefix_cmds.show, no_class, 0,
    542 		 &style_disasm_show_list);
    543 }
    544