comparison lwlib/lw_cmdline.c @ 6:1e5e8ec406fb

Various output cleanups for --help and --usage in lw_cmdline
author lost@l-w.ca
date Sat, 22 Jan 2011 09:31:43 -0700
parents 0e01d1343c02
children fdc11ef4115b
comparison
equal deleted inserted replaced
5:0e01d1343c02 6:1e5e8ec406fb
26 #include "lw_alloc.h" 26 #include "lw_alloc.h"
27 27
28 #define ___lw_cmdline_c_seen___ 28 #define ___lw_cmdline_c_seen___
29 #include "lw_cmdline.h" 29 #include "lw_cmdline.h"
30 30
31 #define DOCCOL 30
32 #define LLEN 78
33
31 static struct lw_cmdline_options builtin[3] = 34 static struct lw_cmdline_options builtin[3] =
32 { 35 {
33 { "help", '?', 0, 0, "give this help list" }, 36 { "help", '?', 0, 0, "give this help list" },
34 { "usage", 0, 0, 0, "give a short usage message" }, 37 { "usage", 0, 0, 0, "give a short usage message" },
35 { "version", 'V', 0, 0, "print program version" } 38 { "version", 'V', 0, 0, "print program version" }
36 }; 39 };
37 40
41 static int cmpr(const void *e1, const void *e2)
42 {
43 struct lw_cmdline_options **o1, **o2;
44 o1 = (struct lw_cmdline_options **)e1;
45 o2 = (struct lw_cmdline_options **)e2;
46
47 return strcmp((*o1) -> name, (*o2) -> name);
48 }
49
50 static int cmpr2(const void *e1, const void *e2)
51 {
52 struct lw_cmdline_options **o1, **o2;
53 o1 = (struct lw_cmdline_options **)e1;
54 o2 = (struct lw_cmdline_options **)e2;
55
56 if ((*o1) -> key < ((*o2) -> key))
57 return -1;
58 if ((*o1) -> key > ((*o2) -> key))
59 return 1;
60 return 0;
61 }
62
38 static void lw_cmdline_usage(struct lw_cmdline_parser *parser, char *name) 63 static void lw_cmdline_usage(struct lw_cmdline_parser *parser, char *name)
39 { 64 {
40 struct lw_cmdline_options **slist, **llist; 65 struct lw_cmdline_options **slist, **llist;
41 int nopt; 66 int nopt;
42 int i; 67 int i;
43 int t; 68 int t;
44 69 int col;
70
45 for (nopt = 0; parser -> options[nopt].name; nopt++) 71 for (nopt = 0; parser -> options[nopt].name; nopt++)
46 /* do nothing */ ; 72 /* do nothing */ ;
47 73
48 slist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3)); 74 slist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3));
49 llist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3)); 75 llist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3));
53 slist[i] = &(parser -> options[i]); 79 slist[i] = &(parser -> options[i]);
54 llist[i] = &(parser -> options[i]); 80 llist[i] = &(parser -> options[i]);
55 } 81 }
56 82
57 /* now sort the two lists */ 83 /* now sort the two lists */
84 qsort(slist, nopt, sizeof(struct lw_cmdline_options *), cmpr2);
85 qsort(llist, nopt, sizeof(struct lw_cmdline_options *), cmpr);
58 86
59 /* now append the automatic options */ 87 /* now append the automatic options */
60 slist[nopt] = &(builtin[0]); 88 slist[nopt] = &(builtin[0]);
61 slist[nopt + 1] = &(builtin[1]); 89 slist[nopt + 1] = &(builtin[1]);
62 slist[nopt + 2] = &(builtin[2]); 90 slist[nopt + 2] = &(builtin[2]);
66 llist[nopt + 2] = &(builtin[2]); 94 llist[nopt + 2] = &(builtin[2]);
67 95
68 /* now show the usage message */ 96 /* now show the usage message */
69 printf("Usage: %s", name); 97 printf("Usage: %s", name);
70 98
99 col = 7 + strlen(name);
100
71 /* print short options that take no args */ 101 /* print short options that take no args */
72 t = 0; 102 t = 0;
73 for (i = 0; i < nopt + 3; i++) 103 for (i = 0; i < nopt + 3; i++)
74 { 104 {
75 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f) 105 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f)
78 { 108 {
79 if (!t) 109 if (!t)
80 { 110 {
81 printf(" [-"); 111 printf(" [-");
82 t = 1; 112 t = 1;
113 col += 3;
83 } 114 }
84 printf("%c", slist[i]->key); 115 printf("%c", slist[i]->key);
116 col++;
85 } 117 }
86 } 118 }
87 } 119 }
88 if (t) 120 if (t)
121 {
122 col++;
89 printf("]"); 123 printf("]");
124 }
90 125
91 /* print short options that take args */ 126 /* print short options that take args */
92 for (i = 0; i < nopt + 3; i++) 127 for (i = 0; i < nopt + 3; i++)
93 { 128 {
94 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f && slist[i] -> arg) 129 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f && slist[i] -> arg)
95 { 130 {
96 if (slist[i]->flags & lw_cmdline_opt_optional) 131 if (slist[i]->flags & lw_cmdline_opt_optional)
97 { 132 {
133 t = 7 + strlen(slist[i] -> arg);
134 if (col + t > LLEN)
135 {
136 printf("\n ");
137 col = 7;
138 }
98 printf(" [-%c[%s]]", slist[i]->key, slist[i]->arg); 139 printf(" [-%c[%s]]", slist[i]->key, slist[i]->arg);
140 col += t;
99 } 141 }
100 else 142 else
101 { 143 {
144 t = 6 + strlen(slist[i] -> arg);
145 if (col + t > LLEN)
146 {
147 printf("\n ");
148 col = 7;
149 }
102 printf(" [-%c %s]", slist[i]->key, slist[i]->arg); 150 printf(" [-%c %s]", slist[i]->key, slist[i]->arg);
151 col += t;
103 } 152 }
104 } 153 }
105 } 154 }
106 155
107 /* print long options */ 156 /* print long options */
108 for (i = 0; i < nopt + 3; i++) 157 for (i = 0; i < nopt + 3; i++)
109 { 158 {
110 if (llist[i]->arg) 159 if (llist[i]->arg)
111 { 160 {
112 printf(" [--%s=%s%s%s]", 161 t = strlen(llist[i] -> name) + 6 + strlen(llist[i] -> arg);
162 if (llist[i] -> flags & lw_cmdline_opt_optional)
163 t += 2;
164 if (col + t > LLEN)
165 {
166 printf("\n ");
167 col = 7;
168 }
169 printf(" [--%s%s=%s%s]",
113 llist[i] -> name, 170 llist[i] -> name,
114 (llist[i] -> flags & lw_cmdline_opt_optional) ? "[" : "", 171 (llist[i] -> flags & lw_cmdline_opt_optional) ? "[" : "",
115 llist[i] -> arg, 172 llist[i] -> arg,
116 (llist[i] -> flags & lw_cmdline_opt_optional) ? "]" : ""); 173 (llist[i] -> flags & lw_cmdline_opt_optional) ? "]" : "");
174 col += t;
117 } 175 }
118 else 176 else
119 { 177 {
178 t = strlen(llist[i] -> name) + 5;
179 if (col + t > LLEN)
180 {
181 printf("\n ");
182 col = 7;
183 }
120 printf(" [--%s]", llist[i] -> name); 184 printf(" [--%s]", llist[i] -> name);
185 col += t;
121 } 186 }
122 } 187 }
123 188
124 /* print "non option" text */ 189 /* print "non option" text */
125 if (parser -> args_doc) 190 if (parser -> args_doc)
126 { 191 {
192 if (col + strlen(parser -> args_doc) + 1 > LLEN)
193 {
194 printf("\n ");
195 }
127 printf(" %s", parser -> args_doc); 196 printf(" %s", parser -> args_doc);
128 } 197 }
129 printf("\n"); 198 printf("\n");
130 199
131 /* clean up scratch lists */ 200 /* clean up scratch lists */
138 struct lw_cmdline_options **llist; 207 struct lw_cmdline_options **llist;
139 int nopt; 208 int nopt;
140 int i; 209 int i;
141 int t; 210 int t;
142 char *tstr; 211 char *tstr;
212 int col = 0;
143 213
144 tstr = parser -> doc; 214 tstr = parser -> doc;
145 for (nopt = 0; parser -> options[nopt].name; nopt++) 215 for (nopt = 0; parser -> options[nopt].name; nopt++)
146 /* do nothing */ ; 216 /* do nothing */ ;
147 217
151 { 221 {
152 llist[i] = &(parser -> options[i]); 222 llist[i] = &(parser -> options[i]);
153 } 223 }
154 224
155 /* now sort the list */ 225 /* now sort the list */
226 qsort(llist, nopt, sizeof(struct lw_cmdline_options *), cmpr);
156 227
157 /* now append the automatic options */ 228 /* now append the automatic options */
158 llist[nopt] = &(builtin[0]); 229 llist[nopt] = &(builtin[0]);
159 llist[nopt + 1] = &(builtin[1]); 230 llist[nopt + 1] = &(builtin[1]);
160 llist[nopt + 2] = &(builtin[2]); 231 llist[nopt + 2] = &(builtin[2]);
180 } 251 }
181 else 252 else
182 { 253 {
183 printf(" "); 254 printf(" ");
184 } 255 }
256 col = 8 + strlen(llist[i] -> name);
185 257
186 printf("--%s", llist[i] -> name); 258 printf("--%s", llist[i] -> name);
187 if (llist[i] -> arg) 259 if (llist[i] -> arg)
188 { 260 {
189 if (llist[i] -> flags & lw_cmdline_opt_optional) 261 if (llist[i] -> flags & lw_cmdline_opt_optional)
190 { 262 {
191 printf("[=%s]", llist[i] -> arg); 263 printf("[=%s]", llist[i] -> arg);
264 col += 3 + strlen(llist[i] -> arg);
192 } 265 }
193 else 266 else
194 { 267 {
195 printf("=%s", llist[i] -> arg); 268 printf("=%s", llist[i] -> arg);
269 col += 1 + strlen(llist[i] -> arg);
196 } 270 }
197 } 271 }
198 if (llist[i] -> doc) 272 if (llist[i] -> doc)
199 { 273 {
200 printf("\t\t%s", llist[i] -> doc); 274 char *s = llist[i] -> doc;
275 char *s2;
276
277 while (*s && isspace(*s))
278 s++;
279
280 if (col > DOCCOL)
281 {
282 fputc('\n', stdout);
283 col = 0;
284 }
285 while (*s)
286 {
287 while (col < (DOCCOL - 1))
288 {
289 fputc(' ', stdout);
290 col++;
291 }
292 for (s2 = s; *s2 && !isspace(*s2); s2++)
293 /* do nothing */ ;
294 if ((col + (s2 - s) + 1) > LLEN && col >= DOCCOL)
295 {
296 /* next line */
297 fputc('\n', stdout);
298 col = 0;
299 continue;
300 }
301 col++;
302 fputc(' ', stdout);
303 while (s != s2)
304 {
305 fputc(*s, stdout);
306 col++;
307 s++;
308 }
309 while (*s && isspace(*s))
310 s++;
311 }
201 } 312 }
202 fputc('\n', stdout); 313 fputc('\n', stdout);
203 } 314 }
204 315
205 printf("\nMandatory or optional arguments to long options are also mandatory or optional\nfor any corresponding short options.\n"); 316 printf("\nMandatory or optional arguments to long options are also mandatory or optional\nfor any corresponding short options.\n");