Dear Slimers,
Well, it hadda happen, I started using SLIME in earnest, as a full-blown replacement to ILISP. Of course, this immediately lead to annoyance at the many missing features.
Now, it turns out that many of these missing features are really just editing conveniences, and don't have a lot (anything?) to do with emacs<-->lisp communication, so I thought I'd ask: what is the avowed policy of this project with regards to borrowing¹ the missing features of ilisp? I'm thinking in particular of all the buffer-movement, narrow-to-X and reindentation commands, for a start. It seems silly to rewrite all this, given that it all works. All that would be needed is some poor schmuck² to import only the strict minimum, track down all the dependencies, and hook in the keybindings, taking care not to trounce too much exising ones without reason or debate.
Opinions?
¹ Ok, maybe the subject line is more accurate than this euphemism. ² Yeah, I know. Probably _me_.
p.s. Is it "slimers" or "slimeys"? :-)
Alain.Picard@memetrics.com writes:
Dear Slimers,
Well, it hadda happen, I started using SLIME in earnest, as a full-blown replacement to ILISP. Of course, this immediately lead to annoyance at the many missing features.
I must have been an ILISP caveman -- we already have more features than I ever learned to use in ILISP. It's good to have you more discerning users around to teach us about the rest :-)
what is the avowed policy of this project with regards to borrowing¹ the missing features of ilisp?
If the code is good then let's use it. If it could be done better, let's rewrite it.
Everything in SLIME gets rewritten a few times anyway. :-)
I'm thinking in particular of all the buffer-movement, narrow-to-X and reindentation commands, for a start.
Which the buffer-movement commands do you mean?
It looks like the `narrow-to-X' commands come from lisp-mode in Emacs and we only need to bind them to keys. Reindentation is mostly the same AFAICS. I could be missing something though.
It seems silly to rewrite all this, given that it all works. All that would be needed is some poor schmuck² to import only the strict minimum
The whole plan sounds good to me. But I predict the final result will be 1-2 pages of totally new code :-)
p.s. Is it "slimers" or "slimeys"? :-)
Either suits me, nor would I object to "slimesters" :-)
Cheers, Luke
Luke Gorrie luke@bluetail.com writes:
It looks like the `narrow-to-X' commands come from lisp-mode in Emacs and we only need to bind them to keys.
Actually, I must be an Emacs caveman, since the narrowing commands I meant are on global bindings (C-x n ...).
Luke Gorrie writes:
I'm thinking in particular of all the buffer-movement, narrow-to-X and reindentation commands, for a start.
Which the buffer-movement commands do you mean?
I think you're right, after doing a bit more investigation. The first one I hit which really annoyed me was M-q which did not reindent the top level form properly (in SLIME). So I looked in ILISP, and M-q was bound to REINDENT-LISP, which is some gawd-awful complicated function which calls a gazillion other complicated functions to do its work.
Then I noticed the emacs provided indent-sexp. :-)
so I guess reindent-defun could be trivially written as [save excursion [goto start of defun] [indent-sexp]] and be bound to M-q.
I too would rather import "as little as possible"; the smaller the codebase, the better. Maximize the number of lines of code not written, is what I always say.
Lastly, I notice slime doesn't rebind lisp-indent-function to be common-lisp-indent-function; is that on design? I imagine SLIME is essentially only used with common lisp, is it not?
And my current initialization file is full of crud like this: (put 'setq 'common-lisp-indent-function '(2 6)) (put 'setf 'common-lisp-indent-function '(2 6)) (put 'unwind-protect 'common-lisp-indent-function '(2 &body)) ;; etc
to get common lisp indentation coming out "standard". Should all this stuff be part of SLIME?
On Wed, Dec 10, 2003 at 09:42:20AM +1100, Alain.Picard@memetrics.com wrote:
I think you're right, after doing a bit more investigation. The first one I hit which really annoyed me was M-q which did not reindent the top level form properly (in SLIME). So I looked in ILISP, and M-q was bound to REINDENT-LISP, which is some gawd-awful complicated function which calls a gazillion other complicated functions to do its work.
Then I noticed the emacs provided indent-sexp. :-)
so I guess reindent-defun could be trivially written as [save excursion [goto start of defun] [indent-sexp]] and be bound to M-q.
REINDENT-LISP does more than that, unfortunatly. It will turn
(defun foo (bar) (if bar baz gronk) ; <- note
or
(defun foo (bar) (if bar baz gronk))) ; <- note
into
(defun foo (bar) (if bar baz gronk)) ; <- note
By correcting the number of parans at the end of the defun, it's really easy to make some changes, bang M-q, examine the "shape" of the defun, and if it's "shaped" right, you can be relatively confident it will compile without worrying about insufficient or extra closing parans on the end.
I used to use this feature a lot, and still miss it.
-bcd
Brian Downing bdowning@lavos.net writes:
REINDENT-LISP does more than that, unfortunatly. [...]
By correcting the number of parans at the end of the defun, it's really easy to make some changes, bang M-q, examine the "shape" of the defun, and if it's "shaped" right, you can be relatively confident it will compile without worrying about insufficient or extra closing parans on the end.
I used to use this feature a lot, and still miss it.
Me too. C-], which did indentation, close-paren balancing, and send-to-lisp, was my most heavily-used binding as an ILISP user.
Zach
Brian Downing writes:
REINDENT-LISP does more than that, unfortunatly. It will turn
(defun foo (bar) (if bar baz gronk) ; <- note into
(defun foo (bar) (if bar baz gronk)) ; <- note
Yeah, and if memory serves, it can often do the _wrong_ thing; like, if your original form has something in column zero, as I recall. I just remember cursing this regularly.
Anyway. Seems there are at least a few people who think it'd be good to have REINDENT-LISP, or something like it, into SLIME, is that the concensus?
Alain.Picard@memetrics.com writes:
Luke Gorrie writes:
I'm thinking in particular of all the buffer-movement, narrow-to-X and reindentation commands, for a start.
Which the buffer-movement commands do you mean?
I think you're right, after doing a bit more investigation. The first one I hit which really annoyed me was M-q which did not reindent the top level form properly (in SLIME). So I looked in ILISP, and M-q was bound to REINDENT-LISP, which is some gawd-awful complicated function which calls a gazillion other complicated functions to do its work.
Then I noticed the emacs provided indent-sexp. :-)
so I guess reindent-defun could be trivially written as [save excursion [goto start of defun] [indent-sexp]] and be bound to M-q.
I too would rather import "as little as possible"; the smaller the codebase, the better. Maximize the number of lines of code not written, is what I always say.
Lastly, I notice slime doesn't rebind lisp-indent-function to be common-lisp-indent-function; is that on design? I imagine SLIME is essentially only used with common lisp, is it not?
And my current initialization file is full of crud like this: (put 'setq 'common-lisp-indent-function '(2 6)) (put 'setf 'common-lisp-indent-function '(2 6)) (put 'unwind-protect 'common-lisp-indent-function '(2 &body)) ;; etc
to get common lisp indentation coming out "standard". Should all this stuff be part of SLIME?
I'm just a lurker here but I'd argue that it'd be nice if the stuff that doesn't *need* to be integrated with SLIME be teased out into a separate thing. I've been using ELI with ACL for a while, after previously using ILISP. While ELI has a bunch of cool features it seems to also install its own elisp to do code formatting which it seems to do less well than ILISP did. If both ELI and ILISP had split their code into two distinct parts--a lisp/emacs interaction bit and a mode for editing lisp source--then I could take the lisp/emacs integration from ELI and the lisp mode from ILISP and be happy.
Anyway, I'll I'm really saying, is don't needlessly couple things. (Now having not looked closely at the code for ILISP, ELI, *or* SLIME there may be reasons to couple these things that I'm not aware of. But it doesn't seem like they ought to be.
Unless of course one decided to use Common Lisp to do code formatting--ship over a form to Common Lisp which then pretty prints it back. Then if I want to change how Lisp formats my code I change the pretty-print dispatch table. Which would be sort of nice because then if I define my own macro that I want indented a certain way, I can include some lisp code that gets loaded with the definition of the macro code to fix up the pp dispatch table. The only problem with this scheme that I haven't been able to work out is how to avoid losing comments. Maybe use a slightly hacked read-table to read the forms coming from emacs that makes comment "objects" which the pretty-printer then knows how to print back out. Just thinking out loud.
-Peter
Peter Seibel writes:
Alain.Picard@memetrics.com writes:
And my current initialization file is full of crud like this: (put 'setq 'common-lisp-indent-function '(2 6)) (put 'setf 'common-lisp-indent-function '(2 6)) (put 'unwind-protect 'common-lisp-indent-function '(2 &body)) ;; etc
to get common lisp indentation coming out "standard". Should all this stuff be part of SLIME?
I'm just a lurker here but I'd argue that it'd be nice if the stuff that doesn't *need* to be integrated with SLIME be teased out into a separate thing.
Okay, let's change the question: should all this sort of crud be part of a common-lisp-edit.el add-on that people can choose to use or not use, as they wish? Whether or not that file is distributed as part of the SLIME project is something we can sort out later.
I agree with your sentiment of separating the editing commands from the inferior lisp communications commands.
Alain.Picard@memetrics.com writes:
Peter Seibel writes:
Alain.Picard@memetrics.com writes:
And my current initialization file is full of crud like this: (put 'setq 'common-lisp-indent-function '(2 6)) (put 'setf 'common-lisp-indent-function '(2 6)) (put 'unwind-protect 'common-lisp-indent-function '(2 &body)) ;; etc
to get common lisp indentation coming out "standard". Should all this stuff be part of SLIME?
I'm just a lurker here but I'd argue that it'd be nice if the stuff that doesn't *need* to be integrated with SLIME be teased out into a separate thing.
Okay, let's change the question: should all this sort of crud be part of a common-lisp-edit.el add-on that people can choose to use or not use, as they wish?
Ideally your example code above belongs in `cl-indent.el' that comes with Emacs. It should know how to indent Common Lisp properly.
Emacs comes with a huge amount of general Lisp-editing code that both SLIME and ILISP use. (I think ELI has its own lisp-mode and even emacs-lisp-mode but I don't know the story - I am curious.) Ideally extensions of this should be contributed into Emacs, but of course it'll take some years before you can reasonablly expect installed Emacsen to have the new features after they're released.
Having a common-lisp-edit.el containing code that can be used with SLIME and ILISP, and could be contributed into Emacs, seems like a good idea. We would probably end up each having a copy in our CVS trees and manually keeping them in sync (as with hyperspec.el today), but that's okay.
FWIW I would start with just a new `outline-minor-mode' section in slime.el personally. Of course we'll be glad to take advantage of your efforts in whichever format you choose :-)
Cheers, Luke
On Wed, Dec 10, 2003 at 03:01:01PM +0100, Luke Gorrie wrote:
Ideally your example code above belongs in `cl-indent.el' that comes with Emacs. It should know how to indent Common Lisp properly.
It should, but it really doesn't. Or at least it gets easily confused. Backquotes and character-read-macros screw it up royally.
Also, it could be made more dwimmish about indentation of some forms if it had an access to their arglists... ;)
trees and manually keeping them in sync (as with hyperspec.el today), but that's okay.
Ob hyperspec... How would you feel about moving that functionality to the CL side of things? Or ar least the symbol->url mapping part of it.
I'm alluding to HYPERSPEC-LOOKUP and HYPERDOC here, of course.
http://common-lisp-net/project/hypespec-lookup/ http://common-lisp-net/project/hyperdoc/
The nice feature of such a move would be the ability for arbitrary packages to provide hypertext documentation.
Cheers,
-- Nikodemus
On Wed, Dec 10, 2003 at 04:02:29PM +0200, Nikodemus Siivola wrote:
It should, but it really doesn't. Or at least it gets easily confused. Backquotes and character-read-macros screw it up royally.
Backquotes work MUCH better in CVS emacs's cl-indent. (Read: They actually indent as code. Actually, there's a customize option for what to do with them.)
-bcd
Nikodemus Siivola nikodemus@random-state.net writes:
It should, but it really doesn't. Or at least it gets easily confused. Backquotes and character-read-macros screw it up royally.
Also, it could be made more dwimmish about indentation of some forms if it had an access to their arglists... ;)
James Bielman did a SLIME hack for this: http://jamesjb.com/slime/slime-indent.el
I have some reservations about Emacs indenting code differently depending on whether it's connected to Lisp and what code Lisp has loaded. But maybe it's the right thing for such an integrated system as SLIME.
Ob hyperspec... How would you feel about moving that functionality to the CL side of things? Or ar least the symbol->url mapping part of it.
How about a cool demo to show the advantage? :-)
Here's a quick primer on SLIME hacking:
Our interface for calling Lisp from Emacs is pretty easy:
(slime-eval COMMON-LISP-FORM &optional PACKAGE-NAME) => VALUE-SEXP
The COMMON-LISP-FORM gets PRIN1'd in Emacs, sent over a socket to Lisp, and then READ in the minimal SWANK-IO-PACKAGE. That means all symbols should be package-qualified. For example:
(slime-eval '(cl:length cl:*features*) "CL-USER") => 27
.. but we don't write snippets like that in practice, instead we only call external functions in the SWANK package and with literal arguments. That avoids having a bunch of CL code snippets strewn about the elisp sources.
In that example, the CL-USER package isn't used automatically, but the Lisp side can find it in swank::*buffer-package*.
So: suppose you wrote a CL function (swank:hyperdoc SYMBOL-NAME) that checks if the symbol is interned, and if so looks it up in hyperdoc and returns the URL. Then you could use `slime-eval' in Emacs to call it and pass the resulting url to `browse-url'. That'd be Emacs-integrated hyperdoc I think.
We also have another interface, which we actually prefer:
(slime-eval-async FORM PACKAGE CONTINUATION) => void
which returns immediately and does the evaluation asynchronously. When the value comes back it is passed to CONTINUATION with funcall. The basic advantage is that it won't lock up Emacs while waiting for Lisp.
When you use slime-eval-async, remember that Elisp has dynamic scope, so by default your local bindings will have disappeared when CONTINUATION gets called. For convenience we have a macro that will lexical'ify the bindings you need:
(with-lexical-bindings (var1 ... varN) body...)
Hopefully slime.el and swank.lisp have plenty of examples of all of this stuff.
Cheers, Luke
Alain Picard writes:
to get common lisp indentation coming out "standard". Should all this stuff be part of SLIME?
ILISP considers Lisp indentation an orthogonal issue--i.e. it doesn't deal with it.
Paolo