Skip to content

Commit 24121e5

Browse files
dpsuttonbbatsov
authored andcommitted
Add babashka repl and readme cleanups
Correct bb arglists form missing a trailing ')' and also didnt' include a :bb branch for the exception type Completion for planck Lumo dumb terminal option
1 parent a7f07a0 commit 24121e5

File tree

3 files changed

+156
-123
lines changed

3 files changed

+156
-123
lines changed

README.md

Lines changed: 133 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,21 @@
88
This package provides basic interaction with a Clojure subprocess (REPL).
99
It's based on ideas from the popular `inferior-lisp` package.
1010

11-
`inf-clojure` has two components - a nice Clojure REPL with
12-
auto-completion and a minor mode (`inf-clojure-minor-mode`), which
13-
extends `clojure-mode` with commands to evaluate forms directly in the
14-
REPL.
11+
`inf-clojure` aims to expose the extensive self-documenting features
12+
of Clojure repls into an emacs package. Inf-clojure does not require
13+
middleware or special tooling. Inf-clojure supports the following
14+
repls:
15+
16+
- Clojure
17+
- ClojureScript
18+
- planck
19+
- lumo
20+
- joker
21+
- babashka
22+
23+
`inf-clojure` has two components - a nice REPL buffer (`inf-clojure`)
24+
(`inf-clojure-minor-mode`), which extends `clojure-mode` with commands
25+
to evaluate forms directly in the REPL.
1526

1627
`inf-clojure` provides a set of essential features for interactive
1728
Clojure(Script) development:
@@ -83,7 +94,7 @@ Add the following to your Emacs config to enable
8394
have overlapping functionality and keybindings and the result will be nothing
8495
short of havoc.**
8596

86-
## Usage
97+
## Basic Usage
8798

8899
Just invoke `M-x inf-clojure` or press `C-c C-z` within a Clojure
89100
source file. You should get a prompt with the supported repl types and
@@ -94,10 +105,6 @@ and you can start interacting with it.
94105
If you've already started a socket repl, use `M-x inf-clojure-connect`
95106
and enter the host and port numbers.
96107

97-
It is highly recommended to use a cons pair like `("localhost" . 5555)` to
98-
connect to a socket REPL, terminal REPLs are inherently hard to work with and
99-
support will be deprecated in the foreseeable future.
100-
101108
Inf-clojure aims to be very simple and offer tooling that the repl
102109
itself exposes. A few commands are:
103110

@@ -107,11 +114,77 @@ itself exposes. A few commands are:
107114
- show source `C-c C-s`
108115
- insert top level form into repl `C-c C-j d`
109116

117+
For a list of all available commands in `inf-clojure-mode` (a.k.a. the
118+
REPL) and `inf-clojure-minor-mode` you can either invoke `C-h f RET
119+
inf-clojure-mode` and `C-h f RET inf-clojure-minor-mode` or simply
120+
browse their menus.
121+
110122
Many `inf-clojure-minor-mode` commands by default act on the symbol at
111123
point. You can, however, change this behaviour by invoking such
112124
commands with a prefix argument. For instance: `C-u C-c C-v` will ask
113125
for the symbol you want to show the docstring for.
114126

127+
## Configuration options
128+
129+
In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely
130+
configurable.
131+
132+
You can set custom values to `inf-clojure` variables on a
133+
per-project basis using [directory
134+
variables](https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html)
135+
or by setting them in in your init file.
136+
137+
You can see all the configuration options available using the command
138+
`M-x customize-group RET inf-clojure`.
139+
140+
The supported repl-features are in an alist called
141+
`inc-clojure-repl-features` and it has the following shape:
142+
143+
```emacs-lisp
144+
'((cljs . ((doc . "(cljs.repl/doc %s)")
145+
(source . "(cljs.repl/source %s)")
146+
(arglists . "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))")
147+
(apropos . "(cljs.repl/apropos \"%s\")")
148+
(ns-vars . "(cljs.repl/dir %s)")
149+
(set-ns . "(in-ns '%s)")
150+
(macroexpand . "(cljs.core/macroexpand '%s)")
151+
(macroexpand-1 . "(cljs.core/macroexpand-1 '%s)"))))
152+
```
153+
154+
If you want to add a new repl type, just `(add-to-list
155+
'inf-clojure-repl-features (cons new-repl-type '((doc
156+
. "(myrepl/doc-command %s") ...)))` since the datastructure is just an
157+
alist of alists.
158+
159+
If you want to update a specific form there is a function
160+
`inf-clojure-update-repl-feature` which can be used like so:
161+
162+
```emacs-lisp
163+
(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")")
164+
```
165+
166+
#### Caveats
167+
168+
It is highly recommended to use a cons pair like `("localhost" . 5555)` to
169+
connect to a socket REPL, terminal REPLs are inherently hard to work with and
170+
support will be deprecated in the foreseeable future. If you use the
171+
same project often, make a dir-locals file with this information in `inf-clojure-custom-startup`.
172+
173+
Note that if you decide _NOT_ to use the socket repl, it is highly recommended
174+
you disable output coloring and/or readline facilities: `inf-clojure` does not
175+
filter out ASCII escape characters at the moment and will not behave correctly.
176+
177+
For leiningen, there are no command line switches and you need to add
178+
a custom [`project.clj`
179+
option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj):
180+
181+
```clojure
182+
...
183+
:repl-options {:color false}
184+
...
185+
```
186+
187+
115188
#### Clojure Command Line Socket REPL
116189

117190
If you have the new [Clojure CLI tools][] installed you can use the `clojure` command:
@@ -125,15 +198,8 @@ clojure -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"
125198
Then either `C-c M-c RET localhost RET 5555` from within Emacs or add the following to your `.dir-locals.el`:
126199

127200
```emacs-lisp
128-
((nil . ((inf-clojure-tools-deps-cmd . ("localhost" . 5555)))))
201+
((nil . ((inf-clojure-custom-startup . ("localhost" . 5555)))))
129202
```
130-
131-
or the following to your [Emacs init file][]:
132-
133-
```emacs-lisp
134-
(setf inf-clojure-tools-deps-cmd '("localhost" . 5555)):
135-
```
136-
137203
#### Leiningen Socket REPL
138204

139205
For Leiningen, add the following option to your `~/.lein/profiles.clj` or your `project.clj`:
@@ -160,43 +226,6 @@ For example if a `project.clj` is present in the project root folder, `inf-cloju
160226

161227
After you launch `lumo ... -n 5555`, as customary, either `C-c M-c RET localhost RET 5555` from within Emacs or add the following to your `.dir-locals.el`:
162228

163-
```emacs-lisp
164-
((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555)))))
165-
```
166-
167-
or the following to your [Emacs init file][]:
168-
169-
```emacs-lisp
170-
(setf inf-clojure-lein-cmd '("localhost" . 5555))
171-
```
172-
173-
Project detection can be completely skipped and the `generic` project type can be used instead:
174-
175-
```emacs-lisp
176-
(setf inf-clojure-project-type . "generic")
177-
(setf inf-clojure-generic-cmd '("localhost" 5555))
178-
```
179-
180-
#### Caveats
181-
182-
Note that if you decide _NOT_ to use the socket repl, it is highly recommended
183-
you disable output coloring and/or readline facilities: `inf-clojure` does not
184-
filter out ASCII escape characters at the moment and will not behave correctly.
185-
186-
You can disable coloring the following way for `boot`:
187-
188-
```emacs-lisp
189-
((nil . ((inf-clojure-boot-cmd . "boot repl -C"))))
190-
```
191-
192-
For leiningen, there are no command line switches and you need to add a custom [`project.clj` option](https://github.com/technomancy/leiningen/blob/master/sample.project.clj):
193-
194-
```clojure
195-
...
196-
:repl-options {:color false}
197-
...
198-
```
199-
200229
#### Multiple Process Support
201230

202231
To run multiple Clojure processes, you start the first up
@@ -235,46 +264,11 @@ one process, this does the right thing. If you run multiple
235264
processes, you might need to change `inf-clojure-buffer` to
236265
whichever process buffer you want to use.
237266

238-
## Configuration options
239-
240-
In the time-honoured Emacs tradition `inf-clojure`'s behaviour is extremely
241-
configurable.
242-
243-
You can see all the configuration options available using the command
244-
`M-x customize-group RET inf-clojure`.
245-
246-
The supported repl-features are in an alist called
247-
`inc-clojure-repl-features` and it has the following shape:
248-
249-
```emacs-lisp
250-
'((cljs . ((doc . "(cljs.repl/doc %s)")
251-
(source . "(cljs.repl/source %s)")
252-
(arglists . "(try (->> '%s cljs.core/resolve cljs.core/meta :arglists) (catch :default _ nil))")
253-
(apropos . "(cljs.repl/apropos \"%s\")")
254-
(ns-vars . "(cljs.repl/dir %s)")
255-
(set-ns . "(in-ns '%s)")
256-
(macroexpand . "(cljs.core/macroexpand '%s)")
257-
(macroexpand-1 . "(cljs.core/macroexpand-1 '%s)"))))
258-
```
259-
260-
If you want to add a new repl type, just `(add-to-list
261-
'inf-clojure-repl-features (cons new-repl-type '((doc
262-
. "(myrepl/doc-command %s") ...)))`
263-
264-
If you want to update a specific form there is a function
265-
`inf-clojure-update-repl-feature` which can be used like so:
266-
267-
```emacs-lisp
268-
(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")")
269-
```
270-
271267
#### REPL Type
272268

273-
An `inf-clojure` REPL can be of different types: Clojure,
274-
ClojureScript, Lumo and Planck are all potentially valid options.
275-
276-
At the moment, the default Clojure REPL, the Lumo REPL, the Planck
277-
REPL and the Joker REPL are supported.
269+
An `inf-clojure` REPL has an associated type. The available types are
270+
`(mapcar 'car inf-clojure-repl-features) ->> (cljs lumo planck joker
271+
clojure babashka)`
278272

279273
What does it mean that a REPL type is supported - well it means that
280274
`inf-clojure` would use the proper code internally to power commands
@@ -284,15 +278,6 @@ and can't be implemented in a REPL-independent way. At startup
284278
and uses this type to dispatch the proper code for the respective REPL
285279
type.
286280

287-
By default `inf-clojure` would start a standard Clojure REPL using
288-
`lein` or `boot` but you can easily change this. To boot some other REPL just use the
289-
right launch command (or connect to the REPL via a socket). For example, for
290-
Lumo just add the following in your `.dir-locals.el`:
291-
292-
```emacs-lisp
293-
((nil . ((inf-clojure-boot-cmd . "lumo -d")))) ;; inf-clojure-lein-cmd if you are using Leiningen
294-
```
295-
296281
#### ElDoc
297282

298283
`eldoc-mode` is supported in Clojure source buffers and `*inferior-clojure*`
@@ -315,31 +300,61 @@ You can leave it enabled, it just won't show anything in the echo area.
315300

316301
#### Code Completion
317302

318-
Code completion is particularly open to customization. Not only you can `setq`
319-
the customary `inf-clojure-completion-form`,
320-
`inf-clojure-completion-form-lumo`, `inf-clojure-completion-form-planck` and
321-
`inf-clojure-completion-form-joker` - the form to send to the REPL - but you
322-
can also use `inf-clojure-completions-fn` for specifying a function that given
323-
the REPL response should return elisp data compatible with
303+
Code completion is a tricky aspect if you are trying to be as close to
304+
a generic repl as possible. Planck and lumo repl implementations
305+
explicitly provide completion functions in their repl namespaces. For
306+
clojure, you will need to have a library on your classpath. If you are
307+
using lein, you already have
308+
[clojure-complete](https://github.com/ninjudd/clojure-complete). You
309+
could alternatively use `compliment {:mvn/version "0.3.10"}`.
310+
311+
```emacs-lisp
312+
;; for clojure-complete
313+
(inf-clojure-update-feature 'clojure 'completion "(complete.core/completions \"%s\")")
314+
315+
;; or
316+
;; for compliment
317+
(inf-clojure-update-feature 'clojure 'completion "(compliment.core/completions \"%s\")")
318+
319+
```
320+
321+
If you give a form for the completion form, it is your responsibility
322+
to ensure that this namespace is on the classpath and required. If
323+
using lein, this is done for you with clojure-complete. If adding
324+
compliment, the following sample deps.edn can conveniently add the dep
325+
to your program.
326+
327+
Sample deps.edn:
328+
329+
```clojure
330+
{:aliases {:compliment {:extra-deps {compliment {:mvn/version "0.3.10"}}}}}
331+
```
332+
333+
334+
Use the startup command: `clojure -A:compliment`. Then require the ns
335+
once so that the completion machinery will work: `(require
336+
'compliment.core)`. Now tab completion should work.
337+
338+
For more advanced customization, code completion is particularly open
339+
to customization. Not only you can `setq` the customary
340+
`inf-clojure-completion-form`, `inf-clojure-completion-form-lumo`,
341+
`inf-clojure-completion-form-planck` and
342+
`inf-clojure-completion-form-joker` - the form to send to the REPL -
343+
but you can also use `inf-clojure-completions-fn` for specifying a
344+
function that given the REPL response should return elisp data
345+
compatible with
324346
[`completion-at-point-functions`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion-in-Buffers.html).
325-
For more info run `M-x describe-variable RET inf-clojure-completions-fn`.
326-
Another option is to have a look at
327-
[how cider does it](https://github.com/clojure-emacs/cider/blob/3e9ed12e8cfbad04d7618e649322765dc9bff5d6/cider-interaction.el#L595).
347+
For more info run `M-x describe-variable RET
348+
inf-clojure-completions-fn`. Another option is to have a look at [how
349+
cider does
350+
it](https://github.com/clojure-emacs/cider/blob/3e9ed12e8cfbad04d7618e649322765dc9bff5d6/cider-interaction.el#L595).
328351

329352
#### Lumo Setup
330353

331354
For an optimal Lumo experience the `-d` needs to be passed to Lumo
332355
when launched from the command line. This disable `readline` support
333356
in order to play nicely with emacs.
334357

335-
For example, you can use the following command (assuming `cp` contains
336-
the classpath) in your `.dir-locals.el`:
337-
338-
```emacs-lisp
339-
((nil . (eval . (setq inf-clojure-generic-cmd (concat "lumo -d -c "
340-
(f-read (concat (inf-clojure-project-root) "cp")))))))
341-
```
342-
343358
## Troubleshooting
344359

345360
### Things seem broken

inf-clojure.el

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,13 @@
7676
;; cljs goes after the selfhosts
7777
(cljs . "cljs.repl")
7878
(joker . "joker.repl")
79+
(babashka . "babashka.classpath")
7980
(clojure . "clojure.core.server")))
8081
(defvar inf-clojure-startup-forms '((clojure . "clojure")
8182
(cljs . "clojure -m cljs.main -r")
82-
(planck . "planck")
83-
(lumo . "lumo")
83+
(planck . "planck -d")
84+
(babashka . "bb")
85+
(lumo . "lumo -d")
8486
(joker . "joker")))
8587

8688
(defvar inf-clojure-repl-features
@@ -117,7 +119,8 @@
117119
(ns-vars . "(planck.repl/dir %s)")
118120
(set-ns . "(in-ns '%s)")
119121
(macroexpand . "(macroexpand '%s)")
120-
(macroexpand-1 . "(macroexpand-1 '%s)")))
122+
(macroexpand-1 . "(macroexpand-1 '%s)")
123+
(completion . "(seq (js->clj (#'planck.repl/get-completions \"%s\")))")))
121124
(joker . ((load . "(load-file \"%s\")")
122125
(doc . "(joker.repl/doc %s)")
123126
(arglists .
@@ -130,6 +133,17 @@
130133
(set-ns . "(in-ns '%s)")
131134
(macroexpand . "(macroexpand '%s)")
132135
(macroexpand-1 . "(macroexpand-1 '%s)")))
136+
(babashka . ((load . "(clojure.core/load-file \"%s\")")
137+
(doc . "(clojure.repl/doc %s)")
138+
(source . "(clojure.repl/source %s)")
139+
(arglists .
140+
"(try (-> '%s clojure.core/resolve clojure.core/meta :arglists)
141+
(catch Throwable e nil))")
142+
(apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println (str var)))")
143+
(ns-vars . "(clojure.repl/dir %s)")
144+
(set-ns . "(clojure.core/in-ns '%s)")
145+
(macroexpand . "(clojure.core/macroexpand '%s)")
146+
(macroexpand-1 . "(clojure.core/macroexpand-1 '%s)")))
133147
(clojure . ((load . "(clojure.core/load-file \"%s\")")
134148
(doc . "(clojure.repl/doc %s)")
135149
(source . "(clojure.repl/source %s)")
@@ -1292,6 +1306,7 @@ Return the number of nested sexp the point was over or after."
12921306

12931307
(defun inf-clojure-eldoc ()
12941308
"Backend function for eldoc to show argument list in the echo area."
1309+
;; todo: this never gets unset once connected and is a lie
12951310
(when (and (inf-clojure-connected-p)
12961311
;; don't clobber an error message in the minibuffer
12971312
(not (member last-command '(next-error previous-error))))

0 commit comments

Comments
 (0)