From 5e8d8cb7d1b1061c293c48310588aee271f77860 Mon Sep 17 00:00:00 2001 From: Martchus Date: Fri, 11 May 2018 16:15:02 +0200 Subject: [PATCH] Show dashes in suggestions --- application/argumentparser.cpp | 33 ++++++++++++++++++++++++--------- application/argumentparser.h | 6 +++--- tests/argumentparsertests.cpp | 8 ++++---- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/application/argumentparser.cpp b/application/argumentparser.cpp index 3f7a6cc..6415aaa 100644 --- a/application/argumentparser.cpp +++ b/application/argumentparser.cpp @@ -65,8 +65,8 @@ ArgumentCompletionInfo::ArgumentCompletionInfo(const ArgumentReader &reader) } struct ArgumentSuggestion { - ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion); - ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion, size_t suggestionSize); + ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion, bool hasDashPrefix); + ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion, size_t suggestionSize, bool hasDashPrefix); bool operator<(const ArgumentSuggestion &other) const; bool operator==(const ArgumentSuggestion &other) const; void addTo(multiset &suggestions, size_t limit) const; @@ -74,17 +74,19 @@ struct ArgumentSuggestion { const char *const suggestion; const size_t suggestionSize; const size_t editingDistance; + const bool hasDashPrefix; }; -ArgumentSuggestion::ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion, size_t suggestionSize) +ArgumentSuggestion::ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion, size_t suggestionSize, bool isOperation) : suggestion(suggestion) , suggestionSize(suggestionSize) , editingDistance(MiscUtilities::computeDamerauLevenshteinDistance(unknownArg, unknownArgSize, suggestion, suggestionSize)) + , hasDashPrefix(isOperation) { } -ArgumentSuggestion::ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion) - : ArgumentSuggestion(unknownArg, unknownArgSize, suggestion, strlen(suggestion)) +ArgumentSuggestion::ArgumentSuggestion(const char *unknownArg, size_t unknownArgSize, const char *suggestion, bool isOperation) + : ArgumentSuggestion(unknownArg, unknownArgSize, suggestion, strlen(suggestion), isOperation) { } @@ -1204,13 +1206,20 @@ string ArgumentParser::findSuggestions(int argc, const char *const *argv, unsign // determine completion info const auto completionInfo(determineCompletionInfo(argc, argv, cursorPos, reader)); + // determine the unknown/misspelled argument + const auto *unknownArg(*reader.argv); + auto unknownArgSize(strlen(unknownArg)); + // -> remove dashes since argument names internally don't have them + if (unknownArgSize >= 2 && unknownArg[0] == '-' && unknownArg[1] == '-') { + unknownArg += 2; + unknownArgSize -= 2; + } + // find best suggestions limiting the results to 2 - const auto *const unknownArg(*reader.argv); - const auto unknownArgSize(strlen(unknownArg)); multiset bestSuggestions; // -> consider relevant arguments for (const Argument *const arg : completionInfo.relevantArgs) { - ArgumentSuggestion(unknownArg, unknownArgSize, arg->name()).addTo(bestSuggestions, 2); + ArgumentSuggestion(unknownArg, unknownArgSize, arg->name(), !arg->denotesOperation()).addTo(bestSuggestions, 2); } // -> consider relevant values for (const Argument *const arg : completionInfo.relevantPreDefinedValues) { @@ -1219,7 +1228,7 @@ string ArgumentParser::findSuggestions(int argc, const char *const *argv, unsign const char *wordEnd(wordStart + 1); for (; *wordEnd && *wordEnd != ' '; ++wordEnd) ; - ArgumentSuggestion(unknownArg, unknownArgSize, wordStart, static_cast(wordEnd - wordStart)).addTo(bestSuggestions, 2); + ArgumentSuggestion(unknownArg, unknownArgSize, wordStart, static_cast(wordEnd - wordStart), false).addTo(bestSuggestions, 2); i = wordEnd; } } @@ -1231,6 +1240,9 @@ string ArgumentParser::findSuggestions(int argc, const char *const *argv, unsign size_t requiredSize = 15; for (const auto &suggestion : bestSuggestions) { requiredSize += suggestion.suggestionSize + 2; + if (suggestion.hasDashPrefix) { + requiredSize += 2; + } } suggestionStr.reserve(requiredSize); @@ -1243,6 +1255,9 @@ string ArgumentParser::findSuggestions(int argc, const char *const *argv, unsign } else if (i > 1) { suggestionStr += ", "; } + if (suggestion.hasDashPrefix) { + suggestionStr += "--"; + } suggestionStr.append(suggestion.suggestion, suggestion.suggestionSize); } suggestionStr += '?'; diff --git a/application/argumentparser.h b/application/argumentparser.h index 357f68e..dd4df22 100644 --- a/application/argumentparser.h +++ b/application/argumentparser.h @@ -768,10 +768,10 @@ inline void Argument::setCombinable(bool value) } /*! - * \brief Returns whether the argument denotes the operation. + * \brief Returns whether the argument denotes an operation. * - * An argument which denotes the operation might be specified - * withouth "--" or "-" prefix as first main argument. + * An argument which denotes an operation might be specified + * without "--" or "-" prefix. * * The default value is false, except for OperationArgument instances. * diff --git a/tests/argumentparsertests.cpp b/tests/argumentparsertests.cpp index 5be5949..a5dbed9 100644 --- a/tests/argumentparsertests.cpp +++ b/tests/argumentparsertests.cpp @@ -196,7 +196,7 @@ void ArgumentParserTests::testParsing() parser.parseArgs(6, argv3); CPPUNIT_FAIL("Exception expected."); } catch (const Failure &e) { - CPPUNIT_ASSERT_EQUAL("The specified argument \"album\" is unknown.\nDid you mean get or help?"s, string(e.what())); + CPPUNIT_ASSERT_EQUAL("The specified argument \"album\" is unknown.\nDid you mean get or --help?"s, string(e.what())); } // error about unknown argument: mistake in final argument @@ -206,7 +206,7 @@ void ArgumentParserTests::testParsing() parser.parseArgs(7, argv18); CPPUNIT_FAIL("Exception expected."); } catch (const Failure &e) { - CPPUNIT_ASSERT_EQUAL("The specified argument \"--fi\" is unknown.\nDid you mean files or no-color?"s, string(e.what())); + CPPUNIT_ASSERT_EQUAL("The specified argument \"--fi\" is unknown.\nDid you mean --files or --no-color?"s, string(e.what())); } // warning about unknown argument @@ -310,7 +310,7 @@ void ArgumentParserTests::testParsing() CPPUNIT_FAIL("Exception expected."); } catch (const Failure &e) { CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent()); - CPPUNIT_ASSERT_EQUAL("The specified argument \"-f\" is unknown.\nDid you mean get or help?"s, string(e.what())); + CPPUNIT_ASSERT_EQUAL("The specified argument \"-f\" is unknown.\nDid you mean get or --help?"s, string(e.what())); } // equation sign syntax @@ -410,7 +410,7 @@ void ArgumentParserTests::testParsing() CPPUNIT_FAIL("Exception expected."); } catch (const Failure &e) { CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent()); - CPPUNIT_ASSERT_EQUAL("The specified argument \"--hel\" is unknown.\nDid you mean help or get?"s, string(e.what())); + CPPUNIT_ASSERT_EQUAL("The specified argument \"--hel\" is unknown.\nDid you mean --help or get?"s, string(e.what())); } // nested operations