unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* Feature request: search for last N modified mails
@ 2016-12-02 14:01 Ico
  2016-12-03 13:22 ` cesar mena
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Ico @ 2016-12-02 14:01 UTC (permalink / raw)
  To: notmuch


My normal mail workflow is to keep todo's in my inbox; these can be a few days
or weeks old if I'm lazy. Every now and then I find myself accidentally
removing things from the inbox, and I have a very hard time finding things
back. As discussed on #notmuch IRC today: I'd like to request a feature for
searching for the last N modified mails, as notmuch already has this info in
the database.

bremner suggested this could be implemented using with a query like

   lastmod:-10



14:39 < Zevv> basically, I'd like to be able to search for the last 10 modified
              mails. Where 'modified' would probably mean changing tags
14:41 < bremner> Zevv: you can get the current value from notmuch count --lastmod '*'
14:41 < bremner> then basically every tag change increments it
14:42 < bremner> so I guess subtract 10 and search?
14:44 < Zevv> Hm that would make it hard to use it as a simple query for in alot
14:45 < bremner> yes.
14:45 < bremner> I never thought about it before, but it would be possible to
                 impliment lastmod:-10
14:47 < Zevv> that would be extremely handy

--
:wq
^X^Cy^K^X^C^C^C^C

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Feature request: search for last N modified mails
  2016-12-02 14:01 Feature request: search for last N modified mails Ico
@ 2016-12-03 13:22 ` cesar mena
  2022-08-08 11:50 ` [PATCH] WIP: provide relative lastmod sexp queries David Bremner
  2022-09-03 11:51 ` Feature request: search for last N modified mails David Bremner
  2 siblings, 0 replies; 6+ messages in thread
From: cesar mena @ 2016-12-03 13:22 UTC (permalink / raw)
  To: Ico, notmuch

hello,

Ico <ico@pruts.nl> writes:

> My normal mail workflow is to keep todo's in my inbox; these can be a few days
> or weeks old if I'm lazy. Every now and then I find myself accidentally
> removing things from the inbox, and I have a very hard time finding things
> back. As discussed on #notmuch IRC today: I'd like to request a feature for
> searching for the last N modified mails, as notmuch already has this info in
> the database.
>
> bremner suggested this could be implemented using with a query like
>
>    lastmod:-10

until such time you can consider using a 'done' tag that's muted.

-cm

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] WIP: provide relative lastmod sexp queries
  2016-12-02 14:01 Feature request: search for last N modified mails Ico
  2016-12-03 13:22 ` cesar mena
@ 2022-08-08 11:50 ` David Bremner
  2022-08-09 11:25   ` [PATCH 2/3] WIP/lib: factor out lastmod range handling from sexp parser David Bremner
  2022-09-03 11:51 ` Feature request: search for last N modified mails David Bremner
  2 siblings, 1 reply; 6+ messages in thread
From: David Bremner @ 2022-08-08 11:50 UTC (permalink / raw)
  To: Ico, notmuch

---

I haven't looked carefully at how much work it would be to add to the
infix parser yet. I suspect it means adding a new RangeProcessor class
modelled on ParseTimeRangeProcessor. Maybe some of the logic from
_parse_sexp_range could be shared with the other parser.

 lib/parse-sexp.cc              | 6 ++++++
 test/T570-revision-tracking.sh | 8 ++++++++
 2 files changed, 14 insertions(+)

diff --git a/lib/parse-sexp.cc b/lib/parse-sexp.cc
index 0f14d8b7..e9ef4268 100644
--- a/lib/parse-sexp.cc
+++ b/lib/parse-sexp.cc
@@ -575,6 +575,9 @@ _sexp_parse_range (notmuch_database_t *notmuch,  const _sexp_prefix_t *prefix,
 	    return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
 	}
 
+	if (from_idx < 0)
+	    from_idx += notmuch_database_get_revision (notmuch, NULL);
+
 	try {
 	    if (EMPTY_STRING (to))
 		to_idx = LONG_MAX;
@@ -585,6 +588,9 @@ _sexp_parse_range (notmuch_database_t *notmuch,  const _sexp_prefix_t *prefix,
 	    return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
 	}
 
+	if (to_idx < 0)
+	    to_idx += notmuch_database_get_revision (notmuch, NULL);
+
 	output = Xapian::Query (Xapian::Query::OP_VALUE_RANGE, NOTMUCH_VALUE_LAST_MOD,
 				Xapian::sortable_serialise (from_idx),
 				Xapian::sortable_serialise (to_idx));
diff --git a/test/T570-revision-tracking.sh b/test/T570-revision-tracking.sh
index e1cc684d..aaa45468 100755
--- a/test/T570-revision-tracking.sh
+++ b/test/T570-revision-tracking.sh
@@ -95,4 +95,12 @@ subtotal=$(notmuch count lastmod:..$lastmod)
 result=$(($subtotal == $total-1))
 test_expect_equal 1 "$result"
 
+if [ $NOTMUCH_HAVE_SFSEXP -eq 1 ]; then
+    test_begin_subtest 'exclude one message using negative lastmod (sexp)'
+    total=$(notmuch count '*')
+    notmuch tag +${RANDOM} id:4EFC743A.3060609@april.org
+    count=$(notmuch count --query=sexp '(lastmod -1 *)')
+    test_expect_equal 1 "$count"
+fi
+
 test_done
-- 
2.35.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] WIP/lib: factor out lastmod range handling from sexp parser.
  2022-08-08 11:50 ` [PATCH] WIP: provide relative lastmod sexp queries David Bremner
@ 2022-08-09 11:25   ` David Bremner
  2022-08-09 11:25     ` [PATCH 3/3] WIP/lib: use common lastmod logic in infix parser David Bremner
  0 siblings, 1 reply; 6+ messages in thread
From: David Bremner @ 2022-08-09 11:25 UTC (permalink / raw)
  To: David Bremner, Ico, notmuch

This will permit the re-use of the same logic in the infix query
parser. The location of the shared code in the infix side is just a
convention at this point.
---
 lib/Makefile.local     |  3 +-
 lib/database-private.h |  6 ++++
 lib/lastmod-fp.cc      | 68 ++++++++++++++++++++++++++++++++++++++++++
 lib/parse-sexp.cc      | 37 ++++-------------------
 4 files changed, 82 insertions(+), 32 deletions(-)
 create mode 100644 lib/lastmod-fp.cc

diff --git a/lib/Makefile.local b/lib/Makefile.local
index 6d67a2a4..4e766305 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -65,7 +65,8 @@ libnotmuch_cxx_srcs =		\
 	$(dir)/open.cc		\
 	$(dir)/init.cc		\
 	$(dir)/parse-sexp.cc	\
-	$(dir)/sexp-fp.cc
+	$(dir)/sexp-fp.cc	\
+	$(dir)/lastmod-fp.cc
 
 libnotmuch_modules := $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)
 
diff --git a/lib/database-private.h b/lib/database-private.h
index 419b9fe6..b9be4e22 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -381,5 +381,11 @@ _notmuch_sexp_string_to_xapian_query (notmuch_database_t *notmuch, const char *q
 notmuch_status_t
 _notmuch_date_strings_to_query (Xapian::valueno slot, const std::string &from, const std::string &to,
 				Xapian::Query &output, std::string &msg);
+
+/* lastmod-fp.h */
+notmuch_status_t
+_notmuch_lastmod_strings_to_query (notmuch_database_t *notmuch,
+				   const std::string &from, const std::string &to,
+				   Xapian::Query &output, std::string &msg);
 #endif
 #endif
diff --git a/lib/lastmod-fp.cc b/lib/lastmod-fp.cc
new file mode 100644
index 00000000..5fdaf281
--- /dev/null
+++ b/lib/lastmod-fp.cc
@@ -0,0 +1,68 @@
+/* lastmod-fp.cc - lastmod range query glue
+ *
+ * This file is part of notmuch.
+ *
+ * Copyright © 2022 David Bremner
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see https://www.gnu.org/licenses/ .
+ *
+ * Author: David Bremner <david@tethera.net>
+ */
+
+#include "database-private.h"
+
+notmuch_status_t
+_notmuch_lastmod_strings_to_query (notmuch_database_t *notmuch,
+				   const std::string &from, const std::string &to,
+				   Xapian::Query &output, std::string &msg)
+{
+    long from_idx = 0L, to_idx = LONG_MAX;
+    long current;
+    std::string str;
+
+    /* revision should not change, but for the avoidance of doubt,
+     * grab for both ends of range, if needed*/
+    current = notmuch_database_get_revision (notmuch, NULL);
+
+    try {
+	if (from.empty ())
+	    from_idx = 0L;
+	else
+	    from_idx = std::stol (from);
+    } catch (std::logic_error &e) {
+	msg = "bad 'from' revision: '" + from + "'";
+	return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
+    }
+
+    if (from_idx < 0)
+	from_idx += current;
+
+    try {
+	if (EMPTY_STRING (to))
+	    to_idx = LONG_MAX;
+	else
+	    to_idx = std::stol (to);
+    } catch (std::logic_error &e) {
+	msg = "bad 'to' revision: '" + to + "'";
+	return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
+    }
+
+    if (to_idx < 0)
+	to_idx += current;
+
+    output = Xapian::Query (Xapian::Query::OP_VALUE_RANGE, NOTMUCH_VALUE_LAST_MOD,
+			    Xapian::sortable_serialise (from_idx),
+			    Xapian::sortable_serialise (to_idx));
+    return NOTMUCH_STATUS_SUCCESS;
+}
diff --git a/lib/parse-sexp.cc b/lib/parse-sexp.cc
index e9ef4268..9cadbc13 100644
--- a/lib/parse-sexp.cc
+++ b/lib/parse-sexp.cc
@@ -563,38 +563,13 @@ _sexp_parse_range (notmuch_database_t *notmuch,  const _sexp_prefix_t *prefix,
     }
 
     if (strcmp (prefix->name, "lastmod") == 0) {
-	long from_idx, to_idx;
-
-	try {
-	    if (EMPTY_STRING (from))
-		from_idx = 0L;
-	    else
-		from_idx = std::stol (from);
-	} catch (std::logic_error &e) {
-	    _notmuch_database_log (notmuch, "bad 'from' revision: '%s'\n", from);
-	    return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
-	}
-
-	if (from_idx < 0)
-	    from_idx += notmuch_database_get_revision (notmuch, NULL);
-
-	try {
-	    if (EMPTY_STRING (to))
-		to_idx = LONG_MAX;
-	    else
-		to_idx = std::stol (to);
-	} catch (std::logic_error &e) {
-	    _notmuch_database_log (notmuch, "bad 'to' revision: '%s'\n", to);
-	    return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
+	notmuch_status_t status;
+	status = _notmuch_lastmod_strings_to_query (notmuch, from, to, output, msg);
+	if (status) {
+	    if (! msg.empty ())
+		_notmuch_database_log (notmuch, "%s\n", msg.c_str ());
 	}
-
-	if (to_idx < 0)
-	    to_idx += notmuch_database_get_revision (notmuch, NULL);
-
-	output = Xapian::Query (Xapian::Query::OP_VALUE_RANGE, NOTMUCH_VALUE_LAST_MOD,
-				Xapian::sortable_serialise (from_idx),
-				Xapian::sortable_serialise (to_idx));
-	return NOTMUCH_STATUS_SUCCESS;
+	return status;
     }
 
     _notmuch_database_log (notmuch, "unimplimented range prefix: '%s'\n", prefix->name);
-- 
2.35.2
\r

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] WIP/lib: use common lastmod logic in infix parser
  2022-08-09 11:25   ` [PATCH 2/3] WIP/lib: factor out lastmod range handling from sexp parser David Bremner
@ 2022-08-09 11:25     ` David Bremner
  0 siblings, 0 replies; 6+ messages in thread
From: David Bremner @ 2022-08-09 11:25 UTC (permalink / raw)
  To: David Bremner, Ico, notmuch

This allows the support of negative lastmod revisions to be
interpreted as relative to the most recent revision.
---
 lib/lastmod-fp.cc              | 15 +++++++++++++
 lib/lastmod-fp.h               | 39 ++++++++++++++++++++++++++++++++++
 lib/open.cc                    |  4 ++--
 test/T570-revision-tracking.sh |  6 ++++++
 4 files changed, 62 insertions(+), 2 deletions(-)
 create mode 100644 lib/lastmod-fp.h

diff --git a/lib/lastmod-fp.cc b/lib/lastmod-fp.cc
index 5fdaf281..f85efd28 100644
--- a/lib/lastmod-fp.cc
+++ b/lib/lastmod-fp.cc
@@ -21,6 +21,7 @@
  */
 
 #include "database-private.h"
+#include "lastmod-fp.h"
 
 notmuch_status_t
 _notmuch_lastmod_strings_to_query (notmuch_database_t *notmuch,
@@ -66,3 +67,17 @@ _notmuch_lastmod_strings_to_query (notmuch_database_t *notmuch,
 			    Xapian::sortable_serialise (to_idx));
     return NOTMUCH_STATUS_SUCCESS;
 }
+
+Xapian::Query
+LastModRangeProcessor::operator() (const std::string &begin, const std::string &end)
+{
+
+    Xapian::Query output;
+    std::string msg;
+
+    if (_notmuch_lastmod_strings_to_query (notmuch, begin, end, output, msg))
+	throw Xapian::QueryParserError (msg);
+
+    return output;
+}
+
diff --git a/lib/lastmod-fp.h b/lib/lastmod-fp.h
new file mode 100644
index 00000000..448241f8
--- /dev/null
+++ b/lib/lastmod-fp.h
@@ -0,0 +1,39 @@
+/* lastmod-fp.h - database revision query glue
+ *
+ * This file is part of notmuch.
+ *
+ * Copyright © 2022 David Bremner
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see https://www.gnu.org/licenses/ .
+ *
+ * Author: David Bremner <david@tethera.net>
+ */
+
+#ifndef NOTMUCH_LASTMOD_FP_H
+#define NOTMUCH_LASTMOD_FP_H
+
+#include <xapian.h>
+
+class LastModRangeProcessor : public Xapian::RangeProcessor {
+protected:
+    notmuch_database_t *notmuch;
+
+public:
+    LastModRangeProcessor (notmuch_database_t *notmuch_, const std::string prefix_)
+	:  Xapian::RangeProcessor(NOTMUCH_VALUE_LAST_MOD, prefix_, 0), notmuch(notmuch_) { }
+
+    Xapian::Query operator() (const std::string &begin, const std::string &end);
+};
+
+#endif /* NOTMUCH_LASTMOD_FP_H */
diff --git a/lib/open.cc b/lib/open.cc
index 30cfcf9e..02ed7285 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -3,6 +3,7 @@
 
 #include "database-private.h"
 #include "parse-time-vrp.h"
+#include "lastmod-fp.h"
 #include "path-util.h"
 
 #if HAVE_XAPIAN_DB_RETRY_LOCK
@@ -431,8 +432,7 @@ _finish_open (notmuch_database_t *notmuch,
 	notmuch->value_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_TIMESTAMP);
 	notmuch->date_range_processor = new ParseTimeRangeProcessor (NOTMUCH_VALUE_TIMESTAMP,
 								     "date:");
-	notmuch->last_mod_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_LAST_MOD,
-									      "lastmod:");
+	notmuch->last_mod_range_processor = new LastModRangeProcessor (notmuch, "lastmod:");
 	notmuch->query_parser->set_default_op (Xapian::Query::OP_AND);
 	notmuch->query_parser->set_database (*notmuch->xapian_db);
 	notmuch->stemmer = new Xapian::Stem ("english");
diff --git a/test/T570-revision-tracking.sh b/test/T570-revision-tracking.sh
index aaa45468..067935b2 100755
--- a/test/T570-revision-tracking.sh
+++ b/test/T570-revision-tracking.sh
@@ -103,4 +103,10 @@ if [ $NOTMUCH_HAVE_SFSEXP -eq 1 ]; then
     test_expect_equal 1 "$count"
 fi
 
+test_begin_subtest 'exclude one message using negative lastmod'
+total=$(notmuch count '*')
+notmuch tag +${RANDOM} id:4EFC743A.3060609@april.org
+count=$(notmuch count lastmod:-1..)
+test_expect_equal 1 "$count"
+
 test_done
-- 
2.35.2
\r

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: Feature request: search for last N modified mails
  2016-12-02 14:01 Feature request: search for last N modified mails Ico
  2016-12-03 13:22 ` cesar mena
  2022-08-08 11:50 ` [PATCH] WIP: provide relative lastmod sexp queries David Bremner
@ 2022-09-03 11:51 ` David Bremner
  2 siblings, 0 replies; 6+ messages in thread
From: David Bremner @ 2022-09-03 11:51 UTC (permalink / raw)
  To: Ico, notmuch

Ico <ico@pruts.nl> writes:

> My normal mail workflow is to keep todo's in my inbox; these can be a few days
> or weeks old if I'm lazy. Every now and then I find myself accidentally
> removing things from the inbox, and I have a very hard time finding things
> back. As discussed on #notmuch IRC today: I'd like to request a feature for
> searching for the last N modified mails, as notmuch already has this info in
> the database.
>
> bremner suggested this could be implemented using with a query like
>
>    lastmod:-10
>
>
>
> 14:39 < Zevv> basically, I'd like to be able to search for the last 10 modified
>               mails. Where 'modified' would probably mean changing tags
> 14:41 < bremner> Zevv: you can get the current value from notmuch count --lastmod '*'
> 14:41 < bremner> then basically every tag change increments it
> 14:42 < bremner> so I guess subtract 10 and search?
> 14:44 < Zevv> Hm that would make it hard to use it as a simple query for in alot
> 14:45 < bremner> yes.
> 14:45 < bremner> I never thought about it before, but it would be possible to
>                  impliment lastmod:-10
> 14:47 < Zevv> that would be extremely handy

The syntax lastmod:-10.. (or '(lastmod -10 *)' is now  supported in git
master.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-09-03 11:51 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-02 14:01 Feature request: search for last N modified mails Ico
2016-12-03 13:22 ` cesar mena
2022-08-08 11:50 ` [PATCH] WIP: provide relative lastmod sexp queries David Bremner
2022-08-09 11:25   ` [PATCH 2/3] WIP/lib: factor out lastmod range handling from sexp parser David Bremner
2022-08-09 11:25     ` [PATCH 3/3] WIP/lib: use common lastmod logic in infix parser David Bremner
2022-09-03 11:51 ` Feature request: search for last N modified mails David Bremner

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).