* Common Lisp indentation improvements
@ 2011-05-06 19:07 Didier Verna
2011-05-13 19:28 ` Stefan Monnier
0 siblings, 1 reply; 6+ messages in thread
From: Didier Verna @ 2011-05-06 19:07 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1401 bytes --]
Hello,
I have just applied a patch to XEmacs'version of cl-indent.el which
improves the indentation of Common Lisp code. I'm attaching this patch
and a ChangeLog entry below in case you're interested. A detailed
description of the modifications is available in the following blog
entry:
http://www.didierverna.com/sciblog/index.php?post/2011/05/06/Common-Lisp-indentation-in-XEmacs
For further discussion, please Cc: me directly, as I'm not a subscriber
of emacs-devel@.
2011-05-06 Didier Verna <didier@xemacs.org>
Common Lisp indentation improvements on defmethod and
lambda-lists.
* cl-indent.el: Advertise the changes and remove obsolete TODO
entries.
* cl-indent.el (lisp-lambda-list-keyword-alignment):
* cl-indent.el (lisp-lambda-list-keyword-parameter-indentation):
* cl-indent.el (lisp-lambda-list-keyword-parameter-alignment): New
customizable user options.
* cl-indent.el (lisp-indent-defun-method): Improve docstring.
* cl-indent.el (extended-loop-p): Fix comment.
* cl-indent.el (lisp-indent-lambda-list-keywords-regexp): New
variable.
* cl-indent.el (lisp-indent-lambda-list): New function.
* cl-indent.el (lisp-indent-259): Use it.
* cl-indent.el (lisp-indent-defmethod): Support for more than one
method qualifier and properly indent methods lambda-lists.
* cl-indent.el: Provide a missing common-lisp-indent-function
property for defgeneric.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cl-indent.patch --]
[-- Type: text/x-patch, Size: 8004 bytes --]
--- cl-indent.el.old 2011-05-06 20:35:49.000000000 +0200
+++ cl-indent.el.new 2011-05-06 20:41:23.000000000 +0200
@@ -31,20 +31,6 @@
;;
;; (setq lisp-indent-function 'common-lisp-indent-function)
-;;>> TODO
-;; :foo
-;; bar
-;; :baz
-;; zap
-;; &key (like &body)??
-
-;; &rest 1 in lambda-lists doesn't work
-;; -- really want (foo bar
-;; baz)
-;; not (foo bar
-;; baz)
-;; Need something better than &rest for such cases
-
;;; Code:
(defgroup lisp-indent nil
@@ -101,9 +87,55 @@
:type 'integer
:group 'lisp-indent)
+(defcustom lisp-lambda-list-keyword-alignment nil
+ "Whether to vertically align lambda-list keywords together.
+If nil (the default), keyworded lambda-list parts are aligned
+with the initial mandatory arguments, like this:
+
+\(defun foo (arg1 arg2 &rest rest
+ &key key1 key2)
+ #|...|#)
+
+If non-nil, alignment is done with the first keyword
+\(or falls back to the previous case), as in:
+
+\(defun foo (arg1 arg2 &rest rest
+ &key key1 key2)
+ #|...|#)"
+ :type 'boolean
+ :group 'lisp-indent)
+
+(defcustom lisp-lambda-list-keyword-parameter-indentation 2
+ "Indentation of lambda list keyword parameters.
+See `lisp-lambda-list-keyword-parameter-alignment'
+for more information."
+ :type 'integer
+ :group 'lisp-indent)
+
+(defcustom lisp-lambda-list-keyword-parameter-alignment nil
+ "Whether to vertically align lambda-list keyword parameters together.
+If nil (the default), the parameters are aligned
+with their corresponding keyword, plus the value of
+`lisp-lambda-list-keyword-parameter-indentation', like this:
+
+\(defun foo (arg1 arg2 &key key1 key2
+ key3 key4)
+ #|...|#)
+
+If non-nil, alignment is done with the first parameter
+\(or falls back to the previous case), as in:
+
+\(defun foo (arg1 arg2 &key key1 key2
+ key3 key4)
+ #|...|#)"
+ :type 'boolean
+ :group 'lisp-indent)
+
\f
(defvar lisp-indent-defun-method '(4 &lambda &body)
- "Indentation for function with `common-lisp-indent-function' property `defun'.")
+ "Defun-like indentation method.
+This applies when the value of the `common-lisp-indent-function' property
+is set to `defun'.")
(defun extended-loop-p (loop-start)
@@ -217,8 +249,7 @@
(let ((depth 0)
;; Path describes the position of point in terms of
;; list-structure with respect to containing lists.
- ;; `foo' has a path of (0 4 1) in `((a b c (d foo) f) g)'
- ;; (Surely (0 3 1)?).
+ ;; `foo' has a path of (0 3 1) in `((a b c (d foo) f) g)'.
(path ())
;; set non-nil when somebody works out the indentation to use
calculated
@@ -381,10 +412,74 @@
;; Love those free variable references!!
lisp-indent-error-function 'common-lisp-indent-function m))
+
+;; Lambda-list indentation is now done in LISP-INDENT-LAMBDA-LIST.
+;; See also `lisp-lambda-list-keyword-alignment',
+;; `lisp-lambda-list-keyword-parameter-alignment' and
+;; `lisp-lambda-list-keyword-parameter-indentation' -- dvl
+
+(defvar lisp-indent-lambda-list-keywords-regexp
+ "&\\(\
+optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\
+\\)\\([ \t]\\|$\\)"
+ "Regular expression matching lambda-list keywords.")
+
+(defun lisp-indent-lambda-list
+ (indent-point sexp-column containing-form-start)
+ (let (limit)
+ (cond ((save-excursion
+ (goto-char indent-point)
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (setq limit (point))
+ (looking-at lisp-indent-lambda-list-keywords-regexp))
+ ;; We're facing a lambda-list keyword.
+ (if lisp-lambda-list-keyword-alignment
+ ;; Align to the first keyword if any, or to the beginning of
+ ;; the lambda-list.
+ (save-excursion
+ (goto-char containing-form-start)
+ (save-match-data
+ (if (re-search-forward
+ lisp-indent-lambda-list-keywords-regexp
+ limit t)
+ (progn
+ (goto-char (match-beginning 0))
+ (current-column))
+ (1+ sexp-column))))
+ ;; Align to the beginning of the lambda-list.
+ (1+ sexp-column)))
+ (t
+ ;; Otherwise, align to the first argument of the last lambda-list
+ ;; keyword, the keyword itself, or the beginning of the
+ ;; lambda-list.
+ (save-excursion
+ (goto-char indent-point)
+ (forward-line -1)
+ (end-of-line)
+ (save-match-data
+ (if (re-search-backward lisp-indent-lambda-list-keywords-regexp
+ containing-form-start t)
+ (let* ((keyword-posn
+ (progn
+ (goto-char (match-beginning 0))
+ (current-column)))
+ (indented-keyword-posn
+ (+ keyword-posn
+ lisp-lambda-list-keyword-parameter-indentation)))
+ (goto-char (match-end 0))
+ (skip-chars-forward " \t")
+ (if (eolp)
+ indented-keyword-posn
+ (if lisp-lambda-list-keyword-parameter-alignment
+ (current-column)
+ indented-keyword-posn)))
+ (1+ sexp-column))))))))
+
;; Blame the crufty control structure on dynamic scoping
;; -- not on me!
-(defun lisp-indent-259 (method path state indent-point
- sexp-column normal-indent)
+(defun lisp-indent-259
+ (method path state indent-point sexp-column normal-indent)
(catch 'exit
(let ((p path)
(containing-form-start (elt state 1))
@@ -452,8 +547,14 @@
(cond ((null p)
(list (+ sexp-column 4) containing-form-start))
((null (cdr p))
- (+ sexp-column 1))
- (t normal-indent))))
+ ;; Indentation within a lambda-list. -- dvl
+ (list (lisp-indent-lambda-list
+ indent-point
+ sexp-column
+ containing-form-start)
+ containing-form-start))
+ (t
+ normal-indent))))
((integerp tem)
(throw 'exit
(if (null p) ;not in subforms
@@ -523,19 +624,26 @@
path state indent-point sexp-column normal-indent)))
-(defun lisp-indent-defmethod (path state indent-point sexp-column
- normal-indent)
- "Indentation function defmethod."
- (lisp-indent-259 (if (and (>= (car path) 3)
- (null (cdr path))
- (save-excursion (goto-char (elt state 1))
- (forward-char 1)
- (forward-sexp 3)
- (backward-sexp)
- (looking-at ":\\|\\sw+")))
- '(4 4 (&whole 4 &rest 4) &body)
- (get 'defun 'common-lisp-indent-function))
- path state indent-point sexp-column normal-indent))
+;; LISP-INDENT-DEFMETHOD now supports the presence of more than one method
+;; qualifier and indents the method's lambda list properly. -- dvl
+(defun lisp-indent-defmethod
+ (path state indent-point sexp-column normal-indent)
+ (lisp-indent-259
+ (let ((nqual 0))
+ (if (and (>= (car path) 3)
+ (save-excursion
+ (beginning-of-defun)
+ (forward-char 1)
+ (forward-sexp 2)
+ (skip-chars-forward " \t\n")
+ (while (looking-at "\\sw\\|\\s_")
+ (incf nqual)
+ (forward-sexp)
+ (skip-chars-forward " \t\n"))
+ (> nqual 0)))
+ (append '(4) (make-list nqual 4) '(&lambda &body))
+ (get 'defun 'common-lisp-indent-function)))
+ path state indent-point sexp-column normal-indent))
(defun lisp-indent-function-lambda-hack (path state indent-point
@@ -577,6 +685,7 @@
(define-modify-macro (4 &lambda &body))
(defsetf (4 &lambda 4 &body))
(defun (4 &lambda &body))
+ (defgeneric (4 &lambda &body))
(define-setf-method . defun)
(define-setf-expander . defun)
(defmacro . defun)
[-- Attachment #3: Type: text/plain, Size: 153 bytes --]
--
Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Common Lisp indentation improvements
2011-05-06 19:07 Common Lisp indentation improvements Didier Verna
@ 2011-05-13 19:28 ` Stefan Monnier
2011-05-14 11:09 ` Didier Verna
0 siblings, 1 reply; 6+ messages in thread
From: Stefan Monnier @ 2011-05-13 19:28 UTC (permalink / raw)
To: Didier Verna; +Cc: emacs-devel
> I have just applied a patch to XEmacs'version of cl-indent.el which
> improves the indentation of Common Lisp code. I'm attaching this patch
> and a ChangeLog entry below in case you're interested. A detailed
> description of the modifications is available in the following blog
> entry:
Thank you very much. Installed on the trunk,
Stefan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Common Lisp indentation improvements
2011-05-13 19:28 ` Stefan Monnier
@ 2011-05-14 11:09 ` Didier Verna
2011-05-16 13:17 ` Stefan Monnier
0 siblings, 1 reply; 6+ messages in thread
From: Didier Verna @ 2011-05-14 11:09 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>> I have just applied a patch to XEmacs'version of cl-indent.el which
>> improves the indentation of Common Lisp code. I'm attaching this
>> patch and a ChangeLog entry below in case you're interested. A
>> detailed description of the modifications is available in the
>> following blog entry:
FWIW, you may also want to keep track of Nikodemus Siivola's fork of
Slime on github. We have done some more work on CL indentation and there
are a couple of neat things like proper indentation of LOOP's
(sub)clauses, destructuring lambda-lists etc.
--
Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Common Lisp indentation improvements
2011-05-14 11:09 ` Didier Verna
@ 2011-05-16 13:17 ` Stefan Monnier
2011-05-16 13:41 ` Nikodemus Siivola
2011-05-16 13:57 ` Didier Verna
0 siblings, 2 replies; 6+ messages in thread
From: Stefan Monnier @ 2011-05-16 13:17 UTC (permalink / raw)
To: Didier Verna; +Cc: emacs-devel
> FWIW, you may also want to keep track of Nikodemus Siivola's fork of
> Slime on github. We have done some more work on CL indentation and there
> are a couple of neat things like proper indentation of LOOP's
> (sub)clauses, destructuring lambda-lists etc.
I generally don't have the time and energy to track external code.
But if someone wants to do that and submit patches here for inclusion,
that'd be very welcome.
Stefan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Common Lisp indentation improvements
2011-05-16 13:17 ` Stefan Monnier
@ 2011-05-16 13:41 ` Nikodemus Siivola
2011-05-16 13:57 ` Didier Verna
1 sibling, 0 replies; 6+ messages in thread
From: Nikodemus Siivola @ 2011-05-16 13:41 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Didier Verna, emacs-devel
On 16 May 2011 16:17, Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>> FWIW, you may also want to keep track of Nikodemus Siivola's fork of
>> Slime on github. We have done some more work on CL indentation and there
>> are a couple of neat things like proper indentation of LOOP's
>> (sub)clauses, destructuring lambda-lists etc.
>
> I generally don't have the time and energy to track external code.
> But if someone wants to do that and submit patches here for inclusion,
> that'd be very welcome.
I intend to do that once the dust settles down properly -- and when I
have the time.
Cheers,
-- nikodemus
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Common Lisp indentation improvements
2011-05-16 13:17 ` Stefan Monnier
2011-05-16 13:41 ` Nikodemus Siivola
@ 2011-05-16 13:57 ` Didier Verna
1 sibling, 0 replies; 6+ messages in thread
From: Didier Verna @ 2011-05-16 13:57 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> I generally don't have the time and energy to track external code. But
> if someone wants to do that and submit patches here for inclusion,
> that'd be very welcome.
Fair enough. In the meantime, our joint work has been merged into
Slime (and I updated XEmacs as well). The consequence is that someone
can look into Slime's contrib directory and simply grab the file named
slime-cl-indent.el (no copyright problem; I've signed the papers 10
years ago).
--
Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-05-16 13:57 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-06 19:07 Common Lisp indentation improvements Didier Verna
2011-05-13 19:28 ` Stefan Monnier
2011-05-14 11:09 ` Didier Verna
2011-05-16 13:17 ` Stefan Monnier
2011-05-16 13:41 ` Nikodemus Siivola
2011-05-16 13:57 ` Didier Verna
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).