xref: /netbsd-src/external/gpl3/gdb/dist/gdb/cli/cli-style.c (revision 865c57e0098351fba0d2d2a97b33e7e0270e62c6)
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