[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7 Advanced Customization Using XEmacs Lisp

This is part 7 of the XEmacs Frequently Asked Questions list. This section is devoted to advanced customization using XEmacs Lisp.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.0: Emacs Lisp and ‘init.el

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.0.1: What version of Emacs am I running?

How can ‘init.el’ determine which of the family of Emacsen I am using?

To determine if you are currently running GNU Emacs 18, GNU Emacs 19, XEmacs 19, XEmacs 20, or Epoch, and use appropriate code, check out the example given in ‘etc/sample.init.el’ (‘etc/sample.emacs’ in XEmacs versions prior to 21.4). There are other nifty things in there as well!

For all new code, all you really need to do is:

(defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.0.2: How can I evaluate Emacs-Lisp expressions?

I know I can evaluate Elisp expressions from *scratch* buffer with C-j after the expression. How do I do it from another buffer?

Press M-: (the default binding of eval-expression), and enter the expression to the minibuffer.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.0.3: (setq tab-width 6) behaves oddly.

If you put (setq tab-width 6) in your ‘init.el’ file it does not work! Is there a reason for this? If you do it at the EVAL prompt it works fine!! How strange.

Use setq-default instead, since tab-width is all-buffer-local.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.0.4: How can I add directories to the load-path?

Here are two ways to do that, one that puts your directories at the front of the load-path, the other at the end:

;;; Add things at the beginning of the load-path, do not add
;;; duplicate directories:
(pushnew "bar" load-path :test 'equal)

(pushnew "foo" load-path :test 'equal)

;;; Add things at the end, unconditionally
(setq load-path (nconc load-path '("foo" "bar")))

Keith (k.p.) Hanlan writes:

To add directories using Unix shell metacharacters use ‘expand-file-name’ like this:

(push (expand-file-name "~keithh/.emacsdir") load-path)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.0.5: How to check if a lisp function is defined?

Use the following elisp:

(fboundp 'foo)

It’s almost always a mistake to test emacs-version or any similar variables.

Instead, use feature-tests, such as featurep, boundp, fboundp, or even simple behavioral tests, eg.:

(defvar foo-old-losing-code-p
  (condition-case nil (progn (losing-code t) nil)
    (wrong-number-of-arguments t)))

There is an incredible amount of broken code out there which could work much better more often in more places if it did the above instead of trying to divine its environment from the value of one variable.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.0.6: Can I force the output of (face-list) to a buffer?

It would be good having it in a buffer, as the output of (face-list) is too wide to fit to a minibuffer.

Evaluate the expression in the ‘*scratch*’ buffer with point after the rightmost paren and typing C-j.

If the minibuffer smallness is the only problem you encounter, you can simply press C-h l to get the former minibuffer contents in a buffer.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1: Emacs Lisp Programming Techniques

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.1: What is the difference in key sequences between XEmacs and GNU Emacs?

Erik Naggum writes;

Emacs has a legacy of keyboards that produced characters with modifier bits, and therefore map a variety of input systems into this scheme even today. XEmacs is instead optimized for X events. This causes an incompatibility in the way key sequences are specified, but both Emacs and XEmacs will accept a key sequence as a vector of lists of modifiers that ends with a key, e.g., to bind M-C-a, you would say [(meta control a)] in both Emacsen. XEmacs has an abbreviated form for a single key, just (meta control a). Emacs has an abbreviated form for the Control and the Meta modifiers to string-characters (the ASCII characters), as in ‘\M-\C-a’. XEmacs users need to be aware that the abbreviated form works only for one-character key sequences, while Emacs users need to be aware that the string-character is rather limited. Specifically, the string-character can accommodate only 256 different values, 128 of which have the Meta modifier and 128 of which have not. In each of these blocks, only 32 characters have the Control modifier. Whereas [(meta control A)] differs from [(meta control a)] because the case differs, ‘\M-\C-a’ and ‘\M-\C-A’ do not. Programmers are advised to use the full common form, both because it is more readable and less error-prone, and because it is supported by both Emacsen.

Another (even safer) way to be sure of the key-sequences is to use the read-kbd-macro function, which takes a string like ‘C-c <up>’, and converts it to the internal key representation of the Emacs you use. The function is available both on XEmacs and GNU Emacs.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.2: Can I generate "fake" keyboard events?

I wonder if there is an interactive function that can generate fake keyboard events. This way, I could simply map them inside XEmacs.

This seems to work:

(defun cg--generate-char-event (ch)
  "Generate an event, as if ch has been typed"
  (dispatch-event (character-to-event ch)))

;;  Backspace and Delete stuff
(global-set-key [backspace]
  (lambda () (interactive) (cg--generate-char-event 127)))
(global-set-key [unknown_keysym_0x4]
  (lambda () (interactive) (cg--generate-char-event 4)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.3: Could you explain read-kbd-macro in more detail?

The read-kbd-macro function returns the internal Emacs representation of a human-readable string (which is its argument). Thus:

(read-kbd-macro "C-c C-a")
⇒ [(control ?c) (control ?a)]

(read-kbd-macro "C-c C-. <up>")
⇒ [(control ?c) (control ?.) up]

In GNU Emacs the same forms will be evaluated to what GNU Emacs understands internally—the sequences "\C-x\C-c" and [3 67108910 up], respectively.

The exact human-readable syntax is defined in the docstring of edmacro-mode. I’ll repeat it here, for completeness.

Format of keyboard macros during editing:

Text is divided into words separated by whitespace. Except for the words described below, the characters of each word go directly as characters of the macro. The whitespace that separates words is ignored. Whitespace in the macro must be written explicitly, as in foo <SPC> bar <RET>.

Any word may be prefixed by a multiplier in the form of a decimal number and *: 3*<right><right> <right> <right>, and 10*foofoofoofoofoofoofoofoofoofoofoo.

Multiple text keys can normally be strung together to form a word, but you may need to add whitespace if the word would look like one of the above notations: ; ; ; is a keyboard macro with three semicolons, but ;;; is a comment. Likewise, \ 1 2 3 is four keys but \123 is a single key written in octal, and < right > is seven keys but <right> is a single function key. When in doubt, use whitespace.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.4: What is the performance hit of let?

In most cases, not noticeable. Besides, there’s no avoiding let—you have to bind your local variables, after all. Some pose a question whether to nest lets, or use one let per function. I think because of clarity and maintenance (and possible future implementation), let-s should be used (nested) in a way to provide the clearest code.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.5: What is the recommended use of setq?

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.6: What is the typical misuse of setq?

A typical misuse is probably setqing a variable that was meant to be local. Such a variable will remain bound forever, never to be garbage-collected. For example, the code doing:

(defun my-function (whatever)
  (setq a nil)
  ... build a large list ...
  ... and exit ...)

does a bad thing, as a will keep consuming memory, never to be unbound. The correct thing is to do it like this:

(defun my-function (whatever)
  (let (a)                              ; default initialization is to nil
    ... build a large list ...
    ... and exit, unbinding `a' in the process  ...)

Not only is this prettier syntactically, but it makes it possible for Emacs to garbage-collect the objects which a used to reference.

Note that even global variables should not be setqed without defvaring them first, because the byte-compiler issues warnings. The reason for the warning is the following:

(defun flurgoze nil)                    ; ok, global internal variable

(setq flurghoze t)                      ; ops!  a typo, but semantically correct.
                                        ; however, the byte-compiler warns.

While compiling toplevel forms:
** assignment to free variable flurghoze

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.7: I like the do form of cl, does it slow things down?

It shouldn’t. Here is what Dave Gillespie has to say about cl.el performance:

Many of the advanced features of this package, such as defun*, loop, and setf, are implemented as Lisp macros. In byte-compiled code, these complex notations will be expanded into equivalent Lisp code which is simple and efficient. For example, the forms

(incf i n)
(push x (car p))

are expanded at compile-time to the Lisp forms

(setq i (+ i n))
(setcar p (cons x (car p)))

which are the most efficient ways of doing these respective operations in Lisp. Thus, there is no performance penalty for using the more readable incf and push forms in your compiled code.

Interpreted code, on the other hand, must expand these macros every time they are executed. For this reason it is strongly recommended that code making heavy use of macros be compiled. A loop using incf a hundred times will execute considerably faster if compiled, and will also garbage-collect less because the macro expansion will not have to be generated, used, and thrown away a hundred times.

You can find out how a macro expands by using the cl-prettyexpand function.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.8: I like recursion, does it slow things down?

Yes. The Emacs byte-compiler cannot do much to optimize recursion. But think well whether this is a real concern in Emacs. Much of the Emacs slowness comes from internal mechanisms such as redisplay, or from the fact that it is an interpreter.

Please try not to make your code much uglier to gain a very small speed gain. It’s not usually worth it.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.9: How do I put a glyph as annotation in a buffer?

Here is a solution that will insert the glyph annotation at the beginning of buffer:

(make-annotation (make-glyph '([FORMAT :file FILE]
                               [string :data "fallback-text"]))

Replace ‘FORMAT’ with an unquoted symbol representing the format of the image (e.g. xpm, xbm, gif, jpeg, etc.) Instead of ‘FILE’, use the image file name (e.g. ‘/usr/local/lib/xemacs-21.4/etc/recycle.xpm’).

You can turn this to a function (that optionally prompts you for a file name), and inserts the glyph at (point) instead of (point-min).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.10: map-extents won’t traverse all of my extents!

I tried to use map-extents to do an operation on all the extents in a region. However, it seems to quit after processing a random number of extents. Is it buggy?

No. The documentation of map-extents states that it will iterate across the extents as long as function returns nil. Unexperienced programmers often forget to return nil explicitly, which results in buggy code. For instance, the following code is supposed to delete all the extents in a buffer, and issue as many ‘fubar!’ messages.

(map-extents (lambda (ext ignore)
               (delete-extent ext)
               (message "fubar!")))

Instead, it will delete only the first extent, and stop right there – because message will return a non-nil value. The correct code is:

(map-extents (lambda (ext ignore)
               (delete-extent ext)
               (message "fubar!")

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.1.11: My elisp program is horribly slow. Is there an easy way to find out where it spends time?

Hrvoje Niksic writes:

Under XEmacs 20.4 and later you can use M-x profile-key-sequence, press a key (say <RET> in the Gnus Group buffer), and get the results using M-x profile-results. It should give you an idea of where the time is being spent.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.2: Mathematics

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.2.1: What are bignums, ratios, and bigfloats in Lisp?

Thanks to Jerry James, XEmacs 21.5.18 and later can use the capabilities of multiple-precision libraries that may be available for your platform. The GNU Multiple Precision (GMP) and BSD Multiple Precision (MP) libraries are partially supported. GMP gives you bignums (arbitrary precision integers), ratios (arbitrary precision fractions), and bigfloats (arbitrary precision floating point numbers). GNU MP is better-supported by XEmacs at the time of writing (2004-04-06). BSD MP support does not include ratios or bigfloats, and it throws errors that aren’t understood.

In most cases, bignum support should be transparent to users and Lisp programmers. A bignum-enabled XEmacs will automatically convert from fixnums to bignums and back in pure integer arithmetic, and for GNU MP, from floats to bigfloats. (Bigfloats must be explicitly coerced to other types, even if they are exactly representable by less precise types.) The Lisp reader and printer have been enhanced to handle bignums, as have the mathematical functions. Rationals (fixnums, bignums, and ratios) are printed using the ‘%d’, ‘%o’, ‘%x’, and ‘%u’ format conversions. The read syntax for ratios is ‘3/5’.

User-visible changes in behavior include (in probable order of annoyance)

Surgeon General’s Warning: The automatic conversions cannot be disabled at runtime. New functions have been added which produce ratios, so there should be few surprises with type conflicts, but they can’t be ruled out. “Arbitrary” precision means precisely what it says. If you work with extremely large numbers, your machine may arbitrarily decide to hand you an unpleasant surprise rather than a bignum XEmacs segfaults when I use very big numbers!.

To configure with GNU MP, add ‘--use-number-lib=gmp’ (‘--enable-bignum=gmp’ in 21.5 or later) to your invocation of ‘configure’. For BSD MP, use ‘--use-number-lib=mp’ (‘--enable-bignum=mp’ for 21.5).

If you would like to help with bignum support, especially on BSD MP, please subscribe to the XEmacs Beta mailing list, and book up on ‘number-gmp.h’ and ‘number-mp.h’. Jerry has promised to write internals documentation eventually, but if your skills run more to analysis and documentation than to writing new code, feel free to fill in the gap!

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.2.2: XEmacs segfaults when I use very big numbers!

GMP by default allocates temporaries on the stack. If you run out of stack space, you’re dead; there is no way that we know of to reliably detect this condition, because ‘alloca’ is typically implemented to be fast rather than robust. If you just need a little more oomph, use a bigger stack (e.g., the ‘ulimit -s’ command in bash(1)). If you want robustness at the cost of speed, configure GMP with ‘--disable-alloca’ and rebuild the GMP library.

We do not know whether BSD MP uses ‘alloca’ or not. Please send any information you have as a bug report (M-x report-xemacs-bug <RET>), which will give us platform information. (We do know that BSD MP implementations vary across vendors, but how much, we do not know yet.)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.2.3: Bignums are really slow!

Many Linux distributions compile all their packages for the i386, and this is costly. An optimized version can give you two or three orders of magnitude better performance for a Pentium III or IV. (Yes, really. See http://www.swox.com/gmp/gmp-speed.html.)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Q7.2.4: Equal bignums don’t compare as equal! What gives?

Ah, Grasshopper, I see you are using (eq x y). The Bodhisattva CLTL2 warned of the illusion that equal numbers would be ‘eq’! Meditate on the deeper truths of ‘eql’, in which numbers of the same type which have equal values compare equal, and ‘=’, which does any necessary type coercions before comparing for equality.

Yeah, yeah, it has always worked for integer types, because fixnums and characters have an immediate representation. Sorry about that; arbitrary precision obviously requires consing new objects because the objects are “large” and of variable size, and the definition of ‘eq’ does not permit different objects to compare as equal.

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Aidan Kehoe on December 27, 2016 using texi2html 1.82.