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 #include <glibmm.h>
18 #include <iomanip>
19 #include <iostream>
20 
21 class ExampleOptionGroup : public Glib::OptionGroup
22 {
23 public:
24   ExampleOptionGroup();
25 
26 private:
27   bool on_pre_parse(Glib::OptionContext& context, Glib::OptionGroup& group) override;
28   bool on_post_parse(Glib::OptionContext& context, Glib::OptionGroup& group) override;
29   void on_error(Glib::OptionContext& context, Glib::OptionGroup& group) override;
30 
31   bool on_option_arg_string(
32     const Glib::ustring& option_name, const Glib::ustring& value, bool has_value);
33   bool on_option_arg_filename(
34     const Glib::ustring& option_name, const std::string& value, bool has_value);
35 
36 public:
37   // These members should live as long as the OptionGroup to which they are added,
38   // and as long as the OptionContext to which that OptionGroup is added.
39   int m_arg_foo;
40   std::string m_arg_filename;
41   Glib::ustring m_arg_goo;
42   bool m_arg_boolean;
43   Glib::OptionGroup::vecustrings m_arg_list;
44   Glib::OptionGroup::vecustrings m_remaining_list;
45   Glib::ustring m_arg_x_string;
46   Glib::ustring m_arg_x_filename;
47 };
48 
ExampleOptionGroup()49 ExampleOptionGroup::ExampleOptionGroup()
50 : Glib::OptionGroup(
51     "example_group", "description of example group", "help description of example group"),
52   m_arg_foo(0),
53   m_arg_boolean(false)
54 {
55   Glib::OptionEntry entry1;
56   entry1.set_long_name("foo");
57   entry1.set_short_name('f');
58   entry1.set_description("The Foo");
59   add_entry(entry1, m_arg_foo);
60 
61   Glib::OptionEntry entry2;
62   entry2.set_long_name("file");
63   entry2.set_short_name('F');
64   entry2.set_description("The Filename");
65   add_entry_filename(entry2, m_arg_filename);
66 
67   Glib::OptionEntry entry3;
68   entry3.set_long_name("goo");
69   entry3.set_short_name('g');
70   entry3.set_description("The Goo");
71   // We can choose a default to be used if the user doesn't specify
72   // this option.
73   m_arg_goo = "default-goo-value";
74   add_entry(entry3, m_arg_goo);
75 
76   Glib::OptionEntry entry4;
77   entry4.set_long_name("activate_something");
78   entry4.set_description("Activate something");
79   add_entry(entry4, m_arg_boolean);
80 
81   Glib::OptionEntry entry5;
82   entry5.set_long_name("list");
83   entry5.set_short_name('l');
84   entry5.set_description("A List");
85   add_entry(entry5, m_arg_list);
86 
87   Glib::OptionEntry entry6;
88   entry6.set_long_name("x-string");
89   entry6.set_short_name('x');
90   entry6.set_description("A string with custom parsing");
91   entry6.set_flags(Glib::OptionEntry::FLAG_OPTIONAL_ARG);
92   m_arg_x_string = "not specified";
93   add_entry(entry6, sigc::mem_fun(*this, &ExampleOptionGroup::on_option_arg_string));
94 
95   Glib::OptionEntry entry7;
96   entry7.set_long_name("x-filename");
97   entry7.set_short_name('X');
98   entry7.set_description("A filename with custom parsing");
99   entry7.set_flags(Glib::OptionEntry::FLAG_OPTIONAL_ARG);
100   m_arg_x_filename = "not specified";
101   add_entry_filename(entry7, sigc::mem_fun(*this, &ExampleOptionGroup::on_option_arg_filename));
102 
103   Glib::OptionEntry entry_remaining;
104   entry_remaining.set_long_name(G_OPTION_REMAINING);
105 
106   add_entry(entry_remaining, m_remaining_list);
107 }
108 
109 bool
on_pre_parse(Glib::OptionContext &,Glib::OptionGroup &)110 ExampleOptionGroup::on_pre_parse(Glib::OptionContext& /* context */, Glib::OptionGroup& /* group */)
111 {
112   // This is called before the m_arg_* instances are given their values.
113   // You do not need to override this method. This is just here to show you how,
114   // in case you want to do any extra processing.
115   std::cout << "on_pre_parse called" << std::endl;
116   return true;
117 }
118 
119 bool
on_post_parse(Glib::OptionContext &,Glib::OptionGroup &)120 ExampleOptionGroup::on_post_parse(
121   Glib::OptionContext& /* context */, Glib::OptionGroup& /* group */)
122 {
123   // This is called after the m_arg_* instances are given their values.
124   // You do not need to override this method. This is just here to show you how,
125   // in case you want to do any extra processing.
126   std::cout << "on_post_parse called" << std::endl;
127   return true;
128 }
129 
130 void
on_error(Glib::OptionContext &,Glib::OptionGroup &)131 ExampleOptionGroup::on_error(Glib::OptionContext& /* context */, Glib::OptionGroup& /* group */)
132 {
133   std::cout << "on_error called" << std::endl;
134 }
135 
136 bool
on_option_arg_string(const Glib::ustring & option_name,const Glib::ustring & value,bool has_value)137 ExampleOptionGroup::on_option_arg_string(
138   const Glib::ustring& option_name, const Glib::ustring& value, bool has_value)
139 {
140   if (option_name != "-x" && option_name != "--x-string")
141   {
142     m_arg_x_string = "on_option_arg_string called with unexpected option_name: " + option_name;
143     throw Glib::OptionError(Glib::OptionError::UNKNOWN_OPTION, m_arg_x_string);
144   }
145 
146   if (!has_value)
147   {
148     m_arg_x_string = "no value";
149     return true;
150   }
151 
152   if (value.empty())
153   {
154     m_arg_x_string = "empty string";
155     return true;
156   }
157 
158   m_arg_x_string = value;
159   if (value == "error")
160   {
161     throw Glib::OptionError(
162       Glib::OptionError::BAD_VALUE, "on_option_arg_string called with value = " + m_arg_x_string);
163   }
164   return value != "false";
165 }
166 
167 bool
on_option_arg_filename(const Glib::ustring & option_name,const std::string & value,bool has_value)168 ExampleOptionGroup::on_option_arg_filename(
169   const Glib::ustring& option_name, const std::string& value, bool has_value)
170 {
171   if (option_name != "-X" && option_name != "--x-filename")
172   {
173     m_arg_x_filename = "on_option_arg_filename called with unexpected option_name: " + option_name;
174     throw Glib::OptionError(Glib::OptionError::UNKNOWN_OPTION, m_arg_x_filename);
175   }
176 
177   if (!has_value)
178   {
179     m_arg_x_filename = "no value";
180     return true;
181   }
182 
183   if (value.empty())
184   {
185     m_arg_x_filename = "empty string";
186     return true;
187   }
188 
189   m_arg_x_filename = value;
190   if (value == "error")
191   {
192     throw Glib::OptionError(Glib::OptionError::BAD_VALUE,
193       "on_option_arg_filename called with value = " + m_arg_x_filename);
194   }
195   return value != "false";
196 }
197 
198 int
main(int argc,char ** argv)199 main(int argc, char** argv)
200 {
201   // This example should be executed like so:
202   //./example --foo=1 --bar=2 --goo=abc
203   //./example --help
204 
205   Glib::init();
206 
207   // Set up the current locale.
208   setlocale(LC_ALL, "");
209 
210   Glib::OptionContext context;
211 
212   ExampleOptionGroup group;
213   context.set_main_group(group);
214 
215   try
216   {
217     context.parse(argc, argv);
218   }
219   catch (const Glib::Error& ex)
220   {
221     std::cout << "Exception: " << ex.what() << std::endl;
222   }
223 
224   std::cout << "parsed values: " << std::endl
225             << "  foo = " << group.m_arg_foo << std::endl
226             << "  filename = " << group.m_arg_filename << std::endl
227             << "  activate_something = " << (group.m_arg_boolean ? "enabled" : "disabled")
228             << std::endl
229             << "  goo = " << group.m_arg_goo << std::endl
230             << "  x-string = " << group.m_arg_x_string << std::endl
231             << "  x-filename = " << group.m_arg_x_filename << std::endl;
232 
233   // This one shows the results of multiple instance of the same option, such as --list=1 --list=a
234   // --list=b
235   std::cout << "  list = ";
236   for (const auto& i : group.m_arg_list)
237 
238   {
239     std::cout << i << ", ";
240   }
241   std::cout << std::endl;
242 
243   // This one shows the remaining arguments on the command line, which had no name= form:
244   std::cout << "  remaining = ";
245   for (const auto& i : group.m_remaining_list)
246   {
247     std::cout << i << ", ";
248   }
249   std::cout << std::endl;
250 
251   return 0;
252 }
253