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

Lisp Interface Changes


Owner: ???

Effort: ???

Dependencies: ???

Abstract: This document covers the major Lisp interface changes that I am proposing for version 22. These changes include full support for keyword parameters everywhere in Elisp, a generalized object property interface, and changes to the toolbar and menu API, in such a way that backward compatibility is maintained for the most part. Most of these changes are being done for the benefit of the improved user interface facilities that I am proposing for version 22 in order to make their associated interfaces cleaner and easier to use. As far as I know, all of these changes can be made in such a way that the byte code format does not need to be modified.

Keyword Parameters

I would like to make keyword parameters an integral part of Elisp. The idea here is that you use the &key identifier in the parameter list of a function and all of the following parameters specified are keyword parameters. This means that when these arguments are specified in a function call, they are immediately preceded in the argument list by a keyword, which is a symbol beginning with the `:' character. This allows any argument to be specified independently of any other argument with no need to place the arguments in any particular order. This is particularly useful for functions that take many optional parameters; using keyword parameters makes the code much cleaner and easier to understand.

The cl package already provides keyword parameters of a sort, but I would like to make this more integrated and useable in a standard fashion. The interface that I am proposing is essentially compatible with the keyword interface in Common Lisp, but it may be a subset of the Common Lisp functionality, especially in the first implementation. There is one departure from the Common Lisp specification that I would like to make in order to make it much easier to add keyword parameters to existing functions with optional parameters, and in general, to make optional and keyword parameters coexist more easily. The Common Lisp specification indicates that if a function has both optional and keyword parameters, the optional parameters are always processed before the keyword parameters. This means, for example, that if a function has three required parameters, two optional parameters, and some number of keyword parameters following, and the program attempts to call this function by passing in the three required arguments, and then some keyword arguments, the first keyword specified and the argument following it get assigned to the first and second optional parameters as specified in the function definition. This is certainly not what is intended, and means that if a function defines both optional and keyword parameters, any calls of this function must specify nil for all of the optional arguments before using any keywords. If the function definition is later changed to add more optional parameters, all existing calls to this function that use any keyword arguments will break. This problem goes away if we simply process keyword parameters before the optional parameters.

The primary changes needed to support the keyword syntax are:

  1. The subr object type needs to be modified to contain additional slots for the number and names of any keyword parameters.

  2. The implementation of the funcall function needs to be modified so that it knows how to process keyword parameters. This is the only place that will require very much intricate coding, and much of the logic that would need to be added can be lifted directly from the cl code.

  3. A new macro, similar to the DEFUN macro, and probably called DEFUN_WITH_KEYWORDS, needs to be defined so that built-in Lisp primitives containing keywords can be created. Now, the DEFUN_WITH_KEYWORDS macro should take an additional parameter which is a string, which consists of the part of the lambda list declaration for this primitive that begins with the &key specifier. This string is parsed in the DEFSUBR macro during XEmacs initialization, and is converted into the appropriate structure that needs to be stored into the subr object. In addition, the max_args parameter of the DEFUN macro needs to be incremented by the number of keyword parameters and these parameters are passed to the C function simply as extra parameters at the end. The DEFSUBR macro can sort out the actual number of required, optional and keyword parameters that the function takes, once it has parsed the keyword parameter string. (An alternative that might make the declaration of a primitive a little bit easier to understand would involve adding another parameter to the DEFUN_WITH_KEYWORDS macro that specifies the number of keyword parameters. However, this would require some additional complexity in the preprocessor definition of the DEFUN_WITH_KEYWORDS macro, and probably isn't worth implementing).

  4. The byte compiler would have to be modified slightly so that it knows about keyword parameters when it parses the parameter declaration of a function. For example, so that it issues the correct warnings concerning calls to that function with incorrect arguments.

  5. The make-docfile program would have to be modified so that it generates the correct parameter lists for primitives defined using the DEFUN_WITH_KEYWORDS macro.

  6. Possibly other aspects of the help system that deal with function descriptions might have to be modified.

  7. A helper function might need to be defined to make it easier for primitives that use both the &rest and &key specifiers to parse their argument lists.

Property Interface Changes

In my past work on XEmacs, I already expanded the standard property functions of get, put, and remprop to work on objects other than symbols and defined an additional function object-plist for this interface. I'd like to expand this interface further and advertise it as the standard way to make property changes in objects, especially the new objects that are going to be defined in order to support the added user interface features of version 22. My proposed changes are as follows:

  1. A new concept associated with each property called a default value is introduced. (This concept already exists, but not in a well-defined way.) The default value is the value that the property assumes for certain value retrieval functions such as get when it is unbound, which is to say that its value has not been explicitly specified. Note: the way to make a property unbound is to call remprop. Note also that for some built-in properties, setting the property to its default value is equivalent to making it unbound.

  2. The behavior of the get function is modified. If the get function is called on a property that is unbound and the third, optional default argument is nil, then the default value of the property is returned. If the default argument is not nil, then whatever was specified as the value of this argument is returned. For the most part, this is upwardly compatible with the existing definition of get because all user-defined properties have an initial default value of nil. Code that calls the get function and specifies nil for the default argument, and expects to get nil returned if the property is unbound, is almost certainly wrong anyway.

  3. A new function, get1 is defined. This function does not take a default argument like the get function. Instead, if the property is unbound, an error is signaled. Note: get can be implemented in terms of get1.

  4. New functions property-default-value and property-bound-p are defined with the obvious semantics.

  5. An additional function property-built-in-p is defined which takes two arguments, the first one being a symbol naming an object type, and the second one specifying a property, and indicates whether the property name has a built-in meaning for objects of that type.

  6. It is not necessary, or even desirable, for all object types to allow user-defined properties. It is always possible to simulate user-defined properties for an object by using a weak hash table. Therefore, whether an object allows a user to define properties or not should depend on the meaning of the object. If an object does not allow user-defined properties, the put function should signal an error, such as undefined-property, when given any property other than those that are predefined.

  7. A function called user-defined-properties-allowed-p should be defined with the obvious semantics. (See the previous item.)

  8. Three more functions should be defined, called built-in-property-name-list, property-name-list, and user-defined-property-name-list.

Toolbar Interface Changes

I propose changing the way that toolbars are specified to make them more flexible.

  1. A new format for the vector that specifies a toolbar item is allowed. In this format, the first three items of the vector are required and are, respectively, a caption, a glyph list, and a callback. The glyph list and callback arguments are the same as in the current toolbar item specification, and the caption is a string specifying the caption text placed below the toolbar glyph. The caption text is required so that toolbar items can be identified for the purpose of retrieving and changing their property values. Putting the caption first also makes it easy to distinguish between the new and the old toolbar item vector formats. In the old format, the first item, the glyph list, is either a list or a symbol. In the new format, the first item is a string. In the new format, following the three required items, are optional keyword items specified using keywords in the same format as the menu item vector format. The keywords that should be predefined are: :help-echo, :context-menu, :drop-handlers, and :enabled-p. The :enabled-p and :help-echo keyword arguments are the same as the third and fourth items in the old toolbar item vector format. The :context-menu keyword is a list in standard menu format that specifies additional items that will appear when the context menu for the toolbar item is popped up. (Typically, this happens when the right mouse button is clicked on the toolbar item). The :drop-handlers keyword is for use by the new drag-n-drop interface (see Drag-n-Drop Interface Changes ), and is not normally specified or modified directly.

  2. Conceivably, there could also be keywords that are associated with a toolbar itself, rather than with a particular toolbar item. These keyword properties would be specified using keywords and arguments that occur before any toolbar item vectors, similarly to how things are done in menu specifications. Possible properties could include :captioned-p (whether the captions are visible under the toolbar), :glyphs-visible-p (whether the toolbar glyphs are visible), and :context-menu (additional items that will appear on the context menus for all toolbar items and additionally will appear on the context menu that is popped up when the right mouse button is clicked over a portion of the toolbar that does not have any toolbar buttons in it). The current standard practice with regards to such properties seems to be to have separate specifiers, such as left-toolbar-width, right-toolbar-width, left-toolbar-visible-p, right-toolbar-visible-p, etc. It could easily be argued that there should be no such toolbar specifiers and that all such properties should be part of the toolbar instantiator itself. In this scheme, the only separate specifiers that would exist for individual properties would be default values. There are a lot of reasons why an interface change like this makes sense. For example, currently when VM sets its toolbar, it also sets the toolbar width and similar properties. If you change which edge of the frame the VM toolbar occurs in, VM will also have to go and modify all of the position-specific toolbar specifiers for all of the other properties associated with a toolbar. It doesn't really seem to make sense to me for the user to be specifying the width and visibility and such of specific toolbars that are attached to specific edges because the user should be free to move the toolbars around and expect that all of the toolbar properties automatically move with the toolbar. (It is also easy to imagine, for example, that a toolbar might not be attached to the edge of the frame at all, but might be floating somewhere on the user's screen). With an interface where these properties are separate specifiers, this has to be done manually. Currently, having the various toolbar properties be inside of toolbar instantiators makes them difficult to modify, but this will be different with the API that I propose below.

  3. I propose an API for modifying toolbar and toolbar item properties, as well as making other changes to toolbar instantiators, such as inserting or deleting toolbar items. This API is based around the concept of a path. There are two kinds of paths here -- toolbar paths and toolbar item paths. Each kind of path is an object (of type toolbar-path and toolbar-item-path, respectively) whose properties specify the location in a toolbar instantiator where changes to the instantiator can be made. A toolbar path, for example, would be created using the make-toolbar-path function, which takes a toolbar specifier (or optionally, a symbol, such as left, right, default, or nil, which refers to a particular toolbar), and optionally, parameters such as the locale and the tag set, which specify which actual instantiator inside of the toolbar specifier is to be modified. A toolbar item path is created similarly using a function called make-toolbar-item-path, which takes a toolbar specifier and a string naming the caption of the toolbar item to be modified, as well as, of course, optionally the locale and tag set parameters and such.

    The usefulness of these path objects is as arguments to functions that will use them as pointers to the place in a toolbar instantiator where the modification should be made. Recall, for example, the generalized property interface described above. If a function such as get or put is called on a toolbar path or toolbar item path, it will use the information contained in the path object to retrieve or modify a property located at the end of the path. The toolbar path objects can also be passed to new functions that I propose defining, such as add-toolbar-item, delete-toolbar-item, and find-toolbar-item. These functions should be parallel to the functions for inserting, deleting, finding, etc. items in a menu. The toolbar item path objects can also be passed to the drop-handler functions defined in Drag-n-Drop Interface Changes to retrieve or modify the drop handlers that are associated with a toolbar item. (The idea here is that you can drag an object and drop it onto a toolbar item, just as you could onto a buffer, an extent, a menu item, or any other graphical element).

  4. We should at least think about allowing for separate default and buffer-local toolbars. The user should either be able to position these toolbars one above the other, or side by side, occupying a single toolbar line. In the latter case, the boundary between the toolbars should be draggable, and if a toolbar takes up more room than is allocated for it, there should be arrows that appear on one or both sides of the toolbar so that the items in the toolbar can be scrolled left or right. (For that matter, this sort of interface should exist even when there is only one toolbar that is on a particular toolbar line, because the toolbar may very well have more items than can be displayed at once, and it's silly in such a case if it's impossible to access the items that are not currently visible).

  5. The default context menu for toolbars (which should be specified using a specifier called default-toolbar-context-menu according to the rules defined above) should contain entries allowing the user to modify the appearance of a toolbar. Entries would include, for example, whether the toolbar is captioned, whether the glyphs for the toolbar are visible (if the toolbar is captioned but its glyphs are not visible, the toolbar appears as nothing but text; you can set things up this way, for example, in Netscape), an option that brings up a package for editing the contents of a toolbar, an option to allow the caption face to be dchanged (perhaps thorough jan edit-faces or custom interface), etc.

Menu API Changes

  1. I propose making a specifier for the menubar associated with the frame. The specifier should be called default-menubar and should replace the existing current-menubar variable. This would increase the power of the menubar interface and bring it in line with the toolbar interface. (In order to provide proper backward compatibility, we might have to complete the symbol value handler mechanism)

  2. I propose an API for modifying menu instantiators similar to the API composed above for toolbar instantiators. A new object called a menu path (of type menu-path) can be created using the make-menu-path function, and specifies a location in a particular menu instantiator where changes can be made. The first argument to make-menu-path specifies which menu to modify and can be a specifier, a value such as nil (which means to modify the default menubar associated with the selected frame), or perhaps some other kind of specification referring to some other menu, such as the context menus invoked by the right mouse button. The second argument to make-menu-path, also required, is a list of zero or more strings that specifies the particular menu or menu item in the instantiator that is being referred to. The remaining arguments are optional and would be a locale, a tag set, etc. The menu path object can be passed to get, put or other standard property functions to access or modify particular properties of a menu or a menu item. It can also be passed to expanded versions of the existing functions such as find-menu-item, delete-menu-item, add-menu-button, etc. (It is really a shame that add-menu-item is an obsolete function because it is a much better name than add-menu-button). Finally, the menu path object can be passed to the drop-handler functions described in Drag-n-Drop Interface Changes to access or modify the drop handlers that are associated with a particular menu item.

  3. New keyword properties should be added to the menu item vector. These include :help-echo, :context-menu and :drop-handlers, with similar semantics to the corresponding keywords for toolbar items. (It may seem a bit strange at first to have a context menu associated with a particular menu item, but it is a user interface concept that exists both in Open Look and in Windows, and really makes a lot of sense if you give it a bit of thought). These properties may not actually be implemented at first, but at least the keywords for them should be defined.

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