]> git.armaanb.net Git - gen-shell.git/blob - src/Sarge/README.md
added argument parsing with Sarge
[gen-shell.git] / src / Sarge / README.md
1 # Sarge #\r
2 \r
3 Sarge is a simple and powerful command line argument parser, with the C++ version consisting out of <200 lines of well-commented C++ code, contained in a single class:\r
4 \r
5 \r
6         -------------------------------------------------------------------------------\r
7         Language                     files          blank        comment           code\r
8         -------------------------------------------------------------------------------\r
9         C++                              1             42             41            116\r
10         C/C++ Header                     1             12              7             35\r
11         -------------------------------------------------------------------------------\r
12         SUM:                             2             54             48            151\r
13         -------------------------------------------------------------------------------\r
14 \r
15  \r
16 \r
17 Simply add the header file and source file to one's C++ project and use the class as in the project's test code:\r
18 \r
19     #include "../src/sarge.h"\r
20         \r
21         #include <iostream>\r
22         \r
23         \r
24         int main(int argc, char** argv) {\r
25                 Sarge sarge;\r
26                 \r
27                 sarge.setArgument("h", "help", "Get help.", false);\r
28                 sarge.setArgument("k", "kittens", "K is for kittens. Everyone needs kittens in their life.", true);\r
29                 sarge.setArgument("n", "number", "Gimme a number. Any number.", true);\r
30                 sarge.setArgument("a", "apple", "Just an apple.", false);\r
31                 sarge.setArgument("b", "bear", "Look, it's a bear.", false);\r
32                 sarge.setArgument("", "snake", "Snakes only come in long form, there are no short snakes.", false);\r
33                 sarge.setDescription("Sarge command line argument parsing testing app. For demonstration purposes and testing.");\r
34                 sarge.setUsage("sarge_test <options>");\r
35                 \r
36                 if (!sarge.parseArguments(argc, argv)) {\r
37                         std::cerr << "Couldn't parse arguments..." << std::endl;\r
38                         return 1;\r
39                 }\r
40                 \r
41                 std::cout << "Number of flags found: " << sarge.flagCount() << std::endl;\r
42                 \r
43                 if (sarge.exists("help")) {\r
44                         sarge.printHelp();\r
45                 }\r
46                 else {\r
47                         std::cout << "No help requested..." << std::endl;\r
48                 }\r
49                 \r
50                 std::string kittens;\r
51                 if (sarge.getFlag("kittens", kittens)) {\r
52                         std::cout << "Got kittens: " << kittens << std::endl;\r
53                 }\r
54 \r
55                 std::string textarg;\r
56                 if (sarge.getTextArgument(0, textarg)) {\r
57                         std::cout << "Got text argument: " << textarg << std::endl;\r
58                 }\r
59                 \r
60                 return 0;\r
61         }\r
62 \r
63 Only dependencies are a reasonably modern C++ compiler, capable of supporting at least C++11 (STL datastructure improvements).\r
64 \r
65 ## API ##\r
66 \r
67         void setArgument(std::string arg_short, std::string arg_long, std::string desc, bool hasVal);\r
68         void setArguments(std::vector<Argument> args);\r
69         void setDescription(std::string desc);\r
70         void setUsage(std::string use);\r
71         bool parseArguments(int argc, char** argv);\r
72         bool getFlag(std::string arg_flag, std::string &arg_value);\r
73         bool exists(std::string arg_flag);\r
74         bool getTextArgument(uint32_t index, std::string &value);\r
75         void printHelp();\r
76         int flagCount();\r
77         std::string executableName();\r
78 \r
79 ## Supported flag types ##\r
80 \r
81 Sarge supports both short and long options, prefixed by one or two dashes ('-') respectively. The short option can be left empty, which will only enable the long option.\r
82 \r
83 Short option: `-h`.\r
84 \r
85 Long option: `--help`.\r
86 \r
87 Options can optionally be followed by a value string. This has to be noted when registering the flag with Sarge in one's code. \r
88 \r
89 It's also supported to supply multiple short options combined to Sarge, e.g.: `-hnklm`. Important here is that options which require a value to follow them have to always be at the end of such a chain.\r
90 \r
91 String without flag associated with them are made available using the `getTextArgument()` method after parsing. These arguments are only allowed to exist after the flags section.\r
92 \r
93 ## Compiling the test application ##\r
94 \r
95 A Makefile has been added to the root of the project. Simply execute `make` in the folder to compile the test binary into the `bin/` folder. Execute `bin/sarge_test` to get the following output:\r
96 \r
97         # ./bin/sarge_test.exe -hk Mew\r
98         Number of flags found: 2\r
99         \r
100         Sarge command line argument parsing testing app. For demonstration purposes and testing.\r
101         \r
102         Usage:\r
103                 sarge_test <options>\r
104         \r
105         Options:\r
106         -h, --help      Get help.\r
107         -k, --kittens   K is for kittens. Everyone needs kittens in their life.\r
108         -n, --number    Gimme a number. Any number.\r
109         -a, --apple     Just an apple.\r
110         -b, --bear      Look, it's a bear.\r
111             --snake     Snakes only come in long form, there are no short snakes.\r
112 \r
113 \r
114 As you can see, no kittens were harmed in the production of this code :)\r
115 \r
116 # Ada version #\r
117 \r
118 The Ada version of Sarge (found in the `ada/` folder) is pretty much a straight port of the C++ version. It consists out of a single package (Sarge), with <200 lines of code. \r
119 \r
120         -------------------------------------------------------------------------------\r
121         Language                     files          blank        comment           code\r
122         -------------------------------------------------------------------------------\r
123         Ada                              2             58             44            197\r
124         -------------------------------------------------------------------------------\r
125         SUM:                             2             58             44            197\r
126         -------------------------------------------------------------------------------\r
127 \r
128 \r
129 Its biggest limitation compared to the C++ version at this point is that one cannot use multiple instances of Sarge since the relevant data structures are part of the package. This should not pose any issues in the average usage scenario, however.\r
130 \r
131 \r
132 ## API ##\r
133 \r
134         procedure setArgument(arg_short: in Unbounded_String; arg_long: in Unbounded_String; desc: in Unbounded_String; hasVal: in boolean);\r
135         procedure setDescription(desc: in Unbounded_String);\r
136         procedure setUsage(usage: in Unbounded_String);\r
137         function parseArguments return boolean;\r
138         function getFlag(arg_flag: in Unbounded_String; arg_value: out Unbounded_String) return boolean;\r
139         function exists(arg_flag: in Unbounded_String) return boolean;\r
140         function getTextArgument(index: in Integer; value: out Unbounded_String) return boolean;\r
141         procedure printHelp;\r
142         function flagCount return integer;\r
143         function executableName return Unbounded_String;\r
144 \r
145 ## Example ##\r
146 \r
147 The test application has also been ported from the C++ version, showing the use of the package:\r
148 \r
149         with Sarge;\r
150         with Ada.Text_IO;\r
151         use Ada.Text_IO;\r
152         with Ada.Strings.Unbounded;\r
153         use Ada.Strings.Unbounded;\r
154         with Ada.Strings.Unbounded.Text_IO;\r
155         use Ada.Strings.Unbounded.Text_IO;\r
156 \r
157 \r
158         procedure Sarge_Test is\r
159 \r
160         function "+"(S : in String) return Unbounded_String renames Ada.Strings.Unbounded.To_Unbounded_String;\r
161 \r
162         kittens: Unbounded_String;\r
163         number: Unbounded_String;\r
164 \r
165         begin\r
166            Sarge.setArgument(+"h", +"help", +"Get help.", False);\r
167                 Sarge.setArgument(+"k", +"kittens", +"K is for kittens. Everyone needs kittens in their life.", True);\r
168                 Sarge.setArgument(+"n", +"number", +"Gimme a number. Any number.", True);\r
169                 Sarge.setArgument(+"a", +"apple", +"Just an apple.", False);\r
170                 Sarge.setArgument(+"b", +"bear", +"Look, it's a bear.", False);\r
171                 Sarge.setArgument(+"", +"snake", +"Snakes only come in long form, there are no short snakes.", False);\r
172                         Sarge.setDescription(+"Sarge command line argument parsing testing app. For demonstration purposes and testing.");\r
173                 Sarge.setUsage(+"sarge_test <options>");\r
174 \r
175                 if Sarge.parseArguments /= True then\r
176                         put_line("Couldn't parse arguments...");\r
177                         return;\r
178                 end if;\r
179 \r
180                 put_line("Number of flags found: " & Sarge.flagCount'Image);\r
181 \r
182                 if Sarge.exists(+"help") /= False then\r
183                         Sarge.printHelp;\r
184                 else\r
185                         put_line("No help requested...");\r
186                 end if;\r
187 \r
188                 -- Read out Kittens and Number.\r
189                 if Sarge.getFlag(+"kittens", kittens) = True then\r
190                         put_line("Got kittens: " & kittens);\r
191                 end if;\r
192 \r
193                 if Sarge.getFlag(+"number", number) = True then\r
194                         put_line("Got number: " & number);\r
195                 end if;\r
196 \r
197                 if Sarge.getTextArgument(0, textarg) = True then\r
198                         put_line("Got text argument: " & textarg);\r
199                 end if;\r
200 \r
201         end Sarge_Test; \r
202 \r
203 The Makefile in the `ada` folder should be used when compiling the test application. The Gnat Programming Studio project file is currently not maintained. \r
204 \r
205 The Sarge package is found in the `ada/src` folder. One can use it directly from there by including it one's project, or copying it into the project's source tree, depending on one's requirements.\r
206 \r
207 \r