NeoMutt  2025-12-11-924-g64e75a
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 <stdbool.h>
31#include <stdio.h>
32#include <string.h>
33#include "private.h"
34#include "mutt/lib.h"
35#include "config/lib.h"
36#include "core/lib.h"
37#include "gui/lib.h"
38#include "lib.h"
39#include "complete/lib.h"
40#include "editor/lib.h"
41#include "index/lib.h"
42
48static void nm_complete_data_init(struct CompletionData *cd, const char *pt)
49{
51 mutt_str_copy(cd->user_typed, pt, sizeof(cd->user_typed));
52 memset(cd->match_list, 0, cd->match_list_len * sizeof(const char *));
53 memset(cd->completed, 0, sizeof(cd->completed));
54 cd->num_matched = 0;
55 cd->free_match_strings = true;
56}
57
65{
66 int rc = -1;
67 struct Mailbox *m_cur = get_current_mailbox();
68 notmuch_database_t *db = NULL;
69 notmuch_tags_t *tags = NULL;
70 const char *db_filename = nm_db_get_filename(m_cur);
71
72#if !LIBNOTMUCH_CHECK_VERSION(5, 4, 0)
73 if (!db_filename)
74 db_filename = cs_subset_string(NeoMutt->sub, "folder");
75#endif
76
77 if (!(db = nm_db_do_open(db_filename, false, false)) ||
78 !(tags = notmuch_database_get_all_tags(db)))
79 {
80 goto done;
81 }
82
83 while (notmuch_tags_valid(tags))
84 {
85 const char *tag = notmuch_tags_get(tags);
86
87 /* Keep a private copy because notmuch owns the iterator storage. */
88 if (*tag && candidate(cd, cd->user_typed, tag, cd->completed, sizeof(cd->completed)))
89 cd->match_list[cd->num_matched - 1] = mutt_str_dup(tag);
90
91 notmuch_tags_move_to_next(tags);
92 }
93
94 rc = 0;
95
96done:
97 if (tags)
98 notmuch_tags_destroy(tags);
99 if (db)
100 nm_db_free(db);
101
102 return rc;
103}
104
112int complete_all_nm_tags(struct CompletionData *cd, const char *pt)
113{
114 int rc = -1;
115
116 nm_complete_data_init(cd, pt);
118 if (rc == 0)
119 {
122 }
123
124 return rc;
125}
126
137bool mutt_nm_query_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
138{
139 char *pt = buf->data;
140 int spaces;
141
142 SKIPWS(pt);
143 spaces = pt - buf->data;
144
145 pt = (char *) buf_rfind(buf, "tag:");
146 if (pt)
147 {
148 pt += 4;
149 if (numtabs == 1)
150 {
151 /* First TAB. Collect all the matches */
152 complete_all_nm_tags(cd, pt);
153
154 /* All matches are stored. Longest non-ambiguous string is ""
155 * i.e. don't change 'buf'. Fake successful return this time. */
156 if (cd->user_typed[0] == '\0')
157 return true;
158 }
159
160 if ((cd->completed[0] == '\0') && (cd->user_typed[0] != '\0'))
161 return false;
162
163 /* cd->num_matched will _always_ be at least 1 since the initial
164 * user-typed string is always stored */
165 if ((numtabs == 1) && (cd->num_matched == 2))
166 {
167 snprintf(cd->completed, sizeof(cd->completed), "%s", NONULL(cd->match_list[0]));
168 }
169 else if ((numtabs > 1) && (cd->num_matched > 2))
170 {
171 /* cycle through all the matches */
172 snprintf(cd->completed, sizeof(cd->completed), "%s",
173 NONULL(cd->match_list[(numtabs - 2) % cd->num_matched]));
174 }
175
176 /* return the completed query */
177 strncpy(pt, cd->completed, buf->data + buf->dsize - pt - spaces);
178 }
179 else
180 {
181 return false;
182 }
183
184 return true;
185}
186
197bool mutt_nm_tag_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
198{
199 if (!buf)
200 return false;
201
202 char *pt = buf->data;
203
204 /* Only examine the last token */
205 char *last_space = strrchr(buf->data, ' ');
206 if (last_space)
207 pt = (last_space + 1);
208
209 /* Skip the +/- */
210 if ((pt[0] == '+') || (pt[0] == '-'))
211 pt++;
212
213 if (numtabs == 1)
214 {
215 /* First TAB. Collect all the matches */
216 complete_all_nm_tags(cd, pt);
217
218 /* All matches are stored. Longest non-ambiguous string is ""
219 * i.e. don't change 'buf'. Fake successful return this time. */
220 if (cd->user_typed[0] == '\0')
221 return true;
222 }
223
224 if ((cd->completed[0] == '\0') && (cd->user_typed[0] != '\0'))
225 return false;
226
227 /* cd->num_matched will _always_ be at least 1 since the initial
228 * user-typed string is always stored */
229 if ((numtabs == 1) && (cd->num_matched == 2))
230 {
231 snprintf(cd->completed, sizeof(cd->completed), "%s", NONULL(cd->match_list[0]));
232 }
233 else if ((numtabs > 1) && (cd->num_matched > 2))
234 {
235 /* cycle through all the matches */
236 snprintf(cd->completed, sizeof(cd->completed), "%s",
237 NONULL(cd->match_list[(numtabs - 2) % cd->num_matched]));
238 }
239
240 /* return the completed query */
241 strncpy(pt, cd->completed, buf->data + buf->dsize - pt);
242
243 return true;
244}
245
250{
251 if (!wdata || ((op != OP_EDITOR_COMPLETE) && (op != OP_EDITOR_COMPLETE_QUERY)))
252 return FR_NO_ACTION;
253
254 int rc = FR_SUCCESS;
255 buf_mb_wcstombs(wdata->buffer, wdata->state->wbuf, wdata->state->curpos);
256 if (!mutt_nm_query_complete(wdata->cd, wdata->buffer, wdata->tabs))
257 rc = FR_ERROR;
258
259 replace_part(wdata->state, 0, buf_string(wdata->buffer));
260 return rc;
261}
262
267{
268 if (!wdata || ((op != OP_EDITOR_COMPLETE) && (op != OP_EDITOR_COMPLETE_QUERY)))
269 return FR_NO_ACTION;
270
271 int rc = FR_SUCCESS;
272 buf_mb_wcstombs(wdata->buffer, wdata->state->wbuf, wdata->state->curpos);
273 if (!mutt_nm_tag_complete(wdata->cd, wdata->buffer, wdata->tabs))
274 rc = FR_ERROR;
275
276 replace_part(wdata->state, 0, buf_string(wdata->buffer));
277 return rc;
278}
279
284 .complete = complete_nm_query,
285};
286
291 .complete = complete_nm_tag,
292};
const char * buf_rfind(const struct Buffer *buf, const char *str)
Find last instance of a substring.
Definition buffer.c:807
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:249
enum FunctionRetval complete_nm_tag(struct EnterWindowData *wdata, int op)
Complete a Notmuch Tag - Implements CompleteOps::complete() -.
Definition complete.c:266
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:726
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:586
static void nm_complete_data_init(struct CompletionData *cd, const char *pt)
Reset the completion state for a tag lookup.
Definition complete.c:48
int complete_all_nm_tags(struct CompletionData *cd, const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition complete.c:112
bool mutt_nm_query_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
Complete to the nearest notmuch tag.
Definition complete.c:137
const struct CompleteOps CompleteNmTagOps
Auto-Completion of NmTags.
Definition complete.c:290
static int complete_all_nm_tags_fresh(struct CompletionData *cd)
Query notmuch directly for a fresh tag list.
Definition complete.c:64
bool mutt_nm_tag_complete(struct CompletionData *cd, struct Buffer *buf, int numtabs)
Complete to the nearest notmuch tag.
Definition complete.c:197
const struct CompleteOps CompleteNmQueryOps
Auto-Completion of NmQuerys.
Definition complete.c:283
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