//===----------------------------------------------------------------------===//
-static StringRef ArgPrefix = " -";
-static StringRef ArgPrefixLong = " --";
+const static size_t DefaultPad = 2;
+
+static StringRef ArgPrefix = "-";
+static StringRef ArgPrefixLong = "--";
static StringRef ArgHelpPrefix = " - ";
-static size_t argPlusPrefixesSize(StringRef ArgName) {
+static size_t argPlusPrefixesSize(StringRef ArgName, size_t Pad = DefaultPad) {
size_t Len = ArgName.size();
if (Len == 1)
- return Len + ArgPrefix.size() + ArgHelpPrefix.size();
- return Len + ArgPrefixLong.size() + ArgHelpPrefix.size();
+ return Len + Pad + ArgPrefix.size() + ArgHelpPrefix.size();
+ return Len + Pad + ArgPrefixLong.size() + ArgHelpPrefix.size();
}
-static StringRef argPrefix(StringRef ArgName) {
- if (ArgName.size() == 1)
- return ArgPrefix;
- return ArgPrefixLong;
+static SmallString<8> argPrefix(StringRef ArgName, size_t Pad = DefaultPad) {
+ SmallString<8> Prefix;
+ for (size_t I = 0; I < Pad; ++I) {
+ Prefix.push_back(' ');
+ }
+ Prefix.append(ArgName.size() > 1 ? ArgPrefixLong : ArgPrefix);
+ return Prefix;
}
// Option predicates...
class PrintArg {
StringRef ArgName;
+ size_t Pad;
public:
- PrintArg(StringRef ArgName) : ArgName(ArgName) {}
- friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg&);
+ PrintArg(StringRef ArgName, size_t Pad = DefaultPad) : ArgName(ArgName), Pad(Pad) {}
+ friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg &);
};
raw_ostream &operator<<(raw_ostream &OS, const PrintArg& Arg) {
- OS << argPrefix(Arg.ArgName) << Arg.ArgName;
+ OS << argPrefix(Arg.ArgName, Arg.Pad) << Arg.ArgName;
return OS;
}
if (NearestHandler) {
// If we know a near match, report it as well.
*Errs << ProgramName << ": Did you mean '"
- << PrintArg(NearestHandlerString) << "'?\n";
+ << PrintArg(NearestHandlerString, 0) << "'?\n";
}
ErrorParsing = true;
if (ArgName.empty())
Errs << HelpStr; // Be nice for positional arguments
else
- Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName);
+ Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName, 0);
Errs << " option: " << Message << "\n";
return true;
EXPECT_TRUE(Errs.empty()); Errs.clear();
cl::ResetAllOptionOccurrences();
}
+
+TEST(CommandLineTest, OptionErrorMessage) {
+ // When there is an error, we expect some error message like:
+ // prog: for the -a option: [...]
+ //
+ // Test whether the "for the -a option"-part is correctly formatted.
+ cl::ResetCommandLineParser();
+
+ StackOption<bool> OptA("a", cl::desc("Some option"));
+ StackOption<bool> OptLong("long", cl::desc("Some long option"));
+
+ std::string Errs;
+ raw_string_ostream OS(Errs);
+
+ OptA.error("custom error", OS);
+ OS.flush();
+ EXPECT_FALSE(Errs.find("for the -a option:") == std::string::npos);
+ Errs.clear();
+
+ OptLong.error("custom error", OS);
+ OS.flush();
+ EXPECT_FALSE(Errs.find("for the --long option:") == std::string::npos);
+ Errs.clear();
+
+ cl::ResetAllOptionOccurrences();
+}
+
+TEST(CommandLineTest, OptionErrorMessageSuggest) {
+ // When there is an error, and the edit-distance is not very large,
+ // we expect some error message like:
+ // prog: did you mean '--option'?
+ //
+ // Test whether this message is well-formatted.
+ cl::ResetCommandLineParser();
+
+ StackOption<bool> OptLong("aluminium", cl::desc("Some long option"));
+
+ const char *args[] = {"prog", "--aluminum"};
+
+ std::string Errs;
+ raw_string_ostream OS(Errs);
+
+ EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
+ OS.flush();
+ EXPECT_FALSE(Errs.find("prog: Did you mean '--aluminium'?\n") ==
+ std::string::npos);
+ Errs.clear();
+
+ cl::ResetAllOptionOccurrences();
+}
} // anonymous namespace