]> granicus.if.org Git - neomutt/commitdiff
Searching with a window over notmuch vfolders
authorBernard 'Guyzmo' Pratz <guyzmo+github+pub@m0g.net>
Mon, 2 Jan 2017 00:42:58 +0000 (01:42 +0100)
committerRichard Russon <rich@flatcap.org>
Thu, 5 Jan 2017 01:20:24 +0000 (01:20 +0000)
When searching over a very large result, the result will be very slow for mutt
to load. So, inspired by sup's feature to iteratively load the results, I figured
adding a couple of commands to move an user set window backward/forward in time
could be useful. And a new command extending the default vfolder-from-query function
is being exposed.

The current window information is user settable, so the user can make a macro that
would do useful stuff about a search (like moving the window's position around, or
further tweaking current search).

* addition of four configuration variables, the first two are aimed at configuring
    the behaviour of the feature, the last two are exposing internals to make it
    hacking friendly:
  - nm_query_window_duration: duration for each window
  - nm_query_window_timebase: time base for each window
  - nm_query_window_current_search: the search being displayed as vfolder
  - nm_query_window_current_position: the current window's position
* addition of three bindable commands:
  - windowed-vfolder-from-query: execute a search with a window applied
  - windowed-vfolder-backward: move the window backwards in time
  - windowed-vfolder-forward: move the window forwards in time

Closes: #278
OPS.NOTMUCH
curs_main.c
doc/manual.xml.head
doc/muttrc.notmuch
doc/vimrc.notmuch
functions.h
globals.h
init.h
mutt_notmuch.c
mutt_notmuch.h

index 4508e4e2babc96de73ccdd61658bb94fc3d89be7..7fdbe7fb4b0edf16dee07c205e6f177463a05b30 100644 (file)
@@ -1,5 +1,8 @@
 OP_MAIN_CHANGE_VFOLDER "open a different virtual folder"
 OP_MAIN_VFOLDER_FROM_QUERY "generate virtual folder from query"
+OP_MAIN_WINDOWED_VFOLDER_FROM_QUERY "generate virtual folder from query and time window"
+OP_MAIN_WINDOWED_VFOLDER_FORWARD "shifts virtual folder time window forwards"
+OP_MAIN_WINDOWED_VFOLDER_BACKWARD "shifts virtual folder time window backwards"
 OP_MAIN_MODIFY_LABELS "modify (notmuch) tags"
 OP_MAIN_MODIFY_LABELS_THEN_HIDE "modify labels and then hide message"
 OP_MAIN_ENTIRE_THREAD "read entire thread of the current message"
index 5c35d8453adc47bba42039f95914aff365e844e0..9bcb52ad72cf10feb3175c40601c7c420e1e1fbe 100644 (file)
@@ -1888,6 +1888,81 @@ int mutt_index_menu (void)
          main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint, 0);
        break;
 
+      case OP_MAIN_WINDOWED_VFOLDER_FROM_QUERY:
+        dprint(2, (debugfile, "OP_MAIN_WINDOWED_VFOLDER_FROM_QUERY\n"));
+        if (NotmuchQueryWindowDuration < 0) 
+        {
+          mutt_message (_("Windowed queries disabled."));
+          break;
+        }
+        if (!nm_query_window_check_timebase(NotmuchQueryWindowTimebase))
+        {
+          mutt_message (_("Invalid nm_query_window_timebase value (valid values are: hour, day, week, month or year)."));
+          break;
+        }
+        buf[0] = '\0';
+        if ((mutt_get_field ("Query: ", buf, sizeof (buf), MUTT_NM_QUERY) != 0) || !buf[0])
+        {
+          mutt_message (_("No query, aborting."));
+          break;
+        }
+        nm_setup_windowed_query(buf, sizeof (buf));
+        nm_query_window_reset();
+        if (!nm_uri_from_windowed_query(Context, buf, sizeof(buf), NotmuchQueryWindowTimebase, NotmuchQueryWindowDuration))
+          mutt_message (_("Failed to create query, aborting."));
+        else
+        {
+          dprint(2, (debugfile, "nm: windowed query (%s)\n", buf));
+          main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint, 0);
+        }
+        break;
+
+      case OP_MAIN_WINDOWED_VFOLDER_BACKWARD:
+        dprint(2, (debugfile, "OP_MAIN_WINDOWED_VFOLDER_BACKWARD\n"));
+        if (NotmuchQueryWindowDuration < 0) 
+        {
+          mutt_message (_("Windowed queries disabled."));
+          break;
+        }
+        if (!nm_query_window_check_timebase(NotmuchQueryWindowTimebase))
+        {
+          mutt_message (_("Invalid nm_query_window_timebase value (valid values are: hour, day, week, month or year)."));
+          break;
+        }
+        buf[0] = '\0';
+        nm_query_window_backward();
+        if (!nm_uri_from_windowed_query(Context, buf, sizeof(buf), NotmuchQueryWindowTimebase, NotmuchQueryWindowDuration))
+          mutt_message (_("Failed to create query, aborting."));
+        else
+        {
+          dprint(2, (debugfile, "nm: - windowed query (%s)\n", buf));
+          main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint, 0);
+        }
+        break;
+
+      case OP_MAIN_WINDOWED_VFOLDER_FORWARD:
+        dprint(2, (debugfile, "OP_MAIN_WINDOWED_VFOLDER_FORWARD\n"));
+        if (NotmuchQueryWindowDuration < 0) 
+        {
+          mutt_message (_("Windowed queries disabled."));
+          break;
+        }
+        if (!nm_query_window_check_timebase(NotmuchQueryWindowTimebase))
+        {
+          mutt_message (_("Invalid nm_query_window_timebase value (valid values are: hour, day, week, month or year)."));
+          break;
+        }
+        buf[0] = '\0';
+        nm_query_window_forward();
+        if (!nm_uri_from_windowed_query(Context, buf, sizeof(buf), NotmuchQueryWindowTimebase, NotmuchQueryWindowDuration))
+          mutt_message (_("Failed to create query, aborting."));
+        else
+        {
+          dprint(2, (debugfile, "nm: + windowed query (%s)\n", buf));
+          main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint, 0);
+        }
+        break;
+
       case OP_MAIN_CHANGE_VFOLDER:
 #endif
 
index 92a2c8553552a35bb9ec1c048e4ccdee345e68bb..dac7c40c02a132801a4a04d20cf97249a120deb9 100644 (file)
@@ -12293,6 +12293,21 @@ virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox"
             <entry><literal>&lt;vfolder-from-query&gt;</literal></entry>
             <entry>generate virtual folder from query</entry>
           </row>
+          <row>
+            <entry>index,pager</entry>
+            <entry><literal>&lt;windowed-vfolder-from-query&gt;</literal></entry>
+            <entry>generate virtual folder from query with window applied</entry>
+          </row>
+          <row>
+            <entry>index,pager</entry>
+            <entry><literal>&lt;windowed-vfolder-forward&gt;</literal></entry>
+            <entry>generate virtual folder by moving the query's time window forward</entry>
+          </row>
+          <row>
+            <entry>index,pager</entry>
+            <entry><literal>&lt;windowed-vfolder-backward&gt;</literal></entry>
+            <entry>generate virtual folder by moving the query's time window backward</entry>
+          </row>
         </tbody>
       </tgroup>
     </table>
@@ -12444,6 +12459,11 @@ set vfolder_format = &quot;%6n(%6N) %f&quot;
 # as a spoolfile.</emphasis>
 set virtual_spoolfile = no
 
+<emphasis role="comment"># setup time window preferences
+# first setup the duration, and then the time unit of that duration</emphasis>
+set nm_query_window_duration=2
+set nm_query_window_timebase="week" # or "hour", "day", "week", "month", "year"
+
 <emphasis role="comment"># --------------------------------------------------------------------------
 # FUNCTIONS - shown with an example mapping
 # --------------------------------------------------------------------------
@@ -12460,6 +12480,11 @@ bind index,pager \` modify-labels
 <emphasis role="comment"># generate virtual folder from query</emphasis>
 bind index,pager \eX vfolder-from-query
 
+<emphasis role="comment"># generate virtual folder from query with time window</emphasis>
+bind index,pager \\ windowed-vfolder-from-query
+bind index,pager &lt; windowed-vfolder-backward
+bind index,pager &gt; windowed-vfolder-forward
+
 <emphasis role="comment"># modify labels and then hide message
 # bind index,pager ??? modify-labels-then-hide
 
@@ -12557,6 +12582,7 @@ color index_tags green default
     <listitem><para>Vladimir Marek <email>Vladimir.Marek@oracle.com</email></para></listitem>
     <listitem><para>Víctor Manuel Jáquez Leal <email>vjaquez@igalia.com</email></para></listitem>
     <listitem><para>Richard Russon <email>rich@flatcap.org</email></para></listitem>
+    <listitem><para>Bernard 'Guyzmo' Pratz <email>guyzmo+github+pub@m0g.net</email></para></listitem>
     </itemizedlist>
   </sect2>
 </sect1>
index d11f76839629d17a2ea3a962de4f71128bfb3e65..d422390d312b8d165f96588bd0972b581ce4f2af 100644 (file)
@@ -44,6 +44,14 @@ set vfolder_format = "%6n(%6N) %f"
 # as a spoolfile.
 set virtual_spoolfile = no
 
+# set the time base to apply to the time window
+# valid values are: "hour", "day", "week", "month", "year"
+set nm_query_window_timebase="week"
+
+# how large shall the window be? Any positive integer value is fine, in the
+# unit of the previously defined timebase. If 0 is set, the feature is disabled.
+set nm_query_window_duration=2
+
 # --------------------------------------------------------------------------
 # FUNCTIONS - shown with an example mapping
 # --------------------------------------------------------------------------
@@ -60,6 +68,15 @@ bind index,pager \` modify-labels
 # generate virtual folder from query
 bind index,pager \eX vfolder-from-query
 
+# generate a virtual folder with a time window
+bind index \\ windowed-vfolder-from-query
+
+# move the time window forward
+bind index >  windowed-vfolder-forward
+
+# move the time window backward
+bind index <  windowed-vfolder-backward
+
 # modify labels and then hide message
 # bind index,pager ??? modify-labels-then-hide
 
index 5cbcfd3c4dad479cf5fde29be2766c4f908a2fd8..786c517b44012abf089009b316b343c1dc92c13d 100644 (file)
@@ -6,6 +6,9 @@ syntax keyword muttrcVarBool    contained skipwhite virtual_spoolfile     nextgr
 syntax keyword muttrcVarNum     contained skipwhite nm_db_limit           nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
 syntax keyword muttrcVarNum     contained skipwhite nm_open_timeout       nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
 
+syntax keyword muttrcVarNum     contained skipwhite nm_query_window_duration nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
+syntax keyword muttrcVarNum     contained skipwhite nm_query_window_timebase nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
+
 syntax keyword muttrcVarStr     contained skipwhite nm_default_uri        nextgroup=muttrcVarEqualsIdxFmt
 syntax keyword muttrcVarStr     contained skipwhite nm_exclude_tags       nextgroup=muttrcVarEqualsIdxFmt
 syntax keyword muttrcVarStr     contained skipwhite nm_hidden_tags        nextgroup=muttrcVarEqualsIdxFmt
@@ -24,4 +27,7 @@ syntax match muttrcFunction     contained "\<modify-labels-then-hide\>"
 syntax match muttrcFunction     contained "\<modify-labels\>"
 syntax match muttrcFunction     contained "\<sidebar-toggle-virtual\>"
 syntax match muttrcFunction     contained "\<vfolder-from-query\>"
+syntax match muttrcFunction     contained "\<windowed-vfolder-from-query\>"
+syntax match muttrcFunction     contained "\<windowed-vfolder-forward\>"
+syntax match muttrcFunction     contained "\<windowed-vfolder-backward\>"
 
index 85e229fa3502e98ed41455e62fb3287002a9a236..ed4ae5e368ac44d99aa492c9417e843081262450 100644 (file)
@@ -209,6 +209,9 @@ const struct binding_t OpMain[] = { /* map: index */
 #ifdef USE_NOTMUCH
   { "change-vfolder",          OP_MAIN_CHANGE_VFOLDER,         NULL },
   { "vfolder-from-query",      OP_MAIN_VFOLDER_FROM_QUERY,     NULL },
+  { "windowed-vfolder-from-query",     OP_MAIN_WINDOWED_VFOLDER_FROM_QUERY, NULL },
+  { "windowed-vfolder-backward",       OP_MAIN_WINDOWED_VFOLDER_BACKWARD,   NULL },
+  { "windowed-vfolder-forward",                OP_MAIN_WINDOWED_VFOLDER_FORWARD,    NULL },
   { "modify-labels",           OP_MAIN_MODIFY_LABELS,          NULL },
   { "modify-labels-then-hide", OP_MAIN_MODIFY_LABELS_THEN_HIDE, NULL },
   { "entire-thread",           OP_MAIN_ENTIRE_THREAD,          NULL },
index 1f86d7d10ea1ac19e2d4964d348059012e32fb58..55e7d871c5818435cb0f2af02e5de8d9ee98a76d 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -320,6 +320,10 @@ WHERE char *VirtFolderFormat;
 WHERE int NotmuchDBLimit;
 WHERE char *NotmuchQueryType;
 WHERE char *NotmuchRecordTags;
+WHERE int NotmuchQueryWindowDuration;
+WHERE char *NotmuchQueryWindowTimebase;
+WHERE int NotmuchQueryWindowCurrentPosition;
+WHERE char *NotmuchQueryWindowCurrentSearch;
 #endif
 
 
diff --git a/init.h b/init.h
index 2675014684fd7f7f4e5fbc8be0ec44136c09937a..2883bbdd85851867f3567096045e44dcb3d625f5 100644 (file)
--- a/init.h
+++ b/init.h
@@ -2049,6 +2049,29 @@ struct option_t MuttVars[] = {
    ** .pp
    ** This variable specifies the default tags applied to messages stored to the mutt record.
    */
+  { "nm_query_window_duration", DT_NUM, R_NONE, UL &NotmuchQueryWindowDuration, 2 },
+  /*
+   ** .pp
+   ** This variable sets the time base of a windowed notmuch query.
+   ** Accepted values are 'minute', 'hour', 'day', 'week', 'month', 'year'
+   */
+  { "nm_query_window_timebase", DT_STR, R_NONE, UL &NotmuchQueryWindowTimebase, UL "week" },
+  /*
+   ** .pp
+   ** This variable sets the time duration of a windowed notmuch query.
+   ** Accepted values all non negative integers. A value of 0 disables the feature.
+   */
+  { "nm_query_window_current_search", DT_STR, R_NONE, UL &NotmuchQueryWindowCurrentSearch, UL "" },
+  /*
+   ** .pp
+   ** This variable sets the time duration of a windowed notmuch query.
+   ** Accepted values all non negative integers. A value of 0 disables the feature.
+   */
+  { "nm_query_window_current_position", DT_NUM, R_NONE, UL &NotmuchQueryWindowCurrentPosition, 0 },
+  /*
+   ** .pp
+   ** This variable contains the currently setup notmuch search for window based vfolder.
+   */
 #endif
   { "pager",           DT_PATH, R_NONE, UL &Pager, UL "builtin" },
   /*
index 28d2889c1e4fd9c2edad3c80d35f3f37f66171a9..7b8cccd180e27e4c4cd55e7b2179379be08c9365 100644 (file)
@@ -1263,6 +1263,64 @@ char *nm_uri_from_query(CONTEXT *ctx, char *buf, size_t bufsz)
        return buf;
 }
 
+void nm_setup_windowed_query(char *buf, size_t bufsz)
+{
+       dprint(2, (debugfile, "nm_setup_windowed_query (%s)\n", buf));
+       mutt_str_replace(&NotmuchQueryWindowCurrentSearch, buf);
+}
+
+int nm_query_window_check_timebase(char *timebase)
+{
+       if ((strcmp(timebase, "hour")  == 0) ||
+           (strcmp(timebase, "day")   == 0) ||
+           (strcmp(timebase, "week")  == 0) ||
+           (strcmp(timebase, "month") == 0) ||
+           (strcmp(timebase, "year")  == 0))
+               return true;
+       return false;
+}
+
+char *nm_uri_from_windowed_query(CONTEXT *ctx, char *buf, size_t bufsz, char *timebase, int duration)
+{
+       dprint(2, (debugfile, "nm_uri_from_windowed_query (%s, %s, %d)\n", buf, timebase, duration));
+
+       int beg = duration * (NotmuchQueryWindowCurrentPosition + 1);
+       int end = duration *  NotmuchQueryWindowCurrentPosition;
+
+       if (NotmuchQueryWindowCurrentSearch == NULL)
+       {
+               nm_query_window_reset();
+               return NULL;
+       }
+
+       if (end == 0)
+               snprintf(buf, bufsz, "date:%d%s..now and %s", beg, timebase, NotmuchQueryWindowCurrentSearch);
+       else
+               snprintf(buf, bufsz, "date:%d%s..%d%s and %s", beg, timebase, end, timebase, NotmuchQueryWindowCurrentSearch);
+
+       return nm_uri_from_query(ctx, buf, bufsz);
+}
+
+void nm_query_window_reset()
+{
+       dprint(2, (debugfile, "nm_query_window_reset ()\n"));
+       NotmuchQueryWindowCurrentPosition = 0;
+}
+
+void nm_query_window_backward()
+{
+       NotmuchQueryWindowCurrentPosition += 1;
+       dprint(2, (debugfile, "nm_query_window_backward (%d)\n", NotmuchQueryWindowCurrentPosition));
+}
+
+void nm_query_window_forward()
+{
+       if (NotmuchQueryWindowCurrentPosition != 0)
+               NotmuchQueryWindowCurrentPosition -= 1;
+
+       dprint(2, (debugfile, "nm_query_window_forward (%d)\n", NotmuchQueryWindowCurrentPosition));
+}
+
 /*
  * returns message from notmuch database
  */
index 8267b1fd114726d273ec93c2e849b5f7054e4af3..c70590a114b9eee133288ff6e505a62d08daddf6 100644 (file)
@@ -15,6 +15,13 @@ int nm_update_filename(CONTEXT *ctx, const char *o, const char *n, HEADER *h);
 char *nm_uri_from_query(CONTEXT *ctx, char *buf, size_t bufsz);
 int nm_modify_message_tags(CONTEXT *ctx, HEADER *hdr, char *tags);
 
+void nm_setup_windowed_query(char *buf, size_t bufsz);
+char *nm_uri_from_windowed_query(CONTEXT *ctx, char *buf, size_t bufsz, char *timebase, int duration);
+void nm_query_window_reset();
+void nm_query_window_backward();
+void nm_query_window_forward();
+int nm_query_window_check_timebase(char *timebase);
+
 void nm_longrun_init(CONTEXT *cxt, int writable);
 void nm_longrun_done(CONTEXT *cxt);