Add an option to show / hide filtered frames vs printing a placeholder

This commit is contained in:
Jeremy Rifkin 2025-02-02 16:20:47 -06:00
parent d1ce9c8896
commit eb83ee2a1c
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
3 changed files with 54 additions and 14 deletions

View File

@ -37,6 +37,7 @@ namespace cpptrace {
formatter& set_snippets(bool);
formatter& set_snippet_context(int);
formatter& include_column(bool);
formatter& show_filtered_frames(bool);
formatter& set_filter(std::function<bool(const stacktrace_frame&)>);
std::string format(const stacktrace_frame&) const;

View File

@ -21,6 +21,7 @@ namespace cpptrace {
bool snippets = false;
int context_lines = 2;
bool columns = true;
bool show_filtered_frames = true;
std::function<bool(const stacktrace_frame&)> filter;
} options;
@ -43,6 +44,9 @@ namespace cpptrace {
void include_column(bool columns) {
options.columns = columns;
}
void show_filtered_frames(bool show) {
options.show_filtered_frames = show;
}
void set_filter(std::function<bool(const stacktrace_frame&)> filter) {
options.filter = filter;
}
@ -140,20 +144,24 @@ namespace cpptrace {
const auto frame_number_width = detail::n_digits(static_cast<int>(frames.size()) - 1);
for(const auto& frame : frames) {
if(options.filter && !options.filter(frame)) {
counter++;
continue;
}
print_frame_internal(stream, frame, color, frame_number_width, counter);
if(frame.line.has_value() && !frame.filename.empty() && options.snippets) {
auto snippet = detail::get_snippet(
frame.filename,
frame.line.value(),
options.context_lines,
color
);
if(!snippet.empty()) {
stream << '\n';
stream << snippet;
if(!options.show_filtered_frames) {
counter++;
continue;
}
print_placeholder_frame(stream, frame_number_width, counter);
} else {
print_frame_internal(stream, frame, color, frame_number_width, counter);
if(frame.line.has_value() && !frame.filename.empty() && options.snippets) {
auto snippet = detail::get_snippet(
frame.filename,
frame.line.value(),
options.context_lines,
color
);
if(!snippet.empty()) {
stream << '\n';
stream << snippet;
}
}
}
if(newline_at_end || &frame != &frames.back()) {
@ -174,6 +182,11 @@ namespace cpptrace {
stream << line;
}
void print_placeholder_frame(std::ostream& stream, unsigned frame_number_width, std::size_t counter) const {
std::string line = microfmt::format("#{<{}} (filtered)", frame_number_width, counter);
stream << line;
}
void print_frame_internal(
std::ostream& stream,
const stacktrace_frame& frame,
@ -258,6 +271,10 @@ namespace cpptrace {
pimpl->include_column(columns);
return *this;
}
formatter& formatter::show_filtered_frames(bool show) {
pimpl->show_filtered_frames(show);
return *this;
}
formatter& formatter::set_filter(std::function<bool(const stacktrace_frame&)> filter) {
pimpl->set_filter(std::move(filter));
return *this;

View File

@ -191,6 +191,24 @@ TEST(FormatterTest, Filtering) {
return frame.filename.find("foo.cpp") != std::string::npos;
});
auto res = split(formatter.format(make_test_stacktrace()), "\n");
EXPECT_THAT(
res,
ElementsAre(
"Stack trace (most recent call first):",
"#0 0x0000000000000001 in foo() at foo.cpp:20:30",
"#1 (filtered)",
"#2 0x0000000000000003 in main at foo.cpp:40:25"
)
);
}
TEST(FormatterTest, DontShowFilteredFrames) {
auto formatter = cpptrace::formatter{}
.set_filter([] (const cpptrace::stacktrace_frame& frame) -> bool {
return frame.filename.find("foo.cpp") != std::string::npos;
})
.show_filtered_frames(false);
auto res = split(formatter.format(make_test_stacktrace()), "\n");
EXPECT_THAT(
res,
ElementsAre(
@ -213,6 +231,7 @@ TEST(FormatterTest, MoveSemantics) {
ElementsAre(
"Stack trace (most recent call first):",
"#0 0x0000000000000001 in foo() at foo.cpp:20:30",
"#1 (filtered)",
"#2 0x0000000000000003 in main at foo.cpp:40:25"
)
);
@ -224,6 +243,7 @@ TEST(FormatterTest, MoveSemantics) {
ElementsAre(
"Stack trace (most recent call first):",
"#0 0x0000000000000001 in foo() at foo.cpp:20:30",
"#1 (filtered)",
"#2 0x0000000000000003 in main at foo.cpp:40:25"
)
);
@ -241,6 +261,7 @@ TEST(FormatterTest, CopySemantics) {
ElementsAre(
"Stack trace (most recent call first):",
"#0 0x0000000000000001 in foo() at foo.cpp:20:30",
"#1 (filtered)",
"#2 0x0000000000000003 in main at foo.cpp:40:25"
)
);
@ -252,6 +273,7 @@ TEST(FormatterTest, CopySemantics) {
ElementsAre(
"Stack trace (most recent call first):",
"#0 0x0000000000000001 in foo() at foo.cpp:20:30",
"#1 (filtered)",
"#2 0x0000000000000003 in main at foo.cpp:40:25"
)
);