[RFC,0/8] add terminal styling to gdb

Message ID 20180906211303.11029-1-tom@tromey.com
Headers show
Series
  • add terminal styling to gdb
Related show

Message

Tom Tromey Sept. 6, 2018, 9:12 p.m.
This series is not ready to review, but I wanted some feedback on the
general approach before committing to writing documentation, test
cases, and comments.

I've wanted gdb to use colors on the terminal for a while now.  I've
actually tried implementing this a few different ways at different
times, the most successful approach so far being a colorizing frame
filter.

This series takes a more direct approach, namely integrating the code
into gdb.  The basic approach is to have gdb know how to emit ANSI
terminal escape codes to control the color and style (currently just
the intensity).  Then, cli-out is changed to style certain fields as
it emits them.  However, because some places do not use ui-out, some
ad hoc changes are also done.

This series styles function names, file names, and variable names.  It
also styles the gdb welcome message for fun.

I think my earlier patch to make the TUI understand ANSI terminal
escapes will make this patch work there.  (I have not tried this yet.)

Other things could be styled as well.  A few ideas I had:

* Style addresses specially
* Style strings specially
* Add styling to "print" and "ptype" (like, field names could be
  styled the way they are in other spots in this series)
* Go the other way and instead of styling the names of variables,
  style their values
* Style gdb-provided identifiers specially so they can be found
  more easily; here I mean something like the thread number or
  breakpoint number, which you have to read to type back to gdb
  sometimes
* Inferior-provided identifiers (PID or thread name) could be styled
  differently too
* ... your idea here, let me know

Tom

Comments

Eli Zaretskii Sept. 7, 2018, 6:23 a.m. | #1
> From: Tom Tromey <tom@tromey.com>

> Date: Thu,  6 Sep 2018 15:12:55 -0600

> 

> I've wanted gdb to use colors on the terminal for a while now.  I've

> actually tried implementing this a few different ways at different

> times, the most successful approach so far being a colorizing frame

> filter.

> 

> This series takes a more direct approach, namely integrating the code

> into gdb.  The basic approach is to have gdb know how to emit ANSI

> terminal escape codes to control the color and style (currently just

> the intensity).  Then, cli-out is changed to style certain fields as

> it emits them.  However, because some places do not use ui-out, some

> ad hoc changes are also done.


This is a worthy goal, IMO, but please allow a level of abstraction
between output styles and ANSI escape sequences.  In particular, the
assumption that changing a style or switching text attributes (like
color, bold, etc.) requires to "emit" something to the terminal, is
not necessarily true.  Please allow for terminals where doing that
requires a function call that doesn't necessarily write anything to
the terminal.

Another, perhaps alternative possibility, would be to use
curses/ncurses features for controlling text color.

Finally, did you consider the use case of running GDB from Emacs (via
the old GUD, which uses CLI I/O)?  Would the color escapes be disabled
in that case, or would that require Emacs to interpret them?  Same
question for other front-ends which use CLI, if there are such.

Thanks.
Joel Brobecker Sept. 7, 2018, 7:25 a.m. | #2
Hi Tom,

> I've wanted gdb to use colors on the terminal for a while now.  I've

> actually tried implementing this a few different ways at different

> times, the most successful approach so far being a colorizing frame

> filter.

> 

> This series takes a more direct approach, namely integrating the code

> into gdb.  The basic approach is to have gdb know how to emit ANSI

> terminal escape codes to control the color and style (currently just

> the intensity).  Then, cli-out is changed to style certain fields as

> it emits them.  However, because some places do not use ui-out, some

> ad hoc changes are also done.

> 

> This series styles function names, file names, and variable names.  It

> also styles the gdb welcome message for fun.

> 

> I think my earlier patch to make the TUI understand ANSI terminal

> escapes will make this patch work there.  (I have not tried this yet.)

> 

> Other things could be styled as well.  A few ideas I had:


This is going to be a very nice improvement, thank you!

I am a bit tied for time to take a first look at the implementation,
but the approach sounds good to me.
-- 
Joel
Tom Tromey Sept. 7, 2018, 2:36 p.m. | #3
>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:


Eli> This is a worthy goal, IMO, but please allow a level of abstraction
Eli> between output styles and ANSI escape sequences.  In particular, the
Eli> assumption that changing a style or switching text attributes (like
Eli> color, bold, etc.) requires to "emit" something to the terminal, is
Eli> not necessarily true.  Please allow for terminals where doing that
Eli> requires a function call that doesn't necessarily write anything to
Eli> the terminal.

I assume you're talking about Windows here.  I don't know anything about
Windows -- could you explain a bit about what's needed to support it?

I can't implement it but I could probably rework the low-level code --
the stuff that interacts with the pager and line wrap buffering -- to
let the stylizing be done in a host-dependent way.

One idea would be to have the line-wrap buffer be a vector that
alternates strings and styles.  Then the terminal-specific output
functions could apply styles in whatever way is appropriate.  Would this
work for Windows?

Eli> Another, perhaps alternative possibility, would be to use
Eli> curses/ncurses features for controlling text color.

Yeah.  I wrote some curses code for this for the TUI.  We could reuse
this when the TUI is available, but since gdb doesn't require curses
currently, this couldn't be the only approach.

It'd be cleaner if each ui-out handled this, so the TUI could implement
styles directly, but there is a layering problem where the pager needs
understand styles, and the pager is beneath ui-out.

Eli> Finally, did you consider the use case of running GDB from Emacs (via
Eli> the old GUD, which uses CLI I/O)?  Would the color escapes be disabled
Eli> in that case, or would that require Emacs to interpret them?  Same
Eli> question for other front-ends which use CLI, if there are such.

Based on experience with my colorizing frame filter, it should all be
fine.

First, looking at gdb in Emacs right now, I see:

    (top-gdb) show env TERM
    TERM = dumb

My patches use this to disable colorizing.

That's not the end of the story though.  comint.el puts
ansi-color-process-output onto comint-output-filter-functions by
default.  So, I think we could have gdb look at getenv("INSIDE_EMACS")
and re-enable the colorizing by default.

Tom
Eli Zaretskii Sept. 7, 2018, 2:56 p.m. | #4
> From: Tom Tromey <tom@tromey.com>

> Cc: Tom Tromey <tom@tromey.com>,  gdb-patches@sourceware.org

> Date: Fri, 07 Sep 2018 08:36:09 -0600

> 

> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

> 

> Eli> This is a worthy goal, IMO, but please allow a level of abstraction

> Eli> between output styles and ANSI escape sequences.  In particular, the

> Eli> assumption that changing a style or switching text attributes (like

> Eli> color, bold, etc.) requires to "emit" something to the terminal, is

> Eli> not necessarily true.  Please allow for terminals where doing that

> Eli> requires a function call that doesn't necessarily write anything to

> Eli> the terminal.

> 

> I assume you're talking about Windows here.


Yes, and there's also go32 (a.k.a. DJGPP, a.k.a. MSDOS).

> I don't know anything about Windows -- could you explain a bit about

> what's needed to support it?


To change the visual appearance of the following text, such as colors
or standout, you need to call a function.  then you write text as
usual, with printf etc., and it appears with the attributes requested
by that function call.  Then, when you want to get back to the
defaults, you need to call the same function again, but with a
different argument.  The argument tells what video attributes shall be
turned on or off.

If you want a working example, you can look at pcterm.c in the
Texinfo's info/ directory, it is used for the stand-alone Info reader.

> I can't implement it but I could probably rework the low-level code --

> the stuff that interacts with the pager and line wrap buffering -- to

> let the stylizing be done in a host-dependent way.


Yes, that's what I was asking for.  The actual implementation should
come from someone else (perhaps myself ;-).

> One idea would be to have the line-wrap buffer be a vector that

> alternates strings and styles.  Then the terminal-specific output

> functions could apply styles in whatever way is appropriate.  Would this

> work for Windows?


Sorry, I don't think I follow.  What is the line-wrap buffer, and how
is it related to the issue at hand?

> Eli> Finally, did you consider the use case of running GDB from Emacs (via

> Eli> the old GUD, which uses CLI I/O)?  Would the color escapes be disabled

> Eli> in that case, or would that require Emacs to interpret them?  Same

> Eli> question for other front-ends which use CLI, if there are such.

> 

> Based on experience with my colorizing frame filter, it should all be

> fine.

> 

> First, looking at gdb in Emacs right now, I see:

> 

>     (top-gdb) show env TERM

>     TERM = dumb

> 

> My patches use this to disable colorizing.

> 

> That's not the end of the story though.  comint.el puts

> ansi-color-process-output onto comint-output-filter-functions by

> default.  So, I think we could have gdb look at getenv("INSIDE_EMACS")

> and re-enable the colorizing by default.


Yes, I agree on both counts.

(I presume this feature is just for CLI, not for the MI output,
right?)

Thanks.
Eli Zaretskii Sept. 7, 2018, 3 p.m. | #5
> Date: Fri, 07 Sep 2018 17:56:00 +0300

> From: Eli Zaretskii <eliz@gnu.org>

> CC: gdb-patches@sourceware.org

> 

> To change the visual appearance of the following text, such as colors

> or standout, you need to call a function.


Sorry, in case it isn't clear: calling that function produces no
output, i.e. nothing is written to the destination buffer or file.
Tom Tromey Oct. 4, 2018, 1:11 p.m. | #6
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:


Tom> This series is not ready to review, but I wanted some feedback on the
Tom> general approach before committing to writing documentation, test
Tom> cases, and comments.

Tom> I've wanted gdb to use colors on the terminal for a while now.  I've
Tom> actually tried implementing this a few different ways at different
Tom> times, the most successful approach so far being a colorizing frame
Tom> filter.

Pedro asked on irc about a styling design closer to what lldb does.
That program lets the user customize the output of commands like 'bt',
by providing a format that is followed.  Adding colorizing to this is
just a matter of adding a color specification to the format.

I did consider a design like this for gdb.  In particular what I
looked at was adding format strings based on the existing ui-out code.
Then, cli-out would be changed to parse these strings, collect fields,
and then format the fields according to the format.  Finally, explicit
formatting at the call sites would be removed and replaced with the
appropriate default format strings.

This seemed like an attractive idea because ui-out is close to what we
would want here, and since the field names are already an advertised
API they could probably be presented to the user as well.

A super simple example that in this plan we could remove:

  uiout->text ("\n");

from print_one_bfd and replace it with a format like

  "{refcount<10}{addr<18}{filename<40}\n"

(Just one possible syntax.)

Table headers would be emitted using the same format.


A further idea in this plan was to get rid of is-mi-like-p tests in
favor of just emitting everything and letting the format simply not
print fields that were uninteresting.  This is harder, though, because
there are more special cases that would have to be handled.


However, I rejected this plan because some of the existing exceptions
to the general approach seemed ugly to deal with.  The formatting
string would have to be a mini language of its own in order to work.

* info_osdata emits a variable number of columns
* print_program_space prints extra information between rows
* breakpoint_1 conditionally emits a column based on whether
  addressprint is set

Also some of the table names or column names are poorly chosen.  I
suppose this could be handled by having some mapping in the CLI.


One thing I like about the approach I took in the current series is
that it allows for semantic styling.  That is, we can style filenames
the same way everywhere.  Also it can easily be done in situations
where gdb is not using ui-out.

Now, one way to handle this in the formatting scenario would be to
introduce formatting constructs to use semantic styling, like "start a
file name now" or whatever.  In this idea, though, the two approaches
are complementary and so we wouldn't need to decide now: we could move
forward with the series as-is and add formatting at a later stage.


Speaking of that, right now the semantic styling is actually done by
matching field names.  I wonder if ui-out should have new methods for
things like "field_filename" or whatever other "type" information we'd
like to associate.  Alternatively I wonder if the style should just be
passed as an optional argument to the various ui-out methods.

Tom