@@ -1654,7 +1654,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
16541654
16551655 if (language_plugin)
16561656 language_plugin_handled = language_plugin->GetFunctionDisplayName (
1657- sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1657+ sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss,
1658+ entry.highlight );
16581659
16591660 if (language_plugin_handled) {
16601661 s << ss.GetString ();
@@ -1690,7 +1691,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
16901691 if (language_plugin)
16911692 language_plugin_handled = language_plugin->GetFunctionDisplayName (
16921693 sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1693- ss);
1694+ ss, entry. highlight );
16941695
16951696 if (language_plugin_handled) {
16961697 s << ss.GetString ();
@@ -1724,7 +1725,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
17241725
17251726 if (language_plugin)
17261727 language_plugin_handled = language_plugin->GetFunctionDisplayName (
1727- sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1728+ sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss,
1729+ entry.highlight );
17281730
17291731 if (language_plugin_handled) {
17301732 s << ss.GetString ();
@@ -2046,6 +2048,64 @@ static const Definition *FindEntry(const llvm::StringRef &format_str,
20462048 return parent;
20472049}
20482050
2051+ // / Parses a single highlighting format specifier.
2052+ // /
2053+ // / Example syntax for such specifier:
2054+ // / \code
2055+ // / ${function.name-with-args:%highlight_basename(ansi.fg.green)}
2056+ // / \endcode
2057+ // /
2058+ // / In the above snippet, the `function.name-with-args` frame-format
2059+ // / variable will have its basename highlighted in green.
2060+ static llvm::Expected<Entry::HighlightSettings>
2061+ ParseHighlightSettings (const Entry &entry) {
2062+ // FIXME: support other function.name-XXX types as well
2063+ if (entry.type != Entry::Type::FunctionNameWithArgs)
2064+ return llvm::createStringError (
2065+ " The 'highlight_basename' format can only be used on "
2066+ " ${function.name-with-args}" );
2067+
2068+ llvm::StringRef format = entry.printf_format ;
2069+ if (!format.consume_front (" highlight_" ))
2070+ return llvm::createStringError (
2071+ " Expected 'highlight_' prefix not found in: %s." ,
2072+ entry.printf_format .c_str ());
2073+
2074+ Entry::HighlightSettings settings;
2075+ if (format.consume_front (" basename" )) {
2076+ settings.kind = Entry::HighlightSettings::Kind::Basename;
2077+ } else {
2078+ return llvm::createStringError (
2079+ " Unsupported highlight kind detected in: %s. "
2080+ " Currently supported: basename" ,
2081+ entry.printf_format .c_str ());
2082+ }
2083+
2084+ llvm::SmallVector<llvm::StringRef, 1 > matches;
2085+ // TODO: support ${ansi.XXX} syntax. ExtractVariableInfo needs
2086+ // to be adjusted to support nested '{}'.
2087+ llvm::Regex color_pattern{R"( ^\(([a-z\.]+)\)$)" };
2088+ if (!color_pattern.match (format, &matches))
2089+ return llvm::createStringError (
2090+ " Couldn't find valid color variable in: %s. "
2091+ " Expected format: %%highlight_basename(ansi.some-color)" ,
2092+ entry.printf_format .c_str ());
2093+
2094+ assert (matches.size () == 2 );
2095+
2096+ std::string color_format = (" ${" + matches[1 ] + " }" ).str ();
2097+ std::string terminal_code = ansi::FormatAnsiTerminalCodes (color_format);
2098+ if (terminal_code.empty () || terminal_code == color_format)
2099+ return llvm::createStringError (" Invalid color variable '%s' found in: %s" ,
2100+ color_format.c_str (),
2101+ entry.printf_format .c_str ());
2102+
2103+ settings.prefix = std::move (terminal_code);
2104+ settings.suffix = ansi::FormatAnsiTerminalCodes (" ${ansi.normal}" );
2105+
2106+ return settings;
2107+ }
2108+
20492109static Status ParseInternal (llvm::StringRef &format, Entry &parent_entry,
20502110 uint32_t depth) {
20512111 Status error;
@@ -2201,6 +2261,7 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
22012261 if (error.Fail ())
22022262 return error;
22032263 bool verify_is_thread_id = false ;
2264+ bool parse_highlight_settings = false ;
22042265 Entry entry;
22052266 if (!variable_format.empty ()) {
22062267 entry.printf_format = variable_format.str ();
@@ -2266,6 +2327,8 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
22662327 clear_printf = true ;
22672328 } else if (entry.printf_format == " tid" ) {
22682329 verify_is_thread_id = true ;
2330+ } else if (entry.printf_format .find (" highlight_" ) == 0 ) {
2331+ parse_highlight_settings = true ;
22692332 } else {
22702333 error = Status::FromErrorStringWithFormat (
22712334 " invalid format: '%s'" , entry.printf_format .c_str ());
@@ -2307,6 +2370,14 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
23072370 " the 'tid' format can only be used on "
23082371 " ${thread.id} and ${thread.protocol_id}" );
23092372 }
2373+ } else if (parse_highlight_settings) {
2374+ auto highlight_or_err = ParseHighlightSettings (entry);
2375+ if (highlight_or_err) {
2376+ entry.highlight = std::move (*highlight_or_err);
2377+ entry.printf_format .clear ();
2378+ } else {
2379+ error = Status::FromError (highlight_or_err.takeError ());
2380+ }
23102381 }
23112382
23122383 switch (entry.type ) {
0 commit comments