1 Return-Path: <Sebastian@SSpaeth.de>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id C8E67431FD8
\r
6 for <notmuch@notmuchmail.org>; Tue, 26 Jan 2010 03:44:23 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-1.837 tagged_above=-999 required=5 tests=[AWL=0.762,
\r
12 BAYES_00=-2.599] autolearn=ham
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id x-rBuP++X4Cn for <notmuch@notmuchmail.org>;
\r
16 Tue, 26 Jan 2010 03:44:21 -0800 (PST)
\r
17 Received: from homiemail-a20.g.dreamhost.com (caiajhbdccah.dreamhost.com
\r
19 by olra.theworths.org (Postfix) with ESMTP id D7F1F431FBD
\r
20 for <notmuch@notmuchmail.org>; Tue, 26 Jan 2010 03:44:20 -0800 (PST)
\r
21 Received: from localhost.localdomain (mtec-hg-docking-2-dhcp-062.ethz.ch
\r
23 by homiemail-a20.g.dreamhost.com (Postfix) with ESMTPA id C68F97EC061;
\r
24 Tue, 26 Jan 2010 03:44:19 -0800 (PST)
\r
25 From: Sebastian Spaeth <Sebastian@SSpaeth.de>
\r
26 To: notmuch@notmuchmail.org
\r
27 Date: Tue, 26 Jan 2010 12:43:41 +0100
\r
28 Message-Id: <1264506221-9636-4-git-send-email-Sebastian@SSpaeth.de>
\r
29 X-Mailer: git-send-email 1.6.3.3
\r
30 In-Reply-To: <1264506221-9636-3-git-send-email-Sebastian@SSpaeth.de>
\r
31 References: <1264506221-9636-1-git-send-email-Sebastian@SSpaeth.de>
\r
32 <1264506221-9636-2-git-send-email-Sebastian@SSpaeth.de>
\r
33 <1264506221-9636-3-git-send-email-Sebastian@SSpaeth.de>
\r
34 Subject: [notmuch] [PATCH 4/4] integrate keithp's date.c into the notmuch
\r
35 date parser and delete my previous own attempt
\r
36 X-BeenThere: notmuch@notmuchmail.org
\r
37 X-Mailman-Version: 2.1.13
\r
39 List-Id: "Use and development of the notmuch mail system."
\r
40 <notmuch.notmuchmail.org>
\r
41 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
42 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
43 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
44 List-Post: <mailto:notmuch@notmuchmail.org>
\r
45 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
46 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
47 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
48 X-List-Received-Date: Tue, 26 Jan 2010 11:44:24 -0000
\r
50 Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
\r
52 lib/database.cc | 84 ++++++++++--------------------------------------------
\r
53 lib/date.c | 59 ++++++--------------------------------
\r
54 lib/notmuch.h | 20 +++++++++++++
\r
56 notmuch.1 | 33 +++++++++++----------
\r
57 notmuch.c | 20 +++++++------
\r
58 6 files changed, 74 insertions(+), 143 deletions(-)
\r
60 diff --git a/lib/database.cc b/lib/database.cc
\r
61 index b386e1a..78cd898 100644
\r
62 --- a/lib/database.cc
\r
63 +++ b/lib/database.cc
\r
64 @@ -219,6 +219,8 @@ notmuch_status_to_string (notmuch_status_t status)
\r
65 return "Erroneous NULL pointer";
\r
66 case NOTMUCH_STATUS_TAG_TOO_LONG:
\r
67 return "Tag value is too long (exceeds NOTMUCH_TAG_MAX)";
\r
68 + case NOTMUCH_STATUS_INVALID_DATE:
\r
69 + return "Date value did not parse to a valid date";
\r
70 case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
\r
71 return "Unbalanced number of calls to notmuch_message_freeze/thaw";
\r
73 @@ -497,83 +499,29 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch)
\r
74 struct MaildateValueRangeProcessor : public Xapian::ValueRangeProcessor {
\r
75 MaildateValueRangeProcessor() {}
\r
78 - parsedate(std::string &str, bool early) {
\r
79 - /* Parse the date to a 'time_t', return NULL on error */
\r
80 - /* possible time formats: YYYY-MM-DD, YYYY-MM, YYYY, */
\r
81 - /* MM-DD (current month), DD (day in current month). */
\r
82 - /* Uses start of time unit when 'early', end otherwise, e.g. */
\r
83 - /* 2001:=2001-01-01:00:00:00 when 'early' or 2001-12-31:23:59:59 */
\r
85 - struct tm *timeinfo;
\r
87 - int year = 0, month = 0, day = 0;
\r
89 - now = (str == "now");
\r
91 - if (str.size() == 2) {
\r
92 - /* We got just current day in month, parse & remove it */
\r
93 - day = atoi(str.c_str());
\r
97 - if (str.size() == 4 or str.size() > 5) {
\r
98 - /* expect a year, parse & remove it */
\r
99 - year = atoi(str.c_str());
\r
103 - /* parse & remove month if there is sth left in the string */
\r
104 - month = atoi(str.c_str());
\r
107 - /* Parse day if we have one left */
\r
109 - day = atoi(str.c_str());
\r
111 - if (!now && year == 0 && month == 0 && day == 0)
\r
112 - // no expected time format
\r
115 - timet = time(NULL); /* init timeinfo with current time */
\r
116 - timeinfo = gmtime(&timet);
\r
119 - /* add timeunit if !early (1 second too much, which we deduct later */
\r
121 - if (year && !month) ++year; /* only year given */
\r
122 - if (year && month && !day) ++month; /* year & month given */
\r
124 - if (year) timeinfo -> tm_year = year - 1900;
\r
125 - if (month) timeinfo -> tm_mon = month - 1;
\r
126 - if (day) timeinfo -> tm_mday = (early ? day : ++day);
\r
127 - else timeinfo -> tm_mday = 1;
\r
129 - timeinfo -> tm_hour = 0;
\r
130 - timeinfo -> tm_min = 0;
\r
131 - timeinfo -> tm_sec = (early ? 0 : -1); /* -1 sec if !early */
\r
133 - timet = mktime(timeinfo);
\r
138 Xapian::valueno operator()(std::string &begin, std::string &end) {
\r
139 - time_t begintime, endtime;
\r
140 + time_t begin_first,begin_last, end_first, end_last;
\r
143 if (begin.substr(0, 5) != "date:")
\r
144 return Xapian::BAD_VALUENO;
\r
147 - begintime = parsedate(begin, true);
\r
148 - endtime = parsedate(end, false);
\r
149 + retval = notmuch_parse_date(begin.c_str(), &begin_first, &begin_last, 0);
\r
151 - if ((begintime == -1) || (endtime == -1))
\r
152 - // parsedate failed, no valid time format
\r
153 + if (retval == NOTMUCH_STATUS_INVALID_DATE) {
\r
154 + fprintf(stderr,"Begin date failed to parse: %s",begin.c_str());
\r
155 return Xapian::BAD_VALUENO;
\r
158 + retval = notmuch_parse_date(end.c_str(),&end_first,&end_last,begin_first);
\r
159 + if (retval == NOTMUCH_STATUS_INVALID_DATE) {
\r
160 + fprintf(stderr,"End date failed to parse: %s",end.c_str());
\r
161 + return Xapian::BAD_VALUENO;
\r
164 - begin.assign(Xapian::sortable_serialise(begintime));
\r
165 - end.assign(Xapian::sortable_serialise(endtime));
\r
166 + begin.assign(Xapian::sortable_serialise(begin_first));
\r
167 + end.assign(Xapian::sortable_serialise(end_last));
\r
169 return NOTMUCH_VALUE_TIMESTAMP;
\r
171 diff --git a/lib/date.c b/lib/date.c
\r
172 index 09c5ef9..805a1d9 100644
\r
175 @@ -37,6 +37,7 @@ today(struct tm *result, time_t after) {
\r
178 static int parse_today(const char *text, time_t *first, time_t *last, time_t after) {
\r
179 + (void)after; /*disable unused paramter warning*/
\r
180 if (strcasecmp(text, "today") == 0) {
\r
183 @@ -56,6 +57,7 @@ static int parse_yesterday(const char *text, time_t *first, time_t *last, time_t
\r
187 + (void)after; /*disable unused paramter warning*/
\r
190 static int parse_thisweek(const char *text, time_t *first, time_t *last, time_t after) {
\r
191 @@ -67,6 +69,7 @@ static int parse_thisweek(const char *text, time_t *first, time_t *last, time_t
\r
195 + (void)after; /*disable unused paramter warning*/
\r
198 static int parse_lastweek(const char *text, time_t *first, time_t *last, time_t after) {
\r
199 @@ -78,6 +81,7 @@ static int parse_lastweek(const char *text, time_t *first, time_t *last, time_t
\r
203 + (void)after; /*disable unused paramter warning*/
\r
206 static int parse_thismonth(const char *text, time_t *first, time_t *last, time_t after) {
\r
207 @@ -94,6 +98,7 @@ static int parse_thismonth(const char *text, time_t *first, time_t *last, time_t
\r
211 + (void)after; /*disable unused paramter warning*/
\r
214 static int parse_lastmonth(const char *text, time_t *first, time_t *last, time_t after) {
\r
215 @@ -115,6 +120,7 @@ static int parse_lastmonth(const char *text, time_t *first, time_t *last, time_t
\r
219 + (void)after; /*disable unused paramter warning*/
\r
222 static const char *months[12][2] = {
\r
223 @@ -308,6 +314,7 @@ static int parse_iso(const char *text, time_t *first, time_t *last, time_t after
\r
227 + (void)after; /*disable unused paramter warning*/
\r
230 /* month[/day[/year]] */
\r
231 @@ -396,8 +403,8 @@ static int (*parsers[])(const char *text, time_t *first, time_t *last, time_t af
\r
235 -static notmuch_status_t
\r
236 -notmuch_one_date(const char *text, time_t *first, time_t *last, time_t after)
\r
238 +notmuch_parse_date(const char *text, time_t *first, time_t *last, time_t after)
\r
241 for (i = 0; parsers[i]; i++)
\r
242 @@ -405,51 +412,3 @@ notmuch_one_date(const char *text, time_t *first, time_t *last, time_t after)
\r
243 return NOTMUCH_STATUS_SUCCESS;
\r
244 return NOTMUCH_STATUS_INVALID_DATE;
\r
248 -notmuch_date(const char *text, time_t *first, time_t *last)
\r
251 - char first_text[80], last_text[80];
\r
252 - notmuch_status_t status;
\r
253 - time_t first_first, first_last, last_first, last_last;
\r
255 - if (strlen(text) > sizeof (first_text))
\r
256 - return NOTMUCH_STATUS_INVALID_DATE;
\r
257 - dots = strstr(text, "..");
\r
259 - strncpy(first_text, text, dots - text);
\r
260 - first_text[dots-text] = '\0';
\r
261 - status = notmuch_one_date(first_text, &first_first, &first_last, 0);
\r
264 - status = notmuch_one_date(dots + 2, &last_first, &last_last, first_first);
\r
267 - *first = first_first;
\r
268 - *last = last_last;
\r
271 - return notmuch_one_date(text, first, last, 0);
\r
276 -main (int argc, char **argv)
\r
279 - for (i = 1; i < argc; i++) {
\r
280 - time_t first, last;
\r
282 - if (notmuch_date(argv[i], &first, &last) == 0) {
\r
283 - char first_string[80], last_string[80];
\r
285 - ctime_r(&first, first_string);
\r
286 - first_string[strlen(first_string)-1] = '\0';
\r
287 - ctime_r(&last, last_string);
\r
288 - last_string[strlen(last_string)-1] = '\0';
\r
289 - printf ("%s: %s - %s\n", argv[i], first_string, last_string);
\r
294 diff --git a/lib/notmuch.h b/lib/notmuch.h
\r
295 index 15c9db4..be474bf 100644
\r
296 --- a/lib/notmuch.h
\r
297 +++ b/lib/notmuch.h
\r
298 @@ -78,6 +78,8 @@ typedef int notmuch_bool_t;
\r
299 * NOTMUCH_STATUS_TAG_TOO_LONG: A tag value is too long (exceeds
\r
302 + * NOTMUCH_STATUS_INVALID_DATE: Date parsing failed
\r
304 * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw
\r
305 * function has been called more times than notmuch_message_freeze.
\r
307 @@ -96,6 +98,7 @@ typedef enum _notmuch_status {
\r
308 NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID,
\r
309 NOTMUCH_STATUS_NULL_POINTER,
\r
310 NOTMUCH_STATUS_TAG_TOO_LONG,
\r
311 + NOTMUCH_STATUS_INVALID_DATE,
\r
312 NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
\r
314 NOTMUCH_STATUS_LAST_STATUS
\r
315 @@ -1086,6 +1089,23 @@ notmuch_filenames_advance (notmuch_filenames_t *filenames);
\r
317 notmuch_filenames_destroy (notmuch_filenames_t *filenames);
\r
320 +notmuch_parse_date(const char *text, time_t *first, time_t *last, time_t after);
\r
321 +/* Parse a string into the first and last possible timestamps.
\r
322 + * It parses the possible formats and stops if one pattern matches.
\r
323 + * Keywords: 'today','yesterday','thisweek','lastweek','thismonth',
\r
325 + * Month-day : month[-day]] (month: January, Jan, or 1)\n"
\r
326 + * ISO format: year[-month[-day]]
\r
327 + * US format : month[/day[/year]]
\r
329 + * 'after' is used to fill in bits from context if left out, e.g. a
\r
330 + * 'date:2004..01' will find from 2004-01-01 through 2004-01-31
\r
333 + * NOTMUCH_STATUS_SUCCESS
\r
334 + * NOTMUCH_STATUS_INVALID_DATE: Error parsing the date string
\r
339 diff --git a/notmuch-new.c b/notmuch-new.c
\r
340 index f25c71f..5da31c1 100644
\r
341 --- a/notmuch-new.c
\r
342 +++ b/notmuch-new.c
\r
343 @@ -431,6 +431,7 @@ add_files_recursive (notmuch_database_t *notmuch,
\r
347 + case NOTMUCH_STATUS_INVALID_DATE:
\r
348 case NOTMUCH_STATUS_FILE_ERROR:
\r
349 case NOTMUCH_STATUS_NULL_POINTER:
\r
350 case NOTMUCH_STATUS_TAG_TOO_LONG:
\r
351 diff --git a/notmuch.1 b/notmuch.1
\r
352 index 38379b1..175fe86 100644
\r
355 @@ -417,22 +417,23 @@ particular time range, (based on the Date: header) with a syntax of:
\r
359 -can be specified in the following formats:
\r
362 -(e.g 2001 meaning since 2001, or through 2001, depending on whether it is the start or end). 2)
\r
364 -meaning from/to month MM in year YYYY, 3)
\r
366 -(from/to that exact day) 4)
\r
368 -(from/to month/day in the current year) 5)
\r
370 -(from/to day DD in current month). 6) the keyword
\r
372 -can be used to denote NOW (so a "05-01..now" finds all mails from May until now).
\r
374 -Formats can be mixed, so "date:2001..22" means from 2001-01-01 until the 22nd this months.
\r
375 +can be specified in various formats. It parses the formats in this order and stops if one pattern matches:
\r
385 + Month-day: month[-day]] (month: "January", "Jan", 1)
\r
387 + ISO format: year[-month[-day]]
\r
389 + US format : month[/day[/year]]
\r
391 +The date parser will try to fill in bits in the enddate from context if left out, e.g. a 'date:2004..01' will find from 2004-01-01 through 2004-01-31.
\r
394 The emacs-based interface to notmuch (available as
\r
395 diff --git a/notmuch.c b/notmuch.c
\r
396 index 808a370..b8fe01a 100644
\r
399 @@ -94,16 +94,18 @@ static const char search_terms_help[] =
\r
400 "\t\tFinally, results can be restricted to only messages within a\n"
\r
401 "\t\tparticular time range, (based on the Date: header) with a\n"
\r
402 "\t\tsyntax of: date:<startdate>..<enddate>\n"
\r
403 - "\t\tIt can be specified in the following formats:\n"
\r
404 - "\t\tYYYY (e.g 2001 meaning since 2001, or through 2001, depending\n"
\r
405 - "\t\ton whether it is the start or end). 2) YYYY-MM meaning from/to\n"
\r
406 - "\t\tmonth MM in year YYYY, 3) YYYY-MM-DD (that exact day) 4)\n"
\r
407 - "\t\tMM-DD (month/day in the current year) 5) DD (day DD in \n"
\r
408 - "\t\tcurrent month). 6) the keyword 'now' can be used to denote\n"
\r
409 - "\t\tNOW (so a 'date:05-01..now' finds all mails from May until now).\n"
\r
411 - "\t\tFormats can be mixed, so 'date:2001..22' means from 2001-01-01\n"
\r
412 - "\t\tuntil the 22nd this months.\n"
\r
413 + "\t\tIt can be specified in the following formats, parsing will \n"
\r
414 + "\t\tstop if the first pattern matches:\n"
\r
415 + "\t\tKeywords: 'today','yesterday','thisweek','lastweek',\n"
\r
416 + "\t\t'thismonth', 'lastmonth'. \n"
\r
417 + "\t\tmonth-day : month[-day]] (month: January, Jan, or 1)\n"
\r
418 + "\t\tISO format: year[-month[-day]] (month: January, Jan, or 1)\n"
\r
419 + "\t\tUS format : month[/day[/year]]\n"
\r
421 + "\t\tThe parser will fill in bits in the enddate from context if\n"
\r
422 + "\t\tleft out, e.g. a 'date:2004..01' will find from 2004-01-01\n"
\r
423 + "\t\tthrough 2004-01-31\n"
\r
426 command_t commands[] = {
\r