ArgsParser.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Function.h>
  8. #include <AK/String.h>
  9. #include <AK/Vector.h>
  10. #include <LibMain/Main.h>
  11. #include <stdio.h>
  12. namespace Core {
  13. class ArgsParser {
  14. public:
  15. ArgsParser();
  16. enum class Required {
  17. Yes,
  18. No
  19. };
  20. enum class FailureBehavior {
  21. PrintUsageAndExit,
  22. PrintUsage,
  23. Exit,
  24. Ignore,
  25. };
  26. /// When an option is hidden.
  27. /// If the hide mode is not None, then it's always hidden from the usage/synopsis.
  28. enum class OptionHideMode {
  29. None,
  30. Markdown,
  31. CommandLineAndMarkdown,
  32. };
  33. struct Option {
  34. bool requires_argument { true };
  35. char const* help_string { nullptr };
  36. char const* long_name { nullptr };
  37. char short_name { 0 };
  38. char const* value_name { nullptr };
  39. Function<bool(char const*)> accept_value;
  40. OptionHideMode hide_mode { OptionHideMode::None };
  41. String name_for_display() const
  42. {
  43. if (long_name)
  44. return String::formatted("--{}", long_name);
  45. return String::formatted("-{:c}", short_name);
  46. }
  47. };
  48. struct Arg {
  49. char const* help_string { nullptr };
  50. char const* name { nullptr };
  51. int min_values { 0 };
  52. int max_values { 1 };
  53. Function<bool(char const*)> accept_value;
  54. };
  55. bool parse(int argc, char* const* argv, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit);
  56. bool parse(Main::Arguments const& arguments, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit)
  57. {
  58. return parse(arguments.argc, arguments.argv, failure_behavior);
  59. }
  60. // *Without* trailing newline!
  61. void set_general_help(char const* help_string) { m_general_help = help_string; };
  62. void set_stop_on_first_non_option(bool stop_on_first_non_option) { m_stop_on_first_non_option = stop_on_first_non_option; }
  63. void print_usage(FILE*, char const* argv0);
  64. void print_usage_terminal(FILE*, char const* argv0);
  65. void print_usage_markdown(FILE*, char const* argv0);
  66. void print_version(FILE*);
  67. void add_option(Option&&);
  68. void add_ignored(char const* long_name, char short_name, OptionHideMode hide_mode = OptionHideMode::None);
  69. void add_option(bool& value, char const* help_string, char const* long_name, char short_name, OptionHideMode hide_mode = OptionHideMode::None);
  70. void add_option(char const*& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  71. void add_option(String& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  72. void add_option(StringView& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  73. void add_option(int& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  74. void add_option(unsigned& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  75. void add_option(double& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  76. void add_option(Optional<double>& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  77. void add_option(Optional<size_t>& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
  78. void add_option(Vector<size_t>& values, char const* help_string, char const* long_name, char short_name, char const* value_name, char separator = ',', OptionHideMode hide_mode = OptionHideMode::None);
  79. void add_positional_argument(Arg&&);
  80. void add_positional_argument(char const*& value, char const* help_string, char const* name, Required required = Required::Yes);
  81. void add_positional_argument(String& value, char const* help_string, char const* name, Required required = Required::Yes);
  82. void add_positional_argument(StringView& value, char const* help_string, char const* name, Required required = Required::Yes);
  83. void add_positional_argument(int& value, char const* help_string, char const* name, Required required = Required::Yes);
  84. void add_positional_argument(unsigned& value, char const* help_string, char const* name, Required required = Required::Yes);
  85. void add_positional_argument(double& value, char const* help_string, char const* name, Required required = Required::Yes);
  86. void add_positional_argument(Vector<char const*>& value, char const* help_string, char const* name, Required required = Required::Yes);
  87. void add_positional_argument(Vector<String>& value, char const* help_string, char const* name, Required required = Required::Yes);
  88. void add_positional_argument(Vector<StringView>& value, char const* help_string, char const* name, Required required = Required::Yes);
  89. private:
  90. void autocomplete(FILE*, StringView program_name, Span<char const* const> remaining_arguments);
  91. Vector<Option> m_options;
  92. Vector<Arg> m_positional_args;
  93. bool m_show_help { false };
  94. bool m_show_version { false };
  95. bool m_perform_autocomplete { false };
  96. char const* m_general_help { nullptr };
  97. bool m_stop_on_first_non_option { false };
  98. };
  99. }