NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
complete.c
Go to the documentation of this file.
1
22
28
29#include "config.h"
30#include <notmuch.h>
31#include <stdbool.h>
32#include <stdio.h>
33#include <string.h>
34#include "private.h"
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "core/lib.h"
38#include "gui/lib.h"
39#include "lib.h"
40#include "complete/lib.h"
41#include "editor/lib.h"
42#include "index/lib.h"
43
49static void nm_complete_data_init(struct CompletionData *cd, const char *pt)
50{
52 mutt_str_copy(cd->user_typed, pt, sizeof(cd->user_typed));
53 memset(cd->match_list, 0, cd->match_list_len * sizeof(const char *));
54 memset(cd->completed, 0, sizeof(cd->completed));
55 cd->num_matched = 0;
56 cd->free_match_strings = true;
57}
58
66{
67 int rc = -1;
68 struct Mailbox *m_cur = get_current_mailbox();
69 notmuch_database_t *db = NULL;
70 notmuch_tags_t *tags = NULL;
71 const char *db_filename = nm_db_get_filename(m_cur);
72
73#if !LIBNOTMUCH_CHECK_VERSION(5, 4, 0)
74 if (!db_filename)
75 db_filename = cs_subset_string(NeoMutt->sub, "folder");
76#endif
77
78 if (!(db = nm_db_do_open(db_filename, false, false)) ||
79 !(tags = notmuch_database_get_all_tags(db)))
80 {
81 goto done;
82 }
83
84 while (notmuch_tags_valid(tags))
85 {
86 const char *tag = notmuch_tags_get(tags);
87
88 /* Keep a private copy because notmuch owns the iterator storage. */
89 if (*tag && candidate(cd, cd->user_typed, tag, cd->completed, sizeof(cd->completed)))
90 cd->match_list[cd->num_matched - 1] = mutt_str_dup(tag);
91
92 notmuch_tags_move_to_next(tags);
93 }
94
95 rc = 0;
96
97done:
98 if (tags)
99 notmuch_tags_destroy(tags);
100 if (db)
101 nm_db_free(db);
102
103 return rc;
104}
105
113int complete_all_nm_tags(struct CompletionData *cd, const char *pt)
114{
115 int rc = -1;
116
117 nm_complete_data_init(cd, pt);
119 if (rc == 0)
120 {
123 }
124
125 return rc;
126}
127
138bool mutt_nm_query_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
139{
140 char *pt = buf->data;
141 int spaces;
142
143 SKIPWS(pt);
144 spaces = pt - buf->data;
145
146 pt = (char *) buf_rfind(buf, "tag:");
147 if (pt)
148 {
149 pt += 4;
150 if (numtabs == 1)
151 {
152 /* First TAB. Collect all the matches */
153 complete_all_nm_tags(cd, pt);
154
155 /* All matches are stored. Longest non-ambiguous string is ""
156 * i.e. don't change 'buf'. Fake successful return this time. */
157 if (cd->user_typed[0] == '\0')
158 return true;
159 }
160
161 if ((cd->completed[0] == '\0') && (cd->user_typed[0] != '\0'))
162 return false;
163
164 /* cd->num_matched will _always_ be at least 1 since the initial
165 * user-typed string is always stored */
166 if ((numtabs == 1) && (cd->num_matched == 2))
167 {
168 snprintf(cd->completed, sizeof(cd->completed), "%s", NONULL(cd->match_list[0]));
169 }
170 else if ((numtabs > 1) && (cd->num_matched > 2))
171 {
172 /* cycle through all the matches */
173 snprintf(cd->completed, sizeof(cd->completed), "%s",
174 NONULL(cd->match_list[(numtabs - 2) % cd->num_matched]));
175 }
176
177 /* return the completed query */
178 strncpy(pt, cd->completed, buf->data + buf->dsize - pt - spaces);
179 }
180 else
181 {
182 return false;
183 }
184
185 return true;
186}
187
198bool mutt_nm_tag_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
199{
200 if (!buf)
201 return false;
202
203 char *pt = buf->data;
204
205 /* Only examine the last token */
206 char *last_space = strrchr(buf->data, ' ');
207 if (last_space)
208 pt = (last_space + 1);
209
210 /* Skip the +/- */
211 if ((pt[0] == '+') || (pt[0] == '-'))
212 pt++;
213
214 if (numtabs == 1)
215 {
216 /* First TAB. Collect all the matches */
217 complete_all_nm_tags(cd, pt);
218
219 /* All matches are stored. Longest non-ambiguous string is ""
220 * i.e. don't change 'buf'. Fake successful return this time. */
221 if (cd->user_typed[0] == '\0')
222 return true;
223 }
224
225 if ((cd->completed[0] == '\0') && (cd->user_typed[0] != '\0'))
226 return false;
227
228 /* cd->num_matched will _always_ be at least 1 since the initial
229 * user-typed string is always stored */
230 if ((numtabs == 1) && (cd->num_matched == 2))
231 {
232 snprintf(cd->completed, sizeof(cd->completed), "%s", NONULL(cd->match_list[0]));
233 }
234 else if ((numtabs > 1) && (cd->num_matched > 2))
235 {
236 /* cycle through all the matches */
237 snprintf(cd->completed, sizeof(cd->completed), "%s",
238 NONULL(cd->match_list[(numtabs - 2) % cd->num_matched]));
239 }
240
241 /* return the completed query */
242 strncpy(pt, cd->completed, buf->data + buf->dsize - pt);
243
244 return true;
245}
246
251{
252 if (!wdata || ((op != OP_EDITOR_COMPLETE) && (op != OP_EDITOR_COMPLETE_QUERY)))
253 return FR_NO_ACTION;
254
255 int rc = FR_SUCCESS;
256 buf_mb_wcstombs(wdata->buffer, wdata->state->wbuf, wdata->state->curpos);
257 if (!mutt_nm_query_complete(wdata->cd, wdata->buffer, wdata->tabs))
258 rc = FR_ERROR;
259
260 replace_part(wdata->state, 0, buf_string(wdata->buffer));
261 return rc;
262}
263
268{
269 if (!wdata || ((op != OP_EDITOR_COMPLETE) && (op != OP_EDITOR_COMPLETE_QUERY)))
270 return FR_NO_ACTION;
271
272 int rc = FR_SUCCESS;
273 buf_mb_wcstombs(wdata->buffer, wdata->state->wbuf, wdata->state->curpos);
274 if (!mutt_nm_tag_complete(wdata->cd, wdata->buffer, wdata->tabs))
275 rc = FR_ERROR;
276
277 replace_part(wdata->state, 0, buf_string(wdata->buffer));
278 return rc;
279}
280
285 .complete = complete_nm_query,
286};
287
292 .complete = complete_nm_tag,
293};
const char * buf_rfind(const struct Buffer *buf, const char *str)
Find last instance of a substring.
Definition buffer.c:805
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
void matches_ensure_morespace(struct CompletionData *cd, int new_size)
Allocate more space for auto-completion.
Definition helpers.c:54
bool candidate(struct CompletionData *cd, char *user, const char *src, char *dest, size_t dlen)
Helper function for completion.
Definition helpers.c:79
Auto-completion.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
void completion_data_free_match_strings(struct CompletionData *cd)
Free the Completion strings.
Definition data.c:38
FunctionRetval
Possible return values for NeoMutt functions.
Definition dispatcher.h:33
@ FR_SUCCESS
Valid function - successfully performed.
Definition dispatcher.h:40
@ FR_ERROR
Valid function - error occurred.
Definition dispatcher.h:39
@ FR_NO_ACTION
Valid function - no action performed.
Definition dispatcher.h:38
void replace_part(struct EnterState *es, size_t from, const char *buf)
Search and replace on a buffer.
Definition functions.c:150
Edit a string.
enum FunctionRetval complete_nm_query(struct EnterWindowData *wdata, int op)
Complete a Notmuch Query - Implements CompleteOps::complete() -.
Definition complete.c:250
enum FunctionRetval complete_nm_tag(struct EnterWindowData *wdata, int op)
Complete a Notmuch Tag - Implements CompleteOps::complete() -.
Definition complete.c:267
Convenience wrapper for the gui headers.
GUI manage the main index (list of emails)
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition index.c:725
void buf_mb_wcstombs(struct Buffer *dest, const wchar_t *wstr, size_t wlen)
Convert a string from wide to multibyte characters.
Definition mbyte.c:257
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition string.c:587
static void nm_complete_data_init(struct CompletionData *cd, const char *pt)
Reset the completion state for a tag lookup.
Definition complete.c:49
int complete_all_nm_tags(struct CompletionData *cd, const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition complete.c:113
bool mutt_nm_query_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
Complete to the nearest notmuch tag.
Definition complete.c:138
const struct CompleteOps CompleteNmTagOps
Auto-Completion of NmTags.
Definition complete.c:291
static int complete_all_nm_tags_fresh(struct CompletionData *cd)
Query notmuch directly for a fresh tag list.
Definition complete.c:65
bool mutt_nm_tag_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
Complete to the nearest notmuch tag.
Definition complete.c:198
const struct CompleteOps CompleteNmQueryOps
Auto-Completion of NmQuerys.
Definition complete.c:284
notmuch_database_t * nm_db_do_open(const char *filename, bool writable, bool verbose)
Open a Notmuch database.
Definition db.c:116
const char * nm_db_get_filename(struct Mailbox *m)
Get the filename of the Notmuch database.
Definition db.c:63
void nm_db_free(notmuch_database_t *db)
Decoupled way to close a Notmuch database.
Definition db.c:262
Notmuch virtual mailbox type.
Notmuch private types.
#define NONULL(x)
Definition string2.h:44
#define SKIPWS(ch)
Definition string2.h:52
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
State data for auto-completion.
Definition data.h:32
int match_list_len
Enough space for all of the config items.
Definition data.h:37
bool free_match_strings
Should the strings in match_list be freed?
Definition data.h:38
char user_typed[1024]
Initial string that starts completion.
Definition data.h:33
char completed[256]
Completed string (command or variable)
Definition data.h:35
int num_matched
Number of matches for completion.
Definition data.h:34
const char ** match_list
Matching strings.
Definition data.h:36
size_t curpos
Position of the cursor.
Definition state.h:36
wchar_t * wbuf
Buffer for the string being entered.
Definition state.h:33
Data to fill the Enter Window.
Definition wdata.h:57
int tabs
Number of times the user has hit tab.
Definition wdata.h:74
struct CompletionData * cd
Auto-completion state data.
Definition wdata.h:78
struct Buffer * buffer
struct Buffer for the result
Definition wdata.h:59
struct EnterState * state
Current state of text entry.
Definition wdata.h:61
A mailbox.
Definition mailbox.h:81
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49