Skip to content

Commit e33a546

Browse files
dpsuttonbbatsov
authored andcommitted
Bugfixes and readme updates
- Check for completion feature before capf functionality - would throw an error in complete at point function rather than before starting - Repl type only in process buffer rather than juggling this in two places just put it in the process buffer.
1 parent 30638a0 commit e33a546

File tree

3 files changed

+69
-80
lines changed

3 files changed

+69
-80
lines changed

README.md

Lines changed: 45 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ You can install `inf-clojure` using the following command:
6262

6363
or if you'd rather keep it in your dotfiles:
6464

65-
```el
65+
```emacs-lisp
6666
(unless (package-installed-p 'inf-clojure)
6767
(package-refresh-contents)
6868
(package-install 'inf-clojure))
@@ -75,7 +75,7 @@ If the installation doesn't work try refreshing the package list:
7575
Add the following to your Emacs config to enable
7676
`inf-clojure-minor-mode` for Clojure source buffers:
7777

78-
```el
78+
```emacs-lisp
7979
(add-hook 'clojure-mode-hook #'inf-clojure-minor-mode)
8080
```
8181

@@ -85,39 +85,27 @@ short of havoc.**
8585

8686
## Usage
8787

88-
Just invoke `M-x inf-clojure` or press `C-c C-z` within a Clojure source file.
89-
This will start a REPL process for the current project and you can start
90-
interacting with it.
88+
Just invoke `M-x inf-clojure` or press `C-c C-z` within a Clojure
89+
source file. You should get a prompt with the supported repl types and
90+
common startup forms. You can select one of these or type in your own
91+
custom startup. This will start a REPL process for the current project
92+
and you can start interacting with it.
9193

92-
Inf-clojure has several custom variables which control the command used to
93-
start a REPL for a particular project type:
94-
95-
- `inf-clojure-lein-cmd` ([Leiningen][])
96-
- `inf-clojure-boot-cmd` ([Boot][])
97-
- `inf-clojure-tools-deps-cmd` ([Clojure cli tools][])
98-
- `inf-clojure-generic-cmd`
99-
100-
Detection is attempted in the above order (see [function
101-
`inf-clojure-project-type` in this
102-
file](https://github.com/clojure-emacs/inf-clojure/blob/master/inf-clojure.el#L611-L618)
103-
but the `inf-clojure-project-type` variable can force a particular
104-
project type, useful for projects that don't have standard layouts.
94+
If you've already started a socket repl, use `M-x inf-clojure-connect`
95+
and enter the host and port numbers.
10596

10697
It is highly recommended to use a cons pair like `("localhost" . 5555)` to
10798
connect to a socket REPL, terminal REPLs are inherently hard to work with and
10899
support will be deprecated in the foreseeable future.
109100

110-
Interactively, use `M-x inf-clojure-connect` (`C-c M-c`) to connect to a
111-
running socket REPL or `C-u C-c C-z` for specifying a different command/cons
112-
pair.
113-
114-
You can also set custom values to `inf-clojure` variables on a per-project
115-
basis using
116-
[directory variables](https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html).
101+
Inf-clojure aims to be very simple and offer tooling that the repl
102+
itself exposes. A few commands are:
117103

118-
For a list of all available commands in `inf-clojure-mode` (a.k.a. the REPL) and
119-
`inf-clojure-minor-mode` you can either invoke `C-h f RET inf-clojure-mode` and
120-
`C-h f RET inf-clojure-minor-mode` or simply browse their menus.
104+
- eval last sexp `C-x C-e`
105+
- show arglists for function `C-c C-a`
106+
- show var documentation `C-c C-v`
107+
- show source `C-c C-s`
108+
- insert top level form into repl `C-c C-j d`
121109

122110
Many `inf-clojure-minor-mode` commands by default act on the symbol at
123111
point. You can, however, change this behaviour by invoking such
@@ -136,13 +124,13 @@ clojure -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"
136124

137125
Then either `C-c M-c RET localhost RET 5555` from within Emacs or add the following to your `.dir-locals.el`:
138126

139-
```el
127+
```emacs-lisp
140128
((nil . ((inf-clojure-tools-deps-cmd . ("localhost" . 5555)))))
141129
```
142130

143131
or the following to your [Emacs init file][]:
144132

145-
```el
133+
```emacs-lisp
146134
(setf inf-clojure-tools-deps-cmd '("localhost" . 5555)):
147135
```
148136

@@ -154,38 +142,14 @@ For Leiningen, add the following option to your `~/.lein/profiles.clj` or your `
154142
:jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"]
155143
```
156144

157-
Then run `lein repl` from within your project directory to start the REPL, and either `C-c M-c RET localhost RET 5555` from within Emacs or add the following to your `.dir-locals.el`:
158-
159-
```el
160-
((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555)))))
161-
```
162-
163-
or the following to your [Emacs init file][]:
164-
165-
```el
166-
(setf inf-clojure-lein-cmd '("localhost" . 5555))
167-
```
168-
169-
#### Boot Socket REPL
145+
Then run `lein repl` from within your project directory to start the
146+
REPL. To connect, you can either `m-x inf-clojure-connect [RET]
147+
localhost [RET] 5555` or you can put in a dir local file the
148+
information on how connect:
170149

171-
For boot, export the environment variable `BOOT_JVM_OPTIONS`:
172-
173-
```shell
174-
export BOOT_JVM_OPTIONS='-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"'
175-
```
176-
177-
or add the following to your `.dir-locals.el`:
178-
179-
```el
180-
((nil . ((inf-clojure-boot-cmd . ("localhost" . 5555)))))
181-
```
182-
183-
or the following to your [Emacs init file][]:
184-
185-
```el
186-
(setf inf-clojure-boot-cmd '("localhost" . 5555))
150+
```emacs-lisp
151+
((nil (inf-clojure-custom-startup "localhost" . 5555)))
187152
```
188-
189153
The socket server REPL configuration options are described [here](https://clojure.org/reference/repl_and_main#_launching_a_socket_server).
190154

191155
#### Lumo Socket REPL
@@ -196,19 +160,19 @@ For example if a `project.clj` is present in the project root folder, `inf-cloju
196160

197161
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`:
198162

199-
```el
163+
```emacs-lisp
200164
((nil . ((inf-clojure-lein-cmd . ("localhost" . 5555)))))
201165
```
202166

203167
or the following to your [Emacs init file][]:
204168

205-
```el
169+
```emacs-lisp
206170
(setf inf-clojure-lein-cmd '("localhost" . 5555))
207171
```
208172

209173
Project detection can be completely skipped and the `generic` project type can be used instead:
210174

211-
```el
175+
```emacs-lisp
212176
(setf inf-clojure-project-type . "generic")
213177
(setf inf-clojure-generic-cmd '("localhost" 5555))
214178
```
@@ -221,7 +185,7 @@ filter out ASCII escape characters at the moment and will not behave correctly.
221185

222186
You can disable coloring the following way for `boot`:
223187

224-
```el
188+
```emacs-lisp
225189
((nil . ((inf-clojure-boot-cmd . "boot repl -C"))))
226190
```
227191

@@ -301,7 +265,7 @@ By default `inf-clojure` would start a standard Clojure REPL using
301265
right launch command (or connect to the REPL via a socket). For example, for
302266
Lumo just add the following in your `.dir-locals.el`:
303267

304-
```el
268+
```emacs-lisp
305269
((nil . ((inf-clojure-boot-cmd . "lumo -d")))) ;; inf-clojure-lein-cmd if you are using Leiningen
306270
```
307271

@@ -317,7 +281,7 @@ echo area.
317281
You can activate ElDoc with `M-x eldoc-mode` or by adding the
318282
following to you Emacs config:
319283

320-
```el
284+
```emacs-lisp
321285
(add-hook 'clojure-mode-hook #'eldoc-mode)
322286
(add-hook 'inf-clojure-mode-hook #'eldoc-mode)
323287
```
@@ -347,13 +311,26 @@ in order to play nicely with emacs.
347311
For example, you can use the following command (assuming `cp` contains
348312
the classpath) in your `.dir-locals.el`:
349313

350-
```el
314+
```emacs-lisp
351315
((nil . (eval . (setq inf-clojure-generic-cmd (concat "lumo -d -c "
352316
(f-read (concat (inf-clojure-project-root) "cp")))))))
353317
```
354318

355319
## Troubleshooting
356320

321+
### Things seem broken
322+
323+
Inf-clojure is intentionally quite simple and just sends commands to a
324+
repl on your behalf to provide features. In order to do this
325+
inf-clojure largely needs to know the repl type so it can format the
326+
correct calls. Most end up in `(lumo.repl/doc [symbol])` or
327+
`(cljs.repl/doc ...)` so its important that the repl type is set
328+
correctly. This repl type exists in the process buffer (repl) and the
329+
source buffers as a cache. If you have problems, run `m-x
330+
inf-clojure-set-repl-type` from the source buffer to set the repl type
331+
in both buffers. To see how simple inf-clojure is, look at
332+
`inf-clojure-repl-features` to see largely how things are laid out.
333+
357334
### REPL not responsive in Windows OS
358335

359336
In Windows, the REPL is not returning anything. For example, type `(+
@@ -373,7 +350,7 @@ jline.terminal=unsupported
373350

374351
Standard Emacs debugging turns out to be difficult when an asynchronous process is involved. In this case try to enable logging:
375352

376-
```el
353+
```emacs-lisp
377354
(setq inf-clojure-log-activity t)
378355
```
379356

inf-clojure.el

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,7 @@
148148

149149
(defun inf-clojure-get-feature (proc feature &optional no-error)
150150
"Get FEATURE based on repl type for PROC."
151-
(let* ((repl-type (or inf-clojure-repl-type
152-
(with-current-buffer (process-buffer proc)
151+
(let* ((repl-type (or (with-current-buffer (process-buffer proc)
153152
inf-clojure-repl-type)
154153
(error "Repl type is not known")))
155154
(feature-form (alist-get feature (alist-get repl-type inf-clojure-repl-features))))
@@ -195,21 +194,18 @@ See http://blog.jorgenschaefer.de/2014/05/race-conditions-in-emacs-process-filte
195194
(type-to-set (intern
196195
(completing-read "Set repl type:"
197196
(sort (mapcar #'symbol-name types) #'string-lessp)))))
198-
(setq-local inf-clojure-repl-type type-to-set)
199197
(with-current-buffer (process-buffer proc)
200198
(setq-local inf-clojure-repl-type type-to-set))))
201199

202200
(defun inf-clojure--set-repl-type (proc)
203201
"Set the REPL type if has not already been set.
204202
It requires a REPL PROC for inspecting the correct type."
205-
(if (not inf-clojure-repl-type)
206-
(let ((repl-type (inf-clojure--detect-repl-type proc)))
207-
;; set the REPL process buffer
208-
(with-current-buffer inf-clojure-buffer
203+
;; todo: don't like this happening so frequently
204+
(with-current-buffer (process-buffer proc)
205+
(if (not inf-clojure-repl-type)
206+
(let ((repl-type (inf-clojure--detect-repl-type proc)))
209207
(setq-local inf-clojure-repl-type repl-type))
210-
;; set in the current buffer
211-
(setq-local inf-clojure-repl-type repl-type))
212-
inf-clojure-repl-type))
208+
inf-clojure-repl-type)))
213209

214210
(defgroup inf-clojure nil
215211
"Run an external Clojure process (REPL) in an Emacs buffer."
@@ -1199,7 +1195,7 @@ This guy was taken from CIDER, thanks folks."
11991195
"Retrieve the list of completions and prompt the user.
12001196
Returns the selected completion or nil."
12011197
(let ((bounds (inf-clojure-completion-bounds-of-expr-at-point)))
1202-
(when bounds
1198+
(when (and bounds (inf-clojure-get-feature (inf-clojure-proc) 'completion 'no-error))
12031199
(list (car bounds) (cdr bounds)
12041200
(if (fboundp 'completion-table-with-cache)
12051201
(completion-table-with-cache #'inf-clojure-completions)

todo.org

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ For some reason ~inf-clojure--set-repl-type~ is called in:
88

99
Seems better to do this on the two different connection methods and then be done with it?
1010

11+
** DONE do we need repl type in both source buffer and connection?
12+
these can get out of sync and lead to confusing errors when closing a repl and opening a new one. It seems like we keep the repl-type in the source buffer to prevent a single ~(with-current-buffer (process-buffer proc) inf-clojure-repl-type)~
13+
1114
** TODO nice startup
1215
There's some project detection but that's becoming less and less useful as time goes on. Shadow, lein, deps.edn can all easily be mixed in the same project. And then lumo, planck, or bb scripts could live side by side. Rather than trying to guess the project type, I think i'd like to mimic geiser's style of handling multiple scheme backends. Perhaps ~m-x inf-clojure-run-planck~ and similar could help out.
1316

1417
Some considerations:
1518
- is this path aware? IE, don't show an option to run planck, lumo, etc, if they aren't visible or installed?
1619
- should it have a rebuild function so that user registered implementations can show up in the ~m-x~ menu as well?
1720

18-
** TODO Better dispatch for the implementations
21+
** DONE Better dispatch for the implementations
1922
Right now the functions are kinda clunky cond statements:
2023
#+BEGIN_SRC emacs-lisp
2124
(defun inf-clojure-cljs-features-dispatch (feature)
@@ -41,6 +44,19 @@ Right now everything is just a format string with a _single_ ~%s~ in it and that
4144
** TODO Simpler way to define an implementation
4245
This first pass is very mechanical and just rearranging so we can easily see which features are where. In the future we should look into just providing the repl namespace and seeing how far we can get with that. For instance, an API like ~(inf-clojure-register 'bb "bb.repl")~ and this would tell us where ~source~, ~doc~, ~apropos~ ...etc live. No reason to duplicate all of these.
4346

47+
** TODO ability to update repl commands
48+
we had this feature originally but now they are all literals. This is almost entirely fine but one problem. It would be common to toss clojure completions on the class path and then add the completions form for clojure.
49+
50+
This should come back but only in a sense: if you don't have this on the classpath its obviously unacceptable to throw errors every time the user hits tab. Do we need some state recording if this is on the classpath or not maybe?
51+
52+
#+BEGIN_SRC emacs-lisp
53+
(defcustom inf-clojure-completion-form
54+
"(complete.core/completions \"%s\")"
55+
"Form to query inferior Clojure for completion candidates."
56+
:type 'string
57+
:safe #'stringp
58+
:package-version '(inf-clojure . "2.0.0"))
59+
#+END_SRC
4460
** TODO Multiple connections
4561
As proven by CIDER, multiple connections are just a pain. Scoping, navigating into dependencies, etc. This is a monster lurking
4662

0 commit comments

Comments
 (0)