#include "mutt_ssl.h"
#endif
-
+#if USE_NOTMUCH
+#include "mutt_notmuch.h"
+#endif
#include "mx.h"
#include "init.h"
static const char* myvar_get (const char* var);
static void myvar_del (const char* var);
+#if USE_NOTMUCH
+/* List of tags found in last call to mutt_nm_query_complete(). */
+static char **nm_tags;
+#endif
+
+
static void toggle_quadoption (int opt)
{
int n = opt/4;
return 0;
}
+#if USE_NOTMUCH
+
+/* Fetch a list of all notmuch tags and insert them into the completion
+ * machinery.
+ */
+static int complete_all_nm_tags (const char *pt)
+{
+ int num;
+ int tag_count_1 = 0;
+ int tag_count_2 = 0;
+
+ Num_matched = 0;
+ strfcpy (User_typed, pt, sizeof (User_typed));
+ memset (Matches, 0, Matches_listsize);
+ memset (Completed, 0, sizeof (Completed));
+
+ /* Work out how many tags there are. */
+ if (nm_get_all_tags(Context, NULL, &tag_count_1) || tag_count_1 == 0)
+ return 0;
+
+ /* Free the old list, if any. */
+ if (nm_tags != NULL) {
+ int i;
+ for (i = 0; nm_tags[i] != NULL; i++)
+ FREE (&nm_tags[i]);
+ FREE (&nm_tags);
+ }
+ /* Allocate a new list, with sentinel. */
+ nm_tags = safe_malloc((tag_count_1 + 1) * sizeof (char *));
+ nm_tags[tag_count_1] = NULL;
+
+ /* Get all the tags. */
+ if (nm_get_all_tags(Context, nm_tags, &tag_count_2) ||
+ tag_count_1 != tag_count_2) {
+ FREE (&nm_tags);
+ nm_tags = NULL;
+ return -1;
+ }
+
+ /* Put them into the completion machinery. */
+ for (num = 0; num < tag_count_1; num++) {
+ candidate (Completed, User_typed, nm_tags[num], sizeof (Completed));
+ }
+
+ matches_ensure_morespace (Num_matched);
+ Matches[Num_matched++] = User_typed;
+ return 0;
+}
+
+/* Return the last instance of needle in the haystack, or NULL.
+ * Like strstr(), only backwards, and for a limited haystack length.
+ */
+static const char* rstrnstr(const char* haystack,
+ size_t haystack_length,
+ const char* needle)
+{
+ int needle_length = strlen(needle);
+ const char* haystack_end = haystack + haystack_length - needle_length;
+ const char* p;
+
+ for (p = haystack_end; p >= haystack; --p)
+ {
+ size_t i;
+ for (i = 0; i < needle_length; ++i) {
+ if (p[i] != needle[i])
+ goto next;
+ }
+ return p;
+
+ next:;
+ }
+ return NULL;
+}
+
+/* Complete the nearest "tag:"-prefixed string previous to pos. */
+int mutt_nm_query_complete (char *buffer, size_t len, int pos, int numtabs)
+{
+ char *pt = buffer;
+ int spaces;
+
+ SKIPWS (buffer);
+ spaces = buffer - pt;
+
+ pt = (char *)rstrnstr((char *)buffer, pos, "tag:");
+ if (pt != NULL) {
+ pt += 4;
+ if (numtabs == 1) {
+ /* First TAB. Collect all the matches */
+ complete_all_nm_tags(pt);
+
+ /* All matches are stored. Longest non-ambiguous string is ""
+ * i.e. don't change 'buffer'. Fake successful return this time.
+ */
+ if (User_typed[0] == 0)
+ return 1;
+ }
+
+ if (Completed[0] == 0 && User_typed[0])
+ return 0;
+
+ /* Num_matched will _always_ be atleast 1 since the initial
+ * user-typed string is always stored */
+ if (numtabs == 1 && Num_matched == 2)
+ snprintf(Completed, sizeof(Completed),"%s", Matches[0]);
+ else if (numtabs > 1 && Num_matched > 2)
+ /* cycle thru all the matches */
+ snprintf(Completed, sizeof(Completed), "%s",
+ Matches[(numtabs - 2) % Num_matched]);
+
+ /* return the completed query */
+ strncpy (pt, Completed, buffer + len - pt - spaces);
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
+
+ /* All matches are stored. Longest non-ambiguous string is ""
+ * i.e. don't change 'buffer'. Fake successful return this time.
+ */
+ if (User_typed[0] == 0)
+ return 1;
+ }
+
+ if (Completed[0] == 0 && User_typed[0])
+ return 0;
+
+ /* Num_matched will _always_ be atleast 1 since the initial
+ * user-typed string is always stored */
+ if (numtabs == 1 && Num_matched == 2)
+ snprintf(Completed, sizeof(Completed),"%s", Matches[0]);
+ else if (numtabs > 1 && Num_matched > 2)
+ /* cycle thru all the matches */
+ snprintf(Completed, sizeof(Completed), "%s",
+ Matches[(numtabs - 2) % Num_matched]);
+
+ /* return the completed query */
+ strncpy (pt, Completed, buffer + len - pt - spaces);
+ }
+ else
+ return 0;
+
+ return 1;
+}
+#endif
+
static int var_to_string (int idx, char* val, size_t len)
{
char tmp[LONG_STRING];