NeoMutt  2024-10-02-37-gfa9146
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
query.c
Go to the documentation of this file.
1
32#include "config.h"
33#include <stddef.h>
34#include <stdio.h>
35#include "mutt/lib.h"
36#include "query.h"
37
49enum NmQueryType nm_parse_type_from_query(char *buf, enum NmQueryType fallback)
50{
51 enum NmQueryType query_type = fallback;
52
53 if (!buf)
54 return query_type;
55
56 size_t buflen = mutt_str_len(buf);
57 const char *message_ptr = mutt_istrn_rfind(buf, buflen, "type=messages");
58 const char *thread_ptr = mutt_istrn_rfind(buf, buflen, "type=threads");
59
60 // No valid type statement found.
61 if (!message_ptr && !thread_ptr)
62 return query_type;
63
64 // Determine the last valid "type=" statement.
65 if ((!message_ptr && thread_ptr) || (thread_ptr > message_ptr))
66 {
67 query_type = NM_QUERY_TYPE_THREADS;
68 }
69 else
70 {
71 query_type = NM_QUERY_TYPE_MESGS;
72 }
73
74 // Clean-up any valid "type=" statements.
75 // The six variations of how "type=" could appear.
76 const char *variants[6] = { "&type=threads", "&type=messages",
77 "type=threads&", "type=messages&",
78 "type=threads", "type=messages" };
79 int variants_size = mutt_array_size(variants);
80
81 for (int i = 0; i < variants_size; i++)
82 {
83 mutt_istr_remall(buf, variants[i]);
84 }
85
86 return query_type;
87}
88
96const char *nm_query_type_to_string(enum NmQueryType query_type)
97{
98 if (query_type == NM_QUERY_TYPE_THREADS)
99 return "threads";
100 return "messages";
101}
102
111{
112 enum NmQueryType query_type = nm_string_to_query_type_mapper(str);
113
114 if (query_type == NM_QUERY_TYPE_UNKNOWN)
115 {
116 mutt_error(_("failed to parse notmuch query type: %s"), NONULL(str));
117 return NM_QUERY_TYPE_MESGS;
118 }
119
120 return query_type;
121}
122
130{
131 if (mutt_str_equal(str, "threads"))
133 if (mutt_str_equal(str, "messages"))
134 return NM_QUERY_TYPE_MESGS;
135
137}
138
149bool nm_query_window_check_timebase(const char *timebase)
150{
151 if ((mutt_str_equal(timebase, "hour")) || (mutt_str_equal(timebase, "day")) ||
152 (mutt_str_equal(timebase, "week")) ||
153 (mutt_str_equal(timebase, "month")) || (mutt_str_equal(timebase, "year")))
154 {
155 return true;
156 }
157 return false;
158}
159
206nm_windowed_query_from_query(char *buf, size_t buflen, const bool force_enable,
207 const short duration, const short cur_pos, const char *cur_search,
208 const char *timebase, const char *or_terms)
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 }
216
217 int beg = duration * (cur_pos + 1);
218 int end = duration * cur_pos;
219
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 }
227
228 if (!nm_query_window_check_timebase(timebase))
229 {
231 }
232
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 }
244
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 }
251
252 // Add current search to window query.
253 snprintf(buf + length, buflen - length, " and %s", cur_search);
254
256}
#define mutt_error(...)
Definition: logging2.h:92
#define FREE(x)
Definition: memory.h:45
#define mutt_array_size(x)
Definition: memory.h:38
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
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:469
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:660
int mutt_istr_remall(char *str, const char *target)
Remove all occurrences of substring, ignoring case.
Definition: string.c:745
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
enum NmQueryType nm_string_to_query_type(const char *str)
Lookup a query type.
Definition: query.c:110
enum NmQueryType nm_string_to_query_type_mapper(const char *str)
Lookup a query type.
Definition: query.c:129
enum NmQueryType nm_parse_type_from_query(char *buf, enum NmQueryType fallback)
Parse a query type out of a query.
Definition: query.c:49
bool nm_query_window_check_timebase(const char *timebase)
Checks if a given timebase string is valid.
Definition: query.c:149
const char * nm_query_type_to_string(enum NmQueryType query_type)
Turn a query type into a string.
Definition: query.c:96
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.
Definition: query.c:206
Notmuch query functions.
NmWindowQueryRc
Return codes for nm_windowed_query_from_query()
Definition: query.h:45
@ NM_WINDOW_QUERY_SUCCESS
Query was successful.
Definition: query.h:46
@ NM_WINDOW_QUERY_INVALID_DURATION
Invalid duration.
Definition: query.h:48
@ NM_WINDOW_QUERY_INVALID_TIMEBASE
Invalid timebase.
Definition: query.h:47
NmQueryType
Notmuch Query Types.
Definition: query.h:35
@ NM_QUERY_TYPE_UNKNOWN
Unknown query type. Error in notmuch query.
Definition: query.h:38
@ NM_QUERY_TYPE_THREADS
Whole threads.
Definition: query.h:37
@ NM_QUERY_TYPE_MESGS
Default: Messages only.
Definition: query.h:36
#define NONULL(x)
Definition: string2.h:37