| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |  * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org> | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-13 05:31:23 -07:00
										 |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  | #include <AK/Function.h>
 | 
					
						
							| 
									
										
										
										
											2019-09-06 15:34:26 +02:00
										 |  |  | #include <AK/String.h>
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:35:30 +02:00
										 |  |  | #include <AK/Vector.h>
 | 
					
						
							| 
									
										
										
										
											2021-11-22 19:01:31 -05:00
										 |  |  | #include <LibMain/Main.h>
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2019-05-13 05:31:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | namespace Core { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ArgsParser { | 
					
						
							| 
									
										
										
										
											2019-05-17 12:46:51 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     ArgsParser(); | 
					
						
							| 
									
										
										
										
											2019-05-13 05:31:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     enum class Required { | 
					
						
							|  |  |  |         Yes, | 
					
						
							|  |  |  |         No | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2019-05-13 05:31:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 01:11:56 +02:00
										 |  |  |     enum class FailureBehavior { | 
					
						
							|  |  |  |         PrintUsageAndExit, | 
					
						
							|  |  |  |         PrintUsage, | 
					
						
							|  |  |  |         Exit, | 
					
						
							|  |  |  |         Ignore, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     struct Option { | 
					
						
							|  |  |  |         bool requires_argument { true }; | 
					
						
							|  |  |  |         const char* help_string { nullptr }; | 
					
						
							|  |  |  |         const char* long_name { nullptr }; | 
					
						
							|  |  |  |         char short_name { 0 }; | 
					
						
							|  |  |  |         const char* value_name { nullptr }; | 
					
						
							|  |  |  |         Function<bool(const char*)> accept_value; | 
					
						
							| 
									
										
										
										
											2019-05-13 05:31:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |         String name_for_display() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (long_name) | 
					
						
							| 
									
										
										
										
											2021-04-21 23:36:31 +02:00
										 |  |  |                 return String::formatted("--{}", long_name); | 
					
						
							|  |  |  |             return String::formatted("-{:c}", short_name); | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2019-05-13 05:31:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     struct Arg { | 
					
						
							|  |  |  |         const char* help_string { nullptr }; | 
					
						
							|  |  |  |         const char* name { nullptr }; | 
					
						
							|  |  |  |         int min_values { 0 }; | 
					
						
							|  |  |  |         int max_values { 1 }; | 
					
						
							|  |  |  |         Function<bool(const char*)> accept_value; | 
					
						
							| 
									
										
										
										
											2019-05-13 05:31:23 -07:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2019-05-17 12:46:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 01:11:56 +02:00
										 |  |  |     bool parse(int argc, char* const* argv, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit); | 
					
						
							| 
									
										
										
										
											2021-11-22 19:01:31 -05:00
										 |  |  |     bool parse(Main::Arguments const& arguments, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return parse(arguments.argc, arguments.argv, failure_behavior); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 15:54:27 +01:00
										 |  |  |     // *Without* trailing newline!
 | 
					
						
							|  |  |  |     void set_general_help(const char* help_string) { m_general_help = help_string; }; | 
					
						
							| 
									
										
										
										
											2021-06-07 21:20:35 +02:00
										 |  |  |     void set_stop_on_first_non_option(bool stop_on_first_non_option) { m_stop_on_first_non_option = stop_on_first_non_option; } | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     void print_usage(FILE*, const char* argv0); | 
					
						
							| 
									
										
										
										
											2021-10-23 13:22:06 +02:00
										 |  |  |     void print_usage_terminal(FILE*, const char* argv0); | 
					
						
							|  |  |  |     void print_usage_markdown(FILE*, const char* argv0); | 
					
						
							| 
									
										
										
										
											2021-08-14 18:50:52 -04:00
										 |  |  |     void print_version(FILE*); | 
					
						
							| 
									
										
										
										
											2019-05-17 12:46:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     void add_option(Option&&); | 
					
						
							| 
									
										
										
										
											2021-10-23 13:44:04 +02:00
										 |  |  |     void add_ignored(const char* long_name, char short_name); | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     void add_option(bool& value, const char* help_string, const char* long_name, char short_name); | 
					
						
							|  |  |  |     void add_option(const char*& value, const char* help_string, const char* long_name, char short_name, const char* value_name); | 
					
						
							| 
									
										
										
										
											2021-04-17 20:39:32 +02:00
										 |  |  |     void add_option(String& value, const char* help_string, const char* long_name, char short_name, const char* value_name); | 
					
						
							| 
									
										
										
										
											2021-06-01 09:01:31 +02:00
										 |  |  |     void add_option(StringView& value, char const* help_string, char const* long_name, char short_name, char const* value_name); | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     void add_option(int& value, const char* help_string, const char* long_name, char short_name, const char* value_name); | 
					
						
							| 
									
										
										
										
											2021-07-06 18:18:10 +02:00
										 |  |  |     void add_option(unsigned& value, const char* help_string, const char* long_name, char short_name, const char* value_name); | 
					
						
							| 
									
										
										
										
											2020-11-05 15:57:22 -05:00
										 |  |  |     void add_option(double& value, const char* help_string, const char* long_name, char short_name, const char* value_name); | 
					
						
							| 
									
										
										
										
											2019-05-17 15:17:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     void add_positional_argument(Arg&&); | 
					
						
							|  |  |  |     void add_positional_argument(const char*& value, const char* help_string, const char* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2021-03-05 21:38:06 +02:00
										 |  |  |     void add_positional_argument(String& value, const char* help_string, const char* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2021-06-01 09:01:31 +02:00
										 |  |  |     void add_positional_argument(StringView& value, char const* help_string, char const* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     void add_positional_argument(int& value, const char* help_string, const char* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2021-07-06 18:18:10 +02:00
										 |  |  |     void add_positional_argument(unsigned& value, const char* help_string, const char* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2020-07-25 20:23:05 +03:00
										 |  |  |     void add_positional_argument(double& value, const char* help_string, const char* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  |     void add_positional_argument(Vector<const char*>& value, const char* help_string, const char* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2021-11-26 22:09:09 +01:00
										 |  |  |     void add_positional_argument(Vector<StringView>& value, char const* help_string, char const* name, Required required = Required::Yes); | 
					
						
							| 
									
										
										
										
											2020-01-27 20:19:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Vector<Option> m_options; | 
					
						
							|  |  |  |     Vector<Arg> m_positional_args; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool m_show_help { false }; | 
					
						
							| 
									
										
										
										
											2021-08-14 13:34:34 -04:00
										 |  |  |     bool m_show_version { false }; | 
					
						
							| 
									
										
										
										
											2020-12-05 15:54:27 +01:00
										 |  |  |     const char* m_general_help { nullptr }; | 
					
						
							| 
									
										
										
										
											2021-06-07 21:20:35 +02:00
										 |  |  |     bool m_stop_on_first_non_option { false }; | 
					
						
							| 
									
										
										
										
											2019-05-17 12:46:51 +02:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | } |