Apply clang-format to source tree
[alexxy/gromacs.git] / src / gromacs / commandline / cmdlineoptionsmodule.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014,2015,2017,2019, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief
37  * Declares gmx::ICommandLineOptionsModule and supporting routines.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_commandline
42  */
43 #ifndef GMX_COMMANDLINE_CMDLINEOPTIONSMODULE_H
44 #define GMX_COMMANDLINE_CMDLINEOPTIONSMODULE_H
45
46 #include <functional>
47 #include <memory>
48
49 #include "gromacs/commandline/cmdlinemodule.h"
50
51 namespace gmx
52 {
53
54 template<typename T>
55 class ArrayRef;
56
57 class CommandLineModuleManager;
58 class ICommandLineModule;
59 class ICommandLineOptionsModule;
60 class IOptionsBehavior;
61 class IOptionsContainer;
62
63 //! Smart pointer to manage an ICommandLineOptionsModule.
64 typedef std::unique_ptr<ICommandLineOptionsModule> ICommandLineOptionsModulePointer;
65
66 /*! \brief
67  * Settings to pass information between a CommandLineOptionsModule and generic
68  * code that runs it.
69  *
70  * \inpublicapi
71  * \ingroup module_commandline
72  */
73 class ICommandLineOptionsModuleSettings
74 {
75 public:
76     /*! \brief
77      * Sets the help text for the module from string array.
78      *
79      * \param[in] help  String array to set as the description.
80      * \throws    std::bad_alloc if out of memory.
81      *
82      * Formatting for the help text is described on \ref page_onlinehelp.
83      *
84      * Example usage:
85      * \code
86        const char *const desc[] = {
87            "This is the description",
88            "for the options"
89        };
90
91        settings->setHelpText(desc);
92        \endcode
93      */
94     virtual void setHelpText(const ArrayRef<const char* const>& help) = 0;
95     /*! \brief
96      * Set text indicating buggy behaviour of a module from string array.
97      *
98      * \param[in] bug String array to set as the bug text.
99      * \throws    std::bad_alloc if out of memory.
100      *
101      * Formatting for the text is described on \ref page_onlinehelp.
102      */
103     virtual void setBugText(const ArrayRef<const char* const>& bug) = 0;
104     /*! \brief
105      * Adds an option behavior that performs actions before
106      * ICommandLineOptionsModule::run() is called.
107      *
108      * For now, this takes a shared_ptr to make it easier for the caller to
109      * keep a reference to the behavior, but the behavior should be treated
110      * as owned by the options module after this call.
111      */
112     virtual void addOptionsBehavior(const std::shared_ptr<IOptionsBehavior>& behavior) = 0;
113
114 protected:
115     // Disallow deletion through the interface.
116     // (no need for the virtual, but some compilers warn otherwise)
117     virtual ~ICommandLineOptionsModuleSettings();
118 };
119
120 /*! \brief
121  * Module that can be run from a command line and uses gmx::Options for
122  * argument processing.
123  *
124  * This class provides a higher-level interface on top of
125  * gmx::ICommandLineModule for cases where gmx::Options will be used
126  * for declaring the command-line arguments.  The module only needs to declare
127  * the options it uses, and the framework takes care of command-line parsing
128  * and help output.  The module typically consists of the following parts:
129  *  - init() allows for some interaction between the module and the framework
130  *    when running the module; see ICommandLineModule::init().  If no
131  *    such customization is necessary, an empty implementation is sufficient.
132  *  - initOptions() is called both for running the module and for printing help
133  *    for the module, and it should add the options that the module
134  *    understands.  Values provided for the options are typically stored in
135  *    member variables.
136  *  - optionsFinished() can be implemented in case additional processing is
137  *    needed (e.g., checking whether an option was set by the user).
138  *  - run() is called when running the module, after command-line options have
139  *    been parsed and their values stored in the corresponding member
140  *    variables.
141  *
142  * registerModule(), runAsMain(), or createModule() can be used to use modules
143  * of this type in all contexts where a gmx::ICommandLineModule is
144  * expected.  These methods create a gmx::ICommandLineModule
145  * implementation that contains the common code needed to parse command-line
146  * options and write help, based on the information provided from the methods
147  * in this class.
148  *
149  * \inpublicapi
150  * \ingroup module_commandline
151  */
152 class ICommandLineOptionsModule
153 {
154 public:
155     /*! \brief
156      * Function pointer to a factory method that returns an interface of
157      * this type.
158      *
159      * \returns Module to run.
160      * \throws  std::bad_alloc if out of memory.
161      */
162     typedef std::function<ICommandLineOptionsModulePointer()> FactoryMethod;
163
164     /*! \brief
165      * Creates a ICommandLineModule to run the specified module.
166      *
167      * \param[in] name        Name for the module.
168      * \param[in] description Short description for the module.
169      * \param[in] module      Module to run.
170      * \returns ICommandLineModule object that runs \p module module.
171      * \throws  std::bad_alloc if out of memory.
172      */
173     static std::unique_ptr<ICommandLineModule> createModule(const char* name,
174                                                             const char* description,
175                                                             ICommandLineOptionsModulePointer module);
176     /*! \brief
177      * Implements a main() method that runs a single module.
178      *
179      * \param     argc    \c argc passed to main().
180      * \param     argv    \c argv passed to main().
181      * \param[in] name        Name for the module.
182      * \param[in] description Short description for the module.
183      * \param[in] factory     Factory that returns the module to run.
184      *
185      * This method allows for uniform behavior for binaries that only
186      * contain a single module without duplicating any of the
187      * implementation from CommandLineModuleManager (startup headers,
188      * common options etc.).
189      *
190      * \see runCommandLineModule()
191      */
192     static int runAsMain(int argc, char* argv[], const char* name, const char* description, FactoryMethod factory);
193     /*! \brief
194      * Registers a module of a certain type to this manager.
195      *
196      * \param     manager     Manager to register to.
197      * \param[in] name        Name for the module.
198      * \param[in] description Short description for the module.
199      * \param[in] factory     Factory that returns the module to register.
200      * \throws  std::bad_alloc if out of memory.
201      *
202      * This method internally creates a ICommandLineModule module
203      * with the given \p name and \p description, and adds that to
204      * \p manager.  When run or asked to write the help, the module calls
205      * \p factory to get the actual module, and forwards the necessary
206      * calls.
207      */
208     static void registerModuleFactory(CommandLineModuleManager* manager,
209                                       const char*               name,
210                                       const char*               description,
211                                       FactoryMethod             factory);
212     /*! \brief
213      * Registers a module to this manager.
214      *
215      * \param     manager     Manager to register to.
216      * \param[in] name        Name for the module.
217      * \param[in] description Short description for the module.
218      * \param[in] module      Module to register.
219      * \throws  std::bad_alloc if out of memory.
220      *
221      * This method internally creates a ICommandLineModule module
222      * with the given \p name and \p description, and adds that to
223      * \p manager.
224      *
225      * This method is mainly used by tests that need to have a reference to
226      * the ICommandLineOptionsModule instance (e.g., for mocking).
227      */
228     static void registerModuleDirect(CommandLineModuleManager*        manager,
229                                      const char*                      name,
230                                      const char*                      description,
231                                      ICommandLineOptionsModulePointer module);
232
233     virtual ~ICommandLineOptionsModule();
234
235     //! \copydoc gmx::ICommandLineModule::init()
236     virtual void init(CommandLineModuleSettings* settings) = 0;
237     /*! \brief
238      * Initializes command-line arguments understood by the module.
239      *
240      * \param[in,out] options  Options object to add the options to.
241      * \param[in,out] settings Settings to communicate information
242      *     to/from generic code running the module.
243      *
244      * When running the module, this method is called after init().
245      * When printing help, there is no call to init(), and this is the only
246      * method called.
247      * In both cases, the implementation should add options understood by
248      * the module to \p options.  Output values from options should be
249      * stored in member variables.
250      */
251     virtual void initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings) = 0;
252     /*! \brief
253      * Called after all option values have been set.
254      *
255      * When running the module, this method is called after all
256      * command-line arguments have been parsed.
257      */
258     virtual void optionsFinished() = 0;
259
260     /*! \brief
261      * Runs the module.
262      *
263      * \throws   unspecified  May throw exceptions to indicate errors.
264      * \returns  Exit code for the program.
265      * \retval   0 on successful termination.
266      *
267      * This method is called after optionsFinished() when running the
268      * module, and should do all the processing for the module.
269      */
270     virtual int run() = 0;
271 };
272
273 } // namespace gmx
274
275 #endif