* On 2005.02.20, in <20050220125951.GB3050@xxxxxxxxxxxxxxxxxxxxx>, * "Mads Laursen" <mutt@xxxxxxxxx> wrote: > > out of date mutt-versions. With a facility to test for features, one > can write a configuration that takes advantage of features, while > still working on older/standard installations. I agree that this kind of functionality is useful. I'm not as concerned with whether it goes into mutt -- this function is available without code changes -- but I also think that code changes are the best way to make it accessible to casual or inexperienced users. I'm using m4 to preprocess my muttrc. I've been meaning for a while to post how I do this, but I'm not sure I'll ever get around to cleaning everything up enough to post. I can post part of it now, though. First I'm going to describe what I'm doing now, and then I'll talk about a couple of suggestions. What I do now: 1. My .muttrc is a quick one-liner: source "~/.mutt/muttrc.sh|" This means that my entire mutt configuration is read from the stdout of the muttrc.sh script. 2. The muttrc.sh script is attached. This egregious program runs "mutt -v" to generate a list of features and patches. It uses sed to transform that into a list of -DSYMBOL and -UNOTSYMBOL expressions. These expressions are passed as arguments to a preprocessor. I use m4, but cpp (or gcc -E) would work, as would any other filter that accepts variables as -D and -U arguments. 3. The muttrc.sh also copies environment variables that begin with MUTT_ as -D parameters, so that you can pass arbitrary information to mutt's dynamic configuration from your shell startup, or whatever. It passes the local hostname too, and also the value of the $DOMAIN variable so that I can choose a different configuration macroscopically depending on what environment I'm running in. 4. The m4/cpp preprocessor reads my muttrc from ~/.mutt/muttrc.m4. This file is a plain old muttrc file, but with some m4 macro expansions, conditionals, etc. to adapt my configuration to the features I have enabled in mutt and to the location I'm running it from. The result is tuned for wherever I'm running it. Here's the command that muttrc.sh generates to read my configuration. This is created dynamically, each time I run mutt, almost all based on "mutt -v" output. m4 -s -DMUTTDIR=.mutt -DMUTT_DOMAIN=uchicago.edu -DMUTT_HOSTNAME=monkey '-DVERSION=156' -UDOMAIN -DDEBUG -UHOMESPOOL -UUSE_SETGID -DUSE_DOTLOCK -UDL_STANDALONE -DUSE_FCNTL -UUSE_FLOCK -DUSE_POP -DUSE_IMAP -UIMAP_EDIT_THREADS -UUSE_GSS -DUSE_SSL -UUSE_SASL -UUSE_SASL2 -DHAVE_REGCOMP -UUSE_GNU_REGEX -DCOMPRESSED -DHAVE_COLOR -UHAVE_START_COLOR -UHAVE_TYPEAHEAD -UHAVE_BKGDSET -UHAVE_CURS_SET -UHAVE_META -UHAVE_RESIZETERM -DCRYPT_BACKEND_CLASSIC_PGP -DCRYPT_BACKEND_CLASSIC_SMIME -UCRYPT_BACKEND_GPGME -UBUFFY_SIZE -UEXACT_ADDRESS -DSUN_ATTACHMENT -DENABLE_NLS -ULOCALES_HACK -DHAVE_WC_FUNCS -DHAVE_LANGINFO_CODESET -DHAVE_LANGINFO_YESEXPR -DHAVE_ICONV -DICONV_NONTRANS -UHAVE_LIBIDN -DHAVE_GETSID -DHAVE_GETADDRINFO '-DISPELL="/opt/bin/ispell"' '-DSENDMAIL="/usr/lib/sendmail"' '-DMAILPATH="/var/mail"' '-DPKGDATADIR="/opt/pkgs/mutt_cvs-0.20041011/share/mutt"' '-DSYSCONFDIR="/opt/pkgs/mutt_cvs-0.20041011/etc"' '-DEXECSHELL="/bin/sh"' -UMIXMASTER -DPATCH_ats_parent_match=1 -DPATCH_ats_parent_match_1 -DPATCH_dgc_setenv=1 -DPATCH_dgc_setenv_1 -DPATCH_dgc_softfill=2 -DPATCH_dgc_softfill_2 -DPATCH_dgc_flagsafe=1 -DPATCH_dgc_flagsafe_1 -DPATCH_dgc_fmtpipe=1 -DPATCH_dgc_fmtpipe_1 -DPATCH_dgc_markmsg=2 -DPATCH_dgc_markmsg_2 -DPATCH_dgc_deepif=1 -DPATCH_dgc_deepif_1 -DPATCH_dgc_groupalts=2 -DPATCH_dgc_groupalts_2 -DPATCH_dgc_xlabel_ext=6 -DPATCH_dgc_xlabel_ext_6 -DPATCH_6_rr= -DPATCH_6_rr_compressed -DPATCH_dgc_attach=5 -DPATCH_dgc_attach_5 -DPATCH_cd_pattern_broken=1 -DPATCH_cd_pattern_broken_1 -DPATCH_cd_edit_threads=9 -DPATCH_cd_edit_threads_9_2 -DPATCH_dgc_isalias=1 -DPATCH_dgc_isalias_1 -DPATCH_ats_mark_old=1 -DPATCH_ats_mark_old_1 -DPATCH_ats_date_conditional=1 -DPATCH_ats_date_conditional_1 -DMUTT_DATEEXP='%?[6M?%\?[7d\?%\\?[18h\\?%[ %H:%M]\\&%[%a %d]\\?\&%[%b %d]\?&%[%y%m%d]?' -DMUTT_SOFTFILL='%?H?*%H* ?%= s%?Y? [%Y&\%\?y\? \" \??%?X? {%X}?' .mutt/muttrc.m4 Note that the PATCH_* defines are defined in two different ways, for the benefit of different kinds of preprocessor. For example, for patch-1.5.6.dgc.xlabel_ext.6, the script creates PATCH_dgc_xlabel_ext=6 PATCH_dgc_xlabel_ext_6 A preprocessor that can do math can make a condition like #if (PATCH_dgc_xlabel_ext >= 5) ... #endif and a preprocessor that cannot can do (making up a syntax) @if PATCH_dgc_xlabel_ext_5 or PATCH_dgc_xlabel_ext_6 ... @endif A preprocessor feature is much more appealing to me as a way of getting conditionality into mutt. It's more flexible than if[n]def alone. It also lets you choose your language -- you can use m4 or cpp, or you can use any other macro language you like as long as you can wrap it in something that takes -D and -U arguments. Use XSLT, that works too. :) The approach I use has worked fine for me for years, but I'm not sure it's the best solution for the new user who wants/needs this functionality -- especially if they need to set it up themselves. I see a few solutions to that: 1. Include something like muttrc.sh with mutt, and make it available in the default configuration without any editing. For example, mutt could include muttrc.sh as /usr/local/bin/muttpp (for mutt preprocessor). Then, either: a. If a user wanted a preprocesed muttrc, he could rename ~/.muttrc to ~/.mutt/muttrc.pp and change ~/.muttrc to do the "source ...|" line. b. If mutt detects a ~/.muttrc.pp (or whatever) file, then it could automatically source it via /usr/local/bin/muttpp. This approach would require no extra configuration from the user, and doesn't really have any disadvantage over (a). I'd prefer it. 2. a. Provide a new configuration variable, $preprocessor. If it's set, then whenever mutt_open_read() receives a filename to open, it instead opens a filter (mutt_create_filter()) using the $preprocessor and the filename. This is completely transparent to the user, and seems the best-integrated approach to me. If $preprocessor is unset, then the file is opened as usual. (There is exactly one other use of mutt_open_read in 1.5.8. It's used to open the signature file, and actually that might be another nice use of the preprocessor.) This option might still require a user to install a .muttrc in order to set $preprocessor, and then to source another file, too, so it could be less convenient than (1a) or (1b). But it can also be set to a default in the system Muttrc, if that seems desirable to a system manager or a packager. Then it's zero-configuration for the end-user. b. As an extension to (2a), mutt could generate all the -D and -U tokens internally, obviating the muttrc.sh/muttpp script. This has some portability advantages, but it's arguably less flexible. (1a) requires the least change in mutt -- just add a file to the distribution and ensure that it's installed by the Makefile. (1b) requires minor code change to detect another file at startup, and respond differently. (2a) is approximately the same in cost: it just detects whether $preprocessor is set, and alters the way it reads that data. (2b) would require some changes in the way that features and patches are represented internally, so that the argv could be assembled for the preprocessor command. But this wouldn't hard or risky, particularly. Personally, my order of preference, then, would be (2a) or (2b), then (1b), then (1a). I'm willing to do any patchwork to make any of these happen, if it seems like a usable design to Thomas. Otherwise, feel free to use this script on your own. :) -- -D. dgc@xxxxxxxxxxxx NSIT::ENSS
Attachment:
muttrc.sh
Description: Bourne shell script