@@ -1661,7 +1661,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
16611661
16621662 if (language_plugin)
16631663 language_plugin_handled = language_plugin->GetFunctionDisplayName (
1664- sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1664+ sc, exe_ctx, Language::FunctionNameRepresentation::eName,
1665+ entry.highlight , ss);
16651666
16661667 if (language_plugin_handled) {
16671668 s << ss.GetString ();
@@ -1697,7 +1698,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
16971698 if (language_plugin)
16981699 language_plugin_handled = language_plugin->GetFunctionDisplayName (
16991700 sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1700- ss);
1701+ entry. highlight , ss);
17011702
17021703 if (language_plugin_handled) {
17031704 s << ss.GetString ();
@@ -1731,7 +1732,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
17311732
17321733 if (language_plugin)
17331734 language_plugin_handled = language_plugin->GetFunctionDisplayName (
1734- sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1735+ sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs,
1736+ entry.highlight , ss);
17351737
17361738 if (language_plugin_handled) {
17371739 s << ss.GetString ();
@@ -2074,6 +2076,64 @@ static const Definition *FindEntry(const llvm::StringRef &format_str,
20742076 return parent;
20752077}
20762078
2079+ // / Parses a single highlighting format specifier.
2080+ // /
2081+ // / Example syntax for such specifier:
2082+ // / \code
2083+ // / ${function.name-with-args:%highlight_basename(ansi.fg.green)}
2084+ // / \endcode
2085+ // /
2086+ // / In the above snippet, the `function.name-with-args` frame-format
2087+ // / variable will have its basename highlighted in green.
2088+ static llvm::Expected<Entry::HighlightSettings>
2089+ ParseHighlightSettings (const Entry &entry) {
2090+ // FIXME: support other function.name-XXX types as well
2091+ if (entry.type != Entry::Type::FunctionNameWithArgs)
2092+ return llvm::createStringError (
2093+ " The 'highlight_basename' format can only be used on "
2094+ " ${function.name-with-args}" );
2095+
2096+ llvm::StringRef format = entry.printf_format ;
2097+ if (!format.consume_front (" highlight_" ))
2098+ return llvm::createStringError (
2099+ " Expected 'highlight_' prefix not found in: %s." ,
2100+ entry.printf_format .c_str ());
2101+
2102+ Entry::HighlightSettings settings;
2103+ if (format.consume_front (" basename" )) {
2104+ settings.kind = Entry::HighlightSettings::Kind::Basename;
2105+ } else {
2106+ return llvm::createStringError (
2107+ " Unsupported highlight kind detected in: %s. "
2108+ " Currently supported: basename" ,
2109+ entry.printf_format .c_str ());
2110+ }
2111+
2112+ llvm::SmallVector<llvm::StringRef, 1 > matches;
2113+ // TODO: support ${ansi.XXX} syntax. ExtractVariableInfo needs
2114+ // to be adjusted to support nested '{}'.
2115+ llvm::Regex color_pattern{R"( ^\(([a-z\.]+)\)$)" };
2116+ if (!color_pattern.match (format, &matches))
2117+ return llvm::createStringError (
2118+ " Couldn't find valid color variable in: %s. "
2119+ " Expected format: %%highlight_basename(ansi.some-color)" ,
2120+ entry.printf_format .c_str ());
2121+
2122+ assert (matches.size () == 2 );
2123+
2124+ std::string color_format = (" ${" + matches[1 ] + " }" ).str ();
2125+ std::string terminal_code = ansi::FormatAnsiTerminalCodes (color_format);
2126+ if (terminal_code.empty () || terminal_code == color_format)
2127+ return llvm::createStringError (" Invalid color variable '%s' found in: %s" ,
2128+ color_format.c_str (),
2129+ entry.printf_format .c_str ());
2130+
2131+ settings.prefix = std::move (terminal_code);
2132+ settings.suffix = ansi::FormatAnsiTerminalCodes (" ${ansi.normal}" );
2133+
2134+ return settings;
2135+ }
2136+
20772137static Status ParseInternal (llvm::StringRef &format, Entry &parent_entry,
20782138 uint32_t depth) {
20792139 Status error;
@@ -2229,6 +2289,7 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
22292289 if (error.Fail ())
22302290 return error;
22312291 bool verify_is_thread_id = false ;
2292+ bool parse_highlight_settings = false ;
22322293 Entry entry;
22332294 if (!variable_format.empty ()) {
22342295 entry.printf_format = variable_format.str ();
@@ -2294,6 +2355,8 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
22942355 clear_printf = true ;
22952356 } else if (entry.printf_format == " tid" ) {
22962357 verify_is_thread_id = true ;
2358+ } else if (entry.printf_format .find (" highlight_" ) == 0 ) {
2359+ parse_highlight_settings = true ;
22972360 } else {
22982361 error = Status::FromErrorStringWithFormat (
22992362 " invalid format: '%s'" , entry.printf_format .c_str ());
@@ -2335,6 +2398,14 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
23352398 " the 'tid' format can only be used on "
23362399 " ${thread.id} and ${thread.protocol_id}" );
23372400 }
2401+ } else if (parse_highlight_settings) {
2402+ auto highlight_or_err = ParseHighlightSettings (entry);
2403+ if (highlight_or_err) {
2404+ entry.highlight = std::move (*highlight_or_err);
2405+ entry.printf_format .clear ();
2406+ } else {
2407+ error = Status::FromError (highlight_or_err.takeError ());
2408+ }
23382409 }
23392410
23402411 switch (entry.type ) {
0 commit comments