Add basic option for shortening paths in the formatter

This commit is contained in:
Jeremy Rifkin 2025-02-13 23:22:12 -06:00
parent 000168b93c
commit ce97e0004d
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
4 changed files with 45 additions and 3 deletions

View File

@ -34,6 +34,13 @@ namespace cpptrace {
none,
};
formatter& addresses(address_mode);
enum class path_mode {
// full path is used
full,
// only the file name is used
basename,
};
formatter& paths(path_mode);
formatter& snippets(bool);
formatter& snippet_context(int);
formatter& columns(bool);

View File

@ -18,6 +18,7 @@ namespace cpptrace {
std::string header = "Stack trace (most recent call first):";
color_mode color = color_mode::automatic;
address_mode addresses = address_mode::raw;
path_mode paths = path_mode::full;
bool snippets = false;
int context_lines = 2;
bool columns = true;
@ -35,6 +36,9 @@ namespace cpptrace {
void addresses(formatter::address_mode mode) {
options.addresses = mode;
}
void paths(path_mode mode) {
options.paths = mode;
}
void snippets(bool snippets) {
options.snippets = snippets;
}
@ -213,7 +217,13 @@ namespace cpptrace {
microfmt::print(stream, " in {}{}{}", yellow, frame.symbol, reset);
}
if(!frame.filename.empty()) {
microfmt::print(stream, " at {}{}{}", green, frame.filename, reset);
microfmt::print(
stream,
" at {}{}{}",
green,
options.paths == path_mode::full ? frame.filename : detail::basename(frame.filename, true),
reset
);
if(frame.line.has_value()) {
microfmt::print(stream, ":{}{}{}", blue, frame.line.value(), reset);
if(frame.column.has_value() && options.columns) {
@ -258,6 +268,10 @@ namespace cpptrace {
pimpl->addresses(mode);
return *this;
}
formatter& formatter::paths(path_mode mode) {
pimpl->paths(mode);
return *this;
}
formatter& formatter::snippets(bool snippets) {
pimpl->snippets(snippets);
return *this;

View File

@ -162,9 +162,9 @@ namespace detail {
// shamelessly stolen from stackoverflow
bool directory_exists(const std::string& path);
inline std::string basename(const std::string& path) {
inline std::string basename(const std::string& path, bool maybe_windows = false) {
// Assumes no trailing /'s
auto pos = path.rfind('/');
auto pos = path.find_last_of(maybe_windows ? "/\\" : "/");
if(pos == std::string::npos) {
return path;
} else {

View File

@ -96,6 +96,27 @@ TEST(FormatterTest, ObjectAddresses) {
);
}
TEST(FormatterTest, PathShortening) {
cpptrace::stacktrace trace;
trace.frames.push_back({0x1, 0x1001, {20}, {30}, "/home/foo/foo.cpp", "foo()", false});
trace.frames.push_back({0x2, 0x1002, {30}, {40}, "/bar.cpp", "bar()", false});
trace.frames.push_back({0x3, 0x1003, {40}, {25}, "baz/foo.cpp", "main", false});
trace.frames.push_back({0x3, 0x1003, {50}, {25}, "C:\\foo\\bar\\baz.cpp", "main", false});
auto formatter = cpptrace::formatter{}
.paths(cpptrace::formatter::path_mode::basename);
auto res = split(formatter.format(trace), "\n");
EXPECT_THAT(
res,
ElementsAre(
"Stack trace (most recent call first):",
"#0 0x0000000000000001 in foo() at foo.cpp:20:30",
"#1 0x0000000000000002 in bar() at bar.cpp:30:40",
"#2 0x0000000000000003 in main at foo.cpp:40:25",
"#3 0x0000000000000003 in main at baz.cpp:50:25"
)
);
}
#ifndef CPPTRACE_NO_TEST_SNIPPETS
TEST(FormatterTest, Snippets) {
cpptrace::stacktrace trace;