fix bug with postional args preventing the warning of missing args

add option to print full filename
fix issue with some help printing full filename
v1
Brett 2023-09-16 17:22:15 -04:00
parent 1e293c7dba
commit 9db6dd8456
2 changed files with 58 additions and 23 deletions

View File

@ -78,6 +78,8 @@ namespace blt
// returns the first flag that starts with '--' otherwise return the first '-' flag // returns the first flag that starts with '--' otherwise return the first '-' flag
[[nodiscard]] std::string getFirstFullFlag() const; [[nodiscard]] std::string getFirstFullFlag() const;
[[nodiscard]] std::string getArgName() const;
}; };
class arg_nargs_t class arg_nargs_t
@ -280,11 +282,11 @@ namespace blt
friend arg_parse; friend arg_parse;
private: private:
// stores dest value not the flag/name! // stores dest value not the flag/name!
HASHSET <std::string> found_args; HASHSET<std::string> found_args;
std::vector<std::string> unrecognized_args; std::vector<std::string> unrecognized_args;
public: public:
std::string program_name; std::string program_name;
HASHMAP <std::string, arg_data_t> data; HASHMAP<std::string, arg_data_t> data;
inline arg_data_t& operator[](const std::string& key) inline arg_data_t& operator[](const std::string& key)
{ {
@ -312,6 +314,7 @@ namespace blt
} loaded_args; } loaded_args;
bool help_disabled = false; bool help_disabled = false;
bool use_full_name = false;
std::string help_inclusion; std::string help_inclusion;
private: private:
static std::string getMetavar(const arg_properties_t* const& arg); static std::string getMetavar(const arg_properties_t* const& arg);
@ -339,6 +342,11 @@ namespace blt
void handleFlag(arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t* properties); void handleFlag(arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t* properties);
std::string getProgramName() const
{
return use_full_name ? loaded_args.program_name : filename(loaded_args.program_name);
}
public: public:
template<typename T> template<typename T>
@ -403,6 +411,14 @@ namespace blt
void printHelp() const; void printHelp() const;
/**
* Sets the parser to use the full file path when printing usage messages
*/
inline void useFullPath()
{
use_full_name = true;
}
inline void setHelpPrefix(const std::string& str) inline void setHelpPrefix(const std::string& str)
{ {
user_args.prefix = str; user_args.prefix = str;

View File

@ -82,6 +82,12 @@ namespace blt
return flag; return flag;
} }
std::string arg_vector_t::getArgName() const {
if (name.empty())
return getFirstFullFlag();
return name;
}
std::string to_string(const arg_data_t& v) std::string to_string(const arg_data_t& v)
{ {
if (holds_alternative<arg_data_internal_t>(v)) if (holds_alternative<arg_data_internal_t>(v))
@ -168,7 +174,7 @@ namespace blt
{ {
// TODO: S // TODO: S
printUsage(); printUsage();
std::cout << filename(loaded_args.program_name) << ": error: flag '" << flag << "' expected " << properties.a_nargs.args std::cout << getProgramName() << ": error: flag '" << flag << "' expected " << properties.a_nargs.args
<< " argument(s) got " << i << " argument(s) instead!\n"; << " argument(s) got " << i << " argument(s) instead!\n";
return false; return false;
} }
@ -176,7 +182,7 @@ namespace blt
if (tokenizer.isFlag()) if (tokenizer.isFlag())
{ {
printUsage(); printUsage();
std::cout << filename(loaded_args.program_name) << ": error: flag '" << flag << "' expected " << properties.a_nargs.args std::cout << getProgramName() << ": error: flag '" << flag << "' expected " << properties.a_nargs.args
<< " argument(s) but found '" << tokenizer.get() << "' instead!\n"; << " argument(s) but found '" << tokenizer.get() << "' instead!\n";
//BLT_WARN("Expected %d arguments, found flag instead!", properties.a_nargs.args); //BLT_WARN("Expected %d arguments, found flag instead!", properties.a_nargs.args);
return false; return false;
@ -211,7 +217,7 @@ namespace blt
if (tokenizer.hasCurrent() && tokenizer.isFlag()) if (tokenizer.hasCurrent() && tokenizer.isFlag())
{ {
printUsage(); printUsage();
std::cout << loaded_args.program_name << ": at least one argument is required for '" << flag << "'\n"; std::cout << getProgramName() << ": at least one argument is required for '" << flag << "'\n";
return false; return false;
} }
while (tokenizer.hasCurrent() && !tokenizer.isFlag()) while (tokenizer.hasCurrent() && !tokenizer.isFlag())
@ -364,7 +370,7 @@ namespace blt
} }
case arg_action_t::VERSION: case arg_action_t::VERSION:
{ {
auto file = filename(loaded_args.program_name); auto file = getProgramName();
std::cout << file.c_str() << " " << properties->a_version << "\n"; std::cout << file.c_str() << " " << properties->a_version << "\n";
break; break;
} }
@ -435,10 +441,8 @@ namespace blt
loaded_args.data[arg->a_dest] = arg->a_default; loaded_args.data[arg->a_dest] = arg->a_default;
} }
// if there was no problems processing then return the loaded args if (!loaded_args.unrecognized_args.empty())
if (loaded_args.unrecognized_args.empty()) {
return loaded_args;
// otherwise construct a string detailing the unrecognized args // otherwise construct a string detailing the unrecognized args
std::string unrec; std::string unrec;
for (const auto& r : loaded_args.unrecognized_args) for (const auto& r : loaded_args.unrecognized_args)
@ -451,10 +455,25 @@ namespace blt
// remove the last space caused by the for loop // remove the last space caused by the for loop
unrec = unrec.substr(0, unrec.size() - 1); unrec = unrec.substr(0, unrec.size() - 1);
printUsage(); printUsage();
std::cout << loaded_args.program_name << ": error: unrecognized args: " << unrec << "\n"; std::cout << getProgramName() << ": error: unrecognized args: " << unrec << "\n";
std::exit(0); std::exit(0);
} }
for (const auto& named_arg : user_args.name_associations)
{
if (takesArgs(named_arg) && !loaded_args.contains(named_arg->a_dest))
{
printUsage();
std::cout << "postional argument '" << named_arg->a_flags.name << "' expected " << named_arg->a_nargs.args << " argument"
<< (named_arg->a_nargs.args > 1 ? "s!" : "!") << std::endl;
std::exit(0);
}
}
// if there was no problems processing then return the loaded args
return loaded_args;
}
bool arg_parse::takesArgs(const arg_properties_t* const& arg) bool arg_parse::takesArgs(const arg_properties_t* const& arg)
{ {
switch (arg->a_action) switch (arg->a_action)
@ -539,7 +558,7 @@ namespace blt
{ {
if (help_disabled) if (help_disabled)
return; return;
std::string usage = "Usage: " + filename(loaded_args.program_name) + " " + help_inclusion + " "; std::string usage = "Usage: " + getProgramName() + " " + help_inclusion + " ";
std::cout << usage; std::cout << usage;
size_t current_line_length = 0; size_t current_line_length = 0;