diff --git a/src/libutil/fmt.cc b/src/libutil/fmt.cc new file mode 100644 index 000000000..914fb62b2 --- /dev/null +++ b/src/libutil/fmt.cc @@ -0,0 +1,38 @@ +#include + +namespace nix { + +std::string hiliteMatches(const std::string &s, std::vector matches, std::string prefix, std::string postfix) { + // Avoid copy on zero matches + if (matches.size() == 0) + return s; + + std::sort(matches.begin(), matches.end(), [](const auto &a, const auto &b) { + return a.position() < b.position(); + }); + + std::string out; + ssize_t last_end = 0; + + for (auto it = matches.begin(); it != matches.end();) { + auto m = *it; + size_t start = m.position(); + out.append(s.substr(last_end, m.position() - last_end)); + // Merge continous matches + ssize_t end = start + m.length(); + while(++it != matches.end() && (*it).position() <= end) { + auto n = *it; + ssize_t nend = start + (n.position() - start + n.length()); + if(nend > end) + end = nend; + } + out.append(prefix); + out.append(s.substr(start, end - start)); + out.append(postfix); + last_end = end; + } + out.append(s.substr(last_end)); + return out; +} + +} diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh index fd335b811..06c4a2049 100644 --- a/src/libutil/fmt.hh +++ b/src/libutil/fmt.hh @@ -2,6 +2,7 @@ #include #include +#include #include "ansicolor.hh" @@ -154,4 +155,6 @@ inline hintformat hintfmt(std::string plain_string) // we won't be receiving any args in this case, so just print the original string return hintfmt("%s", normaltxt(plain_string)); } + +std::string hiliteMatches(const std::string &s, std::vector matches, std::string prefix, std::string postfix); } diff --git a/src/nix/search.cc b/src/nix/search.cc index 01211bae3..0d10d8c2e 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -9,8 +9,8 @@ #include "shared.hh" #include "eval-cache.hh" #include "attr-path.hh" +#include "fmt.hh" -#include #include #include @@ -21,52 +21,6 @@ std::string wrap(std::string prefix, std::string s) return prefix + s + ANSI_NORMAL; } -#define HILITE_COLOR ANSI_GREEN - -std::string hilite(const std::string & s, const std::smatch & m, std::string postfix) -{ - return - m.empty() - ? s - : std::string(m.prefix()) - + HILITE_COLOR + std::string(m.str()) + postfix - + std::string(m.suffix()); -} - -template -std::string hilite_all(const std::string &s, Iter matches_first, Iter matches_last, std::string postfix) { - // Avoid copy on zero matches - if (matches_first == matches_last) - return s; - - std::sort(matches_first, matches_last, [](const auto &a, const auto &b) { - return a.position() < b.position(); - }); - - std::string out; - ssize_t last_end = 0; - - for (Iter it = matches_first; it != matches_last; ++it) { - auto m = *it; - size_t start = m.position(); - out.append(s.substr(last_end, m.position() - last_end)); - // Merge continous matches - ssize_t end = start + m.length(); - while(it + 1 != matches_last && (*(it + 1)).position() <= end) { - auto n = *++it; - ssize_t nend = start + (n.position() - start + n.length()); - if(nend > end) - end = nend; - } - out.append(HILITE_COLOR); - out.append(s.substr(start, end - start)); - out.append(postfix); - last_end = end; - } - out.append(s.substr(last_end)); - return out; -} - struct CmdSearch : InstallableCommand, MixJSON { std::vector res; @@ -177,15 +131,15 @@ struct CmdSearch : InstallableCommand, MixJSON jsonElem.attr("version", name.version); jsonElem.attr("description", description); } else { - auto name2 = hilite_all(name.name, nameMatches.begin(), nameMatches.end(), "\e[0;2m"); + auto name2 = hiliteMatches(name.name, std::move(nameMatches), ANSI_GREEN, "\e[0;2m"); if (results > 1) logger->cout(""); logger->cout( "* %s%s", - wrap("\e[0;1m", hilite_all(attrPath2, attrPathMatches.begin(), attrPathMatches.end(), "\e[0;1m")), + wrap("\e[0;1m", hiliteMatches(attrPath2, std::move(attrPathMatches), ANSI_GREEN, "\e[0;1m")), name.version != "" ? " (" + name.version + ")" : ""); if (description != "") logger->cout( - " %s", hilite_all(description, descriptionMatches.begin(), descriptionMatches.end(), ANSI_NORMAL)); + " %s", hiliteMatches(description, std::move(descriptionMatches), ANSI_GREEN, ANSI_NORMAL)); } } }