<<< Date Index >>>     <<< Thread Index >>>

Re: [PATCH] expand mutt vars as we do environment vars



On Friday, 16 September 2005 at 21:58, Brendan Cully wrote:
> The attached patch causes mutt to expand mutt variables in the same
> way that it expands environment variables. For example, you could do
> something like this in a hook:
> 
> set sendmail="mysmtp -f $from"
> 
> A couple of gotchas: environment variables take precedence, and I
> haven't gotten around to expanding them in a couple of places (notably
> shell-escape).
> 
> At the very least it sets the stage for an easy way of doing xterm
> titles :)

Here's a cute extension of that patch that allows you to define your
own variables. Any variable starting with my_ will be created if you
attempt to set it (and destroyed if you unset it). So you can do some
neat macros that actually clean up after themselves, eg:

macro index,pager \eS '<enter-command>set my_pd="$pipe_decode"<enter>
                       <enter-command>unset pipe_decode<enter>
                       <pipe_message>sa-learn --spam<enter>
                       <enter-command>set pipe_decode="$my_pd"</enter>'

I think it's useful - I always hated that limitation.

Now, if this gets extended to expand variables and % expandos in
shell-exec all kinds of things are possible...

-b
Teach mutt to expand mutt variables as it does environment
variables. For example, you might put something like this into a hook:
set sendmail="mysmtp -f $from"

Environment variables take precedence, and expansion does not occur in
shell-escape.
Index: mutt/init.c
===================================================================
--- mutt.orig/init.c
+++ mutt/init.c
@@ -58,8 +58,21 @@
          return (-1); \
        } else
 
+typedef struct myvar
+{
+  const char* name;
+  const char* value;
+  struct myvar* next;
+} myvar_t;
+
+static myvar_t* MyVars;
+
 static int var_to_string (int idx, char* val, size_t len);
 
+static void myvar_set (const char* var, const char* val);
+static const char* myvar_get (const char* var);
+static void myvar_del (const char* var);
+
 void toggle_quadoption (int opt)
 {
   int n = opt/4;
@@ -270,7 +283,9 @@ int mutt_extract_token (BUFFER *dest, BU
     }
     else if (ch == '$' && (!qc || qc == '"') && (*tok->dptr == '{' || isalpha 
((unsigned char) *tok->dptr)))
     {
-      char *env = NULL, *var = NULL;
+      const char *env = NULL;
+      char *var = NULL;
+      int idx;
 
       if (*tok->dptr == '{')
       {
@@ -288,9 +303,20 @@ int mutt_extract_token (BUFFER *dest, BU
        var = mutt_substrdup (tok->dptr, pc);
        tok->dptr = pc;
       }
-      if (var && (env = getenv (var)))
-       mutt_buffer_addstr (dest, env);
-      FREE (&var);
+      if (var)
+      {
+        if ((env = getenv (var)) || (env = myvar_get (var)))
+          mutt_buffer_addstr (dest, env);
+        else if ((idx = mutt_option_index (var)) != -1)
+        {
+          /* expand settable mutt variables */
+          char val[LONG_STRING];
+
+          if (var_to_string (idx, val, sizeof (val)))
+            mutt_buffer_addstr (dest, val);
+        }
+        FREE (&var);
+      }
     }
     else
       mutt_buffer_addch (dest, ch);
@@ -1213,8 +1239,10 @@ static void mutt_restore_default (struct
 
 static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
 {
-  int idx, query, unset, inv, reset, r = 0;
+  int query, unset, inv, reset, r = 0;
+  int idx = -1;
   char *p, scratch[_POSIX_PATH_MAX];
+  char* myvar = NULL;
 
   while (MoreArgs (s))
   {
@@ -1248,7 +1276,9 @@ static int parse_set (BUFFER *tmp, BUFFE
     /* get the variable name */
     mutt_extract_token (tmp, s, M_TOKEN_EQUAL);
 
-    if ((idx = mutt_option_index (tmp->data)) == -1 &&
+    if (!mutt_strncmp ("my_", tmp->data, 3))
+      myvar = tmp->data;
+    else if ((idx = mutt_option_index (tmp->data)) == -1 &&
        !(reset && !mutt_strcmp ("all", tmp->data)))
     {
       snprintf (err->data, err->dsize, _("%s: unknown variable"), tmp->data);
@@ -1290,10 +1320,13 @@ static int parse_set (BUFFER *tmp, BUFFE
       else
       {
        CHECK_PAGER;
-       mutt_restore_default (&MuttVars[idx]);
+        if (myvar)
+          myvar_del (myvar);
+        else
+          mutt_restore_default (&MuttVars[idx]);
       }
     } 
-    else if (DTYPE (MuttVars[idx].type) == DT_BOOL)
+    else if (!myvar && DTYPE (MuttVars[idx].type) == DT_BOOL)
     { 
       if (s && *s->dptr == '=')
       {
@@ -1331,14 +1364,16 @@ static int parse_set (BUFFER *tmp, BUFFE
       else
        set_option (MuttVars[idx].data);
     }
-    else if (DTYPE (MuttVars[idx].type) == DT_STR ||
+    else if (myvar || DTYPE (MuttVars[idx].type) == DT_STR ||
             DTYPE (MuttVars[idx].type) == DT_PATH ||
             DTYPE (MuttVars[idx].type) == DT_ADDR)
     {
       if (unset)
       {
        CHECK_PAGER;
-       if (DTYPE (MuttVars[idx].type) == DT_ADDR)
+        if (myvar)
+          myvar_del (myvar);
+        else if (DTYPE (MuttVars[idx].type) == DT_ADDR)
          rfc822_free_address ((ADDRESS **) MuttVars[idx].data);
        else
          FREE ((void *) MuttVars[idx].data);
@@ -1346,9 +1381,22 @@ static int parse_set (BUFFER *tmp, BUFFE
       else if (query || *s->dptr != '=')
       {
        char _tmp[STRING];
-       char *val = NULL;
-       
-       if (DTYPE (MuttVars[idx].type) == DT_ADDR)
+       const char *val = NULL;
+
+        if (myvar)
+        {
+          if ((val = myvar_get (myvar)))
+          {
+            snprintf (err->data, err->dsize, "%s=\"%s\"", myvar, val);
+            break;
+          }
+          else
+          {
+            snprintf (err->data, err->dsize, _("%s: unknown variable"), myvar);
+            return (-1);
+          }
+        }
+       else if (DTYPE (MuttVars[idx].type) == DT_ADDR)
        {
          _tmp[0] = '\0';
          rfc822_write_address (_tmp, sizeof (_tmp), *((ADDRESS **) 
MuttVars[idx].data), 0);
@@ -1368,13 +1416,23 @@ static int parse_set (BUFFER *tmp, BUFFE
         s->dptr++;
 
         /* copy the value of the string */
-        if (DTYPE (MuttVars[idx].type) == DT_ADDR)
+        if (myvar)
+        {
+          myvar = safe_strdup (myvar);
+          myvar_del (myvar);
+        }
+        else if (DTYPE (MuttVars[idx].type) == DT_ADDR)
          rfc822_free_address ((ADDRESS **) MuttVars[idx].data);
         else
          FREE ((void *) MuttVars[idx].data);
 
         mutt_extract_token (tmp, s, 0);
-        if (DTYPE (MuttVars[idx].type) == DT_PATH)
+        if (myvar)
+        {
+          myvar_set (myvar, tmp->data);
+          FREE (&myvar);
+        }
+        else if (DTYPE (MuttVars[idx].type) == DT_PATH)
         {
          strfcpy (scratch, tmp->data, sizeof (scratch));
          mutt_expand_path (scratch, sizeof (scratch));
@@ -1659,18 +1717,21 @@ static int parse_set (BUFFER *tmp, BUFFE
       break;
     }
 
-    if (MuttVars[idx].flags & R_INDEX)
-      set_option (OPTFORCEREDRAWINDEX);
-    if (MuttVars[idx].flags & R_PAGER)
-      set_option (OPTFORCEREDRAWPAGER);
-    if (MuttVars[idx].flags & R_RESORT_SUB)
-      set_option (OPTSORTSUBTHREADS);
-    if (MuttVars[idx].flags & R_RESORT)
-      set_option (OPTNEEDRESORT);
-    if (MuttVars[idx].flags & R_RESORT_INIT)
-      set_option (OPTRESORTINIT);
-    if (MuttVars[idx].flags & R_TREE)
-      set_option (OPTREDRAWTREE);
+    if (!myvar)
+    {
+      if (MuttVars[idx].flags & R_INDEX)
+        set_option (OPTFORCEREDRAWINDEX);
+      if (MuttVars[idx].flags & R_PAGER)
+        set_option (OPTFORCEREDRAWPAGER);
+      if (MuttVars[idx].flags & R_RESORT_SUB)
+        set_option (OPTSORTSUBTHREADS);
+      if (MuttVars[idx].flags & R_RESORT)
+        set_option (OPTNEEDRESORT);
+      if (MuttVars[idx].flags & R_RESORT_INIT)
+        set_option (OPTRESORTINIT);
+      if (MuttVars[idx].flags & R_TREE)
+        set_option (OPTREDRAWTREE);
+    }
   }
   return (r);
 }
@@ -2537,3 +2598,64 @@ int mutt_get_hook_type (const char *name
       return c->data;
   return 0;
 }
+
+static void myvar_set (const char* var, const char* val)
+{
+  myvar_t* cur;
+
+  if (!MyVars)
+  {
+    MyVars = safe_calloc (1, sizeof (myvar_t));
+    cur = MyVars;
+  }
+  else
+  {
+    for (cur = MyVars; cur; cur = cur->next)
+    {
+      if (!mutt_strcmp (cur->name, var))
+        break;
+
+      if (!cur->next)
+      {
+        cur->next = safe_calloc (1, sizeof (myvar_t));
+        cur = cur->next;
+        break;
+      }
+    }
+  }
+
+  if (!cur->name)
+    cur->name = safe_strdup (var);
+  FREE (&cur->value);
+  cur->value = safe_strdup (val);
+}
+
+static void myvar_del (const char* var)
+{
+  myvar_t* cur;
+  myvar_t* prev;
+
+  for (prev = cur = MyVars; cur; prev = cur, cur = cur->next)
+  {
+    if (!mutt_strcmp (cur->name, var))
+    {
+      prev->next = cur->next;
+      FREE (&cur->name);
+      FREE (&cur->value);
+      FREE (&cur);
+
+      break;
+    }
+  }
+}
+
+static const char* myvar_get (const char* var)
+{
+  myvar_t* cur;
+
+  for (cur = MyVars; cur; cur = cur->next)
+    if (!mutt_strcmp (cur->name, var))
+      return NONULL(cur->value);
+
+  return NULL;
+}

Attachment: pgpazbQwNE6hN.pgp
Description: PGP signature