Hi,
I'm editing Common Lisp in (X)Emacs and would like to modify
indentation for some constructs. I'm already using cl-indent, but that
does not seem to recognize e.g. loop. I would like to be able to write
(loop for i in 0 to 10 do
(loop for k in 0 to 3 do
instead of
(loop for i in 0 to 10 do
(loop for k in 0 to 3 do
After lurking around in cl-indent.el and lisp.el, I concluded that the
right way would be to modify the property list of
common-lisp-indent-function. I just can't figure out _how_, I haven't
found any documentation anywhere.
What is the right way to do this?
All help appreciated.
Thanks in advance.
Johan Parin
Ericsson AXE Research & Development
From: Johan Parin <······@uab.ericsson.se>
Newsgroups: comp.lang.lisp,comp.emacs.xemacs
Date: 03 Mar 1997 21:56:01 +0100
I'm editing Common Lisp in (X)Emacs and would like to modify
indentation for some constructs. I'm already using cl-indent, but that
does not seem to recognize e.g. loop. I would like to be able to write
(loop for i in 0 to 10 do
(loop for k in 0 to 3 do
instead of
(loop for i in 0 to 10 do
(loop for k in 0 to 3 do
After lurking around in cl-indent.el and lisp.el, I concluded that the
right way would be to modify the property list of
common-lisp-indent-function. I just can't figure out _how_, I haven't
found any documentation anywhere.
There isn't any documentation other than the code.
It isn't clear to me that any documentation would be clearer than the
code anyway; non-programmers shouldn't be messing with it.
What is the right way to do this?
(put 'loop 'common-lisp-indent-hook 'lisp-indent-loop)
(defun lisp-indent-loop (path state indent-point sexp-column normal-indent)
... your code here...)
I nearly got around to writing lisp-indent-loop in 1987, but ran out
of time or interest (I don't use loop) about 20% of the way through.
Look at lisp-indent-tagbody for some hints of how to start.
======================================================================
Addendum: just in case it does anybody any good, here's the GUARANTEED
NON-WORKING code (ie 20% finished, last touched in 1987) I found in in
an old directory.
;; LOOP indenter for use with CL-INDENT
(put 'loop 'common-lisp-indent-hook 'lisp-indent-loop)
(defun lisp-indent-loop (path state indent-point sexp-column normal-indent)
(let ((containing-form-start (elt state 1)))
(cond ((cdr path)
;; loop is only skin-deep
normal-indent)
((= (car path) 1)
;; can't tell yet
normal-indent)
((progn
(goto-char (1+ containing-form-start))
;; move over LOOP
(forward-sexp 1)
;; now looking at first elt of loop body
(parse-partial-sexp (point) indent-point 1 t)
(or (eobp)
(not (eql (char-syntax (following-char)) ?w))))
;; first elt is not a symbol -- this is boring loop
normal-indent)
(t
;; hairy case!
(let ((p (point))
(bound (progn (goto-char indent-point) (end-of-line)
(point))))
(goto-char p)
(catch 'exit
(list
(lisp-indent-loop-259 (current-column) bound)
containing-form-start)))))))
;; >>> side-effects previous-indent!!! <<<
(defun lisp-indent-loop-inhale-keyword (bound &optional indent)
(parse-partial-sexp (point) bound 0 t)
(let ((start (point))
(end (progn (forward-sexp 1) (point))))
(cond ((and (not (eobp))
(eql (char-syntax (char-after start)) ?w))
(let ((tem (intern-soft (buffer-substring start end))))
; (message "inhaled %s" tem) (sit-for 1)
(and tem
(progn (goto-char start)
(skip-chars-backward " \t")
(bolp))
(progn
(goto-char start)
; (debug "previous-indent now %d %s" (current-column) tem) (sit-for 1)
(setq previous-indent (current-column))))
(parse-partial-sexp end bound 0 t)
tem))
((or (eobp) (> (point) bound))
(debug nil "Must throw ..." (or indent (+ previous-indent 2)))
(throw 'exit (or indent (+ previous-indent 2))))
(t
(parse-partial-sexp end bound 0 t)
nil))))
(defun lisp-indent-loop-peek-keyword (name bound &optional indent)
(let* ((p (point))
(sym (lisp-indent-loop-inhale-keyword bound indent)))
(if (eq sym name)
t
(progn
(goto-char p)
nil))))
;; Here's what we should be doing:
;; If this is the first non-named/repear/with/for/as/and/while/until
;; clause, indent it 3 characters relative to the opening paren
;; If this
(defun lisp-indent-loop-259 (previous-indent bound)
(let ((initial t))
(while (< (point) bound)
(let ((sym (lisp-indent-loop-inhale-keyword
bound (if initial previous-indent (+ 2 previous-indent)))))
(cond ((and (eq initial 't)
(not (memq sym
'(named repeat
with for as
and while until))))
(setq initial 'first))
((eq initial 'first)
(setq initial nil)))
(if (eq sym 'and)
(setq sym (lisp-indent-loop-inhale-keyword bound)))
(cond ((memq sym '(named repeat
while until
initially finally
return
always never thereis))
(lisp-indent-loop-inhale-keyword bound))
((memq sym '(with for as))
;; skip variable
(lisp-indent-loop-inhale-keyword bound)
;; possibly a typespec
(setq sym (lisp-indent-loop-inhale-keyword bound))
(if (not (memq sym '(from downfrom upfrom
in on = first being)))
(progn
(setq sym (lisp-indent-loop-inhale-keyword bound))
(if (not (memq sym '(from downfrom upfrom
in on = first being)))
(throw 'exit (+ previous-indent 2)))))
;; inhale in/to/from/etc bound
(lisp-indent-loop-inhale-keyword bound)
(cond
;((eq sym 'and));>>>>>
((memq sym '(from downfrom upfrom))
(lisp-indent-loop-inhale-keyword bound)
(if (lisp-indent-loop-peek-keyword 'by bound)
(lisp-indent-loop-inhale-keyword bound)))
((memq sym '(in on))
(if (lisp-indent-loop-peek-keyword 'by bound)
(lisp-indent-inhale-keyword bound)))
((memq sym '(= first))
(if (lisp-indent-loop-peek-keyword 'then bound)
(lisp-indent-loop-inhale-keyword bound)))
(t ;(eq sym 'being)
;; can't tell.
(lisp-indent-loop-inhale-keyword bound)
(forward-line 1))))
((memq sym '(do doing))
(if initial (setq previous-indent (- previous-indent 3)))
(let ((previous-indent previous-indent))
(while (and (not (eobp))
(not (eql (char-syntax (following-char)) ?w)))
(message "Inhaling form") (sit-for 1)
(lisp-indent-loop-inhale-keyword
bound
(if (prog1 initial (setq initial nil))
previous-indent
(+ previous-indent 3))))))
((memq sym '(collect collecting
nconc nconcing append appending
count counting sum summing
maximize minimize))
(if initial (setq previous-indent (- previous-indent 3)))
(lisp-indent-inhale-loop-keyword bound)
(if (lisp-indent-loop-peek-keyword 'into bound)
(lisp-indent-loop-inhale-keyword bound)))
((memq sym '(if when unless))
(if initial (setq previous-indent (- previous-indent 3)))
;>>>>
)
)))
previous-indent))