mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
add an example of finding close matches
This commit is contained in:
parent
cbbf20ed93
commit
0549f7c450
@ -250,6 +250,8 @@ set_property(TEST retired_retired_test3 PROPERTY PASS_REGULAR_EXPRESSION "WARNIN
|
||||
|
||||
set_property(TEST retired_deprecated PROPERTY PASS_REGULAR_EXPRESSION "deprecated.*not_deprecated")
|
||||
|
||||
add_cli_exe(close_match close_match.cpp)
|
||||
|
||||
#--------------------------------------------
|
||||
add_cli_exe(custom_parse custom_parse.cpp)
|
||||
add_test(NAME cp_test COMMAND custom_parse --dv 1.7)
|
||||
|
107
examples/close_match.cpp
Normal file
107
examples/close_match.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
|
||||
// under NSF AWARD 1414736 and by the respective contributors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Code inspired by discussion from https://github.com/CLIUtils/CLI11/issues/1149
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
// Levenshtein distance function code generated by chatgpt
|
||||
int levenshteinDistance(const std::string& s1, const std::string& s2) {
|
||||
size_t len1 = s1.size(), len2 = s2.size();
|
||||
std::vector<std::vector<int>> dp(len1 + 1, std::vector<int>(len2 + 1));
|
||||
|
||||
for (size_t i = 0; i <= len1; ++i) dp[i][0] = i;
|
||||
for (size_t j = 0; j <= len2; ++j) dp[0][j] = j;
|
||||
|
||||
for (size_t i = 1; i <= len1; ++i) {
|
||||
for (size_t j = 1; j <= len2; ++j) {
|
||||
int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;
|
||||
dp[i][j] = std::min({
|
||||
dp[i - 1][j] + 1, // deletion
|
||||
dp[i][j - 1] + 1, // insertion
|
||||
dp[i - 1][j - 1] + cost // substitution
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return dp[len1][len2];
|
||||
}
|
||||
|
||||
// Finds the closest string from a list
|
||||
std::pair<std::string,int> findClosestMatch(const std::string& input, const std::vector<std::string>& candidates) {
|
||||
std::string closest;
|
||||
int minDistance = std::numeric_limits<int>::max();
|
||||
|
||||
for (const auto& candidate : candidates) {
|
||||
int distance = levenshteinDistance(input, candidate);
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
closest = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return { closest,minDistance };
|
||||
}
|
||||
|
||||
/** This example demonstrates the use of `prefix_command` on a subcommand
|
||||
to capture all subsequent arguments along with an alias to make it appear as a regular options.
|
||||
|
||||
All the values after the "sub" or "--sub" are available in the remaining() method.
|
||||
*/
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
int value{0};
|
||||
CLI::App app{"cose string App"};
|
||||
app.add_option("-v", value, "value");
|
||||
|
||||
app.add_subcommand("install", "");
|
||||
app.add_subcommand("upgrade","");
|
||||
app.add_subcommand("remove","");
|
||||
app.add_subcommand("test","");
|
||||
app.allow_extras(true);
|
||||
|
||||
app.parse_complete_callback([&app]() {
|
||||
auto extras = app.remaining();
|
||||
if (extras.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto subs = app.get_subcommands(nullptr);
|
||||
std::vector<std::string> list;
|
||||
for (const auto* sub : subs) {
|
||||
if (!sub->get_name().empty())
|
||||
{
|
||||
list.push_back(sub->get_name());
|
||||
}
|
||||
auto aliases = sub->get_aliases();
|
||||
if (!aliases.empty())
|
||||
{
|
||||
list.insert(list.end(), aliases.begin(), aliases.end());
|
||||
}
|
||||
|
||||
}
|
||||
for (auto& extra : extras)
|
||||
{
|
||||
if (extra.front() != '-')
|
||||
{
|
||||
auto closest = findClosestMatch(extra,list);
|
||||
if (closest.second <= 3)
|
||||
{
|
||||
std::cout<<"unmatched commands "<<extra<<", closest match is "<<closest.first<<"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
return 0;
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user