if (funcs.empty())
return "";
- // Calculate Levenshtein distance for each symbol
-
- // Sensitivity parameters (open for tweaking)
- #define MAXFUNCS 5 // maximum number of funcs to suggest
-
- multimap<unsigned, string> scores;
- for (set<string>::iterator it=funcs.begin(); it!=funcs.end(); ++it)
- {
- unsigned score = levenshtein(func, *it);
- scores.insert(make_pair(score, *it));
- }
-
- // Print out the top MAXFUNCS funcs
- string suggestions; unsigned i = 0;
- for (multimap<unsigned, string>::iterator it = scores.begin();
- it != scores.end() && i < MAXFUNCS; ++it, i++)
- suggestions += it->second + ", ";
- if (!suggestions.empty())
- suggestions.erase(suggestions.size()-2);
-
- return suggestions;
+ return levenshtein_suggest(func, funcs, 5); // print top 5 funcs only
}
void
// parameter which would abort the operation if we know the final
// distance will be larger than the maximum. This may entail maintaining
// another data structure, and thus the cost might outweigh the benefit
-unsigned levenshtein(const string& a, const string& b)
+unsigned
+levenshtein(const string& a, const string& b)
{
Array2D<unsigned> d(a.size()+1, b.size()+1);
return d(d.width-1, d.height-1);
}
+// Returns comma-separated list of set elements closest to the target string.
+// Print a maximum amount of 'max' elements, with a maximum levenshtein score
+// of 'threshold'.
+string
+levenshtein_suggest(const string& target, // string to match against
+ const set<string>& elems, // elements to suggest from
+ unsigned max, // max elements to print
+ unsigned threshold) // max leven score to print
+{
+ // calculate leven score for each elem and put in map
+ multimap<unsigned, string> scores;
+ for (set<string>::const_iterator it = elems.begin();
+ it != elems.end(); ++it)
+ {
+ unsigned score = levenshtein(target, *it);
+ if (score <= threshold)
+ scores.insert(make_pair(score, *it));
+ }
+
+ string suggestions;
+
+ // Print out the top 'max' elements
+ multimap<unsigned, string>::iterator it = scores.begin();
+ for (unsigned i = 0; it != scores.end() && i < max; ++it, i++)
+ suggestions += it->second + ", ";
+ if (!suggestions.empty())
+ suggestions.erase(suggestions.size()-2);
+
+ return suggestions;
+}
+
#ifndef HAVE_PPOLL
// This is a poor-man's ppoll, only used carefully by readers that need to be
// interruptible, like remote::run and mutator::run. It does not provide the
#include <iomanip>
#include <map>
#include <algorithm>
+#include <limits>
extern "C" {
#if ENABLE_NLS
// String sorter using the Levenshtein algorithm
unsigned levenshtein(const std::string& a, const std::string& b);
+// Returns comma-separated list of set elements closest to the target string.
+// Print a maximum amount of 'max' elements, with a maximum levenshtein score
+// of 'threshold'.
+std::string levenshtein_suggest(const std::string& target,
+ const std::set<std::string>& elems,
+ unsigned max = std::numeric_limits<unsigned>::max(),
+ unsigned threshold = std::numeric_limits<unsigned>::max());
+
#ifndef HAVE_PPOLL
// This is a poor-man's ppoll; see the implementation for more details...
int ppoll(struct pollfd *fds, nfds_t nfds,