NeoMutt  2025-12-11-694-ga89709
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
query.c
Go to the documentation of this file.
1
24
32
33#include "config.h"
34#include <stddef.h>
35#include <stdio.h>
36#include "mutt/lib.h"
37#include "config/lib.h"
38#include "query.h"
39
43static const struct Mapping NmQueryTypeMethods[] = {
44 // clang-format off
45 { "messages", NM_QUERY_TYPE_MESSAGES },
46 { "threads", NM_QUERY_TYPE_THREADS },
47 { NULL, 0 },
48 // clang-format on
49};
50
52const struct EnumDef NmQueryTypeDef = {
53 "nm_query_type",
54 2,
55 (struct Mapping *) &NmQueryTypeMethods,
56};
57
61static const struct Mapping NmTimebaseMethods[] = {
62 // clang-format off
63 { "hour", NMTB_HOUR },
64 { "day", NMTB_DAY },
65 { "week", NMTB_WEEK },
66 { "month", NMTB_MONTH },
67 { "year", NMTB_YEAR },
68 { NULL, 0 },
69 // clang-format on
70};
71
74 "nm_query_window_timebase",
75 5,
76 (struct Mapping *) &NmTimebaseMethods,
77};
78
90enum NmQueryType nm_parse_type_from_query(char *buf, enum NmQueryType fallback)
91{
92 enum NmQueryType query_type = fallback;
93
94 if (!buf)
95 return query_type;
96
97 size_t buflen = mutt_str_len(buf);
98 const char *message_ptr = mutt_istrn_rfind(buf, buflen, "type=messages");
99 const char *thread_ptr = mutt_istrn_rfind(buf, buflen, "type=threads");
100
101 // No valid type statement found.
102 if (!message_ptr && !thread_ptr)
103 return query_type;
104
105 // Determine the last valid "type=" statement.
106 if ((!message_ptr && thread_ptr) || (thread_ptr > message_ptr))
107 {
108 query_type = NM_QUERY_TYPE_THREADS;
109 }
110 else
111 {
112 query_type = NM_QUERY_TYPE_MESSAGES;
113 }
114
115 // Clean-up any valid "type=" statements.
116 // The six variations of how "type=" could appear.
117 const char *variants[6] = { "&type=threads", "&type=messages",
118 "type=threads&", "type=messages&",
119 "type=threads", "type=messages" };
120 int variants_size = countof(variants);
121
122 for (int i = 0; i < variants_size; i++)
123 {
124 mutt_istr_remall(buf, variants[i]);
125 }
126
127 return query_type;
128}
129
137const char *nm_query_type_to_string(enum NmQueryType query_type)
138{
139 const char *name = mutt_map_get_name(query_type, NmQueryTypeMethods);
140 return name ? name : "messages";
141}
142
151{
152 enum NmQueryType query_type = nm_string_to_query_type_mapper(str);
153
154 if (query_type == NM_QUERY_TYPE_UNKNOWN)
155 {
156 mutt_error(_("failed to parse notmuch query type: %s"), NONULL(str));
158 }
159
160 return query_type;
161}
162
170{
171 int query_type = mutt_map_get_value(str, NmQueryTypeMethods);
172 return (query_type < 0) ? NM_QUERY_TYPE_UNKNOWN : query_type;
173}
174
220nm_windowed_query_from_query(char *buf, size_t buflen, const bool force_enable,
221 const short duration, const short cur_pos, const char *cur_search,
222 const enum NmTimebase timebase, const char *or_terms)
223{
224 // if the duration is a non positive integer, disable the window unless the
225 // user explicitly enables windowed queries.
226 if (!force_enable && (duration <= 0))
227 {
229 }
230
231 int beg = duration * (cur_pos + 1);
232 int end = duration * cur_pos;
233
234 // If the duration is 0, we want to generate a query spanning a single timebase.
235 // For example, `date:1month..1month` spans the previous month.
236 if ((duration == 0) && (cur_pos != 0))
237 {
238 end = cur_pos;
239 beg = end;
240 }
241
242 const char *timebase_str = mutt_map_get_name(timebase, NmTimebaseMethods);
243 if (!timebase_str)
244 {
246 }
247
248 size_t length = 0;
249 if (end == 0)
250 {
251 // Open-ended date allows mail from the future.
252 // This may occur is the sender's time settings are off.
253 length = snprintf(buf, buflen, "date:%d%s..", beg, timebase_str);
254 }
255 else
256 {
257 length = snprintf(buf, buflen, "date:%d%s..%d%s", beg, timebase_str, end, timebase_str);
258 }
259
260 if (!mutt_str_equal(or_terms, ""))
261 {
262 char *date_part = mutt_str_dup(buf);
263 length = snprintf(buf, buflen, "(%s or (%s))", date_part, or_terms);
264 FREE(&date_part);
265 }
266
267 // Add current search to window query.
268 snprintf(buf + length, buflen - length, " and %s", cur_search);
269
271}
Convenience wrapper for the config headers.
#define mutt_error(...)
Definition logging2.h:94
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition mapping.c:85
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition mapping.c:42
#define countof(x)
Definition memory.h:49
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
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:257
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:473
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
int mutt_istr_remall(char *str, const char *target)
Remove all occurrences of substring, ignoring case.
Definition string.c:750
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
enum NmQueryType nm_string_to_query_type(const char *str)
Lookup a query type.
Definition query.c:150
static const struct Mapping NmQueryTypeMethods[]
Choices for $nm_query_type
Definition query.c:43
static const struct Mapping NmTimebaseMethods[]
Choices for $nm_query_window_timebase
Definition query.c:61
const struct EnumDef NmQueryWindowTimebaseDef
Data for the $nm_query_window_timebase enumeration.
Definition query.c:73
enum NmQueryType nm_string_to_query_type_mapper(const char *str)
Lookup a query type.
Definition query.c:169
enum NmQueryType nm_parse_type_from_query(char *buf, enum NmQueryType fallback)
Parse a query type out of a query.
Definition query.c:90
const struct EnumDef NmQueryTypeDef
Data for the $nm_query_type enumeration.
Definition query.c:52
const char * nm_query_type_to_string(enum NmQueryType query_type)
Turn a query type into a string.
Definition query.c:137
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 enum NmTimebase timebase, const char *or_terms)
Windows buf with notmuch date: search term.
Definition query.c:220
Notmuch query functions.
NmWindowQueryRc
Return codes for nm_windowed_query_from_query()
Definition query.h:60
@ NM_WINDOW_QUERY_SUCCESS
Query was successful.
Definition query.h:61
@ NM_WINDOW_QUERY_INVALID_DURATION
Invalid duration.
Definition query.h:63
@ NM_WINDOW_QUERY_INVALID_TIMEBASE
Invalid timebase.
Definition query.h:62
NmQueryType
Notmuch Query Types.
Definition query.h:37
@ NM_QUERY_TYPE_UNKNOWN
Unknown query type. Error in notmuch query.
Definition query.h:38
@ NM_QUERY_TYPE_THREADS
Whole threads.
Definition query.h:40
@ NM_QUERY_TYPE_MESSAGES
Default: Messages only.
Definition query.h:39
NmTimebase
Time periods for notmuch windowed queries.
Definition query.h:47
@ NMTB_YEAR
Years.
Definition query.h:53
@ NMTB_MONTH
Months.
Definition query.h:52
@ NMTB_HOUR
Hours.
Definition query.h:49
@ NMTB_WEEK
Weeks.
Definition query.h:51
@ NMTB_DAY
Days.
Definition query.h:50
#define NONULL(x)
Definition string2.h:44
An enumeration.
Definition enum.h:30
Mapping between user-readable string and a constant.
Definition mapping.h:33
const char * name
String value.
Definition mapping.h:34