Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id C8E67431FD8 for ; Tue, 26 Jan 2010 03:44:23 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -1.837 X-Spam-Level: X-Spam-Status: No, score=-1.837 tagged_above=-999 required=5 tests=[AWL=0.762, BAYES_00=-2.599] autolearn=ham Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id x-rBuP++X4Cn for ; Tue, 26 Jan 2010 03:44:21 -0800 (PST) Received: from homiemail-a20.g.dreamhost.com (caiajhbdccah.dreamhost.com [208.97.132.207]) by olra.theworths.org (Postfix) with ESMTP id D7F1F431FBD for ; Tue, 26 Jan 2010 03:44:20 -0800 (PST) Received: from localhost.localdomain (mtec-hg-docking-2-dhcp-062.ethz.ch [82.130.121.62]) by homiemail-a20.g.dreamhost.com (Postfix) with ESMTPA id C68F97EC061; Tue, 26 Jan 2010 03:44:19 -0800 (PST) From: Sebastian Spaeth To: notmuch@notmuchmail.org Date: Tue, 26 Jan 2010 12:43:41 +0100 Message-Id: <1264506221-9636-4-git-send-email-Sebastian@SSpaeth.de> X-Mailer: git-send-email 1.6.3.3 In-Reply-To: <1264506221-9636-3-git-send-email-Sebastian@SSpaeth.de> References: <1264506221-9636-1-git-send-email-Sebastian@SSpaeth.de> <1264506221-9636-2-git-send-email-Sebastian@SSpaeth.de> <1264506221-9636-3-git-send-email-Sebastian@SSpaeth.de> Subject: [notmuch] [PATCH 4/4] integrate keithp's date.c into the notmuch date parser and delete my previous own attempt X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Jan 2010 11:44:24 -0000 Signed-off-by: Sebastian Spaeth --- lib/database.cc | 84 ++++++++++-------------------------------------------- lib/date.c | 59 ++++++-------------------------------- lib/notmuch.h | 20 +++++++++++++ notmuch-new.c | 1 + notmuch.1 | 33 +++++++++++---------- notmuch.c | 20 +++++++------ 6 files changed, 74 insertions(+), 143 deletions(-) diff --git a/lib/database.cc b/lib/database.cc index b386e1a..78cd898 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -219,6 +219,8 @@ notmuch_status_to_string (notmuch_status_t status) return "Erroneous NULL pointer"; case NOTMUCH_STATUS_TAG_TOO_LONG: return "Tag value is too long (exceeds NOTMUCH_TAG_MAX)"; + case NOTMUCH_STATUS_INVALID_DATE: + return "Date value did not parse to a valid date"; case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: return "Unbalanced number of calls to notmuch_message_freeze/thaw"; default: @@ -497,83 +499,29 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch) struct MaildateValueRangeProcessor : public Xapian::ValueRangeProcessor { MaildateValueRangeProcessor() {} - time_t - parsedate(std::string &str, bool early) { - /* Parse the date to a 'time_t', return NULL on error */ - /* possible time formats: YYYY-MM-DD, YYYY-MM, YYYY, */ - /* MM-DD (current month), DD (day in current month). */ - /* Uses start of time unit when 'early', end otherwise, e.g. */ - /* 2001:=2001-01-01:00:00:00 when 'early' or 2001-12-31:23:59:59 */ - bool now = false; - struct tm *timeinfo; - time_t timet; - int year = 0, month = 0, day = 0; - - now = (str == "now"); - - if (str.size() == 2) { - /* We got just current day in month, parse & remove it */ - day = atoi(str.c_str()); - str.erase(0,2); - } - - if (str.size() == 4 or str.size() > 5) { - /* expect a year, parse & remove it */ - year = atoi(str.c_str()); - str.erase(0,5); - } - - /* parse & remove month if there is sth left in the string */ - month = atoi(str.c_str()); - str.erase(0,3); - - /* Parse day if we have one left */ - if (str.size()) - day = atoi(str.c_str()); - - if (!now && year == 0 && month == 0 && day == 0) - // no expected time format - return -1 ; - - timet = time(NULL); /* init timeinfo with current time */ - timeinfo = gmtime(&timet); - - if (!now) { - /* add timeunit if !early (1 second too much, which we deduct later */ - if (!early) { - if (year && !month) ++year; /* only year given */ - if (year && month && !day) ++month; /* year & month given */ - } - if (year) timeinfo -> tm_year = year - 1900; - if (month) timeinfo -> tm_mon = month - 1; - if (day) timeinfo -> tm_mday = (early ? day : ++day); - else timeinfo -> tm_mday = 1; - - timeinfo -> tm_hour = 0; - timeinfo -> tm_min = 0; - timeinfo -> tm_sec = (early ? 0 : -1); /* -1 sec if !early */ - } - timet = mktime(timeinfo); - - return timet; - } - Xapian::valueno operator()(std::string &begin, std::string &end) { - time_t begintime, endtime; + time_t begin_first,begin_last, end_first, end_last; + int retval; if (begin.substr(0, 5) != "date:") return Xapian::BAD_VALUENO; begin.erase(0, 5); - begintime = parsedate(begin, true); - endtime = parsedate(end, false); + retval = notmuch_parse_date(begin.c_str(), &begin_first, &begin_last, 0); - if ((begintime == -1) || (endtime == -1)) - // parsedate failed, no valid time format + if (retval == NOTMUCH_STATUS_INVALID_DATE) { + fprintf(stderr,"Begin date failed to parse: %s",begin.c_str()); return Xapian::BAD_VALUENO; + } + + retval = notmuch_parse_date(end.c_str(),&end_first,&end_last,begin_first); + if (retval == NOTMUCH_STATUS_INVALID_DATE) { + fprintf(stderr,"End date failed to parse: %s",end.c_str()); + return Xapian::BAD_VALUENO; + } - begin.assign(Xapian::sortable_serialise(begintime)); - end.assign(Xapian::sortable_serialise(endtime)); + begin.assign(Xapian::sortable_serialise(begin_first)); + end.assign(Xapian::sortable_serialise(end_last)); return NOTMUCH_VALUE_TIMESTAMP; } diff --git a/lib/date.c b/lib/date.c index 09c5ef9..805a1d9 100644 --- a/lib/date.c +++ b/lib/date.c @@ -37,6 +37,7 @@ today(struct tm *result, time_t after) { } static int parse_today(const char *text, time_t *first, time_t *last, time_t after) { + (void)after; /*disable unused paramter warning*/ if (strcasecmp(text, "today") == 0) { struct tm n; today(&n, 0); @@ -56,6 +57,7 @@ static int parse_yesterday(const char *text, time_t *first, time_t *last, time_t return 0; } return 1; + (void)after; /*disable unused paramter warning*/ } static int parse_thisweek(const char *text, time_t *first, time_t *last, time_t after) { @@ -67,6 +69,7 @@ static int parse_thisweek(const char *text, time_t *first, time_t *last, time_t return 0; } return 1; + (void)after; /*disable unused paramter warning*/ } static int parse_lastweek(const char *text, time_t *first, time_t *last, time_t after) { @@ -78,6 +81,7 @@ static int parse_lastweek(const char *text, time_t *first, time_t *last, time_t return 0; } return 1; + (void)after; /*disable unused paramter warning*/ } static int parse_thismonth(const char *text, time_t *first, time_t *last, time_t after) { @@ -94,6 +98,7 @@ static int parse_thismonth(const char *text, time_t *first, time_t *last, time_t return 0; } return 1; + (void)after; /*disable unused paramter warning*/ } static int parse_lastmonth(const char *text, time_t *first, time_t *last, time_t after) { @@ -115,6 +120,7 @@ static int parse_lastmonth(const char *text, time_t *first, time_t *last, time_t return 0; } return 1; + (void)after; /*disable unused paramter warning*/ } static const char *months[12][2] = { @@ -308,6 +314,7 @@ static int parse_iso(const char *text, time_t *first, time_t *last, time_t after return 0; } return 1; + (void)after; /*disable unused paramter warning*/ } /* month[/day[/year]] */ @@ -396,8 +403,8 @@ static int (*parsers[])(const char *text, time_t *first, time_t *last, time_t af 0, }; -static notmuch_status_t -notmuch_one_date(const char *text, time_t *first, time_t *last, time_t after) +notmuch_status_t +notmuch_parse_date(const char *text, time_t *first, time_t *last, time_t after) { int i; for (i = 0; parsers[i]; i++) @@ -405,51 +412,3 @@ notmuch_one_date(const char *text, time_t *first, time_t *last, time_t after) return NOTMUCH_STATUS_SUCCESS; return NOTMUCH_STATUS_INVALID_DATE; } - -notmuch_status_t -notmuch_date(const char *text, time_t *first, time_t *last) -{ - char *dots; - char first_text[80], last_text[80]; - notmuch_status_t status; - time_t first_first, first_last, last_first, last_last; - - if (strlen(text) > sizeof (first_text)) - return NOTMUCH_STATUS_INVALID_DATE; - dots = strstr(text, ".."); - if (dots) { - strncpy(first_text, text, dots - text); - first_text[dots-text] = '\0'; - status = notmuch_one_date(first_text, &first_first, &first_last, 0); - if (status) - return status; - status = notmuch_one_date(dots + 2, &last_first, &last_last, first_first); - if (status) - return status; - *first = first_first; - *last = last_last; - return 0; - } - return notmuch_one_date(text, first, last, 0); -} - -#if 1 -int -main (int argc, char **argv) -{ - int i; - for (i = 1; i < argc; i++) { - time_t first, last; - - if (notmuch_date(argv[i], &first, &last) == 0) { - char first_string[80], last_string[80]; - - ctime_r(&first, first_string); - first_string[strlen(first_string)-1] = '\0'; - ctime_r(&last, last_string); - last_string[strlen(last_string)-1] = '\0'; - printf ("%s: %s - %s\n", argv[i], first_string, last_string); - } - } -} -#endif diff --git a/lib/notmuch.h b/lib/notmuch.h index 15c9db4..be474bf 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -78,6 +78,8 @@ typedef int notmuch_bool_t; * NOTMUCH_STATUS_TAG_TOO_LONG: A tag value is too long (exceeds * NOTMUCH_TAG_MAX) * + * NOTMUCH_STATUS_INVALID_DATE: Date parsing failed + * * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw * function has been called more times than notmuch_message_freeze. * @@ -96,6 +98,7 @@ typedef enum _notmuch_status { NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID, NOTMUCH_STATUS_NULL_POINTER, NOTMUCH_STATUS_TAG_TOO_LONG, + NOTMUCH_STATUS_INVALID_DATE, NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW, NOTMUCH_STATUS_LAST_STATUS @@ -1086,6 +1089,23 @@ notmuch_filenames_advance (notmuch_filenames_t *filenames); void notmuch_filenames_destroy (notmuch_filenames_t *filenames); +notmuch_status_t +notmuch_parse_date(const char *text, time_t *first, time_t *last, time_t after); +/* Parse a string into the first and last possible timestamps. + * It parses the possible formats and stops if one pattern matches. + * Keywords: 'today','yesterday','thisweek','lastweek','thismonth', + * 'lastmonth' + * Month-day : month[-day]] (month: January, Jan, or 1)\n" + * ISO format: year[-month[-day]] + * US format : month[/day[/year]] + * + * 'after' is used to fill in bits from context if left out, e.g. a + * 'date:2004..01' will find from 2004-01-01 through 2004-01-31 + * + * Return values: + * NOTMUCH_STATUS_SUCCESS + * NOTMUCH_STATUS_INVALID_DATE: Error parsing the date string + */ NOTMUCH_END_DECLS #endif diff --git a/notmuch-new.c b/notmuch-new.c index f25c71f..5da31c1 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -431,6 +431,7 @@ add_files_recursive (notmuch_database_t *notmuch, ret = status; goto DONE; default: + case NOTMUCH_STATUS_INVALID_DATE: case NOTMUCH_STATUS_FILE_ERROR: case NOTMUCH_STATUS_NULL_POINTER: case NOTMUCH_STATUS_TAG_TOO_LONG: diff --git a/notmuch.1 b/notmuch.1 index 38379b1..175fe86 100644 --- a/notmuch.1 +++ b/notmuch.1 @@ -417,22 +417,23 @@ particular time range, (based on the Date: header) with a syntax of: A .B date -can be specified in the following formats: -.BR -.B YYYY -(e.g 2001 meaning since 2001, or through 2001, depending on whether it is the start or end). 2) -.B YYYY-MM -meaning from/to month MM in year YYYY, 3) -.B YYYY-MM-DD -(from/to that exact day) 4) -.B MM-DD -(from/to month/day in the current year) 5) -.B DD -(from/to day DD in current month). 6) the keyword -.B now -can be used to denote NOW (so a "05-01..now" finds all mails from May until now). -.BR -Formats can be mixed, so "date:2001..22" means from 2001-01-01 until the 22nd this months. +can be specified in various formats. It parses the formats in this order and stops if one pattern matches: + + Keywords: +.B today, +.B yesterday, +.B thisweek, +.B lastweek, +.B thismonth, +.B lastmonth. + + Month-day: month[-day]] (month: "January", "Jan", 1) + + ISO format: year[-month[-day]] + + US format : month[/day[/year]] + +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. .SH SEE ALSO The emacs-based interface to notmuch (available as diff --git a/notmuch.c b/notmuch.c index 808a370..b8fe01a 100644 --- a/notmuch.c +++ b/notmuch.c @@ -94,16 +94,18 @@ static const char search_terms_help[] = "\t\tFinally, results can be restricted to only messages within a\n" "\t\tparticular time range, (based on the Date: header) with a\n" "\t\tsyntax of: date:..\n" - "\t\tIt can be specified in the following formats:\n" - "\t\tYYYY (e.g 2001 meaning since 2001, or through 2001, depending\n" - "\t\ton whether it is the start or end). 2) YYYY-MM meaning from/to\n" - "\t\tmonth MM in year YYYY, 3) YYYY-MM-DD (that exact day) 4)\n" - "\t\tMM-DD (month/day in the current year) 5) DD (day DD in \n" - "\t\tcurrent month). 6) the keyword 'now' can be used to denote\n" - "\t\tNOW (so a 'date:05-01..now' finds all mails from May until now).\n" "\n" - "\t\tFormats can be mixed, so 'date:2001..22' means from 2001-01-01\n" - "\t\tuntil the 22nd this months.\n" + "\t\tIt can be specified in the following formats, parsing will \n" + "\t\tstop if the first pattern matches:\n" + "\t\tKeywords: 'today','yesterday','thisweek','lastweek',\n" + "\t\t'thismonth', 'lastmonth'. \n" + "\t\tmonth-day : month[-day]] (month: January, Jan, or 1)\n" + "\t\tISO format: year[-month[-day]] (month: January, Jan, or 1)\n" + "\t\tUS format : month[/day[/year]]\n" + "\n" + "\t\tThe parser will fill in bits in the enddate from context if\n" + "\t\tleft out, e.g. a 'date:2004..01' will find from 2004-01-01\n" + "\t\tthrough 2004-01-31\n" "\n\n"; command_t commands[] = { -- 1.6.3.3