lib/config: fix doc
[nit.git] / lib / config.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Configuration options for nit tools and apps
16 #
17 # This module provides basic services for options handling in your Nit programs.
18 #
19 # ## Basic configuration holder
20 #
21 # The `Config` class can be used as a simple option holder and processor:
22 #
23 # ~~~
24 # import config
25 #
26 # # Create a new config option
27 # var opt_my = new OptionString("My option", "--my")
28 #
29 # # Create the config and add the option
30 # var config = new Config
31 # config.add_option(opt_my)
32 #
33 # # Parse the program arguments, usually `args`
34 # config.parse_options(["--my", "myOption", "arg1", "arg2"])
35 #
36 # # Access the options and args
37 # assert opt_my.value == "myOption"
38 # assert config.args == ["arg1", "arg2"]
39 # ~~~
40 #
41 # ## Custom configuration class
42 #
43 # Instead of using basic `Config` instances, it is better to define new sublcasses
44 # to store options and define custom services.
45 #
46 # ~~~
47 # import config
48 #
49 # class MyConfig
50 # super Config
51 #
52 # var opt_my = new OptionString("My option", "--my")
53 #
54 # init do
55 # super
56 # tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
57 # add_option(opt_my)
58 # end
59 #
60 # fun my: String do return opt_my.value or else "Default value"
61 # end
62 #
63 # var config = new MyConfig
64 # config.parse_options(["--my", "myOption", "arg1", "arg2"])
65 #
66 # assert config.my == "myOption"
67 # assert config.args == ["arg1", "arg2"]
68 # ~~~
69 #
70 # We define the `my` method to provide an elegant shortcut to `opt_my.value`
71 # and define the default value if the option was not set by the user.
72 #
73 # The `tool_description` attribute is used to set the `usage` header printed when
74 # the user request the `help` message.
75 #
76 # ~~~
77 # config.parse_options(["-h"])
78 # if config.help then
79 # config.usage
80 # exit 0
81 # end
82 # ~~~
83 #
84 # This will display the tool usage like this:
85 #
86 # ~~~raw
87 # Usage: MyExample [OPTION]... [ARGS]...
88 # -h, --help Show this help message
89 # --my My option
90 # ~~~
91 #
92 # ## Configuration with `ini` file
93 #
94 # The `IniConfig` class extends `Config` to add an easy way to link your
95 # configuration to an ini file.
96 #
97 # ~~~
98 # class MyIniConfig
99 # super IniConfig
100 #
101 # var opt_my = new OptionString("My option", "--my")
102 #
103 # init do
104 # super
105 # tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
106 # opts.add_option(opt_my)
107 # end
108 #
109 # fun my: String do return opt_my.value or else ini["my"] or else "Default"
110 # end
111 # ~~~
112 #
113 # This time, we define the `my` method to return the option value or the ini
114 # if no option was passed. Finally, if no ini value can be found, we return the
115 # default value.
116 #
117 # By default, `IniConfig` looks at a `config.ini` file in the execution directory.
118 # This can be overrided in multiple ways.
119 #
120 # First by the app user by setting the `--config` option:
121 #
122 # ~~~
123 # var config = new MyIniConfig
124 # config.parse_options(["--config", "my_config.ini"])
125 #
126 # assert config.config_file == "my_config.ini"
127 # ~~~
128 #
129 # Default config file can also be changed by the library client through the
130 # `default_config_file` attribute:
131 #
132 # ~~~
133 # config = new MyIniConfig
134 # config.default_config_file = "my_config.ini"
135 # config.parse_options(["arg"])
136 #
137 # assert config.config_file == "my_config.ini"
138 # ~~~
139 #
140 # Or by the library developper in the custom config class:
141 #
142 # ~~~
143 # class MyCustomIniConfig
144 # super IniConfig
145 #
146 # redef var default_config_file = "my_config.ini"
147 # end
148 #
149 # var config = new MyCustomIniConfig
150 # config.parse_options(["arg"])
151 #
152 # assert config.config_file == "my_config.ini"
153 # ~~~
154 module config
155
156 import ini
157 import opts
158
159 # Basic configuration class
160 #
161 # ~~~
162 # import config
163 #
164 # class MyConfig
165 # super Config
166 #
167 # var opt_my = new OptionString("My option", "--my")
168 #
169 # init do
170 # super
171 # tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
172 # opts.add_option(opt_my)
173 # end
174 #
175 # fun my: String do return opt_my.value or else "Default value"
176 # end
177 #
178 # var config = new MyConfig
179 # config.parse_options(["--my", "hello", "arg1", "arg2"])
180 # assert config.my == "hello"
181 # assert config.args == ["arg1", "arg2"]
182 # ~~~
183 class Config
184
185 # Context used to store and parse options
186 var opts = new OptionContext
187
188 # Help option
189 var opt_help = new OptionBool("Show this help message", "-h", "--help")
190
191 # Redefine this init to add your options
192 init do
193 add_option(opt_help)
194 end
195
196 # Add an option to `self`
197 #
198 # Shortcut to `opts.add_option`.
199 fun add_option(opt: Option...) do opts.add_option(opt...)
200
201 # Initialize `self` options from `args`
202 fun parse_options(args: Collection[String]) do
203 opts.parse(args)
204 end
205
206 # Return the remaining args once options are parsed by `from_args`
207 fun args: Array[String] do return opts.rest
208
209 # Name, usage and synopsis of the tool.
210 # It is mainly used in `usage`.
211 # Should be correctly set by the client before calling `usage`
212 # A multi-line string is recommended.
213 #
214 # eg. `"Usage: tool [OPTION]... [FILE]...\nDo some things."`
215 var tool_description: String = "Usage: [OPTION]... [ARG]..." is writable
216
217 # Was the `--help` option requested?
218 fun help: Bool do return opt_help.value
219
220 # Display `tool_description` and options usage in console
221 fun usage do
222 print tool_description
223 opts.usage
224 end
225 end
226
227 # Configuration class based on a INI file.
228 #
229 # ~~~
230 # class MyIniConfig
231 # super IniConfig
232 #
233 # var opt_my = new OptionString("My option", "--my")
234 #
235 # init do
236 # super
237 # tool_description = "Usage: MyExample [OPTION]... [ARGS]..."
238 # opts.add_option(opt_my)
239 # end
240 #
241 # fun my: String do return opt_my.value or else ini["my"] or else "Default"
242 # end
243 #
244 # var config = new MyIniConfig
245 # config.default_config_file = "my_config.ini"
246 # config.parse_options(args)
247 #
248 # if config.help then
249 # config.usage
250 # exit 0
251 # end
252 #
253 # assert config.my == "Default"
254 # ~~~
255 class IniConfig
256 super Config
257
258 # Config tree used to store config options
259 var ini: ConfigTree is noinit
260
261 # Path to app config file
262 var opt_config = new OptionString("Path to config file", "--config")
263
264 init do
265 super
266 opts.add_option(opt_config)
267 end
268
269 redef fun parse_options(args) do
270 super
271 ini = new ConfigTree(config_file)
272 end
273
274 # Default config file path
275 var default_config_file = "config.ini" is writable
276
277 # Return the config file path from options or the default
278 fun config_file: String do return opt_config.value or else default_config_file
279 end