]> granicus.if.org Git - neomutt/commitdiff
Adds label completion.
authorDavid Champion <dgc@bikeshed.us>
Sun, 29 Jan 2017 02:47:57 +0000 (18:47 -0800)
committerRichard Russon <rich@flatcap.org>
Fri, 10 Feb 2017 03:32:55 +0000 (03:32 +0000)
A global label hash is added, to which labels are added as they're parsed
from a mailbox file or edited manually by the user.  Reference counts are
kept in the hash table so that unused labels are removed from available
completions.  Completion is available in the label editor only, but it
may be feasible to add for search expressions if the preceding text ends
with '~y'.

doc/manual.xml.head
enter.c
headers.c
init.c
main.c
protos.h

index dcf92a1d004fc7cd74b4522c68d7279f46e24776..4e4b75621f27a439590265099dc871f9029f0b03 100644 (file)
@@ -6989,6 +6989,9 @@ field.  When set to <emphasis>yes</emphasis>, the
 You can change or delete the <quote>X-Label:</quote> field within
 Mutt using the <quote>edit-label</quote> command, bound to the
 <quote>y</quote> key by default.  This works for tagged messages, too.
+While in the edit-label function, pressing the &lt;complete&gt;
+binding (TAB, by default) will perform completion against all labels
+currently in use.
 </para>
 
 <para>
diff --git a/enter.c b/enter.c
index 7a806ddcd1dda85fcb748943196527ac7b7d2cc2..1917c75d653f137d6dbfff10a483f4462be75bfe 100644 (file)
--- a/enter.c
+++ b/enter.c
@@ -583,32 +583,26 @@ int _mutt_enter_string (char *buf, size_t buflen, int col,
            }
            break;
          }
-         else if (flags & MUTT_PATTERN && ch == OP_EDITOR_COMPLETE)
-         {
-        char *p;
-           for (i = state->curpos; i && state->wbuf[i-1] != ',' && 
-                state->wbuf[i-1] != ':'; i--)
-             ;
-           for (; i < state->lastchar && state->wbuf[i] == ' '; i++)
-             ;
-           my_wcstombs (buf, buflen, state->wbuf + i, state->curpos - i);
-        p = &buf[i];
-        while (p > buf && *(p-1) != '~')
-          p--;
-        if (*p == '~' && *(p+1) == 'y')
-        {
-             r = mutt_label_complete (buf, buflen, i, state->tabs);
-             replace_part (state, i, buf);
-             if (!r)
-             {
-               rv = 1;
-               goto bye;
-             }
-        }
-        else
-          goto self_insert;
-           break;
-         }
+          else if (flags & MUTT_PATTERN && ch == OP_EDITOR_COMPLETE)
+          {
+            for (i = state->curpos; i && state->wbuf[i-1] != '~'; i--)
+              ;
+            if (i && i < state->curpos && state->wbuf[i-1] == '~' && state->wbuf[i] == 'y')
+            {
+              i++;
+              my_wcstombs (buf, buflen, state->wbuf + i, state->curpos - i);
+              r = mutt_label_complete (buf, buflen, i, state->tabs);
+              replace_part (state, i, buf);
+              if (!r)
+              {
+                rv = 1;
+                goto bye;
+              }
+            }
+            else
+              goto self_insert;
+            break;
+          }
          else if (flags & MUTT_ALIAS && ch == OP_EDITOR_COMPLETE_QUERY)
          {
            /* invoke the query-menu to get more addresses */
index c6c2e7b8be3fa315effa6951d525270927304f60..481c9995d6aa529ffcaf59ac006411349935757c 100644 (file)
--- a/headers.c
+++ b/headers.c
@@ -215,6 +215,31 @@ void mutt_edit_headers (const char *editor,
   }
 }
 
+static void label_ref_dec(char *label)
+{
+  uintptr_t count;
+
+  count = (uintptr_t)hash_find(Labels, label);
+  if (count)
+  {
+    hash_delete(Labels, label, NULL, NULL);
+    count--;
+    if (count > 0)
+      hash_insert(Labels, label, (void *)count, 0);
+  }
+}
+
+static void label_ref_inc(char *label)
+{
+  uintptr_t count;
+
+  count = (uintptr_t)hash_find(Labels, label);
+  if (count)
+    hash_delete(Labels, label, NULL, NULL);
+  count++;  /* was zero if not found */
+  hash_insert(Labels, label, (void *)count, 0);
+}
+
 /*
  * add an X-Label: field.
  */
@@ -224,7 +249,11 @@ static int label_message(HEADER *hdr, char *new)
     return 0;
   if (mutt_strcmp (hdr->env->x_label, new) == 0)
     return 0;
+  if (hdr->env->x_label != NULL)
+    label_ref_dec(hdr->env->x_label);
   mutt_str_replace (&hdr->env->x_label, new);
+  if (hdr->env->x_label != NULL)
+    label_ref_inc(hdr->env->x_label);
   return hdr->changed = hdr->xlabel_changed = 1;
 }
 
@@ -239,7 +268,7 @@ int mutt_label_message(HEADER *hdr)
     strncpy(buf, hdr->env->x_label, LONG_STRING);
   }
 
-  if (mutt_get_field("Label: ", buf, sizeof(buf), 0 /* | MUTT_CLEAR */) != 0)
+  if (mutt_get_field("Label: ", buf, sizeof(buf), MUTT_LABEL /* | MUTT_CLEAR */) != 0)
     return 0;
 
   new = buf;
@@ -264,3 +293,17 @@ int mutt_label_message(HEADER *hdr)
 
   return changed;
 }
+
+/* scan a context (mailbox) and hash all labels we find */
+void mutt_scan_labels(CONTEXT *ctx)
+{
+  int i;
+
+  if (!ctx)
+    return;
+
+  for (i = 0; i < ctx->msgcount; i++)
+    if (ctx->hdrs[i]->env->x_label)
+      label_ref_inc(ctx->hdrs[i]->env->x_label);
+}
+
diff --git a/init.c b/init.c
index 2ee2fd88236795cacc9cc4583956ae89c2feebc2..b7dacf036e88a19a8a97464c17f95c916620087a 100644 (file)
--- a/init.c
+++ b/init.c
@@ -4147,14 +4147,13 @@ int mutt_label_complete (char *buffer, size_t len, int pos, int numtabs)
 {
   char *pt = buffer;
   int spaces; /* keep track of the number of leading spaces on the line */
-  int prefix;
 
   SKIPWS (buffer);
   spaces = buffer - pt;
 
-  for (pt = buffer; pt && *pt && *(pt+1); pt++);
-  for (; pt > buffer && !isspace(*(pt-1)); pt--);
-  prefix = pt - buffer;
+  pt = buffer + pos - spaces;
+  while ((pt > buffer) && !isspace ((unsigned char) *pt))
+    pt--;
 
   /* first TAB. Collect all the matches */
   if (numtabs == 1)
@@ -4192,7 +4191,7 @@ int mutt_label_complete (char *buffer, size_t len, int pos, int numtabs)
              Matches[(numtabs - 2) % Num_matched]);
 
   /* return the completed label */
-  strncpy (&buffer[prefix], Completed, len - spaces);
+  strncpy (buffer, Completed, len - spaces);
 
   return 1;
 }
diff --git a/main.c b/main.c
index 81ae6fea4d8ef07db16fa599de88bf08ec78450c..a0cb3c71f5066df889f3500dddb85c7dbe69e41e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -895,15 +895,16 @@ int main (int argc, char **argv, char **environ)
     if((Context = mx_open_mailbox (folder, ((flags & MUTT_RO) || option (OPTREADONLY)) ? MUTT_READONLY : 0, NULL))
        || !explicit_folder)
     {
+      Labels = hash_create (131, 0);
+      mutt_scan_labels(Context);
 #ifdef USE_SIDEBAR
       mutt_sb_set_open_buffy ();
 #endif
-      Labels = hash_create (131, 0);
       mutt_index_menu ();
       if (Context)
        FREE (&Context);
       if (Labels)
-        hash_destroy(&Labels, NULL);
+       hash_destroy(&Labels, NULL);
     }
 #ifdef USE_IMAP
     imap_logout_all ();
index 1304e40351b9b6756c52a836870147bc29ae2409..d6063fe4bc6840750a0e97aabb672fa0f980e2bf 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -200,6 +200,7 @@ int mutt_label_message (HEADER *);
 void mutt_make_label_hash (CONTEXT *);
 void mutt_label_hash_add (CONTEXT *ctx, HEADER *hdr);
 void mutt_label_hash_remove (CONTEXT *ctx, HEADER *hdr);
+void mutt_scan_labels (CONTEXT *);
 int mutt_label_complete (char *, size_t, int, int);
 void mutt_curses_error (const char *, ...);
 void mutt_curses_message (const char *, ...);