src: Add command-line option guess
This commit is contained in:
parent
a15fc5fbb4
commit
90ea7ba92a
|
@ -1801,6 +1801,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
break;
|
||||
case '?':
|
||||
util::show_candidates(argv[optind - 1], long_options);
|
||||
exit(EXIT_FAILURE);
|
||||
case 0:
|
||||
switch(flag) {
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "app_helper.h"
|
||||
#include "HttpServer.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
|
@ -178,6 +179,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
break;
|
||||
case '?':
|
||||
util::show_candidates(argv[optind - 1], long_options);
|
||||
exit(EXIT_FAILURE);
|
||||
case 0:
|
||||
switch(flag) {
|
||||
|
|
|
@ -52,6 +52,9 @@
|
|||
#include "shrpx_config.h"
|
||||
#include "shrpx_listen_handler.h"
|
||||
#include "shrpx_ssl.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace nghttp2;
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
|
@ -859,6 +862,7 @@ int main(int argc, char **argv)
|
|||
print_version(std::cout);
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
util::show_candidates(argv[optind - 1], long_options);
|
||||
exit(EXIT_FAILURE);
|
||||
case 0:
|
||||
switch(flag) {
|
||||
|
|
72
src/util.cc
72
src/util.cc
|
@ -29,6 +29,7 @@
|
|||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "timegm.h"
|
||||
|
||||
|
@ -281,6 +282,77 @@ void inp_strlower(std::string& s)
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Calculates Damerau–Levenshtein distance between c-string a and b
|
||||
// with given costs. swapcost, subcost, addcost and delcost are cost
|
||||
// to swap 2 adjacent characters, substitute characters, add character
|
||||
// and delete character respectively.
|
||||
int levenshtein
|
||||
(const char* a,
|
||||
const char* b,
|
||||
int swapcost,
|
||||
int subcost,
|
||||
int addcost,
|
||||
int delcost)
|
||||
{
|
||||
int alen = strlen(a);
|
||||
int blen = strlen(b);
|
||||
auto dp = std::vector<std::vector<int>>(3, std::vector<int>(blen+1));
|
||||
for(int i = 0; i <= blen; ++i) {
|
||||
dp[1][i] = i;
|
||||
}
|
||||
for(int i = 1; i <= alen; ++i) {
|
||||
dp[0][0] = i;
|
||||
for(int j = 1; j <= blen; ++j) {
|
||||
dp[0][j] = dp[1][j-1]+(a[i-1] == b[j-1] ? 0 : subcost);
|
||||
if(i >= 2 && j >= 2 && a[i-1] != b[j-1] &&
|
||||
a[i-2] == b[j-1] && a[i-1] == b[j-2]) {
|
||||
dp[0][j] = std::min(dp[0][j], dp[2][j-2]+swapcost);
|
||||
}
|
||||
dp[0][j] = std::min(dp[0][j],
|
||||
std::min(dp[1][j]+delcost, dp[0][j-1]+addcost));
|
||||
}
|
||||
std::rotate(std::begin(dp), std::begin(dp)+2, std::end(dp));
|
||||
}
|
||||
return dp[1][blen];
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void show_candidates(const char *unkopt, option *options)
|
||||
{
|
||||
for(; *unkopt == '-'; ++unkopt);
|
||||
if(*unkopt == '\0') {
|
||||
return;
|
||||
}
|
||||
auto cands = std::vector<std::pair<int, const char*>>();
|
||||
for(size_t i = 0; options[i].name != nullptr; ++i) {
|
||||
// Use cost 0 for prefix match
|
||||
if(istartsWith(options[i].name, unkopt)) {
|
||||
cands.emplace_back(0, options[i].name);
|
||||
continue;
|
||||
}
|
||||
// cost values are borrowed from git, help.c.
|
||||
int sim = levenshtein(unkopt, options[i].name, 0, 2, 1, 3);
|
||||
cands.emplace_back(sim, options[i].name);
|
||||
}
|
||||
if(cands.empty()) {
|
||||
return;
|
||||
}
|
||||
std::sort(std::begin(cands), std::end(cands));
|
||||
int threshold = cands[0].first;
|
||||
// threshold value is a magic value.
|
||||
if(threshold > 6) {
|
||||
return;
|
||||
}
|
||||
std::cerr << "\nDid you mean:\n";
|
||||
for(auto& item : cands) {
|
||||
if(item.first > threshold) {
|
||||
break;
|
||||
}
|
||||
std::cerr << "\t--" << item.second << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
#include "nghttp2_config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -403,6 +406,8 @@ make_unique(size_t size)
|
|||
void to_token68(std::string& base64str);
|
||||
void to_base64(std::string& token68str);
|
||||
|
||||
void show_candidates(const char *unkopt, option *options);
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
|
|
Loading…
Reference in New Issue