ArgumentParser+date: Add value arguments
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
d68f6bd76b
commit
75c48e996a
@ -9,7 +9,9 @@ endfunction()
|
||||
luna_app(init.cpp init)
|
||||
luna_app(cat.cpp cat)
|
||||
luna_app(sh.cpp sh)
|
||||
|
||||
luna_app(date.cpp date)
|
||||
target_link_libraries(date PRIVATE os)
|
||||
|
||||
luna_app(edit.cpp edit)
|
||||
target_link_libraries(edit PRIVATE os)
|
||||
|
@ -1,10 +1,21 @@
|
||||
#include <os/ArgumentParser.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
int main()
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
StringView date;
|
||||
|
||||
ArgumentParser parser;
|
||||
parser.add_value_argument(date, 'd', "date", false);
|
||||
parser.parse(argc, argv);
|
||||
|
||||
time_t now;
|
||||
if (date.is_empty()) { now = time(NULL); }
|
||||
else { now = strtol(date.chars(), nullptr, 10); }
|
||||
|
||||
fputs(ctime(&now), stdout);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ int main(int argc, char** argv)
|
||||
bool show_almost_all;
|
||||
|
||||
ArgumentParser parser;
|
||||
parser.add_positional_argument(pathname, "directory", false, "/");
|
||||
parser.add_positional_argument(pathname, "directory", "/");
|
||||
parser.add_switch_argument(show_all, 'a', "all");
|
||||
parser.add_switch_argument(show_almost_all, 'A', "almost-all");
|
||||
parser.parse(argc, argv);
|
||||
|
@ -8,10 +8,13 @@ class ArgumentParser
|
||||
ArgumentParser() = default;
|
||||
|
||||
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
|
||||
Result<void> add_positional_argument(StringView& out, StringView name, bool required, StringView fallback);
|
||||
Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);
|
||||
|
||||
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag);
|
||||
|
||||
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required);
|
||||
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback);
|
||||
|
||||
void parse(int argc, char* const* argv);
|
||||
|
||||
private:
|
||||
@ -30,6 +33,16 @@ class ArgumentParser
|
||||
StringView long_flag;
|
||||
};
|
||||
|
||||
struct ValueArgument
|
||||
{
|
||||
StringView* out;
|
||||
char short_flag;
|
||||
StringView long_flag;
|
||||
bool required;
|
||||
StringView fallback;
|
||||
};
|
||||
|
||||
Vector<PositionalArgument> m_positional_args;
|
||||
Vector<SwitchArgument> m_switch_args;
|
||||
Vector<ValueArgument> m_value_args;
|
||||
};
|
||||
|
@ -9,10 +9,9 @@ Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView
|
||||
return m_positional_args.try_append(move(arg));
|
||||
}
|
||||
|
||||
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, bool required,
|
||||
StringView fallback)
|
||||
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, StringView fallback)
|
||||
{
|
||||
PositionalArgument arg { &out, name, required, fallback };
|
||||
PositionalArgument arg { &out, name, false, fallback };
|
||||
|
||||
return m_positional_args.try_append(move(arg));
|
||||
}
|
||||
@ -24,6 +23,22 @@ Result<void> ArgumentParser::add_switch_argument(bool& out, char short_flag, Str
|
||||
return m_switch_args.try_append(move(arg));
|
||||
}
|
||||
|
||||
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
|
||||
bool value_required)
|
||||
{
|
||||
ValueArgument arg { &out, short_flag, long_flag, value_required, {} };
|
||||
|
||||
return m_value_args.try_append(move(arg));
|
||||
}
|
||||
|
||||
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
|
||||
StringView fallback)
|
||||
{
|
||||
ValueArgument arg { &out, short_flag, long_flag, false, fallback };
|
||||
|
||||
return m_value_args.try_append(move(arg));
|
||||
}
|
||||
|
||||
static bool looks_like_short_flag(StringView arg)
|
||||
{
|
||||
return arg.length() > 1 && arg[0] == '-';
|
||||
@ -38,12 +53,22 @@ void ArgumentParser::parse(int argc, char* const* argv)
|
||||
{
|
||||
StringView program_name = argv[0];
|
||||
|
||||
Option<ValueArgument> current_value_argument = {};
|
||||
bool is_parsing_value_argument = false;
|
||||
|
||||
bool is_still_parsing_flags = true;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
StringView arg = argv[i];
|
||||
|
||||
if (is_parsing_value_argument)
|
||||
{
|
||||
*current_value_argument->out = arg;
|
||||
is_parsing_value_argument = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_still_parsing_flags)
|
||||
{
|
||||
if (arg == "--")
|
||||
@ -68,6 +93,17 @@ void ArgumentParser::parse(int argc, char* const* argv)
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& current : m_value_args)
|
||||
{
|
||||
if (current.long_flag == flag)
|
||||
{
|
||||
current_value_argument = current;
|
||||
is_parsing_value_argument = true;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) continue;
|
||||
|
||||
fprintf(stderr, "%s: unrecognized option '%s'\n", program_name.chars(), arg.chars());
|
||||
@ -81,6 +117,8 @@ void ArgumentParser::parse(int argc, char* const* argv)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
// FIXME: Implement value arguments for short flags.
|
||||
|
||||
for (const auto& current : m_switch_args)
|
||||
{
|
||||
if (current.short_flag == ' ') continue;
|
||||
@ -113,6 +151,17 @@ void ArgumentParser::parse(int argc, char* const* argv)
|
||||
*current->out = arg;
|
||||
}
|
||||
|
||||
if (is_parsing_value_argument)
|
||||
{
|
||||
if (current_value_argument->required)
|
||||
{
|
||||
fprintf(stderr, "%s: option '--%s' requires an argument\n", program_name.chars(),
|
||||
current_value_argument->long_flag.chars());
|
||||
exit(1);
|
||||
}
|
||||
else { *current_value_argument->out = current_value_argument->fallback; }
|
||||
}
|
||||
|
||||
// Loop through all remaining positional arguments.
|
||||
for (const auto& arg : m_positional_args)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user