ctkCommandLineParser.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. #ifndef __ctkCommandLineParser_h
  15. #define __ctkCommandLineParser_h
  16. // Qt includes
  17. #include <QString>
  18. #include <QStringList>
  19. #include <QVariant>
  20. class QSettings;
  21. // CTK includes
  22. #include "ctkCoreExport.h"
  23. /**
  24. * \ingroup Core
  25. *
  26. * The CTK command line parser.
  27. *
  28. * Use this class to add information about the command line arguments
  29. * your program understands and to easily parse them from a given list
  30. * of strings.
  31. *
  32. * This parser provides the following features:
  33. *
  34. * <ul>
  35. * <li>Add arguments by supplying a long name and/or a short name.
  36. * Arguments are validated using a regular expression. They can have
  37. * a default value and a help string.</li>
  38. * <li>Deprecated arguments.</li>
  39. * <li>Custom regular expressions for argument validation.</li>
  40. * <li>Set different argument name prefixes for native platform look and feel.</li>
  41. * <li>QSettings support. Default values for arguments can be read from
  42. * a QSettings object.</li>
  43. * <li>Create a help text for the command line arguments with support for
  44. * grouping arguments.</li>
  45. * </ul>
  46. *
  47. * Here is an example how to use this class inside a main function:
  48. *
  49. * \code
  50. * #include <ctkCommandLineParser.h>
  51. * #include <QCoreApplication>
  52. * #include <QTextStream>
  53. *
  54. * int main(int argc, char** argv)
  55. * {
  56. * QCoreApplication app(argc, argv);
  57. * // This is used by QSettings
  58. * QCoreApplication::setOrganizationName("MyOrg");
  59. * QCoreApplication::setApplicationName("MyApp");
  60. *
  61. * ctkCommandLineParser parser;
  62. * // Use Unix-style argument names
  63. * parser.setArgumentPrefix("--", "-");
  64. * // Enable QSettings support
  65. * parser.enableSettings("disable-settings");
  66. *
  67. * // Add command line argument names
  68. * parser.addArgument("disable-settings", "", QVariant::Bool, "Do not use QSettings");
  69. * parser.addArgument("help", "h", QVariant::Bool, "Show this help text");
  70. * parser.addArgument("search-paths", "s", QVariant::StringList, "A list of paths to search");
  71. *
  72. * // Parse the command line arguments
  73. * bool ok = false;
  74. * QHash<QString, QVariant> parsedArgs = parser.parseArguments(QCoreApplication::arguments(), &ok);
  75. * if (!ok)
  76. * {
  77. * QTextStream(stderr, QIODevice::WriteOnly) << "Error parsing arguments: "
  78. * << parser.errorString() << "\n";
  79. * return EXIT_FAILURE;
  80. * }
  81. *
  82. * // Show a help message
  83. * if (parsedArgs.contains("help") || parsedArgs.contains("h"))
  84. * {
  85. * QTextStream(stdout, QIODevice::WriteOnly) << parser.helpText();
  86. * return EXIT_SUCCESS;
  87. * }
  88. *
  89. * // Do something
  90. *
  91. * return EXIT_SUCCESS;
  92. * }
  93. * \endcode
  94. */
  95. class CTK_CORE_EXPORT ctkCommandLineParser : public QObject
  96. {
  97. Q_OBJECT
  98. Q_PROPERTY(QString errorString READ errorString)
  99. Q_PROPERTY(QStringList unparsedArguments READ unparsedArguments)
  100. Q_PROPERTY(bool settingsEnabled READ settingsEnabled)
  101. public:
  102. typedef QObject Superclass;
  103. /**
  104. * Constructs a parser instance.
  105. *
  106. * If QSettings support is enabled by a call to <code>enableSettings()</code>
  107. * a default constructed QSettings instance will be used when parsing
  108. * the command line arguments. Make sure to call <code>QCoreApplication::setOrganizationName()</code>
  109. * and <code>QCoreApplication::setApplicationName()</code> before using default
  110. * constructed QSettings objects.
  111. *
  112. * @param newParent The QObject parent.
  113. */
  114. ctkCommandLineParser(QObject* newParent = 0);
  115. /**
  116. * Constructs a parser instance.
  117. *
  118. * If QSettings support is enabled by a call to <code>enableSettings()</code>
  119. * the provided QSettings instance will be used. If the QSettings instance is
  120. * zero, a default constructed QSettings instance will be used when parsing
  121. * the command line arguments. Using a default constructed instance is usually
  122. * what you want, if you have called <code>QCoreApplication::setOrganizationName()</code>
  123. * and <code>QCoreApplication::setApplicationName()</code>.
  124. *
  125. * @param settings A QSettings instance which should be used.
  126. * @param newParent The QObject parent.
  127. *
  128. *
  129. */
  130. ctkCommandLineParser(QSettings* settings, QObject* newParent = 0);
  131. ~ctkCommandLineParser();
  132. /**
  133. * Parse a given list of command line arguments.
  134. *
  135. * This method parses a list of QString elements considering the known arguments
  136. * added by calls to <code>addArgument()</code>. If any one of the argument
  137. * values does not match the corresponding regular expression,
  138. * <code>ok</code> is set to false and an empty QHash object is returned.
  139. *
  140. * The keys in the returned QHash object correspond to the long argument string,
  141. * if it is not empty. Otherwise, the short argument string is used as key. The
  142. * QVariant values can safely be converted to the type specified in the
  143. * <code>addArgument()</code> method call.
  144. *
  145. * @param arguments A QStringList containing command line arguments. Usually
  146. * given by <code>QCoreApplication::arguments()</code>.
  147. * @param ok A pointer to a boolean variable. Will be set to <code>true</code>
  148. * if all regular expressions matched, <code>false</code> otherwise.
  149. * @return A QHash object mapping the long argument (if empty, the short one)
  150. * to a QVariant containing the value.
  151. */
  152. QHash<QString, QVariant> parseArguments(const QStringList &arguments, bool* ok = 0);
  153. /**
  154. * Convenient method allowing to parse a given list of command line arguments.
  155. * @see parseArguments(const QStringList &, bool*)
  156. */
  157. QHash<QString, QVariant> parseArguments(int argc, char** argv, bool* ok = 0);
  158. /**
  159. * Returns a detailed error description if a call to <code>parseArguments()</code>
  160. * failed.
  161. *
  162. * @return The error description, empty if no error occured.
  163. * @see parseArguments(const QStringList&, bool*)
  164. */
  165. QString errorString() const;
  166. /**
  167. * This method returns all unparsed arguments, i.e. all arguments
  168. * for which no long or short name has been registered via a call
  169. * to <code>addArgument()</code>.
  170. *
  171. * @see addArgument()
  172. *
  173. * @return A list containing unparsed arguments.
  174. */
  175. const QStringList& unparsedArguments() const;
  176. /**
  177. * Checks if the given argument has been added via a call
  178. * to <code>addArgument()</code>.
  179. *
  180. * @see addArgument()
  181. *
  182. * @param argument The argument to be checked.
  183. * @return <code>true</code> if the argument was added, <code>false</code>
  184. * otherwise.
  185. */
  186. Q_INVOKABLE bool argumentAdded(const QString& argument) const;
  187. /**
  188. * Checks if the given argument has been parsed successfully by a previous
  189. * call to <code>parseArguments()</code>.
  190. *
  191. * @param argument The argument to be checked.
  192. * @return <code>true</code> if the argument was parsed, <code>false</code>
  193. * otherwise.
  194. */
  195. Q_INVOKABLE bool argumentParsed(const QString& argument) const;
  196. /**
  197. * Adds a command line argument. An argument can have a long name
  198. * (like --long-argument-name), a short name (like -l), or both. The type
  199. * of the argument can be specified by using the <code>type</code> parameter.
  200. * The following types are supported:
  201. *
  202. * <table>
  203. * <tr><td><b>Type</b></td><td><b># of parameters</b></td><td><b>Default regular expr</b></td>
  204. * <td><b>Example</b></td></tr>
  205. * <tr><td>QVariant::String</td><td>1</td><td>.*</td><td>--test-string StringParameter</td></tr>
  206. * <tr><td>QVariant::Bool</td><td>0</td><td>does not apply</td><td>--enable-something</td></tr>
  207. * <tr><td>QVariant::StringList</td><td>-1</td><td>.*</td><td>--test-list string1 string2</td></tr>
  208. * <tr><td>QVariant::Int</td><td>1</td><td>-?[0-9]+</td><td>--test-int -5</td></tr>
  209. * </table>
  210. *
  211. * The regular expressions are used to validate the parameters of command line
  212. * arguments. You can restrict the valid set of parameters by calling
  213. * <code>setExactMatchRegularExpression()</code> for your argument.
  214. *
  215. * Optionally, a help string and a default value can be provided for the argument. If
  216. * the QVariant type of the default value does not match <code>type</code>, an
  217. * exception is thrown. Arguments with default values are always returned by
  218. * <code>parseArguments()</code>.
  219. *
  220. * You can also declare an argument deprecated, by setting <code>deprecated</code>
  221. * to <code>true</code>. Alternatively you can add a deprecated argument by calling
  222. * <code>addDeprecatedArgument()</code>.
  223. *
  224. * If the long or short argument has already been added, or if both are empty strings,
  225. * the method call has no effect.
  226. *
  227. * @param longarg The long argument name.
  228. * @param shortarg The short argument name.
  229. * @param type The argument type (see the list above for supported types).
  230. * @param argHelp A help string describing the argument.
  231. * @param defaultValue A default value for the argument.
  232. * @param ignoreRest All arguments after the current one will be ignored.
  233. * @param deprecated Declares the argument deprecated.
  234. *
  235. * @see setExactMatchRegularExpression()
  236. * @see addDeprecatedArgument()
  237. * @throws std::logic_error If the QVariant type of <code>defaultValue</code>
  238. * does not match <code>type</code>, a <code>std::logic_error</code> is thrown.
  239. */
  240. void addArgument(const QString& longarg, const QString& shortarg,
  241. QVariant::Type type, const QString& argHelp = QString(),
  242. const QVariant& defaultValue = QVariant(),
  243. bool ignoreRest = false, bool deprecated = false);
  244. /**
  245. * Adds a deprecated command line argument. If a deprecated argument is provided
  246. * on the command line, <code>argHelp</code> is displayed in the console and
  247. * processing continues with the next argument.
  248. *
  249. * Deprecated arguments are grouped separately at the end of the help text
  250. * returned by <code>helpText()</code>.
  251. *
  252. * @param longarg The long argument name.
  253. * @param shortarg The short argument name.
  254. * @param argHelp A help string describing alternatives to the deprecated argument.
  255. */
  256. void addDeprecatedArgument(const QString& longarg, const QString& shortarg,
  257. const QString& argHelp);
  258. /**
  259. * Sets a custom regular expression for validating argument parameters. The method
  260. * <code>errorString()</code> can be used the get the last error description.
  261. *
  262. * @param argument The previously added long or short argument name.
  263. * @param expression A regular expression which the arugment parameters must match.
  264. * @param exactMatchFailedMessage An error message explaining why the parameter did
  265. * not match.
  266. *
  267. * @return <code>true</code> if the argument was found and the regular expression was set,
  268. * <code>false</code> otherwise.
  269. *
  270. * @see errorString()
  271. */
  272. bool setExactMatchRegularExpression(const QString& argument, const QString& expression,
  273. const QString& exactMatchFailedMessage);
  274. /**
  275. * The field width for the argument names without the help text.
  276. *
  277. * @return The argument names field width in the help text.
  278. */
  279. int fieldWidth() const;
  280. /**
  281. * Creates a help text containing properly formatted argument names and help strings
  282. * provided by calls to <code>addArgument()</code>. The arguments can be grouped by
  283. * using <code>beginGroup()</code> and <code>endGroup()</code>.
  284. *
  285. * @param charPad The padding character.
  286. * @return The formatted help text.
  287. */
  288. QString helpText(const char charPad = ' ') const;
  289. /**
  290. * Sets the argument prefix for long and short argument names. This can be used
  291. * to create native command line arguments without changing the calls to
  292. * <code>addArgument()</code>. For example on Unix-based systems, long argument
  293. * names start with "--" and short names with "-", while on Windows argument names
  294. * always start with "/".
  295. *
  296. * Note that all methods in ctkCommandLineParser which take an argument name
  297. * expect the name as it was supplied to <code>addArgument</code>.
  298. *
  299. * Example usage:
  300. *
  301. * \code
  302. * ctkCommandLineParser parser;
  303. * parser.setArgumentPrefix("--", "-");
  304. * parser.addArgument("long-argument", "l", QVariant::String);
  305. * QStringList args;
  306. * args << "program name" << "--long-argument Hi";
  307. * parser.parseArguments(args);
  308. * \endcode
  309. *
  310. * @param longPrefix The prefix for long argument names.
  311. * @param shortPrefix The prefix for short argument names.
  312. */
  313. void setArgumentPrefix(const QString& longPrefix, const QString& shortPrefix);
  314. /**
  315. * Begins a new group for documenting arguments. All newly added arguments via
  316. * <code>addArgument()</code> will be put in the new group. You can close the
  317. * current group by calling <code>endGroup()</code> or be opening a new group.
  318. *
  319. * Note that groups cannot be nested and all arguments which do not belong to
  320. * a group will be listed at the top of the text created by <code>helpText()</code>.
  321. *
  322. * @param description The description of the group
  323. */
  324. void beginGroup(const QString& description);
  325. /**
  326. * Ends the current group.
  327. *
  328. * @see beginGroup(const QString&)
  329. */
  330. void endGroup();
  331. /**
  332. * Enables QSettings support in ctkCommandLineParser. If an argument name is found
  333. * in the QSettings instance with a valid QVariant, the value is considered as
  334. * a default value and overwrites default values registered with
  335. * <code>addArgument()</code>. User supplied values on the command line overwrite
  336. * values in the QSettings instance, except for arguments with multiple parameters
  337. * which are merged with QSettings values. Call <code>mergeSettings(false)</code>
  338. * to disable merging.
  339. *
  340. * See <code>ctkCommandLineParser(QSettings*)</code> for information about how to
  341. * supply a QSettings instance.
  342. *
  343. * Additionally, a long and short argument name can be specified which will disable
  344. * QSettings support if supplied on the command line. The argument name must be
  345. * registered as a regular argument via <code>addArgument()</code>.
  346. *
  347. * @param disableLongArg Long argument name.
  348. * @param disableShortArg Short argument name.
  349. *
  350. * @see ctkCommandLineParser(QSettings*)
  351. */
  352. void enableSettings(const QString& disableLongArg = "",
  353. const QString& disableShortArg = "");
  354. /**
  355. * Controlls the merging behavior of user values and QSettings values.
  356. *
  357. * If merging is on (the default), user supplied values for an argument
  358. * which can take more than one parameter are merged with values stored
  359. * in the QSettings instance. If merging is off, the user values overwrite
  360. * the QSettings values.
  361. *
  362. * @param merge <code>true</code> enables QSettings merging, <code>false</code>
  363. * disables it.
  364. */
  365. void mergeSettings(bool merge);
  366. /**
  367. * Can be used to check if QSettings support has been enabled by a call to
  368. * <code>enableSettings()</code>.
  369. *
  370. * @return <code>true</code> if QSettings support is enabled, <code>false</code>
  371. * otherwise.
  372. */
  373. bool settingsEnabled() const;
  374. /**
  375. * Can be used to teach the parser to stop parsing the arguments and return False when
  376. * an unknown argument is encountered. By default <code>StrictMode</code> is disabled.
  377. *
  378. * @see parseArguments(const QStringList &, bool*)
  379. */
  380. void setStrictModeEnabled(bool strictMode);
  381. private:
  382. class ctkInternal;
  383. ctkInternal * Internal;
  384. };
  385. #endif