Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hint when an unknown option is available on different commands #1858

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading