Serenity Operating System
at master 124 lines 5.7 kB view raw
1/* 2 * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Concepts.h> 10#include <AK/DeprecatedString.h> 11#include <AK/Function.h> 12#include <AK/Vector.h> 13#include <LibMain/Main.h> 14#include <stdio.h> 15 16namespace Core { 17 18class ArgsParser { 19public: 20 ArgsParser(); 21 22 enum class Required { 23 Yes, 24 No 25 }; 26 27 enum class FailureBehavior { 28 PrintUsageAndExit, 29 PrintUsage, 30 Exit, 31 Ignore, 32 }; 33 34 enum class OptionArgumentMode { 35 None, 36 Optional, 37 Required, 38 }; 39 40 /// When an option is hidden. 41 /// If the hide mode is not None, then it's always hidden from the usage/synopsis. 42 enum class OptionHideMode { 43 None, 44 Markdown, 45 CommandLineAndMarkdown, 46 }; 47 48 struct Option { 49 OptionArgumentMode argument_mode { OptionArgumentMode::Required }; 50 char const* help_string { nullptr }; 51 char const* long_name { nullptr }; 52 char short_name { 0 }; 53 char const* value_name { nullptr }; 54 Function<bool(StringView)> accept_value; 55 OptionHideMode hide_mode { OptionHideMode::None }; 56 57 DeprecatedString name_for_display() const 58 { 59 if (long_name) 60 return DeprecatedString::formatted("--{}", long_name); 61 return DeprecatedString::formatted("-{:c}", short_name); 62 } 63 }; 64 65 struct Arg { 66 char const* help_string { nullptr }; 67 char const* name { nullptr }; 68 int min_values { 0 }; 69 int max_values { 1 }; 70 Function<bool(StringView)> accept_value; 71 }; 72 73 bool parse(Span<StringView> arguments, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit); 74 bool parse(Main::Arguments const& arguments, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit) 75 { 76 return parse(arguments.strings, failure_behavior); 77 } 78 79 // *Without* trailing newline! 80 void set_general_help(char const* help_string) { m_general_help = help_string; }; 81 void set_stop_on_first_non_option(bool stop_on_first_non_option) { m_stop_on_first_non_option = stop_on_first_non_option; } 82 void print_usage(FILE*, StringView argv0); 83 void print_usage_terminal(FILE*, StringView argv0); 84 void print_usage_markdown(FILE*, StringView argv0); 85 void print_version(FILE*); 86 87 void add_option(Option&&); 88 void add_ignored(char const* long_name, char short_name, OptionHideMode hide_mode = OptionHideMode::None); 89 void add_option(bool& value, char const* help_string, char const* long_name, char short_name, OptionHideMode hide_mode = OptionHideMode::None); 90 void add_option(DeprecatedString& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None); 91 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); 92 template<Integral I> 93 void add_option(I& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None); 94 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); 95 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); 96 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); 97 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); 98 // Note: This option is being used when we expect the user to use the same option 99 // multiple times (e.g. "program --option=example --option=anotherexample ..."). 100 void add_option(Vector<DeprecatedString>& values, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None); 101 102 void add_positional_argument(Arg&&); 103 void add_positional_argument(DeprecatedString& value, char const* help_string, char const* name, Required required = Required::Yes); 104 void add_positional_argument(StringView& value, char const* help_string, char const* name, Required required = Required::Yes); 105 void add_positional_argument(int& value, char const* help_string, char const* name, Required required = Required::Yes); 106 void add_positional_argument(unsigned& value, char const* help_string, char const* name, Required required = Required::Yes); 107 void add_positional_argument(double& value, char const* help_string, char const* name, Required required = Required::Yes); 108 void add_positional_argument(Vector<DeprecatedString>& value, char const* help_string, char const* name, Required required = Required::Yes); 109 void add_positional_argument(Vector<StringView>& value, char const* help_string, char const* name, Required required = Required::Yes); 110 111private: 112 void autocomplete(FILE*, StringView program_name, ReadonlySpan<StringView> remaining_arguments); 113 114 Vector<Option> m_options; 115 Vector<Arg> m_positional_args; 116 117 bool m_show_help { false }; 118 bool m_show_version { false }; 119 bool m_perform_autocomplete { false }; 120 char const* m_general_help { nullptr }; 121 bool m_stop_on_first_non_option { false }; 122}; 123 124}