4

I am trying to create a new mode for Emacs lisp, let's call it xyz-mode.el.

In testing the mode, I want to re-run xyz-mode.el on a potential target file, let's say abc.xyz. In other words, as I edit xyz-mode.el, I want to reload the mode into Emacs so that abc.xyz is viewable under the modified configuration. To be absolutely clear, what I want to do is as follows:

  1. I edit xyz-mode.el to change, say, the syntax for comments;
  2. I re-load xyz-mode.el
  3. I re-view abc.xyz to see whether my changes to xyz-mode.el have had the intended consequences.

I'm not talking about editing abc.xyz, but about editing xyz-mode.el then reloading.

What is the best way to re-run xyz-mode.el and try to re-view the subject file abc.xyz? I have tried using eval-buffer but this does not work correctly. I am currently killing Emacs itself and restarting, which is time-consuming.

  • To the extent that you can provide a minimal working example of your mode, the forum readers may be able to give you some ideas regarding how to test it. As it stands now, without a crystal ball, I don't see how anyone can help you. You may also wish to consider reddit with the Emacs tab -- all the time I see people posing their creations with questions like: What do you think? How can I improve upon what I have written? Etc. emacs.stackexchange.com is more geared towards what everyone would agree upon as being a distinct question with only a few or just one correct answer. – lawlist Jun 21 '18 at 3:59
  • You can do essentially the same thing you're with find-alternate-file, which should shorten re-opening a file to simply C-x C-v RET, provided your mode is already associated with file extension and you're using a file for your tests. – DoMiNeLa10 Jun 21 '18 at 4:24
  • @lawlist - I would be delighted to show you the content of the file, but I'm asking about reloading the mode file without killing the buffer or stopping the editor, so the content of the mode itself is not even slightly relevant to any potential answer. – Dusty Jun 21 '18 at 4:58
  • @DoMiNeLa10 - thanks for your input. I am using "Local variables:" to specify the file type, which works correctly. I want to re-read the xyz-mode.el file, not the file being input. It seems this question was not clear enough, so I'll edit it to clarify. – Dusty Jun 21 '18 at 5:01
  • There's load-file and eval-buffer which can be called with M-x, but these won't work for things like declarations with defvar and defconst, which you can (re)evaluate with C-x C-e after the sexp or C-M-x. – DoMiNeLa10 Jun 21 '18 at 5:04
3

The short answer is: M-x eval-buffer in the Lisp buffer then M-x normal-mode in the XYZ mode buffer.


To test the changes in your mode, you need to do two things: load the modified Lisp code, and apply the modifications to the buffer.

To load the modified Lisp code, M-x eval-buffer in xyz-mode.el mostly works, but there are a few limitations. This runs all the code in the buffer, and in particular it updates all the function definitions. However the values of variables set by defvar and the like (defconst, defcustom, defface) are not updated: defvar does not change the value of a variable that already has one. Updating the value of an existing variable when evaluating a defvar form is a special feature of eval-defun (C-M-x). Keeping the value of an existing variable is the right thing when it has been set by the user, but when it was set by a previous version of the code, you aren't testing the new code.

If the xyz-mode code was originally loaded by load, require or the like, you can run M-x unload-feature xyz-mode RET to unload all the definitions provided by the loaded module, then re-run the code that would load or autoload the module (e.g. re-evaluate (autoload 'xyz-mode "xyz-mode")). This way you'll get the new value for all variables, as long as those variables were loaded as part of the module. Also, if you removed some definition as part of your changes, it won't exist anymore, so you don't risk validating code that's actually using a definition that no longer exists. But note that variables and functions that were created with C-M-x during development won't have been unloaded since they weren't recorded as being part of the module.

Whatever method you use to load the changed implementation of the major mode, you also need to apply the changes to the existing buffer. Reloading the Lisp code applies some changes automatically, but some things require initialization in each buffer (e.g. syntax table, keymap, sometimes font lock settings). Re-run the major mode function in the abc.xyz buffer: M-x xyz-mode RET or (assuming the mode is the default for a file by that name) M-x normal-mode RET or M-x revert-buffer RET.

If this was a minor mode, turn it off and back on.

There is still a risk that the new code accidentally depends on some old feature that still exists in your session. Therefore, I recommend that from time to time, you run a new Emacs session to test the file. Keep your existing Emacs session open and run a new one just with the abc.xyz file to see that all is well. Do keep your existing Emacs session, so that for instance if you wrote a new function and then accidentally deleted it, you can recover it through undo or through the kill ring.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.