This man page describes the four mechanisms used to customize Exmh: , the MH profile, X resources, and custom Tcl code.
Exmh is built with the assumption that you will want to customize it to some degree. The simplest way is by the user interface, which exposes numerous knobs and dials that you can adjust to control a lot of the behavior of exmh. The second way is by defining X resources. You will need to do this if you want to control fonts and colors. It would be great if there was a user interface for this, but this is something that has not been crossed off the TODO list, yet. You also use X resources to define new buttons and menus. The third way is by adding custom Tcl code to the implementation of exmh. A personal library of Tcl routines is supported. You can either add new buttons or menus to invoke your functionality, or take advantage of some hook points inside exmh to slip in your new feature. It is also possible to completely replace any module of the exmh implementation. Finally, there are a few MH profile components introduced by exmh, although these may eventually migrate out of the profile and into the package.
After you have used exmh a little, you should explore all its capabilities by clicking on the button. There is a two-level preferences scheme, mainly because there are too many knobs and dials. At the top-level you see a menu that corresponds to different modules of the implementation. Clicking on one of the items brings up the preferences items for that module. Use the Help... button to display more detailed information about the preference items. If you click on the label of an item, the help text is scrolled to the information for that item.
There are three types of options you can set through the dialog: choices, booleans, and general items. Each of these are tied to a Tcl variable and an X resource name. Changes in the Preference user interface change the value of the Tcl variable, which affects the exmh runtime behavior. Then, when you click Save in the dialog, the values are saved as X resource settings in your ~/.exmh/exmh-defaults file.
Choices are represented by radio-style buttons where only one button in the set can be enabled at once. Changes take effect immediately. Booleans are represented by check-style buttons. If the checkbox is dark, then the option is turned on. Changes take effect immediately. Numeric and filename settings have entry widgets in which you can type in a new value. Press <Return> for the change to take effect immediately (or choose Save).
You can cycle through all the preference dialogs by using the Next button, which takes you to the next preference section. There is also a Prev button to go back. You should take time at least once to go through all the Preference sections to get an idea of what sort of options are available.
If you decide you like your settings, click Save in the main dialog to save them in a exmh-defaults file in your ~/.exmh directory. Click Reset All in the main dialog to restore all the settings to those of your last Save. Within each module's preference dialog there is a Reset button that resets only those module's settings.
Warning! If you click Dismiss in the main dialog, some preferences may have been set for the current session, but they will not have been saved to your ~/.exmh/exmh-defaults file.
Here is a short summary of the preference sections and what features they control. The Tcl module that the section corresponds to is listed so you can dig into the code if you want to.
There are a number of keystroke bindings already defined by exmh that invoke different Tcl commands. You can change the bindings and add bindings for new commands via the Bind dialog. Open the dialog from the menu entry under the Bindings menu. The dialog presents a scrollable column of commands and their bindings, plus an area at the top to define a new binding.
Binding Syntax. The following is a very brief summary of the Tk bind syntax. For the complete story, consult the Tk man page for the bind command. The Tk syntax for the bindings events looks like this:
A modifier is a key that you hold down while pressing another key. The modifiers you are likely to use are listed below. Capitalization is important.<modifier-type-detail>
The type is the event type, and it can left out if the detail part implies the type. The types you will usually use are:Control Shift Meta
The detail specifies the key or button number for the event. Keys are named by their X keysym. For the letters and digits, the keysym is just the letter or digit, e.g., <Key-a>, which can be shortened to <a>. For punctuation, however,Key Button
the keysyms are words. Here are some examples, and again the Key type is left out.
Perhaps the easiest way to figure out the keysym is to use the following Tcl/Tk command. Run the Tcl/Tk shell, wish, and enter this command. Then type with the mouse over the little window it displays.<comma> <period> <dollar> <asciicircum> <question> <exclam>
bind . <Any-Key> {puts stdout "keysym = %K letter = %A"}
Exmh uses a couple of things from your .mh_profile file, including several components that are new.
By default, show all headers. If a header is in the Header-Suppress list, do not show it. If a header is in the Header-Display list, show it. The default values for these profile components are: Header-Suppress: .* Header-Display: Subject To From Date Cc Newsgroups
If you are a mail junky, you may want to use Header-Suppress to explicitly suppress the boring header components you already know about. The new, interesting components inserted by random mailers will be displayed for you to check out. In contrast, the default for Header-Suppress will hide everything, and you explicitly choose what headers you want to see by setting Header-Display.
* matches a sequence of any characters. ? matches any character. The default Folder-Order puts your inbox first. Folder-Order: inbox * My Folder-Order looks like: Folder-Order: personal exmh mxedit * mail* sun m3 mach background
The other effect of Folder-Order is to define a traversal order for visiting folders with unread mail in them. When you do a Next and are at the end of a folder, exmh will automatically change folders to the next one in the Folder-Order that has unseen messages, if any. When there are no more folders with unseen mail, then you will change back to the first folder in your Folder-Order, unless you disable this by turning off the Cycle back to first preference setting under the Unseen Folders section.
The X resource database is used as a repository of Preference settings, window positions, and definitions of fonts, colors, buttons, and menus. The information in the database can come from a variety of sources, which can be confusing. The default values come from the app-defaults file that is kept in the script library directory for exmh. Color-specific resources are contained in the app-defaults-color or app-defaults-mono file. One of these two is used depending on the display.
A site administrator can add local resource specifications in the local-app-defaults file. Put this into the exmh script library directory (the same place as app-defaults). To handle site-specific color-specific resources, exmh will also read the local.app-defaults-color or local.app-defaults-mono if those files exist.
Each user has a ~/.exmh/exmh-defaults file in their home directory. To handle personal color-specific resources, exmh will also read your ~/.exmh/exmh-defaults-color or ~/.exmh/exmh-defaults-mono if those files exist.
I do not recommend putting exmh-related resource settings in your ~/.Xdefaults, although you can do that. If you do, be warned that values from the ~/.Xdefaults file and the RESOURCE_MANAGER property on the root window will be overridden by things in your ~/.exmh/exmh-defaults file.
The ~/.exmh/exmh-defaults file is divided into sections. The first section is for things you add by hand. The remaining sections are automatically managed by exmh. If you manually add settings to your ~/.exmh/exmh-defaults file, add entries to the beginning of this file. Add them before the comment about the rest of the file being automatically generated and you will not lose your changes.
If a resource has a multiword value, you *should not quote* the value in the resource file. The right way to specify these in your ~/.exmh/exmh-defaults file is shown below. The leading "*" gets around quirks in the way Tk names its applications; different instances of the application have different names.
*scrollbarSide: left *c_current: violet red
Finally, if you are really serious about fiddling with resources, you should look through the app-defaults file. For one thing, there is no guarantee that the resource names used in this man page, which correspond to version 1.5, will be exactly the same in later versions of exmh. Furthermore, there might be new goodies that appear in future versions that are not described here. Only by reading the app-defaults file of the current version will you be sure you are setting things correctly in your ~/.exmh/exmh-defaults file. (Hint: read through the main exmh script for the definition of the exmh(library) Tcl variable, which is the script library where app-defaults lives. The script is short, and the definition is near the beginning.)
If you want to dive into the widget tree and fiddle with fonts and colors and such, here are the class descriptions. I also highly recommend the tkinspect program, which you can find in the Tcl archives.
exmh uses X resources to specify its buttons and menus on the main display, the editor window, and the What Now dialog. You can add a button to one of these areas of the user interface by listing it in a ubuttonlist resource and then adding some more resources that describe the button. X resource names are hierarchical, and these are the button list resources used by exmh.
Fops is the set of folder operation buttons. Mops is the set of message operations buttons. Sedit.Menubar is the buttons in the built-in editor. WhatNow is the What Now dialog used with external editors. The ubuttonlist resource is necessary because there is no easy way to enumerate the contents of the resource database.*Main.ubuttonlist *Fops.ubuttonlist *Mops.ubuttonlist *Sedit.Menubar.ubuttonlist *WhatNow.ubuttonlist
There are actually several resources associated with each set of buttons in order to provide maximum flexibility. There are three sources of button definitions: system buttons are defined by the base release ("at the factory"); local buttons are defined by your site administrator; user buttons are defined by each user. In addition, the site and the user can delete buttons with other resources. The resources are:
When exmh creates a set of buttons, (e.g., the *Main buttons), t asks for the definition of all these resources to determine what buttons are being defined (e.g., *Main.buttonlist, *Main.ubuttonlist, and so on.) For each of these buttons, additional resources specify the text label and command for each button. This is best explained by an example. Here are the definitions for the main buttons:buttonlist The list of system defined buttons lbuttonlist The list of local (site) defined buttons ubuttonlist The list of user defined buttons l-buttonlist The list of buttons deleted at the local level. u-buttonlist The list of buttons deleted at the user level.
The *Main.buttonlist resource names the buttons that appear in the top row of buttons. Its value, in turn causes exmh to look around for the other resources that define the text and command attributes for each button. The command is a Tcl command, and most are simple commands of one or two words. If you are really inspired you can set many different attributes of a Tk button via resources, but you'll have to consult the Tk man page on button for the details.*Main.buttonlist: quit pref alias *Main.quit.text: Quit *Main.quit.command: Exmh_Done *Main.pref.text: Preferences *Main.pref.command: Preferences_Dialog *Main.alias.text: Aliases *Main.alias.command: Aliases_Pref
As another example, here is how you would add a Repl button to the message buttons. By default, there are a few variations on Reply under the Reply... menu. You might like a Repl button that does your most common form of reply. The Msg_Reply Tcl command takes regular arguments for the MH repl program.
*Mops.ubuttonlist: myrepl *Mops.myrepl.text: Repl *Mops.myrepl.command: Msg_Reply -filter myrepl.filter -cc all
If you hate the Reply... menu altogether, you can remove it by adding it to the u-buttonlist resource. You'll have to look at the master app-defaults file to find out the internal name of each button.
*Mops.u-buttonlist: reply
The menus in exmh are defined in a similar way. It is a little more complex because there is more to a menu than a button, but the general idea is the same. There are parallel sets of resources for the system-defined and user-defined parts. Each section has a list of menus defined with the following resources:
menulist The list of system defined menus lmenulist The list of local (site) defined menus umenulist The list of user defined menus l-menulist The list of menus deleted at the local level. u-menulist The list of menus deleted at the user level.
Each menu, in turn, has a text resource that defines the label on the menubutton. The entrylist resource lists the entries that are found under the menu. Again, the system-defined entries are listed under entrylist, the administrator defines lentrylist, and users are meant to add new entries to uentrylist. System (or local) defined entries can be removed by adding them to the l-entrylist and u-entrylist resources.
For each menu entry there are resources with the following naming convention (this is not standard Tk): if the entrylist item is foo, then:
For more information, it might be helpful to consult the Tk man page for menu. For example, here is how the main menus for exmh are defined:l_foo defines the label (text) for the entry. c_foo defines the command. t_foo defines the type: "command", "check", "radio", "cascade", or "separator". v_foo defines the variable associated with check and radio entries. m_foo defines the menu associated with cascade entries.
*Main.menulist: bind help *Main.bind.text: Bindings *Main.bind.m.entrylist: command sedit *Main.bind.m.l_command: Commands *Main.bind.m.c_command: Bind_Pref *Main.bind.m.l_sedit: Simple Edit *Main.bind.m.c_sedit: Sedit_Pref *Main.help.text: Help... *Main.help.m.entrylist: help colorkey faq *Main.help.m.l_colorkey: Color Legend *Main.help.m.c_colorkey: Help_KeyDisplay *Main.help.m.l_help: Quick Intro *Main.help.m.c_help: Help *Main.help.m.l_faq: Frequently Asked Questions *Main.help.m.c_faq: Help FAQ
Note the additional .m component in the *Main.help.m.entrylist resource name. The *Main.help resource corresponds to the menubutton, and *Main.help.m corresponds to the menu associated with that button.
For another example, we can use the uentrylist resource to add a new menu entry to the message More... menu. It will be a check-button type entry that will set the Tcl variable that controls the "skip marked" behavior of Next and Prev. In addition, we will separate the user-defined entries from the system entries with a special separator menu entry. The resources in your ~/.exmh/exmh-defaults would look something like this:
*Mops.more.m.uentrylist: sep skip *Mops.more.m.t_sep: separator *Mops.more.m.t_skip: check *Mops.more.m.l_skip: Skip marked messages *Mops.more.m.v_skip: ftoc(skipMarked)
In this case the Tcl variable is ftoc(skipMarked), which is an element of an associative Tcl array. Menu entries that use Tcl variables defined by exmh might stop working in a future release. However, you can easily get an idea of what the important variables are by searching through the code for Preferences_Add calls. These calls set up the relationship between the internal Tcl variables and the Preference items you see in the interface. In most cases the variables are elements of an associative array. In this example, ftoc is the array that holds the state variables for ftoc.tcl, which implements the scan listing.
When you use exmh, you will notice that some of the message buttons are disabled when there is no current message. This is implemented by putting the Mops buttons and menu entries into groups. The group membership is defined via resources. The groups are current, range, and nodraft. The current group contains all the buttons and menu entries that are enabled when there is a current message. The range group contains buttons and menu entries that can be applied to multiple messages. The nodraft group is for those buttons and menu entries that ought to be disabled when you are in the drafts folder.
For each group there are several corresponding resources that list the buttons, (system, local, and user), and menu entries, (system, local, and user), in the group. These are the group-defining resources and (part of) their default values.
The naming convention for buttons and menu entries is different. The buttons are named the same way they appear in the buttonlist resource specification. The menu entries are named by their textual label. If a menu entry label includes spaces, then the label must be grouped. Braces are used for compatibility with the Tcl grouping syntax.*Mops.g_current: link move delete reply forward *Mops.gm_current: Print {Unmark (Undo)} Clip Redistribute {Burst Digest} *Mops.lg_current: *Mops.lgm_current: *Mops.ug_current: *Mops.ugm_current: *Mops.l-g_current: *Mops.l-gm_current: *Mops.u-g_current: *Mops.u-gm_current: *Mops.g_range: link move delete forward *Mops.gm_range: Print Unmark {Mark Unseen} *Mops.lg_range: *Mops.lgm_range: *Mops.ug_range: *Mops.ugm_range: *Mops.l-g_range: *Mops.l-gm_range: *Mops.u-g_range: *Mops.u-gm_range: *Mops.g_nodraft: reply forward *Mops.gm_nodraft: Redistribute *Mops.lg_nodraft: *Mops.lgm_nodraft: *Mops.ug_nodraft: *Mops.ugm_nodraft: *Mops.l-g_nodraft: *Mops.l-gm_nodraft: *Mops.u-g_nodraft: *Mops.u-gm_nodraft:
Warning! If you move things between the *Mops.buttonlist and the *Mops.more.m.entrylist, then you will have to adjust your group settings because the naming convention for buttons and menus is different.
The basic TK widget color attributes are listed below. Most of these are defined in app-defaults-color to obtain a family of gray levels.
You can specify colors for particular classes of widgets. All the labels are blue in exmh, by default, because of the following in app-defaults:
*Label.foreground: blue
The following resources are used to control the looks in the folder label display. The fact that some have a trailing Bg or Fg is purely historical accident. Originally you could only specify the foreground (for current and unseen) or the background (for moved and deleted) but now, for the benefit of grayscale users, you can specify all of them. You might also look at the fdispColor.tcl and ftocColor.tcl files that use these resources.
The following resources are used to control how sequences are highlighted in the scan listing. This includes both (n)mh sequences and also some exmh specific sequences.
A set of resources are used to specify colors and other font attributes of message headers.
For example, here is what I have in my own ~/.exmh/exmh-defaults file:
*m_tagnames: hidden subject from x-filters-matched default *m_hidden: -font 6x10 *m_default: -foreground black *m_subject: -foreground blue *m_x-phase-of-moon: -foreground blue *m_from: -foreground "medium sea green"
Exmh automatically remembers the position of top-level windows, both within a session and between successive runs of exmh. It does this by saving some position resource specifications in your ~/.exmh/exmh-defaults file. In addition, exmh will remember the geometry of the main window and of the detached folder display.
Warning: If you use a virtual root window manager, the memory of a window location will cause problems if you start exmh in a new "room". If you move exmh to a new room, you'll have to edit your ~/.exmh/exmh-defaults and delete all the *position resource specifications. Or, you can turn off the Remember Window Positions preference item under Window Stuff. Then, when exmh exits, it removes these for you.
You can adjust the width and height of some of the text windows. Here are the default values.
The iconposition resources specify the location of the icons, both for the main window and the detached folder display (if any). The format is +X+Y to specify the upper-left hand point. If you use - instead of +, then the position is relative to the lower-right corner instead of the upper-left corner. By default no position is specified so your window manager will place the icon. The iconic resource indicates the startup disposition of the window.
You can control the bitmap and the label on the icon. There are three states for the icon: no mail, spooled mail, and unread mail. For each of these states you can define a bitmap and a label. The label can include references to exmh variables, as you will see in the default values. The value for the Bitmap is a file name. If it is relative then it is assumed to be in the exmh script library. Specify an absolute pathname otherwise.
You can reference any global exmh variable in the icon label. The two most useful are $flist(totalcount,unseen), which is a count across all folders of messages in the unseen sequence, and $exmh(numUnInced), which is the number of messages in your system spool file. This later value is only computed by the background "count" operation.
The icon*Glyph values are color images for the icons; the icon*Bitmap values are black & white images for the icons and are used if the Glyph is not available; the icon*Mask values are masks to allow transparency in black and white icons.
The color icons may be disabled and the black and white used in their place by providing a meaningless value (such as "none") for the Glyph.
Resources are used to define the set of understood MIME types and to define the font families used to display messages in various character sets.
text/plain text/richtext text/enriched multipart/mixed multipart/digest multipart/parallel multipart/alternative application/octet-stream message/external-body message/rfc822 image/gif *mimeUTypes: *mime_text/plain: Mime_ShowText *mime_text/richtext: Mime_ShowRichText *mime_text/enriched: Mime_ShowRichText *mime_multipart/mixed: Mime_ShowMultipart *mime_multipart/digest: Mime_ShowMultipartDigest *mime_multipart/parallel: Mime_ShowMultipartParallel *mime_multipart/alternative: Mime_ShowMultipartAlternative *mime_application/octet-stream: Mime_ShowApplicationOctet *mime_message/external-body: Mime_ShowMessageExternal *mime_message/rfc822: Mime_ShowRfc822 *mime_image/gif: Mime_ShowImage
*mimeCharsets: us-ascii iso-8859-1 iso-8859-8 iso-2022-jp *mimeUCharsets: *mime_us-ascii_registry: iso8859 *mime_us-ascii_encoding: * *mime_iso-8859-1_registry: iso8859 *mime_iso-8859-1_encoding: 1 *mime_iso-8859-8_registry: iso8859 *mime_iso-8859-8_encoding: 8 *mime_iso-2022-jp_registry: jisx0208.1983 *mime_iso-2022-jp_encoding: *
*mime_us-ascii_plain_families: fixed clean lucidatypewriter courier terminal *mime_iso-8859-1_plain_families: lucidatypewriter fixed courier terminal *mime_iso-8859-8_plain_families: fixed *mime_iso-2022-jp_plain_families: fixed
*mime_us-ascii_fixed_families: lucidatypewriter fixed clean courier terminal *mime_iso-8859-1_fixed_families: lucidatypewriter fixed courier terminal *mime_iso-8859-8_fixed_families: fixed *mime_iso-2022-jp_fixed_families: fixed
*mime_us-ascii_proportional_families: times "new century schoolbook" lucidabright charter lucida helvetica *mime_iso-8859-1_proportional_families: times "new century schoolbook" lucidabright charter lucida helvetica *mime_iso-8859-8_proportional_families: *mime_iso-2022-jp_proportional_families:
*mime_us-ascii_title_families: times "new century schoolbook" lucidabright charter lucida helvetica *mime_iso-8859-1_title_families: times "new century schoolbook" lucidabright charter lucida helvetica *mime_iso-8859-8_title_families: *mime_iso-2022-jp_title_families:
*mimeExtMethods: local-file anon-ftp *mimeUExtMethods: *mime_local-file: MimeLocalFileTransfer *mime_anon-ftp: MimeFTPTransfer
Date:
header. This resource describes
the format, which uses the strftime(3C)
syntax.
The default value is:
%H:%M %Z
Example:
If no value of mime_alternative_prefs is provided, exmh will display the last alternative that it is capable of displaying.*mime_alternative_prefs: text/plain text/richtext text/html
Exmh is implemented as a Tcl/Tk script that uses the MH programs to manage your mail. The script is interpreted at runtime and is therefore distributed in source form. You can read the source to figure out what really going on. Furthermore, you can take advantage of the Tcl library facility in order to override parts of the implementation. Warning: it is easy to add new Tcl procedures, or to replace whole modules (i.e., files) of the exmh implementation. It is more awkward to override the definition of a single Tcl procedure, as explained below.
By the way, if you do anything interesting to the sources, send the results to [email protected] so they can be folded back into the master sources. Many of the good features in exmh came about this way.
Even if you do not know Tcl you can probably figure it out as you read through the source. There is not enough room here to talk in any detail about Tcl programming. There are reasonably good on-line manual pages that come with Tcl and Tk. There are books about Tcl, too. John Ousterhout, the creator of Tcl and Tk, has written Tcl and the Tk Toolkit, by Addison-Wesley. I have written Practical Programming in Tcl and Tk, published by Prentice-Hall, ISBN 0-13-616830-2.
Your custom Tcl code is kept in your ~/.tk/exmh directory. You maintain this as a Tcl library, which amounts to keeping a file called tclIndex up-to-date. This index file records which files implement which Tcl procedures. The normal Tcl shells (tclsh and wish) provide a Tcl command auto_mkindex that generates this file for you. Within a Tcl shell you use it like this:
The first argument is a directory name, and the second argument is a filename pattern, which is usually *.tcl. If you add a new file or procedure to this directory, remember to update the index by running this command.auto_mkindex ~/.tk/exmh *.tcl
The Tcl library facility is used by exmh for the main sources, too. The implementation has been chopped up into over 50 files, and these are loaded on demand as different features of exmh are invoked. The per-user library directory is search first, which means you can replace parts of the exmh implementation. While this is quite flexible, it is not ideal. The natural unit of replacement is a whole file, which might contain several Tcl procedures, even though you only want to change one. See below for an explanation of the patch procedure that lets you modify a main library script file.
NOTE: if you use TclX, then the auto_path stuff is different and the personal library seems not to work. If you figure out the right thing to do in auto_path_update (in the main exmh script), let me know.
In most cases you will merely supply new code as opposed to replacing (i.e., fixing) parts of the implementation. Because you can define buttons and menus that invoke this new code without touching the released sources, you should be able to graft on new functionality somewhat cleanly.
The user.tcl file contains two empty hook procedures, User_Init and User_Layout. User_Init is called early, before most other modules are initialized. User_Layout is called late, just after the widget tree has been created and basically every module initialized.
IMPORTANTYou must supply both User_Init and User_Layout because of the way Tcl auto-loading works. Just copy user.tcl and edit it.
Version 2.0.2 and later support a patching facility. Suppose you want to change the Msg_CompTo procedure in the standard msg.tcl file. You could edit a copy of msg.tcl and put that into your user script library directory. However, then you need to track changes to msg.tcl when new releases come out. Another way is to put the procedure definition into msg.patch and put that file into your script library. Now, enable the "source hook" preference item in Hacking Support and restart exmh. The next time exmh sources msg.tcl from its main library, it will also source the msg.patch file from your private library. Your new definition of Msg_CompTo will replace the standard version.
There are some optional hook procedures with names beginning with Hook_. These procedures are called if they exist, so you do not need stub versions if you don't use them. Because of the way the library facility works, though, you have to include your Hook procedures in your copy of user.tcl or source the file that contains them from inside your User_Init procedure.
In addition, you can have several hook procedures called from the same point by appending things to the standard hook names. That is, the implementation will call all procedures that match the pattern Hook_Foo*, so you could define Hook_FooBrent and Hook_FooWelch and both would be called at the Foo hook point. The hook points are:
Note that the MsgParseFrom procedure, which is defined in msgShow.tcl, will extract the address part of a header line, so use it as a starting point for your code.
I've tried to split up exmh into meaningful modules, separating out display modules (e.g., fdisp) from those that maintain display-independent data structures (e.g., flist). Things like the Find and Pick dialogs are in their own file, so you can easily replace those. I have not documented the interfaces between modules at all, so you'll have to read some code. Note that the .tcl file names reflect the names of the procedures defined in them so you can locate definitions. In addition, many modules use a single global array to hold their state variables, and this array variable has the same name as the module.
If you are really interested in the internals of exmh (i.e., something about it really bugs you!) you can look into the implementation in order to see what is wrong and how you might do things better. The following is a list of the files in the implementation along with a short explanation of what the Tcl procedures in it are for.
The remainder of the files are kept in the script library.