NeoMutt  2021-10-29-43-g6b8931
Teaching an old dog new tricks
query.c File Reference

Notmuch query functions. More...

#include "config.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "mutt/lib.h"
#include "query.h"
+ Include dependency graph for query.c:

Go to the source code of this file.


enum NmQueryType nm_parse_type_from_query (char *buf)
 Parse a query type out of a query. More...
const char * nm_query_type_to_string (enum NmQueryType query_type)
 Turn a query type into a string. More...
enum NmQueryType nm_string_to_query_type (const char *str)
 Lookup a query type. More...
enum NmQueryType nm_string_to_query_type_mapper (const char *str)
 Lookup a query type. More...
bool nm_query_window_check_timebase (const char *timebase)
 Checks if a given timebase string is valid. More...
enum NmWindowQueryRc nm_windowed_query_from_query (char *buf, size_t buflen, const bool force_enable, const short duration, const short cur_pos, const char *cur_search, const char *timebase, const char *or_terms)
 Windows buf with notmuch date: search term. More...

Detailed Description

Notmuch query functions.

  • Austin Ray

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

Definition in file query.c.

Function Documentation

◆ nm_parse_type_from_query()

enum NmQueryType nm_parse_type_from_query ( char *  buf)

Parse a query type out of a query.

bufBuffer for URL
Return values
Notmuchquery type. Default: NM_QUERY_TYPE_MESGS

If a user writes a query for a vfolder and includes a type= statement, that type= will be encoded, which Notmuch will treat as part of the query= statement. This method will remove the type= and return its corresponding NmQueryType representation.

Definition at line 1 of file query.c.

49 {
50  if (!buf)
53  enum NmQueryType query_type = NM_QUERY_TYPE_MESGS;
55  size_t buf_len = mutt_str_len(buf);
56  const char *message_ptr = mutt_istrn_rfind(buf, buf_len, "type=messages");
57  const char *thread_ptr = mutt_istrn_rfind(buf, buf_len, "type=threads");
59  // No valid type statement found.
60  if (!message_ptr && !thread_ptr)
61  return query_type;
63  // Determine the last valid "type=" statement.
64  if ((!message_ptr && thread_ptr) || (thread_ptr > message_ptr))
65  {
66  query_type = NM_QUERY_TYPE_THREADS;
67  }
68  else
69  {
70  query_type = NM_QUERY_TYPE_MESGS;
71  }
73  // Clean-up any valid "type=" statements.
74  // The six variations of how "type=" could appear.
75  const char *variants[6] = { "&type=threads", "&type=messages",
76  "type=threads&", "type=messages&",
77  "type=threads", "type=messages" };
78  int variants_size = mutt_array_size(variants);
80  for (int i = 0; i < variants_size; i++)
81  {
82  mutt_istr_remall(buf, variants[i]);
83  }
85  return query_type;
86 }
#define mutt_array_size(x)
Definition: memory.h:33
const char * mutt_istrn_rfind(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring, ignoring case.
Definition: string.c:448
int mutt_istr_remall(char *str, const char *target)
Remove all occurrences of substring, ignoring case.
Definition: string.c:881
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:475
Notmuch Query Types.
Definition: query.h:35
Whole threads.
Definition: query.h:37
Default: Messages only.
Definition: query.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_query_type_to_string()

const char* nm_query_type_to_string ( enum NmQueryType  query_type)

Turn a query type into a string.

query_typeQuery type
Return values
This is a static string and must not be freed.

Definition at line 95 of file query.c.

96 {
97  if (query_type == NM_QUERY_TYPE_THREADS)
98  return "threads";
99  return "messages";
100 }
+ Here is the caller graph for this function:

◆ nm_string_to_query_type()

enum NmQueryType nm_string_to_query_type ( const char *  str)

Lookup a query type.

strString to lookup
Return values
numQuery type, e.g. NM_QUERY_TYPE_MESGS

If there's an unknown query type, default to NM_QUERY_TYPE_MESGS.

Definition at line 95 of file query.c.

110 {
111  enum NmQueryType query_type = nm_string_to_query_type_mapper(str);
113  if (query_type == NM_QUERY_TYPE_UNKNOWN)
114  {
115  mutt_error(_("failed to parse notmuch query type: %s"), NONULL(str));
116  return NM_QUERY_TYPE_MESGS;
117  }
119  return query_type;
120 }
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
enum NmQueryType nm_string_to_query_type_mapper(const char *str)
Lookup a query type.
Definition: query.c:129
Unknown query type. Error in notmuch query.
Definition: query.h:38
#define NONULL(x)
Definition: string2.h:37
+ Here is the caller graph for this function:

◆ nm_string_to_query_type_mapper()

enum NmQueryType nm_string_to_query_type_mapper ( const char *  str)

Lookup a query type.

strString to lookup
Return values
numQuery type

Definition at line 95 of file query.c.

130 {
131  if (mutt_str_equal(str, "threads"))
133  if (mutt_str_equal(str, "messages"))
134  return NM_QUERY_TYPE_MESGS;
137 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:715

◆ nm_query_window_check_timebase()

bool nm_query_window_check_timebase ( const char *  timebase)

Checks if a given timebase string is valid.

[in]timebasestring containing a time base
Return values
trueThe given time base is valid

This function returns whether a given timebase string is valid or not, which is used to validate the user settable configuration setting:


Definition at line 149 of file query.c.

150 {
151  if ((strcmp(timebase, "hour") == 0) || (strcmp(timebase, "day") == 0) ||
152  (strcmp(timebase, "week") == 0) || (strcmp(timebase, "month") == 0) ||
153  (strcmp(timebase, "year") == 0))
154  {
155  return true;
156  }
157  return false;
158 }
+ Here is the caller graph for this function:

◆ nm_windowed_query_from_query()

enum NmWindowQueryRc nm_windowed_query_from_query ( char *  buf,
size_t  buflen,
const bool  force_enable,
const short  duration,
const short  cur_pos,
const char *  cur_search,
const char *  timebase,
const char *  or_terms 

Windows buf with notmuch date: search term.

[out]bufallocated string buffer to receive the modified search query
[in]buflenallocated maximum size of the buf string buffer
[in]force_enableEnables windowing for duration=0
[in]durationDuration of time between beginning and end for notmuch date search term
[in]cur_posCurrent position of vfolder window
[in]cur_searchCurrent notmuch search
[in]timebaseTimebase for date: search term. Must be: hour, day, week, month, or year
[in]or_termsAdditional notmuch search terms
Return values
NM_WINDOW_QUERY_SUCCESSPrepended buf with date: search term
NM_WINDOW_QUERY_INVALID_DURATIONDuration out-of-range for search term. buf not prepended with date:
NM_WINDOW_QUERY_INVALID_TIMEBASETimebase isn't one of hour, day, week, month, or year

This is where the magic of windowed queries happens. Taking a vfolder search query string as parameter, it will use the following two user settings:

  • duration and
  • timebase

to amend given vfolder search window. Then using a third parameter:

  • cur_pos

it will generate a proper notmuch date: parameter. For example, given a duration of 2, a timebase set to week and a position defaulting to 0, it will prepend to the 'tag:inbox' notmuch search query the following string:

  • query: tag:inbox
  • buf: and tag:inbox

If the position is set to 4, with duration=3 and timebase=month:

  • query: tag:archived
  • buf: date:12month..9month and tag:archived

The window won't be applied:

  • If the duration of the search query is set to 0 this function will be disabled unless a user explicitly enables windowed queries. This returns NM_WINDOW_QUERY_INVALID_DURATION
  • If the timebase is invalid, it will return NM_WINDOW_QUERY_INVALID_TIMEBASE

Definition at line 149 of file query.c.

209 {
210  // if the duration is a non positive integer, disable the window unless the
211  // user explicitly enables windowed queries.
212  if (!force_enable && (duration <= 0))
213  {
215  }
217  int beg = duration * (cur_pos + 1);
218  int end = duration * cur_pos;
220  // If the duration is 0, we want to generate a query spanning a single timebase.
221  // For example, `date:1month..1month` spans the previous month.
222  if ((duration == 0) && (cur_pos != 0))
223  {
224  end = cur_pos;
225  beg = end;
226  }
228  if (!nm_query_window_check_timebase(timebase))
229  {
231  }
233  size_t length = 0;
234  if (end == 0)
235  {
236  // Open-ended date allows mail from the future.
237  // This may occur is the sender's time settings are off.
238  length = snprintf(buf, buflen, "date:%d%s..", beg, timebase);
239  }
240  else
241  {
242  length = snprintf(buf, buflen, "date:%d%s..%d%s", beg, timebase, end, timebase);
243  }
245  if (!mutt_str_equal(or_terms, ""))
246  {
247  char *date_part = mutt_str_dup(buf);
248  length = snprintf(buf, buflen, "(%s or (%s))", date_part, or_terms);
249  FREE(&date_part);
250  }
252  // Add current search to window query.
253  snprintf(buf + length, buflen, " and %s", cur_search);
256 }
#define FREE(x)
Definition: memory.h:40
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:181
bool nm_query_window_check_timebase(const char *timebase)
Checks if a given timebase string is valid.
Definition: query.c:149
Query was successful.
Definition: query.h:46
Invalid duration.
Definition: query.h:48
Invalid timebase.
Definition: query.h:47
+ Here is the caller graph for this function: