@@ -123,7 +123,7 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
123
123
}
124
124
125
125
int parse_options (int argc , const char * * argv , const struct option * options ,
126
- const char * usagestr , int flags )
126
+ const char * const usagestr [] , int flags )
127
127
{
128
128
struct optparse_t args = { argv + 1 , argc - 1 , NULL };
129
129
int j = 0 ;
@@ -140,9 +140,9 @@ int parse_options(int argc, const char **argv, const struct option *options,
140
140
args .opt = arg + 1 ;
141
141
do {
142
142
if (* args .opt == 'h' )
143
- usage (usagestr );
143
+ usage_with_options (usagestr , options );
144
144
if (parse_short_opt (& args , options ) < 0 )
145
- usage (usagestr );
145
+ usage_with_options (usagestr , options );
146
146
} while (args .opt );
147
147
continue ;
148
148
}
@@ -156,12 +156,75 @@ int parse_options(int argc, const char **argv, const struct option *options,
156
156
}
157
157
158
158
if (!strcmp (arg + 2 , "help" ))
159
- usage (usagestr );
159
+ usage_with_options (usagestr , options );
160
160
if (parse_long_opt (& args , arg + 2 , options ))
161
- usage (usagestr );
161
+ usage_with_options (usagestr , options );
162
162
}
163
163
164
164
memmove (argv + j , args .argv , args .argc * sizeof (* argv ));
165
165
argv [j + args .argc ] = NULL ;
166
166
return j + args .argc ;
167
167
}
168
+
169
+ #define USAGE_OPTS_WIDTH 24
170
+ #define USAGE_GAP 2
171
+
172
+ void usage_with_options (const char * const * usagestr ,
173
+ const struct option * opts )
174
+ {
175
+ struct strbuf sb ;
176
+
177
+ strbuf_init (& sb , 4096 );
178
+ strbuf_addstr (& sb , * usagestr );
179
+ strbuf_addch (& sb , '\n' );
180
+ while (* ++ usagestr )
181
+ strbuf_addf (& sb , " %s\n" , * usagestr );
182
+
183
+ if (opts -> type != OPTION_GROUP )
184
+ strbuf_addch (& sb , '\n' );
185
+
186
+ for (; opts -> type != OPTION_END ; opts ++ ) {
187
+ size_t pos ;
188
+ int pad ;
189
+
190
+ if (opts -> type == OPTION_GROUP ) {
191
+ strbuf_addch (& sb , '\n' );
192
+ if (* opts -> help )
193
+ strbuf_addf (& sb , "%s\n" , opts -> help );
194
+ continue ;
195
+ }
196
+
197
+ pos = sb .len ;
198
+ strbuf_addstr (& sb , " " );
199
+ if (opts -> short_name )
200
+ strbuf_addf (& sb , "-%c" , opts -> short_name );
201
+ if (opts -> long_name && opts -> short_name )
202
+ strbuf_addstr (& sb , ", " );
203
+ if (opts -> long_name )
204
+ strbuf_addf (& sb , "--%s" , opts -> long_name );
205
+
206
+ switch (opts -> type ) {
207
+ case OPTION_INTEGER :
208
+ strbuf_addstr (& sb , " <n>" );
209
+ break ;
210
+ case OPTION_STRING :
211
+ if (opts -> argh )
212
+ strbuf_addf (& sb , " <%s>" , opts -> argh );
213
+ else
214
+ strbuf_addstr (& sb , " ..." );
215
+ break ;
216
+ default :
217
+ break ;
218
+ }
219
+
220
+ pad = sb .len - pos ;
221
+ if (pad <= USAGE_OPTS_WIDTH )
222
+ pad = USAGE_OPTS_WIDTH - pad ;
223
+ else {
224
+ strbuf_addch (& sb , '\n' );
225
+ pad = USAGE_OPTS_WIDTH ;
226
+ }
227
+ strbuf_addf (& sb , "%*s%s\n" , pad + USAGE_GAP , "" , opts -> help );
228
+ }
229
+ usage (sb .buf );
230
+ }
0 commit comments