1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
3// Copyright (C) 2013 David Faure <faure@kde.org>
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#include "qcommandlineoption.h"
7
8#include "qset.h"
9
10QT_BEGIN_NAMESPACE
11
12class QCommandLineOptionPrivate : public QSharedData
13{
14public:
15 Q_NEVER_INLINE
16 explicit QCommandLineOptionPrivate(const QString &name)
17 : names(removeInvalidNames(nameList: QStringList(name)))
18 { }
19
20 Q_NEVER_INLINE
21 explicit QCommandLineOptionPrivate(const QStringList &names)
22 : names(removeInvalidNames(nameList: names))
23 { }
24
25 static QStringList removeInvalidNames(QStringList nameList);
26
27 //! The list of names used for this option.
28 QStringList names;
29
30 //! The documentation name for the value, if one is expected
31 //! Example: "-o <file>" means valueName == "file"
32 QString valueName;
33
34 //! The description used for this option.
35 QString description;
36
37 //! The list of default values used for this option.
38 QStringList defaultValues;
39
40 QCommandLineOption::Flags flags;
41};
42
43/*!
44 \since 5.2
45 \class QCommandLineOption
46 \brief The QCommandLineOption class defines a possible command-line option.
47 \inmodule QtCore
48 \ingroup shared
49 \ingroup tools
50
51 This class is used to describe an option on the command line. It allows
52 different ways of defining the same option with multiple aliases possible.
53 It is also used to describe how the option is used - it may be a flag (e.g. \c{-v})
54 or take a value (e.g. \c{-o file}).
55
56 Examples:
57 \snippet code/src_corelib_tools_qcommandlineoption.cpp 0
58
59 \sa QCommandLineParser
60*/
61
62/*!
63 \fn QCommandLineOption &QCommandLineOption::operator=(QCommandLineOption &&other)
64
65 Move-assigns \a other to this QCommandLineOption instance.
66
67 \since 5.2
68*/
69
70/*!
71 Constructs a command line option object with the name \a name.
72
73 The name can be either short or long. If the name is one character in
74 length, it is considered a short name. Option names must not be empty,
75 must not start with a dash or a slash character, must not contain a \c{=}
76 and cannot be repeated.
77
78 \sa setDescription(), setValueName(), setDefaultValues()
79*/
80QCommandLineOption::QCommandLineOption(const QString &name)
81 : d(new QCommandLineOptionPrivate(name))
82{
83}
84
85/*!
86 Constructs a command line option object with the names \a names.
87
88 This overload allows to set multiple names for the option, for instance
89 \c{o} and \c{output}.
90
91 The names can be either short or long. Any name in the list that is one
92 character in length is a short name. Option names must not be empty,
93 must not start with a dash or a slash character, must not contain a \c{=}
94 and cannot be repeated.
95
96 \sa setDescription(), setValueName(), setDefaultValues()
97*/
98QCommandLineOption::QCommandLineOption(const QStringList &names)
99 : d(new QCommandLineOptionPrivate(names))
100{
101}
102
103/*!
104 Constructs a command line option object with the given arguments.
105
106 The name of the option is set to \a name.
107 The name can be either short or long. If the name is one character in
108 length, it is considered a short name. Option names must not be empty,
109 must not start with a dash or a slash character, must not contain a \c{=}
110 and cannot be repeated.
111
112 The description is set to \a description. It is customary to add a "."
113 at the end of the description.
114
115 In addition, the \a valueName needs to be set if the option expects a value.
116 The default value for the option is set to \a defaultValue.
117
118 In Qt versions before 5.4, this constructor was \c explicit. In Qt 5.4
119 and later, it no longer is and can be used for C++11-style uniform
120 initialization:
121
122 \snippet code/src_corelib_tools_qcommandlineoption.cpp cxx11-init
123
124 \sa setDescription(), setValueName(), setDefaultValues()
125*/
126QCommandLineOption::QCommandLineOption(const QString &name, const QString &description,
127 const QString &valueName,
128 const QString &defaultValue)
129 : d(new QCommandLineOptionPrivate(name))
130{
131 setValueName(valueName);
132 setDescription(description);
133 setDefaultValue(defaultValue);
134}
135
136/*!
137 Constructs a command line option object with the given arguments.
138
139 This overload allows to set multiple names for the option, for instance
140 \c{o} and \c{output}.
141
142 The names of the option are set to \a names.
143 The names can be either short or long. Any name in the list that is one
144 character in length is a short name. Option names must not be empty,
145 must not start with a dash or a slash character, must not contain a \c{=}
146 and cannot be repeated.
147
148 The description is set to \a description. It is customary to add a "."
149 at the end of the description.
150
151 In addition, the \a valueName needs to be set if the option expects a value.
152 The default value for the option is set to \a defaultValue.
153
154 In Qt versions before 5.4, this constructor was \c explicit. In Qt 5.4
155 and later, it no longer is and can be used for C++11-style uniform
156 initialization:
157
158 \snippet code/src_corelib_tools_qcommandlineoption.cpp cxx11-init-list
159
160 \sa setDescription(), setValueName(), setDefaultValues()
161*/
162QCommandLineOption::QCommandLineOption(const QStringList &names, const QString &description,
163 const QString &valueName,
164 const QString &defaultValue)
165 : d(new QCommandLineOptionPrivate(names))
166{
167 setValueName(valueName);
168 setDescription(description);
169 setDefaultValue(defaultValue);
170}
171
172/*!
173 Constructs a QCommandLineOption object that is a copy of the QCommandLineOption
174 object \a other.
175
176 \sa operator=()
177*/
178QCommandLineOption::QCommandLineOption(const QCommandLineOption &other)
179 : d(other.d)
180{
181}
182
183/*!
184 Destroys the command line option object.
185*/
186QCommandLineOption::~QCommandLineOption()
187{
188}
189
190/*!
191 Makes a copy of the \a other object and assigns it to this QCommandLineOption
192 object.
193*/
194QCommandLineOption &QCommandLineOption::operator=(const QCommandLineOption &other)
195{
196 d = other.d;
197 return *this;
198}
199
200/*!
201 \fn void QCommandLineOption::swap(QCommandLineOption &other)
202
203 Swaps option \a other with this option. This operation is very
204 fast and never fails.
205*/
206
207/*!
208 Returns the names set for this option.
209 */
210QStringList QCommandLineOption::names() const
211{
212 return d->names;
213}
214
215namespace {
216 struct IsInvalidName
217 {
218 typedef bool result_type;
219 typedef QString argument_type;
220
221 Q_NEVER_INLINE
222 result_type operator()(const QString &name) const noexcept
223 {
224 if (Q_UNLIKELY(name.isEmpty()))
225 return warn(what: "be empty");
226
227 const QChar c = name.at(i: 0);
228 if (Q_UNLIKELY(c == u'-'))
229 return warn(what: "start with a '-'");
230 if (Q_UNLIKELY(c == u'/'))
231 return warn(what: "start with a '/'");
232 if (Q_UNLIKELY(name.contains(u'=')))
233 return warn(what: "contain a '='");
234
235 return false;
236 }
237
238 Q_NEVER_INLINE
239 static bool warn(const char *what) noexcept
240 {
241 qWarning(msg: "QCommandLineOption: Option names cannot %s", what);
242 return true;
243 }
244 };
245} // unnamed namespace
246
247// static
248QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList)
249{
250 if (Q_UNLIKELY(nameList.isEmpty()))
251 qWarning(msg: "QCommandLineOption: Options must have at least one name");
252 else
253 nameList.removeIf(pred: IsInvalidName());
254 return nameList;
255}
256
257/*!
258 Sets the name of the expected value, for the documentation, to \a valueName.
259
260 Options without a value assigned have a boolean-like behavior:
261 either the user specifies --option or they don't.
262
263 Options with a value assigned need to set a name for the expected value,
264 for the documentation of the option in the help output. An option with names \c{o} and \c{output},
265 and a value name of \c{file} will appear as \c{-o, --output <file>}.
266
267 Call QCommandLineParser::value() if you expect the option to be present
268 only once, and QCommandLineParser::values() if you expect that option
269 to be present multiple times.
270
271 \sa valueName()
272 */
273void QCommandLineOption::setValueName(const QString &valueName)
274{
275 d->valueName = valueName;
276}
277
278/*!
279 Returns the name of the expected value.
280
281 If empty, the option doesn't take a value.
282
283 \sa setValueName()
284 */
285QString QCommandLineOption::valueName() const
286{
287 return d->valueName;
288}
289
290/*!
291 Sets the description used for this option to \a description.
292
293 It is customary to add a "." at the end of the description.
294
295 The description is used by QCommandLineParser::showHelp().
296
297 \sa description()
298 */
299void QCommandLineOption::setDescription(const QString &description)
300{
301 d->description = description;
302}
303
304/*!
305 Returns the description set for this option.
306
307 \sa setDescription()
308 */
309QString QCommandLineOption::description() const
310{
311 return d->description;
312}
313
314/*!
315 Sets the default value used for this option to \a defaultValue.
316
317 The default value is used if the user of the application does not specify
318 the option on the command line.
319
320 If \a defaultValue is empty, the option has no default values.
321
322 \sa defaultValues() setDefaultValues()
323 */
324void QCommandLineOption::setDefaultValue(const QString &defaultValue)
325{
326 QStringList newDefaultValues;
327 if (!defaultValue.isEmpty()) {
328 newDefaultValues.reserve(asize: 1);
329 newDefaultValues << defaultValue;
330 }
331 // commit:
332 d->defaultValues.swap(other&: newDefaultValues);
333}
334
335/*!
336 Sets the list of default values used for this option to \a defaultValues.
337
338 The default values are used if the user of the application does not specify
339 the option on the command line.
340
341 \sa defaultValues() setDefaultValue()
342 */
343void QCommandLineOption::setDefaultValues(const QStringList &defaultValues)
344{
345 d->defaultValues = defaultValues;
346}
347
348/*!
349 Returns the default values set for this option.
350
351 \sa setDefaultValues()
352 */
353QStringList QCommandLineOption::defaultValues() const
354{
355 return d->defaultValues;
356}
357
358/*!
359 Returns a set of flags that affect this command-line option.
360
361 \since 5.8
362 \sa setFlags(), QCommandLineOption::Flags
363 */
364QCommandLineOption::Flags QCommandLineOption::flags() const
365{
366 return d->flags;
367}
368
369/*!
370 Set the set of flags that affect this command-line option to \a flags.
371
372 \since 5.8
373 \sa flags(), QCommandLineOption::Flags
374 */
375void QCommandLineOption::setFlags(Flags flags)
376{
377 d->flags = flags;
378}
379
380/*!
381 \enum QCommandLineOption::Flag
382
383 \value HiddenFromHelp Hide this option in the user-visible help output. All
384 options are visible by default. Setting this flag for a particular
385 option makes it internal, i.e. not listed in the help output.
386
387 \value ShortOptionStyle The option will always be understood as a short
388 option, regardless of what was set by
389 QCommandLineParser::setSingleDashWordOptionMode.
390 This allows flags such as \c{-DDEFINE=VALUE} or \c{-I/include/path} to be
391 interpreted as short flags even when the parser is in
392 QCommandLineParser::ParseAsLongOptions mode.
393
394 \sa QCommandLineOption::setFlags(), QCommandLineOption::flags()
395*/
396
397QT_END_NAMESPACE
398

source code of qtbase/src/corelib/tools/qcommandlineoption.cpp