Skip to main content

cxx_qt_lib_extras/core/
qcommandlineparser.rs

1// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
2// SPDX-FileContributor: Laurent Montel <laurent.montel@kdab.com>
3//
4// SPDX-License-Identifier: MIT OR Apache-2.0
5use cxx::{type_id, ExternType};
6use cxx_qt_lib::{QString, QStringList};
7use std::mem::MaybeUninit;
8
9#[cxx::bridge]
10mod ffi {
11    /// This enum describes the way the parser interprets options that occur after positional arguments.
12    #[repr(i32)]
13    #[namespace = "rust::cxxqtlib1"]
14    #[derive(Debug)]
15    enum QCommandLineParserOptionsAfterPositionalArgumentsMode {
16        /// `application argument --opt -t` is interpreted as setting the options `opt` and `t`,
17        /// just like `application --opt -t argument` would do. This is the default parsing mode.
18        /// In order to specify that `--opt` and `-t` are positional arguments instead, the user can use `--`,
19        /// as in `application argument -- --opt -t`.
20        ParseAsOptions,
21        /// `application argument --opt` is interpreted as having two positional arguments, `argument` and `--opt`.
22        /// This mode is useful for executables that aim to launch other executables (e.g. wrappers, debugging tools, etc.)
23        /// or that support internal commands followed by options for the command. argument is the name of the command,
24        /// and all options occurring after it can be collected and parsed by another command line parser, possibly in another executable.
25        ParseAsPositionalArguments,
26    }
27
28    /// This enum describes the way the parser interprets command-line options that use a single dash followed by multiple letters, as `-abc`.
29    #[repr(i32)]
30    #[namespace = "rust::cxxqtlib1"]
31    #[derive(Debug)]
32    enum QCommandLineParserSingleDashWordOptionMode {
33        /// `-abc` is interpreted as `-a -b -c`, i.e. as three short options that have been compacted on the command-line, if none of the options take a value. If `a` takes a value, then it is interpreted as `-a bc`, i.e. the short option a followed by the value `bc`. This is typically used in tools that behave like compilers, in order to handle options such as `-DDEFINE=VALUE` or `-I/include/path`. This is the default parsing mode. New applications are recommended to use this mode.
34        ParseAsCompactedShortOptions,
35        /// `-abc` is interpreted as `--abc`, i.e. as the long option named `abc`. This is how Qt's own tools (uic, rcc...) have always been parsing arguments. This mode should be used for preserving compatibility in applications that were parsing arguments in such a way. There is an exception if the `a` option has the [`QCommandLineOption::ShortOptionStyle`] flag set, in which case it is still interpreted as `-a bc`.
36        ParseAsLongOptions,
37    }
38
39    unsafe extern "C++" {
40        include!("cxx-qt-lib-extras/core/qcommandlineparser.h");
41        type QCommandLineParser = super::QCommandLineParser;
42        include!("cxx-qt-lib-extras/core/qcommandlineoption.h");
43        type QCommandLineOption = crate::QCommandLineOption;
44
45        include!("cxx-qt-lib/qstring.h");
46        type QString = cxx_qt_lib::QString;
47        include!("cxx-qt-lib/qstringlist.h");
48        type QStringList = cxx_qt_lib::QStringList;
49
50        /// Adds help options to the command-line parser.
51        ///
52        /// The options specified for this command-line are described by `-h` or `--help`. On Windows, the alternative `-?` is also supported. The option `--help-all` extends that to include generic Qt options, not defined by this command, in the output.
53        ///
54        /// These options are handled automatically by `QCommandLineParser`.
55        #[rust_name = "add_help_option"]
56        fn addHelpOption(self: &mut QCommandLineParser) -> QCommandLineOption;
57
58        /// Adds the option `option` to look for while parsing.
59        /// Returns `true` if adding the option was successful; otherwise returns `false`.
60        ///
61        /// Adding the option fails if there is no name attached to the option,
62        /// or the option has a name that clashes with an option name added before.
63        #[rust_name = "add_option"]
64        fn addOption(self: &mut QCommandLineParser, option: &QCommandLineOption) -> bool;
65
66        /// Adds the `-v` / `--version` option, which displays the version string of the application.
67        ///
68        /// This option is handled automatically by `QCommandLineParser`.
69        #[rust_name = "add_version_option"]
70        fn addVersionOption(self: &mut QCommandLineParser) -> QCommandLineOption;
71
72        /// Returns the application description.
73        #[rust_name = "application_description"]
74        fn applicationDescription(self: &QCommandLineParser) -> QString;
75
76        /// Clears the definitions of additional arguments from the help text.
77        #[rust_name = "clear_positional_arguments"]
78        fn clearPositionalArguments(self: &mut QCommandLineParser);
79
80        /// Returns a translated error text for the user. This should only be called when [`parse`](Self::parse) returns `false`.
81        #[rust_name = "error_text"]
82        fn errorText(self: &QCommandLineParser) -> QString;
83
84        /// Returns a string containing the complete help information.
85        #[rust_name = "help_text"]
86        fn helpText(self: &QCommandLineParser) -> QString;
87
88        /// Returns a list of option names that were found.
89        ///
90        /// This returns a list of all the recognized option names found by the parser, in the order in which they were found. For any long options that were in the form {–option=value}, the value part will have been dropped.
91        ///
92        /// The names in this list do not include the preceding dash characters. Names may appear more than once in this list if they were encountered more than once by the parser.
93        ///
94        /// Any entry in the list can be used with [`value`](Self::value) or with [`values`](Self::values) to get any relevant option values.
95        #[rust_name = "option_names"]
96        fn optionNames(self: &QCommandLineParser) -> QStringList;
97
98        /// Parses the command line arguments.
99        ///
100        /// Most programs don't need to call this, a simple call to [`process`] is enough.
101        ///
102        /// This function is more low-level, and only does the parsing. The application will have to take care of the error handling, using [`error_text`] if this function returns `false`. This can be useful for instance to show a graphical error message in graphical programs.
103        ///
104        /// Calling this function instead of [`process`] can also be useful in order to ignore unknown options temporarily, because more option definitions will be provided later on (depending on one of the arguments), before calling [`process`].
105        ///
106        /// Don't forget that arguments must start with the name of the executable (ignored, though).
107        ///
108        /// Returns `false` in case of a parse error (unknown option or missing value); returns `true` otherwise.
109        ///
110        /// [`process`]: Self::process
111        /// [`error_text`]: Self::error_text
112        fn parse(self: &mut QCommandLineParser, arguments: &QStringList) -> bool;
113
114        /// Returns a list of positional arguments.
115        ///
116        /// These are all of the arguments that were not recognized as part of an option.
117        #[rust_name = "positional_arguments"]
118        fn positionalArguments(self: &QCommandLineParser) -> QStringList;
119
120        /// Processes the command line arguments.
121        ///
122        /// In addition to parsing the options (like [`parse`](Self::parse)), this function also handles the builtin options and handles errors.
123        ///
124        /// The builtin options are `--version` if [`add_version_option`](Self::add_version_option) was called and `--help` / `--help-all` if [`add_help_option`](Self::add_help_option) was called.
125        ///
126        /// When invoking one of these options, or when an error happens (for instance an unknown option was passed), the current process will then stop, using the [exit](https://doc.qt.io/qt/qcoreapplication.html#exit)() function.
127        fn process(self: &mut QCommandLineParser, arguments: &QStringList);
128
129        /// Sets the application description shown by [`help_text`](Self::help_text).
130        #[rust_name = "set_application_description"]
131        fn setApplicationDescription(self: &mut QCommandLineParser, description: &QString);
132
133        /// Sets the parsing mode to `single_dash_word_option_mode`. This must be called before [`process`](Self::process) or [`parse`](Self::parse).
134        #[rust_name = "set_single_dash_word_option_mode"]
135        fn setSingleDashWordOptionMode(
136            self: &mut QCommandLineParser,
137            single_dash_word_option_mode: QCommandLineParserSingleDashWordOptionMode,
138        );
139
140        /// Sets the parsing mode to `parsing_mode`. This must be called before [`process`](Self::process) or [`parse`](Self::parse).
141        #[rust_name = "set_options_after_positional_arguments_mode"]
142        fn setOptionsAfterPositionalArgumentsMode(
143            self: &mut QCommandLineParser,
144            parsing_mode: QCommandLineParserOptionsAfterPositionalArgumentsMode,
145        );
146
147        /// Displays the version information from [`QCoreApplication::application_version`](cxx_qt_lib::QCoreApplication::application_version), and exits the application.
148        ///
149        ///  This is automatically triggered by the `–version` option, but can also be used to display the version when not using [`process`](Self::process). The exit code is set to `EXIT_SUCCESS` (0).
150        #[rust_name = "show_version"]
151        fn showVersion(self: &mut QCommandLineParser);
152
153        /// Returns a list of unknown option names.
154        ///
155        /// This list will include both long and short name options that were not recognized. For any long options that were in the form {–option=value}, the value part will have been dropped and only the long name is added.
156        ///
157        /// The names in this list do not include the preceding dash characters. Names may appear more than once in this list if they were encountered more than once by the parser.
158        #[rust_name = "unknown_option_names"]
159        fn unknownOptionNames(self: &QCommandLineParser) -> QStringList;
160    }
161    #[namespace = "rust::cxxqtlib1"]
162    unsafe extern "C++" {
163        #[rust_name = "qcommandlineparser_value"]
164        fn qcommandlineparserValue(parser: &QCommandLineParser, optionName: &QString) -> QString;
165
166        #[rust_name = "qcommandlineparser_values"]
167        fn qcommandlineparserValues(
168            parser: &QCommandLineParser,
169            optionName: &QString,
170        ) -> QStringList;
171
172        #[rust_name = "is_set_from_qstring"]
173        fn qcommandlineparserIsSetFromQString(parser: &QCommandLineParser, name: &QString) -> bool;
174    }
175
176    #[namespace = "rust::cxxqtlib1"]
177    unsafe extern "C++" {
178        include!("cxx-qt-lib/common.h");
179        type QCommandLineParserOptionsAfterPositionalArgumentsMode;
180        type QCommandLineParserSingleDashWordOptionMode;
181
182        #[doc(hidden)]
183        #[rust_name = "qcommandlineparser_drop"]
184        fn drop(parser: &mut QCommandLineParser);
185
186        #[doc(hidden)]
187        #[rust_name = "qcommandlineparser_init_default"]
188        fn construct() -> QCommandLineParser;
189    }
190}
191
192/// The QCommandLineParser class provides a means for handling the command line options.
193///
194/// Qt Documentation: [QCommandLineParser](https://doc.qt.io/qt/qcommandlineparser.html#details)
195#[derive(Debug, Clone)]
196#[repr(C)]
197pub struct QCommandLineParser {
198    _space: MaybeUninit<usize>,
199}
200
201impl QCommandLineParser {
202    /// Returns the option value found for the given option name `option_name`, or an empty string if not found.
203    ///
204    /// The name provided can be any long or short name of any option that was added with [`add_option`](Self::add_option). All the option names are treated as being equivalent. If the name is not recognized or that option was not present, an empty string is returned.
205    ///
206    /// For options found by the parser, the last value found for that option is returned. If the option wasn't specified on the command line, the default value is returned.
207    ///
208    /// If the option does not take a value, a warning is printed, and an empty string is returned.
209    pub fn value(&self, option_name: &QString) -> QString {
210        ffi::qcommandlineparser_value(self, option_name)
211    }
212
213    /// Returns a list of option values found for the given option name `option_name`, or an empty list if not found.
214    ///
215    /// The name provided can be any long or short name of any option that was added with [`add_option`](Self::add_option). All the options names are treated as being equivalent. If the name is not recognized or that option was not present, an empty list is returned.
216    ///
217    /// For options found by the parser, the list will contain an entry for each time the option was encountered by the parser. If the option wasn't specified on the command line, the default values are returned.
218    ///
219    /// An empty list is returned if the option does not take a value.
220    pub fn values(&self, option_name: &QString) -> QStringList {
221        ffi::qcommandlineparser_values(self, option_name)
222    }
223
224    /// Checks whether the option `name` was passed to the application.
225    ///
226    /// Returns `true` if the option `name` was set, `false` otherwise.
227    ///
228    /// The name provided can be any long or short name of any option that was added with [`add_option`](Self::add_option). All the options names are treated as being equivalent. If the name is not recognized or that option was not present, `false` is returned.
229    pub fn is_set(&self, name: &QString) -> bool {
230        ffi::is_set_from_qstring(self, name)
231    }
232}
233
234impl Default for QCommandLineParser {
235    /// Constructs a command line parser object.
236    fn default() -> Self {
237        ffi::qcommandlineparser_init_default()
238    }
239}
240
241impl Drop for QCommandLineParser {
242    fn drop(&mut self) {
243        ffi::qcommandlineparser_drop(self);
244    }
245}
246
247// Safety:
248//
249// Static checks on the C++ side to ensure the size is the same.
250unsafe impl ExternType for QCommandLineParser {
251    type Id = type_id!("QCommandLineParser");
252    type Kind = cxx::kind::Trivial;
253}
254
255#[cfg(test)]
256mod tests {
257    use super::*;
258
259    #[test]
260    fn test_default_value() {
261        let commandlineparser = ffi::qcommandlineparser_init_default();
262        assert!(commandlineparser.error_text().is_empty());
263        assert!(commandlineparser.application_description().is_empty());
264    }
265}