1/* Copyright (C) 2004 The glibmm Development Team
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17_DEFS(glibmm,glib)
18
19#include <glibmm/optionentry.h>
20#include <glibmm/optiongroup.h>
21#include <glibmm/error.h>
22#include <sigc++/signal.h>
23
24#ifndef DOXYGEN_SHOULD_SKIP_THIS
25extern "C" { typedef struct _GOptionContext GOptionContext; }
26#endif
27
28
29namespace Glib
30{
31
32/** Exception class for options.
33 */
34_WRAP_GERROR(OptionError, GOptionError, G_OPTION_ERROR, NO_GTYPE, decl_prefix GLIBMM_API)
35
36/** An OptionContext defines and parses commandline options, using OptionGroup%s and \link OptionEntry option entries \endlink.
37 *
38 * It supports short and long commandline options, as shown in the following example:
39 *
40 * <tt>testtreemodel -r 1 --max-size 20 --rand --display=:1.0 -vb -- file1 file2</tt>
41 *
42 * The example demonstrates a number of features of the GOption
43 * commandline parser:
44 * - Options can be single letters, prefixed by a single dash.
45 * - Multiple short options can be grouped behind a single dash.
46 * - Long options are prefixed by two consecutive dashes.
47 * - Options can have an extra argument, which can be a number, a string or
48 *   a filename. For long options, the extra argument can be appended with
49 *   an equals sign after the option name, which is useful if the extra
50 *   argument starts with a dash, which would otherwise cause it to be
51 *   interpreted as another option.
52 * - Non-option arguments are returned to the application as rest arguments.
53 * - An argument consisting solely of two dashes turns off further parsing,
54 *   any remaining arguments (even those starting with a dash) are returned
55 *   to the application as rest arguments.
56 *
57 * The OptionContext groups options in OptionGroups, which makes it easy to
58 * incorporate options from multiple sources. The intended use for this is
59 * to let applications collect option groups from the libraries it uses,
60 * add them to their OptionContext, and parse all options by a single call
61 * to parse(). See Gtk::Main::add_gtk_option_group(), for an example.
62 *
63 * Add options by creating OptionEntry instances and appropriately-typed variables,
64 * and adding them to an OptionGroup with OptionGroup::add_entry() or
65 * OptionGroup::add_entry_filename(). The option group should then be added to
66 * the OptionContext with set_main_group() or add_group().
67 *
68 * You might find it convenient to derive your own class from OptionGroup to
69 * contain these OptionEntry instances and member variables.
70 *
71 * If an option is of type string (see OptionGroup::add_entry()) or filename
72 * (see OptionGroup::add_entry_filename()), OptionContext takes
73 * care of converting it to the right encoding. strings are returned in
74 * UTF-8 encoding and filenames are returned in the GLib filename encoding.
75 * Note that this only works if setlocale() has been called before
76 * OptionContext::parse().
77 *
78 * OptionContext can automatically generate nicely formatted help output. Unless it is
79 * explicitly turned off with set_help_enabled(), this will recognize
80 * the --help, -?, --help-all and --help-groupname options
81 * (where groupname is the name of an OptionGroup) and write suitable text to
82 * stdout.
83 *
84 *
85 */
86class GLIBMM_API OptionContext
87{
88  _CLASS_GENERIC(OptionContext, GOptionContext)
89  _IGNORE(g_option_context_free)
90public:
91
92  /** Creates a new option context.
93   * @param parameter_string A string which is displayed in the first line of --help output, after programname [OPTION...]
94   */
95  explicit OptionContext(const Glib::ustring& parameter_string = Glib::ustring());
96
97  //Note that, unlike Glib::wrap(), this would create a second C++ instance for the same C instance,
98  //so it should be used carefully. For instance you could not access data in a derived class via this second instance.
99  explicit OptionContext(GOptionContext* castitem, bool take_ownership = false);
100
101  //TODO?:
102  //OptionContext(const OptionContext& other) = delete;
103  //OptionContext& operator=(const OptionContext& other) = delete;
104
105  OptionContext(OptionContext&& other) noexcept;
106  OptionContext& operator=(OptionContext&& other) noexcept;
107
108  virtual ~OptionContext();
109
110  _WRAP_METHOD(void set_help_enabled(bool help_enabled = true), g_option_context_set_help_enabled)
111  _WRAP_METHOD(bool get_help_enabled() const, g_option_context_get_help_enabled)
112  _WRAP_METHOD(void set_ignore_unknown_options(bool ignore_unknown = true), g_option_context_set_ignore_unknown_options)
113  _WRAP_METHOD(bool get_ignore_unknown_options() const, g_option_context_get_ignore_unknown_options)
114
115  _WRAP_METHOD(void set_strict_posix(bool strict_posix = true), g_option_context_set_strict_posix)
116  _WRAP_METHOD(bool get_strict_posix() const, g_option_context_get_strict_posix)
117
118#m4 _CONVERSION(`char**&',`gchar***',`&($3)')
119  _WRAP_METHOD(bool parse(int& argc, char**& argv), g_option_context_parse, errthrow "Glib::OptionError, Glib::ConvertError", errthrow)
120
121  /** Parses the command line arguments.
122   *
123   * This function is similar to parse(int& argc, char**& argv) except that it
124   * respects the normal memory rules when dealing with a strv instead of
125   * assuming that the passed-in array is the argv of the main function.
126   * In particular, strings that are removed from the arguments list will
127   * be freed using g_free().
128   *
129   * On Windows, the strings are expected to be in UTF-8. This is in
130   * contrast to parse(int& argc, char**& argv) which expects them to be in the
131   * system codepage, which is how they are passed as @a argv to main().
132   * See g_win32_get_command_line() or Gio::ApplicationCommandLine::get_arguments()
133   * for a solution.
134   *
135   * This function is useful if you are trying to use OptionContext with
136   * Gio::Application.
137   *
138   * @newin{2,50}
139   *
140   * @param[in,out] argv A pointer to the command line arguments
141   *   (which must be in UTF-8 on Windows).
142   * @return <tt>true</tt> if the parsing was successful,
143   *         <tt>false</tt> if an error occurred.
144   * @throw Glib::OptionError
145   * @throw Glib::ConvertError
146   */
147  _WRAP_METHOD(bool parse(char**& argv), g_option_context_parse_strv, errthrow)
148
149  //g_option_context_add_main_entries(), just creates a group internally, adds them to it, and does a set_main_group()
150  //- a group without callbacks seems to do some simple default parsing.
151  _IGNORE(g_option_context_add_main_entries)
152
153  /** Adds an OptionGroup to the context, so that parsing with context will recognize the options in the group.
154   * Note that the group will not be copied, so it should exist for as long as the context exists.
155   *
156   * @param group The group to add.
157   */
158  void add_group(OptionGroup& group);
159  _IGNORE(g_option_context_add_group)
160
161  /** Sets an OptionGroup as the main group of the context. This has the same effect as calling add_group(), the only
162   * difference is that the options in the main group are treated differently when generating --help output.
163   * Note that the group will not be copied, so it should exist for as long as the context exists.
164   *
165   * @param group The group to add.
166   */
167  void set_main_group(OptionGroup& group);
168  _IGNORE(g_option_context_set_main_group)
169
170  //We don't need this (hopefully), and the memory management would be really awkward.
171  //OptionGroup& get_main_group();
172  //const OptionGroup& get_main_group() const;
173  _IGNORE(g_option_context_get_main_group)
174
175  #m4 _CONVERSION(`const OptionGroup&',`GOptionGroup*',`const_cast<GOptionGroup*>(($3).gobj())')
176  _WRAP_METHOD(Glib::ustring get_help(bool main_help, const OptionGroup& group) const, g_option_context_get_help)
177
178  /** Returns a formatted, translated help text for the given context.
179   *
180   * - To obtain the text produced by --help, call get_help(true).
181   * - To obtain the text produced by --help-all, call get_help(false).
182   * - To obtain the help text for an option group, call get_help(false, group).
183   *
184   * @param main_help If true, only include the main group.
185   * @result string containing the help text.
186   */
187  Glib::ustring get_help(bool main_help = true) const;
188
189  GOptionContext*       gobj()       { return gobject_; }
190  const GOptionContext* gobj() const { return gobject_; }
191
192  _WRAP_METHOD(void set_summary(const Glib::ustring& summary), g_option_context_set_summary)
193  _WRAP_METHOD(Glib::ustring get_summary() const, g_option_context_get_summary)
194  _WRAP_METHOD(void set_description(const Glib::ustring& description), g_option_context_set_description)
195  _WRAP_METHOD(Glib::ustring get_description() const, g_option_context_get_description)
196
197  _WRAP_METHOD(void set_translation_domain(const Glib::ustring& domain), g_option_context_set_translation_domain)
198
199  /**
200   * This function is used to translate user-visible strings, for --help output.
201   * The function takes an untranslated string and returns a translated string
202   */
203  using SlotTranslate = sigc::slot<Glib::ustring, const Glib::ustring&>;
204
205  /**
206   * Sets the function which is used to translate user-visible
207   * strings, for --help output.  Different groups can use different functions.
208   *
209   * If you are using gettext(), you only need to set the translation domain,
210   * see set_translation_domain().
211   *
212   * @newin{2,14}
213   */
214  void set_translate_func (const SlotTranslate& slot);
215  _IGNORE(g_option_context_set_translate_func)
216
217protected:
218
219  GOptionContext* gobject_;
220  bool has_ownership_;
221};
222
223
224} // namespace Glib
225
226