XEmacs -- Emacs: The Next Generation
     Searching XEmacs
Quick Links About XEmacs Getting XEmacs Customizing XEmacs Troubleshooting XEmacs Developing XEmacs

Better Initialization File Scheme

Owner: ???

Effort: ???

Dependencies: ???

Abstract: A proposal is outlined for converting XEmacs to use the .xemacs subdirectory for its initialization files instead of putting them in the user's home directory. In the process, a general pre-initialization scheme is created whereby all of the initialization parameters, such as the location of the initialization files, whether these files are loaded or not, where the initial frame is created, etc. that are currently specified by command line arguments, by environment variables, and other means, can be specified in a uniform way using Lisp code. Reasonable default behavior for everything will still be provided, and the older, simpler means can be used if desired. Compatibility with the current location and name of the initialization file, and the current ill-chosen use for the .xemacs directory is maintained, and the problem of how to gracefully migrate a user from the old scheme into the new scheme while still allowing the user to use GNU Emacs or older versions of XEmacs is solved. A proposal for changing the way that the initial frame is mapped is also outlined; this would allow the user's initialization file to control the way that the initial frame appears without resorting to hacks, while still making echo area messages visible as they appear, and allowing the user to debug errors in the initialization file.

Principles in the new scheme

  1. XEmacs has a defined pre-initialization process. This process, whose purpose is to compute the values of the parameters that control how the initializiaton process proceeds, occurs as early as possible after the Lisp engine has been initialized, and in particular, it occurs before any devices have been opened, or before any initialization parameters are set that could reasonably be expected to be changed. In fact, the pre-initialization process should take care of setting these parameters. The code that implements the pre-initialization process should be written in Lisp and should be called from the Lisp function normal-top-level, and the general way that the user customizes this process should also be done using Lisp code.

  2. The pre-initialization process involves a number of properties, for example the directory containing the user initialization files (normally the .xemacs subdirectory), the name of the user init file, the name of the custom init file, where and what type the initial device is, whether and when the initial frame is mapped, etc. A standard interface is provided for getting and setting the values of these properties using functions such as set-pre-init-property, pre-init-property, etc. At various points during the pre-initialization process, the value of many of these properties can be undecided, which means that at the end of the process, the value of these properties will be derived from other properties in some fashion that is specific to each property.

  3. The default values of these properties are set first from the registry under Windows, then from environment variables, then from command line switches, such as -q and -nw.

  4. One of the command line switches is -pre-init, whose value is a Lisp expression to be evaluated at pre-initialization time, similar to the -eval command line switch. This allows any pre-initialization property to be set from the command line.

  5. Let's define the term to determine a pre-initialization property to mean if the value of a property is undetermined, it is computed and set according to a rule that is specific to the property. Then after the pre-init properties are initialized from the registry, from the environment variables, from command line arguments, two of the pre-init properties (specifically the init file directory and the location of the pre-init file) are determined. The purpose of the pre-init file is to contain Lisp code that is run at pre-initialization time, and to control how the initialization proceeds. It is a bit similar to the standard init file, but the code in the pre-init file shouldn't do anything other than set pre-init properties. Executing any code that does I/O might not produce expected results because the only device that will exist at the time is probably a stream device connected to the standard I/O of the XEmacs process.

  6. After the pre-init file has been run, all of the rest of the pre-init properties are determined, and these values are then used to control the initialization process. Some of the rules used in determining specific properties are:

    1. If the .xemacs sub-directory exists, and it's not obviously a package root (which probably means that it contains a file like init.el or pre-init.el, or if neither of those files is present, then it doesn't contain any sub-directories or files that look like what would be in a package root), then it becomes the value of the init file directory. Otherwise the user's home directory is used.

    2. If the init file directory is the user's home directory, then the init file is called .emacs. Otherwise, it's called init.el.

    3. If the init file directory is the user's home directory, then the pre-init file is called .xemacs-pre-init.el. Otherwise it's called pre-init.el. (One of the reasons for this rule has to do with the dialog box that might be displayed at startup. This will be described below.)

    4. If the init file directory is the user's home directory, then the custom init file is called .xemacs-custom-init.el. Otherwise, it's called custom-init.el.

  7. After the first normal device is created, but before any frames are created on it, the XEmacs initialization code checks to see if the old init file scheme is being used, which is to say that the init file directory is the same as the user's home directory. If that's the case, then normally a dialog box comes up (or a question is asked on the terminal if XEmacs is being run in a non-windowing mode) which asks if the user wants to migrate his initialization files to the new scheme. The possible responses are Yes, No, and No, and don't ask this again. If this last response is chosen, then the file .xemacs-pre-init.el in the user's home directory is created or appended to with a line of Lisp code that sets up a pre-init property indicating that this dialog box shouldn't come up again. If the Yes option is chosen, then any package root files in .xemacs are moved into .xemacs/packages, the file .emacs is moved into .xemacs/init.el and .emacs in the home directory becomes a symlink to this file. This way some compatibility is still maintained with GNU Emacs and older versions of XEmacs. The code that implements this has to be written very carefully to make sure that it doesn't accidentally delete or mess up any of the files that get moved around.

The custom init file

The custom init file is where the custom package writes its options. This obviously needs to be a separate file from the standard init file. It should also be loaded before the init file rather than after, as is usually done currently, so that the init file can override these options if it wants to.

Frame mapping

In addition to the above scheme, the way that XEmacs handles mapping the initial frame should be changed. However, this change perhaps should be delayed to a later version of XEmacs because of the user visible changes that it entails and the possible breakage in people's init files that might occur. (For example, if the rest of the scheme is implemented in 21.2, then this part of the scheme might want to be delayed until version 22.) The basic idea is that the initial frame is not created before the initialization file is run, but instead a banner frame is created containing the XEmacs logo, a button that allows the user to cancel the execution of the init file and an area where messages that are output in the process of running this file are displayed. This area should contain a number of lines, which makes it better than the current scheme where only the last message is visible. After the init file is done, the initial frame is mapped. This way the init file can make face changes and other such modifications that affect initial frame and then have the initial frame correctly come up with these changes and not see any frame dancing or other problems that exist currently.

There should be a function that allows the initialization file to explicitly create and map the first frame if it wants to. There should also be a pre-init property that controls whether the banner frame appears (of course it defaults to true) a property controlling when the initial frame is created (before or after the init file, defaulting to after), and a property controlling whether the initial frame is mapped (normally true, but will be false if the -unmapped command line argument is given).

If an error occurs in the init file, then the initial frame should always be created and mapped at that time so that the error is displayed and the debugger has a place to be invoked.

Ben Wing

Conform with <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Automatically validated by PSGML