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