summaryrefslogtreecommitdiff
path: root/examples/options/main.cc
blob: f0f06699496cfe3f833bb7387b685c0d5cfeedc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/* Copyright (C) 2004 The glibmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glibmm.h>
#include <iomanip>
#include <iostream>


class ExampleOptionGroup : public Glib::OptionGroup
{ 
public:
  ExampleOptionGroup();

  virtual bool on_pre_parse(Glib::OptionContext& context, Glib::OptionGroup& group);
  virtual bool on_post_parse(Glib::OptionContext& context, Glib::OptionGroup& group);
  virtual void on_error(Glib::OptionContext& context, Glib::OptionGroup& group);

  bool on_option_arg_string(const Glib::ustring& option_name,
    const Glib::ustring& value, bool has_value);
  bool on_option_arg_filename(const Glib::ustring& option_name,
    const std::string& value, bool has_value);

  //These members should live as long as the OptionGroup to which they are added, 
  //and as long as the OptionContext to which that OptionGroup is added.
  int m_arg_foo;
  std::string m_arg_filename;
  Glib::ustring m_arg_goo;
  bool m_arg_boolean;
  Glib::OptionGroup::vecustrings m_arg_list;
  Glib::OptionGroup::vecustrings m_remaining_list;
  Glib::ustring m_arg_x_string;
  std::string m_arg_x_filename;
};

ExampleOptionGroup::ExampleOptionGroup()
: Glib::OptionGroup("example_group", "description of example group", "help description of example group"),
  m_arg_foo(0), m_arg_boolean(false)
{
  Glib::OptionEntry entry1;
  entry1.set_long_name("foo");
  entry1.set_short_name('f');
  entry1.set_description("The Foo");
  add_entry(entry1, m_arg_foo);
      
  Glib::OptionEntry entry2;
  entry2.set_long_name("file");
  entry2.set_short_name('F');
  entry2.set_description("The Filename");
  add_entry_filename(entry2, m_arg_filename);
 
  Glib::OptionEntry entry3;
  entry3.set_long_name("goo");
  entry3.set_short_name('g');
  entry3.set_description("The Goo");
  m_arg_goo = "default-goo-value"; //We can choose a default to be used if the user doesn't specify this option.
  add_entry(entry3, m_arg_goo);
  
  Glib::OptionEntry entry4;
  entry4.set_long_name("activate_something");
  entry4.set_description("Activate something");
  add_entry(entry4, m_arg_boolean);
  
  Glib::OptionEntry entry5;
  entry5.set_long_name("list");
  entry5.set_short_name('l');
  entry5.set_description("A List");
  add_entry(entry5, m_arg_list);

  Glib::OptionEntry entry6;
  entry6.set_long_name("x-string");
  entry6.set_short_name('x');
  entry6.set_description("A string with custom parsing");
  entry6.set_flags(Glib::OptionEntry::FLAG_OPTIONAL_ARG);
  m_arg_x_string = "not specified";
  add_entry(entry6, sigc::mem_fun(*this, &ExampleOptionGroup::on_option_arg_string));

  Glib::OptionEntry entry7;
  entry7.set_long_name("x-filename");
  entry7.set_short_name('X');
  entry7.set_description("A filename with custom parsing");
  entry7.set_flags(Glib::OptionEntry::FLAG_OPTIONAL_ARG);
  m_arg_x_filename = "not specified";
  add_entry_filename(entry7, sigc::mem_fun(*this, &ExampleOptionGroup::on_option_arg_filename));

  Glib::OptionEntry entry_remaining;
  entry_remaining.set_long_name(G_OPTION_REMAINING);
  entry_remaining.set_arg_description(G_OPTION_REMAINING);

  add_entry(entry_remaining, m_remaining_list);
}

bool ExampleOptionGroup::on_pre_parse(Glib::OptionContext& /* context */, Glib::OptionGroup& /* group */)
{
  //This is called before the m_arg_* instances are given their values.
  // You do not need to override this method. This is just here to show you how,
  // in case you want to do any extra processing.
  std::cout << "on_pre_parse called" << std::endl;
  return true;
}

bool ExampleOptionGroup::on_post_parse(Glib::OptionContext& /* context */, Glib::OptionGroup& /* group */)
{
  //This is called after the m_arg_* instances are given their values.
  // You do not need to override this method. This is just here to show you how,
  // in case you want to do any extra processing.
  std::cout << "on_post_parse called" << std::endl;
  return true;
}

void ExampleOptionGroup::on_error(Glib::OptionContext& /* context */, Glib::OptionGroup& /* group */)
{
  std::cout << "on_error called" << std::endl;
}

bool ExampleOptionGroup::on_option_arg_string(const Glib::ustring& option_name,
    const Glib::ustring& value, bool has_value)
{
  if(option_name != "-x" && option_name != "--x-string")
  {
    m_arg_x_string = "on_option_arg_string called with unexpected option_name: " + option_name;
    throw Glib::OptionError(Glib::OptionError::UNKNOWN_OPTION, m_arg_x_string);
  }

  if(!has_value)
  {
    m_arg_x_string = "no value";
    return true;
  }

  if(value.empty())
  {
    m_arg_x_string = "empty string";
    return true;
  }

  m_arg_x_string = value;
  if(value == "error")
  {
    throw Glib::OptionError(Glib::OptionError::BAD_VALUE,
      "on_option_arg_string called with value = " + m_arg_x_string);
  }
  return value != "false";
}

bool ExampleOptionGroup::on_option_arg_filename(const Glib::ustring& option_name,
    const std::string& value, bool has_value)
{
  if(option_name != "-X" && option_name != "--x-filename")
  {
    m_arg_x_filename = "on_option_arg_filename called with unexpected option_name: " + option_name;
    throw Glib::OptionError(Glib::OptionError::UNKNOWN_OPTION, m_arg_x_filename);
  }

  if(!has_value)
  {
    m_arg_x_filename = "no value";
    return true;
  }

  if(value.empty())
  {
    m_arg_x_filename = "empty string";
    return true;
  }

  m_arg_x_filename = value;
  if(value == "error")
  {
    throw Glib::OptionError(Glib::OptionError::BAD_VALUE,
      "on_option_arg_filename called with value = " + m_arg_x_filename);
  }
  return value != "false";
}


int main(int argc, char** argv)
{
  //This example should be executed like so:
  //./example --foo=1 --bar=2 --goo=abc
  //./example --help
  
  Glib::init();

  //Set up the current locale.
  setlocale(LC_ALL, "");

  Glib::OptionContext context;
  
  ExampleOptionGroup group;
  context.set_main_group(group);
  
  try
  {
    context.parse(argc, argv);
  }
  catch(const Glib::Error& ex)
  {
    std::cout << "Exception: " << ex.what() << std::endl;
  }

  std::cout << "parsed values: " << std::endl <<
    "  foo = " << group.m_arg_foo << std::endl << 
    "  filename = " << group.m_arg_filename << std::endl <<
    "  activate_something = " << (group.m_arg_boolean ? "enabled" : "disabled") << std::endl <<
    "  goo = " << group.m_arg_goo << std::endl <<
    "  x-string = " << group.m_arg_x_string << std::endl <<
    "  x-filename = " << group.m_arg_x_filename << std::endl;
    
  //This one shows the results of multiple instance of the same option, such as --list=1 --list=a --list=b
  std::cout << "  list = ";
  for(auto iter = group.m_arg_list.begin(); iter != group.m_arg_list.end(); ++iter)
  {
    std::cout << *iter << ", ";
  }
  std::cout << std::endl;

  //This one shows the remaining arguments on the command line, which had no name= form:
  std::cout << "  remaining = ";
  for(auto iter = group.m_remaining_list.begin(); iter != group.m_remaining_list.end(); ++iter)
  {
    std::cout << *iter << ", ";
  }
  std::cout << std::endl;
 
  return 0;
}