I have a nasty habit of writing macros with multiple keyword clauses in them--like this:
(deffoo foo (stuff) (:bar (a b) (cons a b)) (:zot (a b c) (fii a b c)) (:default 42) (:error (crap)))
which of course tend to indent terribly
(deffoo foo (stuff) (:bar (a b) (cons a b)) (:zot (a b c) (fii a b c)) (:default 42) (:error (crap)))
I've occasionally added special indentation rules for these things in .emacs, but that's no fun at all. I've also sometimes used non-keyword symbols and added global definitions which tell slime how to indent things:
(defmacro bar (lambda-list &body body) (error "oops, not in DEFFOO"))
None of these is really satisfactory: hacking .emacs means users of a library that has macros with this style don't get the correct indentation in Slime out of the box. Using non-keyword symbols makes the code harder to read. (Keywords make it obvious that those are clauses or options of some sort.)
Can someone suggest something better?
Cheers,
-- Nikodemus
* Nikodemus Siivola: Wrote on Wed, 30 Mar 2011 16:08:46 +0300:
| I have a nasty habit of writing macros with multiple keyword clauses | in them--like this: | | (deffoo foo (stuff) | (:bar (a b) | (cons a b)) | (:zot (a b c) | (fii a b c)) | (:default | 42) | (:error | (crap))) | | which of course tend to indent terribly | | (deffoo foo (stuff) | (:bar (a b) | (cons a b)) | (:zot (a b c) | (fii a b c)) | (:default | 42) | (:error | (crap)))
With Emacs you could try the appended Kludge (incomplete), which would then indent it as:
(deffoo foo (stuff) (:bar (a b) (cons a b)) (:zot (a b c) (fii a b c)) (:default 42) (:error (crap)))
--- cl-indent.el.orig 2011-01-28 21:36:00.000000000 +0530 +++ cl-indent.el 2011-03-30 21:33:07.000000000 +0530 @@ -253,6 +253,7 @@ (setq tem (intern-soft function) method (get tem 'common-lisp-indent-function)) (cond ((and (null method) + (not (string-match "^:" function)) (string-match ":[^:]+" function)) ;; The pleblisp package feature (setq function (substring function @@ -297,6 +298,7 @@ (setq method lisp-indent-defun-method)))
(cond ((and (or (eq (char-after (1- containing-sexp)) ?') + (eq (char-after (1+ containing-sexp)) ?:) (and (not lisp-backquote-indentation) (eq (char-after (1- containing-sexp)) ?`))) (not (eq (char-after (- containing-sexp 2)) ?#)))
On 30 March 2011 19:22, Madhu enometh@meer.net wrote:
With Emacs you could try the appended Kludge (incomplete), which would
--- cl-indent.el.orig 2011-01-28 21:36:00.000000000 +0530 +++ cl-indent.el 2011-03-30 21:33:07.000000000 +0530
Actually this gets me
(deffoo foo (stuff) (:bar (a b) (cons a b)) (:zot (a b c) (fii a b c)) (:default 42) (:error (crap)))
which /is/ better, but not I'm looking for. More importantly, it doesn't help anyone else.
The question isn't how to do this for myself -- I can put
(setf (get ':bar 'common-lisp-indent-function) '1) (setf (get ':zot 'common-lisp-indent-function) '1) (setf (get ':default 'common-lisp-indent-function) '0) (setf (get ':error 'common-lisp-indent-function) '0)
in my .emacs. The question is how to make it automatically right for everyone. If I write a library that provides a DEFFOO like this, I would like it to be correctly indented for all Slime users.
Cheers,
-- Nikodemus
On Wed, Mar 30, 2011 at 2:33 PM, Nikodemus Siivola nikodemus@random-state.net wrote:
The question is how to make it automatically right for everyone. If I write a library that provides a DEFFOO like this, I would like it to be correctly indented for all Slime users.
Isn't indentation is a matter of personal preference? That's why the methods for controlling indentation are user-dependent.
-- Scott
Isn't indentation is a matter of personal preference? That's why the methods for controlling indentation are user-dependent.
Kind of, but on a team of people working on a single project with requirements for all to adhere to the same indentation scheme, this falls down. This scenario is common and desirable.
This information would ideally be encoded in the project's lisp side and communicated to emacs via slime.
I believe the mechanism for swank to communicate indentation already exists as this is how the macros are properly indented and would only need to be broken out if it is not already.
On 30 March 2011 22:17, Scott Turner srt19170@gmail.com wrote:
Isn't indentation is a matter of personal preference? That's why the methods for controlling indentation are user-dependent.
Sure, but there's "obviously wrong" and "wrong for me" -- and I claim that the way DEFFOO currently gets indented is obviously wrong.
The dummy DEFMACRO solution I alluded to earlier gets things right, but loses the clarity of the keywords -- maybe that's the price I have to pay.
Telling Slime that :BAR should be indented like a LAMBDA gives the right result in this case, but wrong in all other uses of :BAR -- whereas for MYPACKAGE:BAR that's much less of an issue.
I guess I'm really wondering if I should hack up SWANK:DEFINE-INDENTATION, or if something along those lines already exists somewhere.
Cheers,
-- Nikodemus
* Nikodemus Siivola [2011-03-30 20:24] writes:
I guess I'm really wondering if I should hack up SWANK:DEFINE-INDENTATION, or if something along those lines already exists somewhere.
How's that different from putting it in your .emacs? It will only help SLIME users and leave Vi or Hemlock users out in the dark.
Helmut
On 31 March 2011 00:57, Helmut Eller heller@common-lisp.net wrote:
I guess I'm really wondering if I should hack up SWANK:DEFINE-INDENTATION, or if something along those lines already exists somewhere.
How's that different from putting it in your .emacs? It will only help SLIME users and leave Vi or Hemlock users out in the dark.
All intersection(Slime users,DEFFOO users) benefit, as opposed to just me? I care less about how Vi and Hemlock users indent their code?
But, having been reminded of Tobias' Editor Hints project, I can be nicer and promise to use as portable and generally useful facilities as are available. :)
Cheers,
-- Nikodemus
"Nikodemus" == Nikodemus Siivola nikodemus@random-state.net writes:
Nikodemus> The question isn't how to do this for myself -- I can Nikodemus> put
Nikodemus> (setf (get ':bar 'common-lisp-indent-function) '1) Nikodemus> (setf (get ':zot 'common-lisp-indent-function) '1) Nikodemus> (setf (get ':default 'common-lisp-indent-function) '0) Nikodemus> (setf (get ':error 'common-lisp-indent-function) '0)
Nikodemus> in my .emacs. The question is how to make it Nikodemus> automatically right for everyone. If I write a library Nikodemus> that provides a DEFFOO like this, I would like it to be Nikodemus> correctly indented for all Slime users.
Isn't the emacs answer to this is to use the file local variables at the end of the file to set set this the way you want? Then every one editing the file will get the indentation that you want, if he chooses to accept the settings in the file local variables.
I used to do this at work to get the C indentation style set correctly for our C code.
Ray
Nikodemus Siivola nikodemus@random-state.net writes:
On 30 March 2011 19:22, Madhu enometh@meer.net wrote:
With Emacs you could try the appended Kludge (incomplete), which would
--- cl-indent.el.orig 2011-01-28 21:36:00.000000000 +0530 +++ cl-indent.el 2011-03-30 21:33:07.000000000 +0530
Actually this gets me
(deffoo foo (stuff) (:bar (a b) (cons a b)) (:zot (a b c) (fii a b c)) (:default 42) (:error (crap)))
which /is/ better, but not I'm looking for. More importantly, it doesn't help anyone else.
The question isn't how to do this for myself -- I can put
(setf (get ':bar 'common-lisp-indent-function) '1) (setf (get ':zot 'common-lisp-indent-function) '1) (setf (get ':default 'common-lisp-indent-function) '0) (setf (get ':error 'common-lisp-indent-function) '0)
in my .emacs. The question is how to make it automatically right for everyone. If I write a library that provides a DEFFOO like this, I would like it to be correctly indented for all Slime users.
Use Common Lisp. Put in the source file:
(cl:declaim (cl:declaration cl-user::indentation)) (cl:declaim (cl-user::indentation (:bar 1) (:zot 1) (:default 0) (:error 0)))
and have slime parse it.
I use this technique to declare package dependencies in addition to what's specified in defpackage (ie. qualified symbols, and dynamic INTERN). Then my make-depend script can parse it easily, to generate the ASD file.
So, turns out that slime-indentation contrib has the hooks for just what I needed.
...only the code had a bit of bitrot in it, as intentation specs with symbols in them ended up having strings on the Emacs side. I just committed a fix for that, so what now I can do eg:
(defvar *indentation-hint-table* nil)
(defun hint-slime-indentation () (let* ((swank (find-package :swank)) (tables (when swank (find-symbol (string '#:*application-hints-tables*) swank)))) (when tables (let ((table (make-hash-table :test #'eq))) (setf (gethash 'defrule table) '(4 &lambda &rest (&whole 2 &lambda &body))) (set tables (cons table (remove *indentation-hint-table* (symbol-value tables)))) (setf *indentation-hint-table* table)) t)))
(hint-slime-indentation)
on the CL side to tell Slime how to indent things it's regular heuristics don't get right.
Cheers,
-- Nikodemus