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