About Lectures Research Software Blog
Musical Site
MySpace
Facebook

Moods Blog

Dojo Shin Kaï

RSS Feed
Thank you!

XHTML 1.0 conformant
CSS 2.0 conformant
Didier Verna's scientific blog: Lisp, Emacs, LaTeX and random stuff.

Tag - Emacs Lisp

Entries feed - Comments feed

Tuesday, May 28 2013

el-rcfiles is released (first public version)

I've been using this for years, but never bothered to make it public until now.

el-rcfiles is a very small and simple library which provides Unix-like RC files for Emacs Lisp libraries. It's compatible with GNU Emacs and XEmacs, available in ELPA form, as a tarball and from GitHub. More details (including download) available here, but here is also the library's commentary section, for quick reference.

;;; Commentary:

;; The purpose of el-rcfiles is to provide the equivalent of traditional
;; Unix rc files (i.e. configuration files) for Emacs Lisp
;; libraries. The advantages of using configuration files are the
;; following:
;;   - your initialization file is less bloated,
;;   - since configuration files are lazily loaded, your Emacs session
;;     is (or begins) lighter. That is unless you already use lots of
;;     EVAL-AFTER-LOAD forms...

;; Usage:

;; 1. Load the library, go to the rcfiles Custom group and tweak (or not).
;; 2. Put a call to (rcfiles-register-rc-files) in your initialization
;;    file. This function can also be called interactively anytime you
;;    add, remove or modify a configuration file.
;; 3. Put your configuration code for a library `foo' in a file called
;;    `<rcfiles-directory>/foo<rcfiles-pseudo-extension>.el'.


Tuesday, May 14 2013

Emacs session bootstrap tweaks

This article essentially describes the top of my Emacs init file. That part of the code is devoted to modify the session bootstrap process, that is, some things that are normally done very early. It mostly deals with the package infrastructure but also contains a couple of other tricks that some people may consider useful. It goes like this…

The first line is self-explanatory (and please, be warned that I will discard any comment about it. You know why).

(require 'cl)

Platform-specific tweaks

A self-contained Emacs.app on MacOS X has its own site-lisp directory, but I want to make sure that the standard Unix one is here as well, and takes precedence.

(when (featurep 'ns)
  (add-to-list 'load-path "/usr/local/share/emacs/site-lisp"))

Updated When /not/ starting Emacs from the command-line (e.g. MacOS X app clicks or Quicksilver/Alfred, Unitiy launcher on Ubuntu etc.), I don't necessarily get my environment-based exec-path which can be problematic (e.g. for finding auxiliary programs such as movemail, gpg etc.). Emacs used to store the build-time value of exec-path in the custom's standard-value property, which was convenient for me because since I compile it myself, I could reuse that. This has changed however since this commit:

commit 2fc11b3fa3418e0e8a624376ea8bf4cbc70c2657
Author: Ludovic Courtès <ludo@gnu.org>
Date:   Mon Apr 20 17:44:23 2015 -0400

So now instead, I have patched it to save the build-time value in a new variable called BUILD-TIME-EXEC-PATH.

(when (boundp 'build-time-exec-path)
  (mapc (lambda (path) (setq exec-path (remove path exec-path)))
	build-time-exec-path)
  (setq exec-path (append build-time-exec-path exec-path)))

ELPA infrastructure

Initialize ELPA now so that the rest of the initialization process may rely on packages without having to go through after-init-hook.

(require 'package)

I want system-wide directories to be named emacs-packages instead of site-lisp/elpa.

(setq package-directory-list
      (let (result)
        (dolist (path load-path)
          (and (stringp path)
                 (equal (file-name-nondirectory path) "site-lisp")
                 (push (expand-file-name "emacs-packages"
                                                     (file-name-directory
                                                       (directory-file-name path)))
                          result)))
	(nreverse result)))

I want my local directory to follow the same convention.

(setq package-user-dir "~/.emacs.d/emacs-packages")

Now, it's okay to initialize ELPA.

(package-initialize)

Now that the packages have been initialized, I actually want ELPA to install in /usr/local/share/emacs/emacs-packages by default, and keep my local directory for manual installations. One simple way to achieve that is to set my local directory to /usr/local/share/emacs/emacs-packages and to remove that from the system-wide directory list. One small drawback of this is that my local path is gone, so any new package installed there won't be seen until the next restart. This is not much of a problem though.

(setq package-user-dir "/usr/local/share/emacs/emacs-packages"
        package-directory-list (remove "/usr/local/share/emacs/emacs-packages"
				                     package-directory-list))

Site and local (non ELPA) packages infrastructure

The purpose of this other infrastructure is to support packages that would be installed manually, outside ELPA, and in a way similar to XEmacs packages. A packages directory has lisp/, etc/ and info/ subdirectories. Every package installs its stuff directly in etc/ and info/, but adds its own subdirectory to lisp/ and puts its code (including a potential autoloads file) in there.

This additional infrastructure comes in handy in several situations. For instance, having Slime (auto)loaded in your session now becomes as simple as this:

ln -s /path/to/slime /usr/local/share/emacs/local-packages/lisp/

(defun dvl-initialize-packages (directory)
  "Initialize non-ELPA packages DIRECTORY.
This means:
  - adding the whole lisp/ subtree to LOAD-PATH,
  - loading the autoload files found there.
  - adding DIRECTORY to INFO-DEFAULT-DIRECTORY-LIST."
  (let ((default-directory (expand-file-name "lisp" directory)))
    ;; 1. Update LOAD-PATH
    (setq load-path
	  (append
	   (let ((load-path (copy-sequence load-path)))
	     (append (copy-sequence (normal-top-level-add-to-load-path '(".")))
		          (normal-top-level-add-subdirs-to-load-path)))
	   load-path))
    ;; 2. Load autoload files
    (loop for directory in load-path
	    while (string-prefix-p default-directory directory)
	    do (mapc #'load (directory-files directory t "-autoloads\\.el$"))))
  ;; 3. Update the default Info directory list
  (add-to-list 'Info-default-directory-list
   (expand-file-name "info" directory)))

(require 'info)

Be sure to do this by increasing priority order.

(mapc #'dvl-initialize-packages
      `("/usr/local/share/emacs/local-packages"
	 "~/.emacs.d/local-packages"))

And now we can re-initialize Info with the proper defaults.

(setq Info-directory-list nil)
(info-initialize)

Custom settings

Now that we have bootstrapped the complete packages infrastructure, we can set the Custom file to something that makes sense and load it now.

(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)

RC Files

Finally, install the rc files loader and we're done bootstrapping.

(rcfiles-register-rc-files)

That completes my session bootstrap process.

Tuesday, January 17 2012

Patcher 4.0 is released

I'm happy to announce the release of Patcher version 4.0. This is a major release introducing many new features and enhancements.

Patcher is a tool designed to automate and ease the maintenance of archive-based projects. It provides assistance in building, reporting and committing patches, as well as in handling the corresponding ChangeLog entries, for example by creating skeletons. Patcher is the official tool for XEmacs development.

NEW FEATURES

  • Support floating projects and temporary relocation allowing to use the same project descriptor for various directories.
  • Support for automatic detection of submodules via the :submodule-detection-function project option and the patcher-detect-submodules function. Currently supported RCS submodules are Mercurial and Git via the functions 'patcher-hg-detect-submodules.
  • Support ephemeral ChangeLogs thanks to a new :change-logs-status project option. Ephemeral ChangeLogs are not stored in ChangeLog files, but exist only temporarily for mail or log message insertion (See ChangeLogs Status in the documentation).
  • ChangeLog minor mode providing easy navigation through the mail/ChangeLog buffers cycle via C-c C-p n, C-c C-p p, C-c C-p N, C-c C-p P and C-c C-p m (See ChangeLogs Navigation in the documentation).
  • Support for switching to mail buffer and inserting ChangeLogs at once via C-c C-p l from ChangeLog buffers.
  • patcher-mail-insert-change-logs gets a prefix argument allowing to temporarily change the ChangeLogs appearance. It also supports inserting ChangeLogs even when the project is set not to.
  • Additional binding for patcher-logmsg-commit: C-c C-p c
  • Commit command buffer is now editable Commit is done via C-c C-p c or C-c C-c (patcher-cmtcmd-commit).
  • Fontification of commit command and log message buffers with comment syntax and initial informative help. See new Patcher faces.
  • Support for commit or log message canceling via C-c C-z.
  • Support for project abortion via C-c C-p k or C-c C-k in all relevant buffers, including ChangeLogs.
  • Support Subject: header modification in mail adaptation routines via a new project option :subject-rewrite-format.
  • Support project-wide dynamic subject modification via C-c C-p S in both mail and log message buffers.
  • Implement :kill-source-files-after-sending project option
  • Support for source file saving
  • Support for CVS diff's broken exit code policy via a new project option: :ignore-diff-status.

FIXES AND IMPROVEMENTS

  • Improved support for temporary subprojects making them behave like permanent ones (with a specific subdirectory and set of files).
  • Much better error handling including exit code checking for external processes.
  • Improved support for overlapping Patcher instances through buffer and file referencing for both ChangeLog and source files.
  • Documentation rewrite and sections organization cleanup
  • More checks for project consistency including missing or spurious ChangeLog entries, source diffs, undiffable and uncommittable projects etc.
  • Improved project rediffing including support for partially generated ChangeLog skeletons, and interactive prompting for skeleton un/re-generation.

BACKWARD INCOMPATIBLE CHANGES

  • Mercurial themes renamed from 'mercurial to 'hg in order to remain consistent with the other RCS theme names.
  • ChangeLogs insertion in mail buffers rebound to C-c C-p l
  • Compressed ChangeLogs insertion in logmsg buffers rebound to C-c C-p L
  • Removed directory-sep-char hacks until the need for it raises again. Probably better implemented via project options anyway.
  • Diff commands can no longer be changed from patcher-mail-adapt but instead, the prefix argument allows for temporary subproject specification.
  • patcher-*-subproject entry points removed since they are no longer needed (see above).
  • Removed :kill-source-file-after-diffing option
  • :kill-source-files-after-sending renamed to :kill-sources-after-sending
  • patcher-mail-check-change-logs-insertion is now a project option named :check-change-logs-insertion.
  • patcher-mail-check-commit-action is now a project option named :check-commit.
  • :change-logs-diff-command option now understands nil instead of 'diff
  • The 'packed ChangeLogs appearance has been renamed to 'pack

Tuesday, December 27 2011

XEmacs now has a "foreback" face property

The "foreback" face property at workHere's another new face property in XEmacs. This one is probably not going to be used ever, but still it fixes one particular problem. Until now, XEmacs used the background and foreground colors to display a face background bitmap (as opposed to a regular pixmap). This basically rendered the text unreadable.

The new face property is called "foreback" (I'm running short of sensible property names these days). It's the "foreground of the background" if you will. When a face has a background bitmap, it uses the regular background color for bitmap's background, but the foreback color for the bitmap's foreground. See the attached screenshot for a concrete example of the problem it fixes.

The bitmap I used for this example is X11's xsnow bitmap. Nice Christmas XEmacs screenshot, isn't it? :-)

In order to set a face's foreback color, either use the Custom interface, or the set-face-foreback function.

Thursday, December 22 2011

XEmacs now has a "flush" face property

The "flush" face property at workI have just implemented a new face property in XEmacs 21.5, called "flush". When some text is displayed in a face which has this property set to t (it's a Boolean property), then the face extends until the right border of the window instead of just the end of the actual line of text. The effect is only visible if the face has a non-default background color or pixmap and gives the text segment the appearance of a block instead of being ragged right. In fact (if that rings a bell to you), this is the equivalent of the block value for the HTML display property.

See the attached screenshot for an example. In that particular case, the buffer displays an article in Gnus and the concerned face is mm-uu-extract. You can see two versions of the same buffer, with and without the property set. There are a number of situations in which setting a face to flush is nicer visually. Probably the most obvious case is that of text selection. Below is a list of faces that I'm currently setting to flush. I'll be updating this list as needed. In order to set a face to flush, either use the Custom interface or the set-face-flush-p function directly.

zmacs-region
diff-nonexistent-face
gnus-summary-cancelled[-face]
mm-uu-extract
mmm-default-submode-face
mmm-code-submode-face

Wednesday, July 20 2011

One more indentation hack

Here's yet another indentation hack that I came up with recently.

All the work done by Nikodemus on the Slime indentation contrib is pretty cool, especially the notion of indentation style (though I wish the styles were Custom variables, but that is another story). I tend to use indentation styles for global, maybe collaborative preferences, but on several occasions however, I find that this approach has a couple of drawbacks.

  • One of them is that the indentation information is far away from the corresponding symbol, in a separate file. If you change a function's prototype for instance, you may also need to load the file(s) in which the corresponding style(s) is (are) defined and edit them.
  • The other problem is that if you want to let other people edit your source code and honor your indentation style, you also need to provide them with the style definition, and they need to load it separately.

For those reasons, I tend to think that the indentation style approach is not very well suited for project-specific indentation settings. What I would like is to provide indentation information close to the function definition, and also to have that information automatically available when anyone loads the project into Slime. Here's a way to do it.

The key to success here is the function swank:eval-in-emacs which, as its name suggests, sends some Emacs Lisp code to your (X)Emacs session for evaluation. This function effectively allows you to trigger some Emacs Lisp computation from a Common Lisp file. Remember that indentation information is stored in the common-lisp-indent-function property of a symbol. The function clindent below does this:

(defun clindent (symbol indent)
  "Set SYMBOL's indentation to INDENT in (X)Emacs.
This function sets SYMBOL's common-lisp-indent-function property.
If INDENT is a symbol, use its indentation definition.
Otherwise, INDENT is considered as an indentation definition."
  (when (and (member :swank *features*)
	     (let ((configuration
		     (find-symbol "MY.PACKAGE.CONFIGURATION" :cl-user)))
	       (when (and configuration (boundp configuration))
		 (getf (symbol-value configuration) :swank-eval-in-emacs))))
    (funcall (intern "EVAL-IN-EMACS" :swank)
	     `(put ',symbol 'common-lisp-indent-function
		   ,(if (symbolp indent)
			`(get ',indent 'common-lisp-indent-function)
		      `',indent))
	     t)))

As explained in the docstring, this function will ask (X)Emacs to put SYMBOL's common-lisp-indent-function property to a definition, either provided directly, or retrieved from another symbol. For example, if your package defines an econd macro, you may want to call it like this:

(clindent 'econd 'cond)

This function ensures that Swank is actually available before using it (first condition in the and clause). I will explain the other weird bits later on.

The next question is when exactly do we want to call this function? The answer is: pretty much on all occasions. Your code might be loaded from source and interpreted, or it might be compiled. But then, it might be compiled within or outside a Slime environment. In any case, you want your indentation information to be sent to (X)Emacs everytime it's possible. So obviously, we're gonna wrap this function in an eval-when form thanks to a macro. This is also a good opportunity to save some quoting.

(defmacro defindent (symbol indent)
  "Set SYMBOL's indentation to INDENT in (X)Emacs.
SYMBOL and INDENT need not be quoted.
See CLINDENT for more information."
  `(eval-when (:compile-toplevel :execute :load-toplevel)
     (clindent ',symbol ',indent)))

And now, right on top of your econd definition, you can just say this:

(defindent econd cond)

Now here's one final step. If your package uses its own readtable, it's even more convenient to define a reader-macro for indentation information. I choose #i:

(defun i-reader (stream subchar arg)
  "Read an argument list for the DEFINDENT macro."
  (declare (ignore subchar arg))
  (cons 'defindent (read stream)))
 
(set-dispatch-macro-character #\# #\i #'i-reader *readtable*)

And now, the code in my package will look like this:

#i(econd cond)
(defmacro econd #|...|#)

Pretty cool, eh?

All right. We still have two weirdos to explain in the clindent function.

First, you noticed that the function's computation is conditionalized on the existence of a cl-user::my.package.configuration variable, which actually stores a property list of various compiling or loading options for this package. The option we're interested in is :swank-eval-in-emacs, which must be set to non-nil. Here's why. The execution of Emacs Lisp code from Swank is (rightfully) considered as a security risk so it is disabled by default. If you want to authorize that, you need to set the (Emacs) variable slime-enable-evaluate-in-emacs to t. Otherwise, calling swank:evaluate-in-emacs is like calling 911. So we have a chicken-and-egg problem here: if we want to avoid an error in clindent, we would need to check the value of this variable, but in order to do that, we would need to evaluate something in (X)Emacs ;-)

The solution I choose is hence to disable the functionality by default, and document the fact that if people want to use my indentation information, they need to set both the Slime variable and my package-specific option to non-nil before loading the package (possibly setting them back to nil afterwards). They also need to trust that I'm not going to inject anything suspicious into their (X)Emacs session at the same time...

The last bit we need to explain is the final t argument passed to swank:eval-in-emacs. The corresponding parameter is called nowait in the function's prototype. It has something to do with asynchronous computation, and in fact, I don't really know what's going on under the hood, but what I do know is that if you set it to t, Swank doesn't care about the return value of your form anymore, which is fine because we're only doing a side effect. On the other hand, if you omit that parameter, Swank will try to interpret the return value in some way, and you will most probably get a serialization error. Indeed, the return value is the indentation definition itself, so for example, (&rest (&whole 2 &rest 1)) doesn't make (Common Lisp) sense.

That's it. Happy indenting!

Wednesday, April 27 2011

XEmacs 21.5.30 "garlic" is released

At long last, there is a new release of XEmacs 21.5. A lot of stuff has happened in this release, but the most important thing is that this is the last GPLv2 version of XEmacs. Future versions (including the current trunk) will be licensed GPLv3 or later. In fact, the first GPLv3 release, 21.5.31, is expected to follow this one by a couple of days. Thanks mostly to Aidan Kehoe, I'm also quite happy that XEmacs Lisp is more Common Lisp'y than ever.

Monday, May 10 2010

ELS 2010 paper now available

My paper entitled "CLoX: Common Lisp Objects for XEmacs", presented at the 3rd European Lisp Symposium last week, is now available for download on my website.

You can find it here.

Tuesday, March 9 2010

Paper accepted at ELS 2010

I'm happy to announce that I will be presenting a paper at ELS 2010, the next European Lisp Symposium, in Lisbon. The abstract is given below:


CloX: Common Lisp Objects for XEmacs

CloX is an ongoing attempt to provide a full Emacs Lisp implementation of the Common Lisp Object System, including its underlying meta-object protocol, for XEmacs. This paper describes the early development stages of this project. CloX currently consists in a port of Closette to Emacs Lisp, with some additional features, most notably, a deeper integration between types and classes and a comprehensive test suite. All these aspects are described in the paper, and we also provide a feature comparison with an alternative project called EIEIO.

Thursday, February 25 2010

Translucent XEmacs coming in hot !!

I'm uploading a set of changes to the XEmacs 21.5 Mercurial repository right now. These changes implement a new face property named "background-placement" which makes an XEmacs frame "slide" over a face's background pixmap when the property is set to 'absolute.

If you do this on the default face, then you can achieve some sort of pseudo-translucency, for example by using the same (or a darkened version of) the root window's background pixmap.

Here are a couple of screenshots that illustrate this.

 


Monday, February 15 2010

RT for Emacs Lisp, version 1.0

I'm happy to announce the first public version of RT for Emacs Lisp, a port of the original Common Lisp regression testing package.

Grab it here.

Tuesday, July 1 2008

CCL Objective C bridge code indentation

A whole bunch of CCL Cocoa coding involves calls to ObjC methods. For instance, the following ObjC code:
[cell drawWithFrame: frame inView: view];
will translate into this in CLL:
(#/drawWithFrame:inView: cell frame view)
. Indeed, Objective C is designed around the record-based model (methods belong to classes), so the cell object receives the drawWithFrame:inView: message via the funny bracket syntax. On the other hand, the Lisp translation involves a generic function call with the usual funcall syntax. The dispatch occurs on the first argument (the cell), and the rest is actual arguments to the message.

This layout is obviously not optimal for readability. One could define a bracket reader-macro to simulate ObjC's message passing syntax in Lisp, but I prefer to stick to the "Lisp Way". The first argument should still be considered "special" though.

For readability (especially when the method name is long), I like to put the arguments to the message (not the receiver!) on subsequent lines. However, XEmacs's cl-indent-function will indent this as an ordinary function call, like this:
(#/drawWithFrame:inView: cell
frame view
which is awfull. What I want is the following indentation:
(#/drawWithFrame:inView: cell
frame view
This kind of indentation is normally achieved by putting a common-lisp-indent-function property of 1 on the function symbol. However, you don't want to do that on all possible ObjC message by hand (and you don't know them all in advance anyway). The following advice on common-lisp-indent-function (from the cl-indent package does the trick. It dynamically puts the property on each relevant symbol every time it is subject to indentation. A bit brute force, but it works smoothly.
(defadvice common-lisp-indent-function (before ccl-objc-bridge activate)
"Improve indentation scheme of the CCL Objective-C bridge.
Currently, this does the following:

- All (#/doThis:withThat: ...) forms are indented as per a
lisp-indent-function property of 1. This effectively treats the first argument
(an object or a class) as special. The indentation you get is:

(#/function arg1 instead of: (#/function arg1
arg2 ...) arg2 ...)"
(let ((containing-form-start (elt state 1)))
(save-excursion
(goto-char containing-form-start)
(forward-char 1)
(cond ((looking-at "#/\\(\\w\\|:\\)*:")
;; We're looking at a (#/doThis:withThat: ...) form. In its holy
;; brokenness, common-lisp-indent-function with the help of
;; parse-partial-sexp will consider that the function name in
;; this form is "/functioncall:". Our trick here is to
;; dynamically put a lisp-indent-function property of 1 on this
;; symbol, so that the subsequent (original) indenting function
;; will handle it.
(let* ((beg (progn (forward-char 1) (point)))
(sym (progn
(forward-sexp 1)
(intern (downcase (buffer-substring beg
(point)))))))
(put sym 'common-lisp-indent-function 1)))))))

One last thing and I'll be happy: I want to indent CCL's slet and slet* constructs just as let:
(put 'slet 'common-lisp-indent-function 
'((&whole 4 &rest (&whole 1 1 2)) &body))
(put 'slet* 'common-lisp-indent-function
'((&whole 4 &rest (&whole 1 1 2)) &body))

Et voilà !

Wednesday, February 27 2008

Patcher 3.10 is released

I'm happy to announce the release of Patcher 3.10. Patcher is an XEmacs package for automating the maintenance of version control system based projects. Patcher is the official tool for XEmacs development.

What's new in this version:

** New feature: provide built-in themes for some revision control systems
These are PRCS, CVS, Subversion, Darcs and Mercurial. Also coming with
whitespace-resistant counterparts.
** Documentation: a chapter on how to setup Patcher for XEmacs development
** Bugfixes:
*** Cleanup the log messages wrt trailing whitespaces
*** Correctly display a missing theme name in error message
French Flag English Flag
Copyright (C) 2008 -- 2013 Didier Verna didier@lrde.epita.fr