ArgumentParser+ls: Add switch 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
a164dcc160
commit
d68f6bd76b
@ -8,9 +8,13 @@
|
|||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
StringView pathname;
|
StringView pathname;
|
||||||
|
bool show_all;
|
||||||
|
bool show_almost_all;
|
||||||
|
|
||||||
ArgumentParser parser;
|
ArgumentParser parser;
|
||||||
parser.add_positional_argument(pathname, "directory", false, "/");
|
parser.add_positional_argument(pathname, "directory", false, "/");
|
||||||
|
parser.add_switch_argument(show_all, 'a', "all");
|
||||||
|
parser.add_switch_argument(show_almost_all, 'A', "almost-all");
|
||||||
parser.parse(argc, argv);
|
parser.parse(argc, argv);
|
||||||
|
|
||||||
DIR* dp = opendir(pathname.chars());
|
DIR* dp = opendir(pathname.chars());
|
||||||
@ -24,6 +28,8 @@ int main(int argc, char** argv)
|
|||||||
do {
|
do {
|
||||||
struct dirent* ent = readdir(dp);
|
struct dirent* ent = readdir(dp);
|
||||||
if (!ent) break;
|
if (!ent) break;
|
||||||
|
if (show_almost_all && (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))) continue;
|
||||||
|
if (!show_all && !show_almost_all && *ent->d_name == '.') continue;
|
||||||
printf(first_ent ? "%s" : " %s", ent->d_name);
|
printf(first_ent ? "%s" : " %s", ent->d_name);
|
||||||
first_ent = 0;
|
first_ent = 0;
|
||||||
} while (1);
|
} while (1);
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
class String
|
class String
|
||||||
{
|
{
|
||||||
|
typedef char* Iterator;
|
||||||
|
typedef const char* ConstIterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
String(char* c_str);
|
String(char* c_str);
|
||||||
String(char* c_str, usize length);
|
String(char* c_str, usize length);
|
||||||
@ -43,6 +46,26 @@ class String
|
|||||||
|
|
||||||
const char& operator[](usize) const;
|
const char& operator[](usize) const;
|
||||||
|
|
||||||
|
Iterator begin()
|
||||||
|
{
|
||||||
|
return m_inline ? m_inline_storage : m_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator begin() const
|
||||||
|
{
|
||||||
|
return chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator end()
|
||||||
|
{
|
||||||
|
return begin() + m_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator end() const
|
||||||
|
{
|
||||||
|
return begin() + m_length;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
union {
|
union {
|
||||||
char* m_string { nullptr };
|
char* m_string { nullptr };
|
||||||
|
@ -5,6 +5,8 @@ class String;
|
|||||||
|
|
||||||
class StringView
|
class StringView
|
||||||
{
|
{
|
||||||
|
typedef const char* Iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringView(const char* c_str);
|
StringView(const char* c_str);
|
||||||
StringView(const char* c_str, usize length);
|
StringView(const char* c_str, usize length);
|
||||||
@ -32,6 +34,19 @@ class StringView
|
|||||||
|
|
||||||
const char& operator[](usize) const;
|
const char& operator[](usize) const;
|
||||||
|
|
||||||
|
bool operator==(const char* other) const;
|
||||||
|
bool operator==(StringView other) const;
|
||||||
|
|
||||||
|
Iterator begin() const
|
||||||
|
{
|
||||||
|
return m_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator end() const
|
||||||
|
{
|
||||||
|
return m_string + m_length;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* m_string { nullptr };
|
const char* m_string { nullptr };
|
||||||
|
|
||||||
|
@ -36,6 +36,16 @@ const char& StringView::operator[](usize index) const
|
|||||||
return m_string[index];
|
return m_string[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StringView::operator==(const char* other) const
|
||||||
|
{
|
||||||
|
return !strcmp(m_string, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringView::operator==(StringView other) const
|
||||||
|
{
|
||||||
|
return !strcmp(m_string, other.m_string);
|
||||||
|
}
|
||||||
|
|
||||||
Result<String> StringView::to_string()
|
Result<String> StringView::to_string()
|
||||||
{
|
{
|
||||||
return String::from_cstring(m_string);
|
return String::from_cstring(m_string);
|
||||||
|
@ -10,6 +10,8 @@ class ArgumentParser
|
|||||||
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
|
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, bool required, StringView fallback);
|
||||||
|
|
||||||
|
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag);
|
||||||
|
|
||||||
void parse(int argc, char* const* argv);
|
void parse(int argc, char* const* argv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -21,5 +23,13 @@ class ArgumentParser
|
|||||||
StringView fallback;
|
StringView fallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<PositionalArgument> m_positional_args;
|
struct SwitchArgument
|
||||||
|
{
|
||||||
|
bool* out;
|
||||||
|
char short_flag;
|
||||||
|
StringView long_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<PositionalArgument> m_positional_args;
|
||||||
|
Vector<SwitchArgument> m_switch_args;
|
||||||
};
|
};
|
||||||
|
@ -17,13 +17,92 @@ Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView
|
|||||||
return m_positional_args.try_append(move(arg));
|
return m_positional_args.try_append(move(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<void> ArgumentParser::add_switch_argument(bool& out, char short_flag, StringView long_flag)
|
||||||
|
{
|
||||||
|
SwitchArgument arg { &out, short_flag, long_flag };
|
||||||
|
|
||||||
|
return m_switch_args.try_append(move(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool looks_like_short_flag(StringView arg)
|
||||||
|
{
|
||||||
|
return arg.length() > 1 && arg[0] == '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool looks_like_long_flag(StringView arg)
|
||||||
|
{
|
||||||
|
return arg.length() > 2 && arg[0] == '-' && arg[1] == '-';
|
||||||
|
}
|
||||||
|
|
||||||
void ArgumentParser::parse(int argc, char* const* argv)
|
void ArgumentParser::parse(int argc, char* const* argv)
|
||||||
{
|
{
|
||||||
StringView program_name = argv[0];
|
StringView program_name = argv[0];
|
||||||
|
|
||||||
|
bool is_still_parsing_flags = true;
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
StringView arg = argv[i];
|
StringView arg = argv[i];
|
||||||
|
|
||||||
|
if (is_still_parsing_flags)
|
||||||
|
{
|
||||||
|
if (arg == "--")
|
||||||
|
{
|
||||||
|
is_still_parsing_flags = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (looks_like_long_flag(arg))
|
||||||
|
{
|
||||||
|
StringView flag = &arg[2];
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (const auto& current : m_switch_args)
|
||||||
|
{
|
||||||
|
if (current.long_flag == flag)
|
||||||
|
{
|
||||||
|
*current.out = true;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) continue;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: unrecognized option '%s'\n", program_name.chars(), arg.chars());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else if (looks_like_short_flag(arg))
|
||||||
|
{
|
||||||
|
StringView flags = &arg[1];
|
||||||
|
|
||||||
|
for (char c : flags)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (const auto& current : m_switch_args)
|
||||||
|
{
|
||||||
|
if (current.short_flag == ' ') continue;
|
||||||
|
|
||||||
|
if (current.short_flag == c)
|
||||||
|
{
|
||||||
|
*current.out = true;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) continue;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: invalid option -- '%c'\n", program_name.chars(), c);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Option<PositionalArgument> current = m_positional_args.try_dequeue();
|
Option<PositionalArgument> current = m_positional_args.try_dequeue();
|
||||||
if (!current.has_value())
|
if (!current.has_value())
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user