February 19, 2002
Living in emacs

For the past year I've been doing 100% of my lisp programming inside emacs. Since it took me some time and effort to customize emacs for that task, and the payoff was significant, I figured I would share the stuff in my .emacs that makes me more productive. I'm no elisp hacker; I accumulated all of this code from people who know more than I did. Now I'm just passing it on.

This is what I have in my .emacs on my Windows PC, where I use ACL and GNU emacs for Windows with Franz' emacs-lisp interface. (I use ilisp under Linux with cmucl sometimes, but I barely know how to use it. You should be helping me.)

Initialization

Big deal, everyone has this.

(load "c:/program files/acl61/eli/fi-site-init")
(setq fi:common-lisp-image-name "c:/program files/acl61/alisp")

HyperSpec Access

Press a key while the cursor is on a Common Lisp function, macro, variable, constant or special operator, and instantly see the official documentation of the symbol in the HyperSpec. You need this.

There are several different HyperSpec lookup interfaces for emacs (the ilisp distribution has all the major ones). I just happen to use hyperspec-naggum.el because it's the one I know. Whichever you choose, just put it in your emacs site-lisp directory.

So that I don't need to have net access while coding, I downloaded and installed a local copy of the Hyperspec from Xanalys (see the link at the bottom of the page to download). You can put it anywhere you want on your machine, you just have to set the common-lisp-hyperspec-root variable to point to it.

I had to install a small helper application called shelex.exe so that emacs could open URLs on my PC. For emacs 20.4 and later you shouldn't need to, but check the emacs for Windows FAQ for details.

Finally, I bind the F1 key to hyperspec-lookup in both the lisp listener and lisp editing buffers.

;; Look up Common Lisp symbols in the Hyperspec.
(load-library "hyperspec-naggum")
(setq common-lisp-hyperspec-root "file://c:/HyperSpec/")


;; From the GNU Emacs for NT homepage
;; <http://www.cs.washington.edu/homes/voelker/ntemacs.html#browse-url>

(defvar shell-execute-helper "shelex.exe")

(defun shell-execute-url (url &optional new-window)
  "Invoke the shell-execute-helper program to call ShellExecute
   and launch or re-direct a web browser on the specified url."
  (interactive "sURL: ")
  (call-process shell-execute-helper nil nil nil url))
(setq browse-url-browser-function 'shell-execute-url)


;; Add F1 to do a hyperspec lookup.

(add-hook 'fi:lisp-listener-mode-hook
  (function
   (lambda ()
     (local-set-key [f1]     'hyperspec-lookup))))

(add-hook 'fi:common-lisp-mode-hook
  (function (lambda ()
	      (local-set-key [f1] 'hyperspec-lookup))))

Indentation

I don't like the way that emacs indents if expressions, with the then clause indented more than the else clause. I want them indented the same distance, which is how the FRED editor in MCL does it, and the way I am used to. Erik Naggum helped me get this right.

I spend a lot of time editing RAPs code, which is an s-expr based language, so I put emacs into lisp mode when I edit a *.raps file, and I also customize the indentation of some RAP forms a little bit.

;; Indent IF the way MCL does it.
;; From Erik Naggum, see <http://x23.deja.com/getdoc.xp?AN=495562135>

(put 'if 'lisp-indent-function 1)
(put 'if 'fi:lisp-indent-hook 1)


;; From Jim Firby, for indenting RAPs.

(setq auto-mode-alist
  (cons '("\\.raps" . common-lisp-mode)
	auto-mode-alist))

(put 'define-rap 'lisp-indent-function 1)
(put 'define-rap 'fi:lisp-indent-hook 1)
(put 'define-primitive-event 'lisp-indent-function 1)
(put 'define-primitive-event 'fi:lisp-indent-hook 1)
(put 'define-rap-function 'lisp-indent-function 1)
(put 'define-rap-function 'fi:lisp-indent-hook 1)

(put 'define-memory-rule 'lisp-indent-function 1)
(put 'define-memory-rule 'fi:lisp-indent-hook 1)

Syntax coloring

My old co-worker from Neodesic, Jim Bullard, shared this code to turn on maximum syntax highlighting. Don't worry, it's not very maximum.

;; From Jim Bullard, for automatically fontifying Java buffers
;; (and others).

(cond ((fboundp 'global-font-lock-mode)
       (global-font-lock-mode t)
       (setq font-lock-maximum-decoration t)))

Arglist Information

This is the most obscure, and second most useful (after hyperspec access) emacs customization I have.

MCL and ilisp both display function argument lists in the editor minibuffer when you type a function call followed by a space, e.g., "(print ". It's incredibly handy. Unfortunately, Franz' emacs-lisp interface doesn't include this functionality.

Luckily I ran across some code written by Simon Andras, called elidoc, that adds this to eli. The only place that I know it is available is in the archive of the ACL mailing list. Download it from ftp://ftp.franz.com/pub/misc/allegro-cl-log, and search the 3.5 MB file for "elidoc". The first message you find will be Andras' from February 2000. Extract the elisp code from his message and save it in a file named elidoc.el in your site-lisp directory.

(autoload 'turn-on-elidoc-mode "elidoc" nil t)
(add-hook 'fi:common-lisp-mode-hook 'turn-on-elidoc-mode)
(add-hook 'fi:inferior-common-lisp-mode-hook 'turn-on-elidoc-mode)
(add-hook 'fi:lisp-listener-mode-hook 'turn-on-elidoc-mode)

History Tweaking

Somewhere along the line I became used to using control-up arrow and control-down arrow to navigate through command histories. This bit of code makes that work in the lisp listener.

;; From Will Fitzgerald.  Makes C-up and C-down act like C-c C-p
;; and C-c C-n respectively, in a lisp interaction buffer.

(add-hook 'fi:lisp-listener-mode-hook
  (function
   (lambda ()
     (local-set-key [C-up]   'fi:pop-input)
     (local-set-key [C-down] 'fi:push-input))))

Which reminds me. ilisp would not aggravate me half as much if I could navigate through previous commands without moving the point, which is what fi:pop-input and fi:pop-output do. ilisp's comint-previous-prompt and comint-next-prompt suck in comparison. I'm probably missing something obvious.

Thats the stuff I use every day. I hope it helps.

Posted by jjwiseman at February 19, 2002 10:28 AM
Comments

I've looked, and now I am pretty sure that ilisp doesn't have popping and pushing of input.

Maybe that should be my first major emacs coding experience.

Posted by: jjwiseman on February 24, 2002 03:23 AM

Will mentioned that he likes (setq fi:lisp-electric-semicolon 'T).

Posted by: jjwiseman on February 25, 2002 12:04 PM

I'm using emacs-21.3 and ACL 6.2 and I've tried several solutions to change the if indentation but they don't work:
1.
(put 'if 'lisp-indent-function 1)
(put 'if 'fi:lisp-indent-hook 1)

2.
(add-hook 'lisp-mode-hook
(lambda ()
(set (make-local-variable lisp-indent-function)
'common-lisp-indent-function)))

any suggestion?

Posted by: Giannandrea on October 3, 2003 05:26 AM

How about (put 'if 'lisp-indent-function 3)? (This aligns both then and else forms at the same level.)

Posted by: jdz on October 9, 2003 01:00 AM

Also see the following post by Bill Clementson for getting arglist info in ELI:

http://groups.google.com/groups?selm=1b3ac8a3.0308090633.60de7b70%40posting.google.com

Posted by: John Wiseman on November 18, 2003 02:47 PM

I tested out the "History Tweaking" part of this and, at least on Xemacs, it seems not to work. The vector notation [c-up] is not acceptable to Xemacs.

I think '(control up) is the equivalent for Xemacs....

Posted by: Robert Goldman on November 24, 2003 02:51 PM

I think also that for history tweaking you want this on the fi:inferior-lisp-mode-hook, too. The lisp listener mode hook AFAICT is only run when you start up an ADDITIONAL lisp listener; not for the initial one, which is in inferior-lisp-mode....

Posted by: Robert Goldman on November 26, 2003 07:32 AM
Post a comment
Name:


Email Address:


URL:




Unless you answer this question, your comment will be classified as spam and will not be posted.
(I'll give you a hint: the answer is “lisp”.)

Comments:


Remember info?