From f792d2e464a12bb7d47c4b5981e2b6926663461a Mon Sep 17 00:00:00 2001 From: Jesse Rosenthal Date: Tue, 7 Feb 2012 13:29:05 +1900 Subject: [PATCH] Re: newbie questions --- f2/61fd0551708223a87e26ea1c780dd764e982ba | 138 ++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 f2/61fd0551708223a87e26ea1c780dd764e982ba diff --git a/f2/61fd0551708223a87e26ea1c780dd764e982ba b/f2/61fd0551708223a87e26ea1c780dd764e982ba new file mode 100644 index 000000000..86359e0da --- /dev/null +++ b/f2/61fd0551708223a87e26ea1c780dd764e982ba @@ -0,0 +1,138 @@ +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 E3B07431FAF + for ; Mon, 6 Feb 2012 10:29:08 -0800 (PST) +X-Virus-Scanned: Debian amavisd-new at olra.theworths.org +X-Spam-Flag: NO +X-Spam-Score: -2.3 +X-Spam-Level: +X-Spam-Status: No, score=-2.3 tagged_above=-999 required=5 + tests=[RCVD_IN_DNSWL_MED=-2.3] autolearn=disabled +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 CG-8x8yjb-fm for ; + Mon, 6 Feb 2012 10:29:08 -0800 (PST) +Received: from ipex1.johnshopkins.edu (ipex1.johnshopkins.edu [162.129.8.141]) + (using TLSv1 with cipher RC4-SHA (128/128 bits)) + (No client certificate requested) + by olra.theworths.org (Postfix) with ESMTPS id E4D24431FAE + for ; Mon, 6 Feb 2012 10:29:07 -0800 (PST) +X-IronPort-AV: E=Sophos;i="4.73,372,1325480400"; d="scan'208";a="126653374" +Received: from pool-173-52-130-33.nycmny.east.verizon.net (HELO gogo) + ([173.52.130.33]) + by ipex1.johnshopkins.edu with ESMTP/TLS/AES256-SHA; + 06 Feb 2012 13:29:06 -0500 +Received: from jkr by gogo with local (Exim 4.76) + (envelope-from ) + id 1RuTJJ-0003M8-Fc; Mon, 06 Feb 2012 13:29:05 -0500 +From: Jesse Rosenthal +To: Tomi Ollila , Tamas Papp , + notmuch@notmuchmail.org +Subject: Re: newbie questions +In-Reply-To: +References: <20120203115934.GA5605@daedalus> + +User-Agent: Notmuch/0.11+137~g7cd907b (http://notmuchmail.org) Emacs/24.0.93.1 + (i686-pc-linux-gnu) +Date: Mon, 06 Feb 2012 13:29:05 -0500 +Message-ID: <877gzz4xzi.fsf@jhu.edu> +MIME-Version: 1.0 +Content-Type: text/plain +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: Mon, 06 Feb 2012 18:29:09 -0000 + +On Mon, 06 Feb 2012 08:51:15 +0200, Tomi Ollila wrote: +> On Fri, 3 Feb 2012 12:59:34 +0100, Tamas Papp wrote: +> > +> > 1. How can I restrict searches (eg of my inbox) to the last few +> > messages (eg 50-100) or some date (eg last 2 weeks)? I am using the +> > Emacs interface. +> +> Currently, if you have GNU date you can run from command line: +> +> date +%s.. --date '2 weeks ago' +> +> Then paste the string 1327300096.. to the search field. + +FWIW, I actually have a hacky date parser baked into my +remote-usage-and-other-stuff script (a more idiosyncratc python +version of the bash script on the wiki). I found that I needed +date-searching pretty frequently, since language and senders seem to be +repeated pretty often in my world. It just parses a "date:" term, passes +it to GNU date, and proceeds with a term in notmuch language. It also +does some day-rounding, since by "date:'2 days ago'..yesterday", I mean +"beginning of day before yesterday to end of yesterday," not "48 hours +ago until 24 hours ago." + +I'm not swearing by its efficiency, or even its correctness, but it has +made my life easier. The basics are as follows: + + DATE_PATTERN = re.compile(r'^date:([^.]+)(\.\.)?([^.]+)?') + + def replace_date_args(st): + out = subprocess.check_output([GNU_DATE, "+%s", "-d", st]) + return out.strip() + + def round_day_down(timestamp): + tup = datetime.fromtimestamp(int(timestamp)).date().timetuple() + return time.mktime(tup) + + def round_day_up(timestamp): + date = datetime.fromtimestamp(int(timestamp)).date() + date += timedelta(days=1) + tup = date.timetuple() + return time.mktime(tup) + + def parse_date_args(st): + re_match = DATE_PATTERN.match(st) + if re_match: + grps = re_match.groups() + start_term = grps[0] + if not (grps[1] or grps[2]): + stop_term = start_term + elif not grps[2]: + stop_term = "now" + else: + stop_term = grps[2] + + try: + start = round_day_down(replace_date_args(start_term)) + stop = round_day_up(replace_date_args(stop_term)) + return "%d..%d" % (start, stop) + except OSError: + return st + else: + return st + +And then in the main routine, I have a parse-and-replace step: + + args = sys.argv[1:] + try: + if args[-1] == ")'": + args = args[:-2] + shlex.split(sys.argv[-2]) + [")'"] + else: + args = args[:-1] + shlex.split(sys.argv[-1]) + except IndexError, ValueError: + pass + + args = [parse_date_args(a) for a in args] + +I'm only giving the relevant parts here, of course. + +Best, +Jesse + + -- 2.26.2