-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[lldb][breakpoint] Grey out disabled breakpoints #91404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb][breakpoint] Grey out disabled breakpoints #91404
Conversation
@llvm/pr-subscribers-lldb Author: Chelsea Cassanova (chelcassanova) ChangesThis commit adds colour highlighting to the Full diff: https://github.com/llvm/llvm-project/pull/91404.diff 2 Files Affected:
diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index 7bf545717422f..3dc3a7190d03e 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -400,6 +400,12 @@ friend class Breakpoint;
/// Which options are set at this level.
/// Drawn from BreakpointOptions::SetOptionsFlags.
Flags m_set_flags;
+ /// Settings that allow the 'disabled' keyword to be displayed in red.
+ Stream::HighlightSettings m_disbaled_breakpoint_highlight_settings{
+ "disabled",
+ "\x1b[31m",
+ "\x1b[37m",
+ };
};
} // namespace lldb_private
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index 6c6037dd9edd3..993de590b0d4f 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -534,7 +534,8 @@ void BreakpointOptions::GetDescription(Stream *s,
if (m_ignore_count > 0)
s->Printf("ignore: %d ", m_ignore_count);
- s->Printf("%sabled ", m_enabled ? "en" : "dis");
+ s->PutCStringColorHighlighted(m_enabled ? "enabled " : "disabled ",
+ m_disbaled_breakpoint_highlight_settings);
if (m_one_shot)
s->Printf("one-shot ");
|
Stream::HighlightSettings m_disbaled_breakpoint_highlight_settings{ | ||
"disabled", | ||
"\x1b[31m", | ||
"\x1b[37m", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to hardcode these values yourself. Take a look at AnsiTerminal.h
, there are some constants defined for this purpose.
@@ -400,6 +400,12 @@ friend class Breakpoint; | |||
/// Which options are set at this level. | |||
/// Drawn from BreakpointOptions::SetOptionsFlags. | |||
Flags m_set_flags; | |||
/// Settings that allow the 'disabled' keyword to be displayed in red. | |||
Stream::HighlightSettings m_disbaled_breakpoint_highlight_settings{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: disbaled
-> disabled
s->PutCStringColorHighlighted(m_enabled ? "enabled " : "disabled ", | ||
m_disbaled_breakpoint_highlight_settings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to regex search for disabled and then replace it with its colored variant. That seems unnecessarily inefficient. You know whether you're going to put enabled or disabled, so you could print it colored right away.
You might also have to check the debugger setting for whether colors are enabled (Debugger::GetUseColor()
). Sometimes it's set at the stream level: the stream might have colors disabled if it was created somewhere were the setting was checked). I don't know if that's always going to be the case here. If it's not, we should check the setting here. To find out I would run lldb with --no-use-colors
and see if the colors still get printed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so using Printf
with ansi::FormatAnsiTerminalCodes
instead? And yes using this with --no-use-colors
does show the colour here so it looks like this isn't being checked at the stream level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, you can get this output both when lldb decides to print in the terminal, and when someone does:
stream = lldb.SBStream()
bkpt.GetDescription(stream, eDescriptionLevelWhatever)
At present SBStream's are backed by StreamString objects which get constructed with use_color -> false. So you should be okay there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems odd you can't ask the stream whether it is using colors or not. Because if I'm running with use-colors on, but I want to use the description of a breakpoint w/o colors - say to put it in a log - then I would correctly make an SBStream which is supposed to not use colors, and pass that to the description. If you ONLY check whether the debugger is using colors, and override the stream's setting, then you will do the wrong thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that only the debugger tells you whether or not you're using colours then? BreakpointOptions::GetDescription()
doesn't seem to have a reference to the debugger, target or interpreter so I'm wondering what the next best options to determine if we're using colours is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wouldn't be a problem if we make sure that whoever makes the Streams for use by the command interpreter consults GetUseColor when it creates the stream, and then we can rely on the stream to tell us what to do. If you are calling stream API's that add the color for you, that should just work. If you are doing a Print by hand with the color codes or not, you should consult the stream. For that we'll have to add Stream::GetUseColor. If we always get that right, the only problem will be if there are persistent streams, we may need to change their state or replace them when GetUseColor changes.
That seems the most principled way to solve this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was speaking to Ismail about this and seems like it would be nice if we had a Stream::GetUseColor
for this given that you can set whether or not the stream has colours at construction but you can't query the state of it after that.
More of a styling preference, but I wouldn't use red as the color for disabled breakpoint, I think it would be more suited for unresolved ones (that could be done in a follow-up). Instead, I'd use the |
4458e95
to
c334f73
Compare
I changed this PR to make disabled breakpoints greyed out (per Ismail's suggestion). Since this is being done at the |
if (GetTarget().GetDebugger().GetUseColor()) | ||
s->Printf("%s", | ||
IsEnabled() | ||
? ansi::FormatAnsiTerminalCodes("${ansi.normal}").c_str() | ||
: ansi::FormatAnsiTerminalCodes("${ansi.faint}").c_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to reset the color after printing, otherwise everything in the terminal printed after will be faint. Also seems like you can simplify this by moving the check for IsEnabled()
into the first if
:
const bool print_faint = !IsEnabled() && GetTarget().GetDebugger().GetUseColor();
if (print_faint)
s->Print(ansi::FormatAnsiTerminalCodes("${ansi.faint}"));
[...]
if (print_faint)
s->Print(ansi::FormatAnsiTerminalCodes("${ansi.reset}"));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c334f73
to
0e45ade
Compare
I'm not sure checking the debugger here resolves the difficulty I pointed out earlier. If I make an SBStream and call SBBreakpoint::GetDescription, I will have passed in an SBStream with |
Hm, so in that case should we focus on adding an |
That's the only way it makes sense to me. But if we are going to rely on the stream, we also have to be sure that we're setting the Streams "use color" correctly when we make them. That might be an annoying accounting exercise. I think an easier way to allow streams to both get their "use color" from context and also override it for special purposes is to replace the "use color" bool with a "use color, don't use color, no opinion" enum. We'd make streams creation default to "no opinion". The SB API's would instead create them with "no use color" - and we should add an accessor to the SB API's. And then internally, "no opinion" means "consult the debugger" - but more generally it means "determine my use color value from context". Actually, I'm being old-fashioned, the modern way to do this is convert the bool to an optional. I like the no opinion in an enum because it says explicitly what the unset state means... Anyway, that way saves you from having to track down all the cases where streams were made and get their "use color" right. Instead, you only need to check at the places where you were intending to add color, obeying the definite settings or whatever your context is. |
Cool, sorry for the delay but I made changes to |
The stream already knows whether color support is enabled, but it looks like we're only storing that in the underlying llvm stream, which is commonly used in combination with
Alternatively, we could add a helper that does that under the hood.
So instead of having to write:
You can just write:
and have it do the right thing. |
0e45ade
to
5724d6c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good, but needs a (pexpect) test. I would also like to add a setting to make the prefix and suffix configurable, like we do for things like show-progress-ansi-prefix
and show-autosuggestion-ansi-prefix
. That way user can pick their own preferred color, or even just turn this one feature off without having to disable color if they want to.
Just making sure, a setting for changing the prefix/suffix would be in |
895f29d
to
950386a
Compare
✅ With the latest revision this PR passed the Python code formatter. |
950386a
to
c4ee8ba
Compare
lldb/source/API/SBStream.cpp
Outdated
|
||
void SBStream::FormatAnsiTerminalCodes(llvm::StringRef format) { | ||
if (HasColor()) | ||
Printf("%s", ansi::FormatAnsiTerminalCodes(format).c_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Printf("%s", ansi::FormatAnsiTerminalCodes(format).c_str()); | |
m_opaque_up->PutCString(ansi::FormatAnsiTerminalCodes(format)); |
self.child = pexpect.spawn("expect", encoding="utf-8") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is probably unnecessary, I was modeling this test after another pexpect
test that spawns pexpect with the expect
program but I don't think this tests needs that now that I'm looking at this again, I can remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure this was doing nothing as self.launch
overwrites the child
member. I recall we have one test which uses pexpect
(the python module) to drive expect
(the unix utility which lent its name to the former) to drive lldb
. We definitely don't need that here (and tbh, I'm not sure the original test does either).
ansi_red_color_code = "\x1b[31m" | ||
|
||
self.launch(use_colors=True, dimensions=(100, 100)) | ||
self.child.sendline( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason you can't use self.expect instead?
Even if you don't pass it any expectations to it, that function will at least check for the lldb prompt, which means it will wait for lldb to process the previous command before you feed it the next one. That makes the test much more deterministic and reliable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm understanding correctly, you mean using self.expect
instead of self.child.sendline
to set up the breakpoints here? If so, I can change this here, I didn't know that self.expect
checked for the prompt as well. I was originally using sendline
and checking each output with expect
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's what I meant. The expect
function was meant to be used to inject lldb commands, some tests use the pexpect API directly because they're doing something more complicated (or because the thing they're driving is not lldb), but that's not the case here.
c683d86
to
c7c554e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm kinda late to the party (particularly as there's an analogous "progress" setting), but I have to say I was surprised to see a disable-breakpoint-ansi-suffix
setting. That sounds like too low level of a model. The model I would expect/find more natural is if there was a single setting describing the "normal" text colour, and then several (not necessarily one each item that needs colouring) settings defining the colour of items that need colouring.
I find it hard to imagine why one would ever want to set different values for the "suffix" colours, as that means the colour of random text would depend on what was printed before it.
I don't want to make this a blocking objection, but I would urge you to consider if this is the behavior you want.
lldb/include/lldb/API/SBStream.h
Outdated
@@ -47,6 +48,10 @@ class LLDB_API SBStream { | |||
|
|||
void Print(const char *str); | |||
|
|||
bool HasColor(); | |||
|
|||
void FormatAnsiTerminalCodes(llvm::StringRef format); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't have a StringRef in the SB API. This needs to be a const char *. All the internal APIs can and should use StringRefs though.
self.expect("br l") | ||
self.child.expect_exact(ansi_red_color_code + "1:") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.expect("br l") | |
self.child.expect_exact(ansi_red_color_code + "1:") | |
self.expect("br l", substrs=[ansi_red_color_code + "1:"]) |
The idea is to make this mostly look like the existing SB API tests.
Kinda surprised it works without it. If I had to guess, I'd say its because of the prompt coloring code causes the prompt substring to be present more than once (which then means the substring search loses synch).
(That's one more reason to add some sort of expectations to the previous commands. The other reason is that they give you an earlier indication if something goes wrong during the test -- the pexpect error messages aren't of the most readable type)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion to use substrs
here! By "expectations" you just mean adding a self.expect
after all the previous commands to check that their output is fine right? If so then yeah I can add that 👍🏾
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant was adding a substr
argument to the existing expect
calls (e.g. self.expect("br dis", substrs=["All breakpoints disabled."])
), not adding new expect calls.
self.child = pexpect.spawn("expect", encoding="utf-8") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure this was doing nothing as self.launch
overwrites the child
member. I recall we have one test which uses pexpect
(the python module) to drive expect
(the unix utility which lent its name to the former) to drive lldb
. We definitely don't need that here (and tbh, I'm not sure the original test does either).
ansi_red_color_code = "\x1b[31m" | ||
|
||
self.launch(use_colors=True, dimensions=(100, 100)) | ||
self.child.sendline( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's what I meant. The expect
function was meant to be used to inject lldb commands, some tests use the pexpect API directly because they're doing something more complicated (or because the thing they're driving is not lldb), but that's not the case here.
I agree that those who want to change their colours in LLDB shouldn't have to touch the ANSI suffix setting in order to do this. We do use settings for changing the suffix in other places in LLDB, so if we were change how this setting works then I think it's outside of the scope of this patch and it would be better as a larger refactor to the colour settings. |
I also agree with how I was misusing the |
c7c554e
to
4fee5ee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the feautre but I think this PR can be a lot simpler:
- I don't think you need any of the changes to
Stream
orSBStream
. You already have to get the setting from the debugger, so just check if it has colors enabled and write the prefix (and fixed suffix) if colors are enabled. - I think we had settled on adding a new setting for highlighting "disabled things", with breakpoints being just one example of that. The setting should be generic, something like
disable-ansi-prefix
(*). I'm find with omitting the suffix and always issuing a clear. I can't think of a reason anyone would ever want to change that.
(*) I would prefer to call the settingdisable-format
, but then it should go through FormatEntity which is definitely overkill. I think given the existing settings, disable-ansi-prefix
is the most consistent.
lldb/include/lldb/API/SBStream.h
Outdated
bool HasColor(); | ||
|
||
void FormatAnsiTerminalCodes(llvm::StringRef format); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC we don't need any changes to the SBStream class anymore, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not, though does that now mean that I'd just be writing the prefix/suffix with something like Stream::Printf
now instead of the format function here?
4fee5ee
to
8608a94
Compare
Just updated this patch to:
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
75061e1
to
ab03eca
Compare
@@ -838,6 +840,14 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level, | |||
bool show_locations) { | |||
assert(s != nullptr); | |||
|
|||
// Grey out any disabled breakpoints in the list of breakpoints. | |||
const bool highlight_disabled = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: rename this variable to "dim_breakpoint_description" or something like that.
The word "highlight_disabled" could also be applied to situations where colors are not enabled.
@@ -838,6 +840,14 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level, | |||
bool show_locations) { | |||
assert(s != nullptr); | |||
|
|||
// Grey out any disabled breakpoints in the list of breakpoints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I suggest removing the comment. I think naming the conditions variable better should make this clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just applied both of these suggestions to the patch.
This commit adds colour settings to the list of breakpoints in order to grey out breakpoints that have been disabled.
ab03eca
to
dd94ef4
Compare
This commit adds colour settings to the list of breakpoints in order to
grey out breakpoints that have been disabled.