Commit 256e0eb6 256e0eb62991288b84d9e852e82c2911699316b1 by Sergey Poznyakoff

Implemented

1 parent fc77c565
Showing 1 changed file with 202 additions and 18 deletions
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
19 19
20 #include <mh.h> 20 #include <mh.h>
21 #include <regex.h> 21 #include <regex.h>
22 #include <pick.h>
23 #include <pick-gram.h>
24 #define obstack_chunk_alloc malloc
25 #define obstack_chunk_free free
26 #include <obstack.h>
22 27
23 const char *argp_program_version = "pick (" PACKAGE_STRING ")"; 28 const char *argp_program_version = "pick (" PACKAGE_STRING ")";
24 static char doc[] = N_("GNU MH pick\v" 29 static char doc[] = N_("GNU MH pick\v"
...@@ -37,6 +42,8 @@ static struct argp_option options[] = { ...@@ -37,6 +42,8 @@ static struct argp_option options[] = {
37 {"pattern", ARG_PATTERN, N_("STRING"), 0, 42 {"pattern", ARG_PATTERN, N_("STRING"), 0,
38 N_("A pattern to look for"), 1}, 43 N_("A pattern to look for"), 1},
39 {"search", 0, NULL, OPTION_ALIAS, NULL, 1}, 44 {"search", 0, NULL, OPTION_ALIAS, NULL, 1},
45 {"cflags", ARG_CFLAGS, N_("STRING"), 0,
46 N_("Flags controlling the type of regular expressions. STRING must consist of one or more of the following letters: B=basic, E=extended, I=ignore case, C=case sensitive. Default is \"EI\". The flags remain in effect until the next occurrence of --cflags option. The option must occur right before --pattern or --component option (or its alias).") },
40 {"cc", ARG_CC, N_("STRING"), 0, 47 {"cc", ARG_CC, N_("STRING"), 0,
41 N_("Same as --component cc --pattern STRING"), 1}, 48 N_("Same as --component cc --pattern STRING"), 1},
42 {"date", ARG_DATE, N_("STRING"), 0, 49 {"date", ARG_DATE, N_("STRING"), 0,
...@@ -50,11 +57,11 @@ static struct argp_option options[] = { ...@@ -50,11 +57,11 @@ static struct argp_option options[] = {
50 57
51 {N_("Date constraint operations:"), 0, NULL, OPTION_DOC, NULL, 1}, 58 {N_("Date constraint operations:"), 0, NULL, OPTION_DOC, NULL, 1},
52 {"datefield",ARG_DATEFIELD, N_("STRING"), 0, 59 {"datefield",ARG_DATEFIELD, N_("STRING"), 0,
53 N_("Search in the named date header field (default is `Date:')"), 2}, 60 N_("* Search in the named date header field (default is `Date:')"), 2},
54 {"after", ARG_AFTER, N_("DATE"), 0, 61 {"after", ARG_AFTER, N_("DATE"), 0,
55 N_("Match messages after the given date"), 2}, 62 N_("* Match messages after the given date"), 2},
56 {"before", ARG_BEFORE, N_("DATE"), 0, 63 {"before", ARG_BEFORE, N_("DATE"), 0,
57 N_("Match messages before the given date"), 2}, 64 N_("* Match messages before the given date"), 2},
58 65
59 {N_("Logical operations and grouping:"), 0, NULL, OPTION_DOC, NULL, 2}, 66 {N_("Logical operations and grouping:"), 0, NULL, OPTION_DOC, NULL, 2},
60 {"and", ARG_AND, NULL, 0, 67 {"and", ARG_AND, NULL, 0,
...@@ -111,13 +118,32 @@ struct mh_option mh_option[] = { ...@@ -111,13 +118,32 @@ struct mh_option mh_option[] = {
111 {NULL} 118 {NULL}
112 }; 119 };
113 120
114 static int list; 121 static int list = 1;
115 static int mode_public = 1; 122 static int seq_flags = 0; /* Create public sequences;
116 static int mode_zero = 0; 123 Do not zero the sequence before addition */
124 static list_t seq_list; /* List of sequence names to operate upon */
125
126 static list_t lexlist; /* List of input tokens */
127
128 static struct obstack msgno_stk; /* Stack of selected message numbers */
129 static size_t msgno_count; /* Number of items on the stack */
130
131 static void
132 add_sequence (char *name)
133 {
134 if (!seq_list && list_create (&seq_list))
135 {
136 mh_error (_("can't create sequence list"));
137 exit (1);
138 }
139 list_append (seq_list, name);
140 }
117 141
118 static int 142 static int
119 opt_handler (int key, char *arg, void *unused) 143 opt_handler (int key, char *arg, void *unused, struct argp_state *state)
120 { 144 {
145 char *s, *p;
146
121 switch (key) 147 switch (key)
122 { 148 {
123 case '+': 149 case '+':
...@@ -126,7 +152,8 @@ opt_handler (int key, char *arg, void *unused) ...@@ -126,7 +152,8 @@ opt_handler (int key, char *arg, void *unused)
126 break; 152 break;
127 153
128 case ARG_SEQUENCE: 154 case ARG_SEQUENCE:
129 /* add_sequence (arg); */ 155 add_sequence (arg);
156 list = 0;
130 break; 157 break;
131 158
132 case ARG_LIST: 159 case ARG_LIST:
...@@ -137,52 +164,209 @@ opt_handler (int key, char *arg, void *unused) ...@@ -137,52 +164,209 @@ opt_handler (int key, char *arg, void *unused)
137 list = 0; 164 list = 0;
138 break; 165 break;
139 166
140 case ARG_COMPONENT: 167 case ARG_COMPONENT:
141 case ARG_PATTERN: 168 pick_add_token (&lexlist, T_COMP, arg);
142 case ARG_CC: 169 break;
170
171 case ARG_PATTERN:
172 pick_add_token (&lexlist, T_STRING, arg);
173 break;
174
175 case ARG_CC:
176 pick_add_token (&lexlist, T_COMP, "cc");
177 pick_add_token (&lexlist, T_STRING, arg);
178 break;
179
143 case ARG_DATE: 180 case ARG_DATE:
181 pick_add_token (&lexlist, T_COMP, "date");
182 pick_add_token (&lexlist, T_STRING, arg);
183 break;
184
144 case ARG_FROM: 185 case ARG_FROM:
186 pick_add_token (&lexlist, T_COMP, "from");
187 pick_add_token (&lexlist, T_STRING, arg);
188 break;
189
145 case ARG_SUBJECT: 190 case ARG_SUBJECT:
146 case ARG_TO: 191 pick_add_token (&lexlist, T_COMP, "subject");
192 pick_add_token (&lexlist, T_STRING, arg);
193 break;
194
195 case ARG_TO:
196 pick_add_token (&lexlist, T_COMP, "to");
197 pick_add_token (&lexlist, T_STRING, arg);
198 break;
199
147 case ARG_DATEFIELD: 200 case ARG_DATEFIELD:
201 pick_add_token (&lexlist, T_DATEFIELD, arg);
202 break;
203
148 case ARG_AFTER: 204 case ARG_AFTER:
205 pick_add_token (&lexlist, T_AFTER, NULL);
206 pick_add_token (&lexlist, T_STRING, arg);
207 break;
208
149 case ARG_BEFORE: 209 case ARG_BEFORE:
210 pick_add_token (&lexlist, T_BEFORE, NULL);
211 pick_add_token (&lexlist, T_STRING, arg);
212 break;
213
150 case ARG_AND: 214 case ARG_AND:
215 pick_add_token (&lexlist, T_AND, NULL);
216 break;
217
151 case ARG_OR: 218 case ARG_OR:
219 pick_add_token (&lexlist, T_OR, NULL);
220 break;
221
152 case ARG_NOT: 222 case ARG_NOT:
223 pick_add_token (&lexlist, T_NOT, NULL);
224 break;
225
153 case ARG_LBRACE: 226 case ARG_LBRACE:
227 pick_add_token (&lexlist, T_LBRACE, NULL);
228 break;
229
154 case ARG_RBRACE: 230 case ARG_RBRACE:
231 pick_add_token (&lexlist, T_RBRACE, NULL);
232 break;
233
234 case ARG_CFLAGS:
235 pick_add_token (&lexlist, T_CFLAGS, arg);
155 break; 236 break;
156 237
157 case ARG_PUBLIC: 238 case ARG_PUBLIC:
158 mode_public = is_true (arg); 239 if (is_true (arg))
240 seq_flags &= ~SEQ_PRIVATE;
241 else
242 seq_flags |= SEQ_PRIVATE;
159 break; 243 break;
160 244
161 case ARG_NOPUBLIC: 245 case ARG_NOPUBLIC:
162 mode_public = 0; 246 seq_flags |= SEQ_PRIVATE;
163 break; 247 break;
164 248
165 case ARG_ZERO: 249 case ARG_ZERO:
166 mode_zero = is_true (arg); 250 if (is_true (arg))
251 seq_flags |= SEQ_ZERO;
252 else
253 seq_flags &= ~SEQ_ZERO;
167 break; 254 break;
168 255
169 case ARG_NOZERO: 256 case ARG_NOZERO:
170 mode_zero = 0; 257 seq_flags &= ~SEQ_ZERO;
258 break;
259
260 case ARGP_KEY_ERROR:
261 s = state->argv[state->next - 1];
262 if (memcmp (s, "--", 2))
263 {
264 argp_error (state, _("invalid option -- %s"), s);
265 exit (1);
266 }
267 p = strchr (s, '=');
268 if (p)
269 *p++ = 0;
270
271 pick_add_token (&lexlist, T_COMP, s + 2);
272
273 if (!p)
274 {
275 if (state->next == state->argc)
276 {
277 mh_error (_("invalid option -- %s"), s);
278 exit (1);
279 }
280 p = state->argv[state->next++];
281 }
282
283 pick_add_token (&lexlist, T_STRING, p);
171 break; 284 break;
172 285
173 default: 286 default:
174 return 1; 287 return 1;
175 } 288 }
289
176 return 0; 290 return 0;
177 } 291 }
178 292
293 void
294 pick_message (mailbox_t mbox, message_t msg, size_t num, void *data)
295 {
296 if (pick_eval (msg))
297 {
298 mh_message_number (msg, &num);
299 if (list)
300 printf ("%lu\n", (unsigned long) num);
301 if (seq_list)
302 {
303 obstack_grow (&msgno_stk, &num, sizeof (num));
304 msgno_count++;
305 }
306 }
307 }
308
309 static int
310 action_add (void *item, void *data)
311 {
312 mh_seq_add ((char *)item, (mh_msgset_t *)data, seq_flags);
313 return 0;
314 }
315
316 /* NOTICE: For the compatibility with the RAND MH we have to support
317 the following command line syntax:
318
319 --FIELD STRING
320
321 where `FIELD' may be any string and which is equivalent to
322 `--field FIELD --pattern STRING'. Obviously this is in conflict
323 with the usual GNU long options paradigm which requires that any
324 unrecognized long option produce an error. Unfortunately, mh-pick.el
325 relies heavily on this syntax, so it can't be simply removed.
326 The approach taken here allows to properly recognize such syntax,
327 however it has an undesirable side effect: due to the specifics of
328 the underlying arpg library the --help and --usage options get
329 disabled. To make them work as well, the following approach is
330 taken: the mh-compatible syntax gets enabled only if the file
331 descriptor of stdin is not connected to a terminal, which is true
332 when invoked from mh-pick.el module. Otherwise, it is disabled
333 and the standard GNU long option syntax is in force. */
179 int 334 int
180 main (int argc, char **argv) 335 main (int argc, char **argv)
181 { 336 {
337 int status;
182 int index; 338 int index;
339 mailbox_t mbox;
340 mh_msgset_t msgset;
341 int flags;
183 342
343 flags = isatty (0) ? 0 : ARGP_NO_ERRS;
184 mu_init_nls (); 344 mu_init_nls ();
185 mh_argp_parse (argc, argv, options, mh_option, args_doc, doc, 345 mh_argp_parse (argc, argv, flags, options, mh_option,
186 opt_handler, NULL, &index); 346 args_doc, doc, opt_handler, NULL, &index);
347 if (pick_parse (lexlist))
348 return 1;
349
350 mbox = mh_open_folder (current_folder, 0);
351
352 argc -= index;
353 argv += index;
354
355 if (seq_list)
356 obstack_init (&msgno_stk);
357
358 mh_msgset_parse (mbox, &msgset, argc, argv, "all");
359 status = mh_iterate (mbox, &msgset, pick_message, NULL);
360
361 if (seq_list)
362 {
363 mh_msgset_t msgset;
364 msgset.count = msgno_count;
365 msgset.list = obstack_finish (&msgno_stk);
366 list_do (seq_list, action_add, (void*) &msgset);
367 }
368
369 mh_global_save_state ();
370 return status;
187 } 371 }
188 372
......