Skip to content

Commit

Permalink
Hint when an unknown option is available on different commands
Browse files Browse the repository at this point in the history
Closes: #1830
  • Loading branch information
kontura authored and jrohel committed Nov 19, 2024
1 parent c6e94f7 commit 53cdd9c
Showing 1 changed file with 48 additions and 2 deletions.
50 changes: 48 additions & 2 deletions dnf5/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1261,13 +1261,59 @@ int main(int argc, char * argv[]) try {
context.print_error(libdnf5::utils::sformat(
_("{}. Add \"--help\" for more information about the arguments."), ex.what()));
}
// If the error is an unknown top-level command, suggest
// installing a package that provides the command

if (auto * unknown_arg_ex = dynamic_cast<libdnf5::cli::ArgumentParserUnknownArgumentError *>(&ex)) {
if (unknown_arg_ex->get_command() == "dnf5" && unknown_arg_ex->get_argument()[0] != '-') {
// If the error is an unknown top-level command, suggest
// installing a package that provides the command

context.print_error(libdnf5::utils::sformat(
_("It could be a command provided by a plugin, try: dnf5 install 'dnf5-command({})'"),
unknown_arg_ex->get_argument()));

} else if (unknown_arg_ex->get_argument()[0] == '-') {
// If the error is an unknown option check if it is used by some other command and provide a hint

std::unordered_set<std::string> commands_with_option;
// Remove any values passed with the option
std::string tmp =
unknown_arg_ex->get_argument().substr(0, unknown_arg_ex->get_argument().find("="));
// Both short and long options start with a '-', remove it
tmp.erase(0, 1);
std::function<bool(libdnf5::cli::ArgumentParser::NamedArg * arg, const std::string & tmp)>
comparator;
if (tmp[0] == '-') {
// Long option, erase the second '-'
tmp.erase(0, 1);
comparator = [](libdnf5::cli::ArgumentParser::NamedArg * arg,
const std::string & tmp) -> bool { return (arg->get_long_name() == tmp); };
} else {
// Short option
comparator = [](libdnf5::cli::ArgumentParser::NamedArg * arg,
const std::string & tmp) -> bool {
return (arg->get_short_name() == tmp[0]);
};
}

for (const auto & cmd : arg_parser.get_commands()) {
for (const auto & arg : cmd->get_named_args()) {
if (comparator(arg, tmp)) {
if (!dynamic_cast<libdnf5::cli::ArgumentParser::CommandAlias *>(cmd.get())) {
auto invoc = cmd->get_invocation();
// Erase first element which is the root command (dnf)
invoc.erase(invoc.begin());
commands_with_option.insert(libdnf5::utils::string::join(invoc, " "));
}
}
}
}

if (!commands_with_option.empty()) {
context.print_error(libdnf5::utils::sformat(
_("The argument is available for commands: {}. (It has to be placed after the "
"command.)"),
libdnf5::utils::string::join(commands_with_option, _(", "))));
}
}
}
return static_cast<int>(libdnf5::cli::ExitCode::ARGPARSER_ERROR);
Expand Down

0 comments on commit 53cdd9c

Please sign in to comment.