mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
application.hpp
Go to the documentation of this file.
1 /** \file application.hpp
2  * \author Jared R. Males
3  * \brief A class for managing application configuration and execution
4  *
5  */
6 
7 //***********************************************************************//
8 // Copyright 2015, 2016, 2017, 2018 Jared R. Males (jaredmales@gmail.com)
9 //
10 // This file is part of mxlib.
11 //
12 // mxlib is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // mxlib is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
24 //***********************************************************************//
25 
26 #ifndef app_application_hpp
27 #define app_application_hpp
28 
29 
30 #include "appConfigurator.hpp"
31 #include "../ioutils/textTable.hpp"
32 
33 namespace mx
34 {
35 namespace app
36 {
37 
38 
39 /// A class for managing application configuration and execution
40 /** Derived classes should implement at a minimum
41  *
42  * \code
43  virtual void setupConfig();
44  virtual void loadConfig();
45  virtual int execute();
46  \endcode
47  *
48  * These are executed in the order shown by the call to \ref main().
49  *
50  * This class uses a cascaded configuration system. The application configuration is built up from the following sources, in increasing order of precedence:
51  * - A global configuration file
52  * - A user configuration file (which may be specified relative to the users home directory)
53  * - A local configuration file (in the pwd)
54  * - A configuration file specified on the command line
55  * - The command line
56  *
57  * At each step in the above order, values read from that configuration source override any previous settings. So the command line has the highest precedence.
58  *
59  * The configuration is set up and accessed using an object of type \ref appConfigurator named `config`.
60  * For specification of the configuration file syntax and command line arguments see \ref appConfigurator.
61  *
62  * The configuration should be set up in the \ref setupConfig function. This is normally done using
63  * the appConfigurator::add method, as in:
64  * \code
65  void derived_class::setupConfig()
66  {
67  config.add("name", "s", "long", argType::Required, "section", "keyword", false, "int", "help message");
68  }
69  \endcode
70  * The configuration is then accessed using the `config` member's operator as in
71  \code
72  void derived_class::loadConfig()
73  {
74  int val = 0;
75  config(val, "name");
76  }
77  \endcode
78  * In these examples, a config target with name "name" is created. If the user sets a value of 2
79  * via the command line with `-s 2`, `--long=2` or in a configuration file with
80  \verbatim
81  [section]
82  keyword=2
83  \endverbatim
84  then val will be set to 2. Otherwise, `val` will remain 0.
85  *
86  * Standard target `-h`/`--help` with name "help" to trigger printing a help message,
87  * and `-c`/`--config` with name "config" to pass a config file via the command line. This
88  * behavior can be changed by overriding functions.
89  *
90  * \note After loadConfig() but before execute(), the containers in \ref config are de-allocated , so they can not be used inside execute.
91  *
92  * A standard help message is produced when requested by the `-h`/`--help` option. This behavior can be changed
93  * by overriding the \ref help method.
94  *
95  * \ingroup mxApp
96  */
98 {
99 
100 protected:
101 
102  std::string invokedName; ///< The name used to invoke this application.
103 
104  std::string m_configPathGlobal; ///< The path to the gobal configuration file. Set in constructor to use.
105  std::string m_configPathGlobal_env; ///< Environment variable to check for the global config path. Set in constructor to use.
106  std::string m_configPathUser; ///< The path to the user's configuration file. If the first character is not '/' or '~', this is added to HOME. Set in constructor to use.
107  std::string m_configPathUser_env; ///< Environment variable to check fo the user config path. Set in constructor to use.
108  std::string m_configPathLocal; ///< The path to a local configuration file. Set in constructor to use.
109  std::string m_configPathLocal_env; ///< Environment variable to check for the local config path. Set in constructor to use.
110 
111  bool m_requireConfigPathLocal {true}; ///< Flag controlling whether lack of a local configuration file should be reported.
112 
113  std::string m_configPathCL; ///< The path to a configuration file specified on the command line.
114  std::string m_configPathCLBase; ///< A base path to add to the CL path. Set in constructor to use.
115  std::string m_configPathCLBase_env; ///< Environment variable to check for the CL base path. Set in constructor to use.
116 
117  appConfigurator config; ///< The structure used for parsing and storing the configuration.
118 
119  bool m_preserveConfig {false}; ///< Flag controlling whether the configuration is cleared before execution. Set in derived constructor.
120 
121  bool doHelp {false}; ///< Flag to control whether the help message is printed or not.
122 
123  int m_helpWidth {120} ; ///< The total text width available for the help message.
124  int m_helpSOColWidth {2}; ///< The width of the short option (-o) column in the help message.
125  int m_helpLOColWidth {25}; ///< The width of the long option (--option) column in the help message.
126  int m_helpCFColWidth {25}; ///< The width of the config file option column in the help message.
127  int m_helpTypeColWidth {15}; ///< The width of the argument type column in the help message.
128 
129  int m_argc; ///< Store argc for later use. E.g. in reReadConfig().
130  char ** m_argv; ///< Store argv for later use. E.g. in reReadConfig().
131 
132 public:
133  //application();
134 
135  virtual ~application();
136 
137  ///The application main function.
138  /** Call this from the true main function, passing the command line arguments to be processed.
139  * This calls \ref setup(), then checks if the doHelp flag was set. If so, it calls \ref help() and returns.
140  * If doHelp is not set, it then clears the config structure, and then calls \ref execute().
141  *
142  * The configuration is cleared before the call to execute, unless m_preserveConfig = true.
143  *
144  * \returns 1 if help is executed.
145  * \returns -1 on error.
146  * \returns the value of \ref execute() otherwise.
147  */
148  int main( int argc, ///< [in] standard command line result specifying number of argumetns in argv
149  char **argv ///< [in] standard command line result containing the arguments.
150  );
151 
152  ///Set the global configuration path
153  void setConfigPathGlobal(const std::string & s /**< [in] the new path */);
154 
155  ///Set the user configuration path
156  /** If the provided path does not star with a '/' or '~', then it will appended to
157  * the users HOME directory obtained from the environment.
158  */
159  void setConfigPathUser(const std::string & s /**< [in] the new path to the user config file*/);
160 
161  ///Set the local configuration path
162  void setConfigPathLocal( const std::string & s /**< [in] the new path */);
163 
164 protected:
165 
166  /** \name Required Overrides
167  * These methods should be implemented in derived classes to use an mx::application in its default behavior.
168  * @{
169  */
170 
171  ///In derived classes this is where the config targets are added to \ref config.
172  virtual void setupConfig();
173 
174  ///Override this function to extract the configured values and set up the application.
175  virtual void loadConfig();
176 
177  ///This function is where the derived class should do its work.
178  /** The application will exit with the return value of execute.
179  */
180  virtual int execute();
181 
182  ///@}
183 
184  /** \name Optional Overrides
185  * These methods do not need to be implemented in derived classes unless it is desired to change behavior.
186  * @{
187  */
188 
189  ///Sets up the application by executing the configuration steps
190  /** This is the key method which defines the mx::application configuration system.
191  * This will not normally need to be implemented by derived clasess --
192  * only do so if you intend to change the configuration process!
193  */
194  virtual void setup( int argc, ///< [in] standard command line result specifying number of argumetns in argv
195  char ** argv ///< [in] standard command line result containing the arguments.
196  );
197 
198 
199  ///Re-read the config stack.
200  /** This would be used if some config targets can only be constructed after
201  * a first pass. Note that all previously read values will be appended as if
202  * entered twice, so you must be careful to only access new targets
203  * after calling this.
204  *
205  * \returns 0 on success.
206  * \returns -1 on error.
207  */
208  int reReadConfig();
209 
210  ///Set the default search paths for config files
211  /** In general you should not need to redefine this.
212  *
213  * The comand line arguments are not used by the default version, but are parameters in
214  * case derived classes need access when overriding.
215  *
216  */
217  virtual void setDefaults( int argc, ///< [in] standard command line result specifying number of arguments in argv
218  char ** argv ///< [in] standard command line result containing the arguments.
219  );
220 
221 
222  ///Set up the command-line config option in a standard way.
223  /** This adds "-c --config" as command line options.
224  * You can override this function to change this behavior, or simply clear config
225  * at the beginning of \ref setupConfig(). If you do this, you should also override \ref loadStandardConfig().
226  */
227  virtual void setupStandardConfig();
228 
229  ///Set up the help an options in a standard way.
230  /** This adds "-h and --help" as command line options.
231  * You can override this function to change this behavior, or simply clear config
232  * at the beginning of \ref setupConfig(). If you do this, you should also override \ref loadStandardHelp().
233  */
234  virtual void setupStandardHelp();
235 
236  ///Loads the values of "config".
237  /** Override this function if you do not want to use this, or have different behavior.
238  * See also \ref setupStandardConfig().
239  */
240  virtual void loadStandardConfig();
241 
242  ///Loads the value of "help" into doHelp.
243  /** Override this function if you do not want to use this, or have different behavior.
244  * See also \ref setupStandardConfig().
245  */
246  virtual void loadStandardHelp();
247 
248  /// Format a configTarget for the help message.
249  virtual void optionHelp( configTarget & tgt, ///< [in] The Target
250  ioutils::textTable & tt ///< [out] the textTable being populated
251  );
252 
253  /// Setup a basic configuration. Can be used in an intermediate derived class to allow its children to use setupConfig.
254  /** This is called just before setupConfig().
255  */
256  virtual void setupBasicConfig();
257 
258  /// Load a basic configuration. Can be used in an intermediate derived class to allow its children to use loadConfig.
259  /** This is called just before loadConfig().
260  */
261  virtual void loadBasicConfig();
262 
263  /// Check the config. This is called at the end of setup, before the configuration is cleared.
264  /** It is up to you to decide how to handle the outcome. If a bad config results in printing help,
265  * you can set the doHelp flag.
266  */
267  virtual void checkConfig();
268 
269  ///Print a formatted help message, based on the config target inputs.
270  virtual void help();
271 
272  ///@}
273 
274 };
275 
276 
277 
278 
279 
280 } //namespace app
281 } //namespace mx
282 
283 #endif // app_application_hpp
284 
285 //Deprecations:
286 // Produce errors if older code is compiled which attempts to define-config the config:
287 
288 #ifdef MX_APP_DEFAULT_configPathGlobal
289  #error MX_APP_DEFAULT_configPathGlobal no longer works. Set m_configPathGlobal in constructor.
290 #endif
291 
292 #ifdef MX_APP_DEFAULT_configPathGlobal_env
293  #error MX_APP_DEFAULT_configPathGlobal_env no longer works. Set m_configPathGlobal_env in constructor.
294 #endif
295 
296 #ifdef MX_APP_DEFAULT_configPathUser
297  #error MX_APP_DEFAULT_configPathUser no longer works. Set m_configPathUser in constructor.
298 #endif
299 
300 #ifdef MX_APP_DEFAULT_configPathUser_env
301  #error MX_APP_DEFAULT_configPathUser_env no longer works. Set m_configPathUser_env in constructor.
302 #endif
303 
304 #ifdef MX_APP_DEFAULT_configPathLocal
305  #error MX_APP_DEFAULT_configPathLocal no longer works. Set m_configPathLocal in constructor.
306 #endif
307 
308 #ifdef MX_APP_DEFAULT_configPathLocal_env
309  #error MX_APP_DEFAULT_configPathLocal_env no longer works. Set m_configPathLocal_env in constructor.
310 #endif
311 
312  #ifdef MX_APP_DEFAULT_configPathCLBase_env
313  #error MX_APP_DEFAULT_configPathCLBase_env no longer works. Set m_configPathCLBase_env in constructor.
314 #endif
An application configuration manager.
A class for managing application configuration and execution.
Definition: application.hpp:98
virtual void setup(int argc, char **argv)
Sets up the application by executing the configuration steps.
Definition: application.cpp:92
std::string invokedName
The name used to invoke this application.
std::string m_configPathCLBase
A base path to add to the CL path. Set in constructor to use.
virtual void setupStandardConfig()
Set up the command-line config option in a standard way.
std::string m_configPathUser
The path to the user's configuration file. If the first character is not '/' or '~',...
std::string m_configPathUser_env
Environment variable to check fo the user config path. Set in constructor to use.
virtual void checkConfig()
Check the config. This is called at the end of setup, before the configuration is cleared.
virtual void setupStandardHelp()
Set up the help an options in a standard way.
bool doHelp
Flag to control whether the help message is printed or not.
virtual void loadBasicConfig()
Load a basic configuration. Can be used in an intermediate derived class to allow its children to use...
int reReadConfig()
Re-read the config stack.
virtual void loadStandardConfig()
Loads the values of "config".
int main(int argc, char **argv)
The application main function.
Definition: application.cpp:39
char ** m_argv
Store argv for later use. E.g. in reReadConfig().
virtual void loadConfig()
Override this function to extract the configured values and set up the application.
Definition: application.cpp:82
int m_argc
Store argc for later use. E.g. in reReadConfig().
void setConfigPathUser(const std::string &s)
Set the user configuration path.
Definition: application.cpp:67
std::string m_configPathLocal_env
Environment variable to check for the local config path. Set in constructor to use.
int m_helpLOColWidth
The width of the long option (–option) column in the help message.
int m_helpCFColWidth
The width of the config file option column in the help message.
bool m_preserveConfig
Flag controlling whether the configuration is cleared before execution. Set in derived constructor.
int m_helpTypeColWidth
The width of the argument type column in the help message.
appConfigurator config
The structure used for parsing and storing the configuration.
bool m_requireConfigPathLocal
Flag controlling whether lack of a local configuration file should be reported.
int m_helpWidth
The total text width available for the help message.
virtual void optionHelp(configTarget &tgt, ioutils::textTable &tt)
Format a configTarget for the help message.
virtual void setDefaults(int argc, char **argv)
Set the default search paths for config files.
virtual void help()
Print a formatted help message, based on the config target inputs.
virtual void setupBasicConfig()
Setup a basic configuration. Can be used in an intermediate derived class to allow its children to us...
virtual int execute()
This function is where the derived class should do its work.
Definition: application.cpp:87
std::string m_configPathCL
The path to a configuration file specified on the command line.
std::string m_configPathGlobal
The path to the gobal configuration file. Set in constructor to use.
virtual void loadStandardHelp()
Loads the value of "help" into doHelp.
std::string m_configPathGlobal_env
Environment variable to check for the global config path. Set in constructor to use.
void setConfigPathGlobal(const std::string &s)
Set the global configuration path.
Definition: application.cpp:62
virtual void setupConfig()
In derived classes this is where the config targets are added to config.
Definition: application.cpp:77
int m_helpSOColWidth
The width of the short option (-o) column in the help message.
std::string m_configPathLocal
The path to a local configuration file. Set in constructor to use.
std::string m_configPathCLBase_env
Environment variable to check for the CL base path. Set in constructor to use.
void setConfigPathLocal(const std::string &s)
Set the local configuration path.
Definition: application.cpp:72
The mxlib c++ namespace.
Definition: mxError.hpp:107
Class to manage a set of configurable values, and read their values from config/ini files and the com...
A configuration target.
An ascii table formatter.
Definition: textTable.hpp:61