@@ -49,21 +49,21 @@ namespace boost { namespace program_options {
49
49
}
50
50
51
51
option_description::
52
- option_description (const char * name ,
52
+ option_description (const char * names ,
53
53
const value_semantic* s)
54
54
: m_value_semantic(s)
55
55
{
56
- this ->set_name (name );
56
+ this ->set_names (names );
57
57
}
58
58
59
59
60
60
option_description::
61
- option_description (const char * name ,
61
+ option_description (const char * names ,
62
62
const value_semantic* s,
63
63
const char * description)
64
64
: m_description(description), m_value_semantic(s)
65
65
{
66
- this ->set_name (name );
66
+ this ->set_names (names );
67
67
}
68
68
69
69
option_description::~option_description ()
@@ -77,38 +77,42 @@ namespace boost { namespace program_options {
77
77
bool short_ignore_case) const
78
78
{
79
79
match_result result = no_match;
80
+ std::string local_option = (long_ignore_case ? tolower_ (option) : option);
80
81
81
- std::string local_long_name ((long_ignore_case ? tolower_ (m_long_name) : m_long_name));
82
-
83
- if (!local_long_name.empty ()) {
84
-
85
- std::string local_option = (long_ignore_case ? tolower_ (option) : option);
82
+ for (std::vector<std::string>::const_iterator it (m_long_names.begin ()); it != m_long_names.end (); it++)
83
+ {
84
+ std::string local_long_name ((long_ignore_case ? tolower_ (*it) : *it));
86
85
87
- if (*local_long_name.rbegin () == ' *' )
88
- {
89
- // The name ends with '*'. Any specified name with the given
90
- // prefix is OK.
91
- if (local_option.find (local_long_name.substr (0 , local_long_name.length ()-1 ))
92
- == 0 )
93
- result = approximate_match;
94
- }
86
+ if (!local_long_name.empty ()) {
95
87
96
- if (local_long_name == local_option)
97
- {
98
- result = full_match;
99
- }
100
- else if (approx)
101
- {
102
- if (local_long_name.find (local_option) == 0 )
88
+
89
+ if ((result == no_match) && (*local_long_name.rbegin () == ' *' ))
90
+ {
91
+ // The name ends with '*'. Any specified name with the given
92
+ // prefix is OK.
93
+ if (local_option.find (local_long_name.substr (0 , local_long_name.length ()-1 ))
94
+ == 0 )
95
+ result = approximate_match;
96
+ }
97
+
98
+ if (local_long_name == local_option)
99
+ {
100
+ result = full_match;
101
+ break ;
102
+ }
103
+ else if (approx)
103
104
{
104
- result = approximate_match;
105
+ if (local_long_name.find (local_option) == 0 )
106
+ {
107
+ result = approximate_match;
108
+ }
105
109
}
106
110
}
111
+
107
112
}
108
-
113
+
109
114
if (result != full_match)
110
115
{
111
- std::string local_option (short_ignore_case ? tolower_ (option) : option);
112
116
std::string local_short_name (short_ignore_case ? tolower_ (m_short_name) : m_short_name);
113
117
114
118
if (local_short_name == local_option)
@@ -122,30 +126,35 @@ namespace boost { namespace program_options {
122
126
123
127
const std::string&
124
128
option_description::key (const std::string& option) const
125
- {
126
- if (!m_long_name.empty ())
127
- if (m_long_name.find (' *' ) != string::npos)
129
+ {
130
+ // We make the arbitrary choise of using the first long
131
+ // name as the key, regardless of anything else
132
+ if (!m_long_names.empty ()) {
133
+ const std::string& first_long_name = *m_long_names.begin ();
134
+ if (first_long_name.find (' *' ) != string::npos)
128
135
// The '*' character means we're long_name
129
136
// matches only part of the input. So, returning
130
137
// long name will remove some of the information,
131
138
// and we have to return the option as specified
132
139
// in the source.
133
140
return option;
134
141
else
135
- return m_long_name;
142
+ return first_long_name;
143
+ }
136
144
else
137
145
return m_short_name;
138
146
}
139
147
140
148
std::string
141
149
option_description::canonical_display_name (int prefix_style) const
142
150
{
143
- if (!m_long_name.empty ())
151
+ // We prefer the first long name over any others
152
+ if (!m_long_names.empty ())
144
153
{
145
154
if (prefix_style == command_line_style::allow_long)
146
- return " --" + m_long_name ;
155
+ return " --" + *m_long_names. begin () ;
147
156
if (prefix_style == command_line_style::allow_long_disguise)
148
- return " -" + m_long_name ;
157
+ return " -" + *m_long_names. begin () ;
149
158
}
150
159
// sanity check: m_short_name[0] should be '-' or '/'
151
160
if (m_short_name.length () == 2 )
@@ -155,8 +164,8 @@ namespace boost { namespace program_options {
155
164
if (prefix_style == command_line_style::allow_dash_for_short)
156
165
return string (" -" ) + m_short_name[1 ];
157
166
}
158
- if (!m_long_name .empty ())
159
- return m_long_name ;
167
+ if (!m_long_names .empty ())
168
+ return *m_long_names. begin () ;
160
169
else
161
170
return m_short_name;
162
171
}
@@ -165,21 +174,46 @@ namespace boost { namespace program_options {
165
174
const std::string&
166
175
option_description::long_name () const
167
176
{
168
- return m_long_name;
177
+ static std::string empty_string (" " );
178
+ return m_long_names.empty () ? empty_string : *m_long_names.begin ();
179
+ }
180
+
181
+ const std::pair<const std::string*, std::size_t >
182
+ option_description::long_names () const
183
+ {
184
+ return (m_long_names.empty ())
185
+ ? std::pair<const std::string*, size_t >( NULL , 0 )
186
+ : std::pair<const std::string*, size_t >( &(*m_long_names.begin ()), m_long_names.size ());
169
187
}
170
188
171
189
option_description&
172
- option_description::set_name (const char * _name )
190
+ option_description::set_names (const char * _names )
173
191
{
174
- std::string name (_name);
175
- string::size_type n = name.find (' ,' );
176
- if (n != string::npos) {
177
- assert (n == name.size ()-2 );
178
- m_long_name = name.substr (0 , n);
179
- m_short_name = ' -' + name.substr (n+1 ,1 );
180
- } else {
181
- m_long_name = name;
192
+ m_long_names.clear ();
193
+ std::istringstream iss (_names);
194
+ std::string name;
195
+
196
+ while (std::getline (iss, name, ' ,' )) {
197
+ m_long_names.push_back (name);
198
+ }
199
+ assert (!m_long_names.empty () && " No option names were specified" );
200
+
201
+ bool try_interpreting_last_name_as_a_switch = m_long_names.size () > 1 ;
202
+ if (try_interpreting_last_name_as_a_switch) {
203
+ const std::string& last_name = *m_long_names.rbegin ();
204
+ if (last_name.length () == 1 ) {
205
+ m_short_name = ' -' + last_name;
206
+ m_long_names.pop_back ();
207
+ // The following caters to the (valid) input of ",c" for some
208
+ // character c, where the caller only wants this option to have
209
+ // a short name.
210
+ if (m_long_names.size () == 1 && (*m_long_names.begin ()).empty ()) {
211
+ m_long_names.clear ();
212
+ }
213
+ }
182
214
}
215
+ // We could theoretically also ensure no remaining long names
216
+ // are empty, or that none of them have length 1
183
217
return *this ;
184
218
}
185
219
@@ -200,12 +234,12 @@ namespace boost { namespace program_options {
200
234
{
201
235
if (!m_short_name.empty ())
202
236
{
203
- return m_long_name .empty ()
237
+ return m_long_names .empty ()
204
238
? m_short_name
205
239
: string (m_short_name).append (" [ --" ).
206
- append (m_long_name ).append (" ]" );
240
+ append (*m_long_names. begin () ).append (" ]" );
207
241
}
208
- return string (" --" ).append (m_long_name );
242
+ return string (" --" ).append (*m_long_names. begin () );
209
243
}
210
244
211
245
std::string
0 commit comments