65
65
66
66
(require 'comint )
67
67
(require 'clojure-mode )
68
+ (require 'clojure-ts-mode nil :no-error )
68
69
(require 'eldoc )
69
70
(require 'thingatpt )
70
71
(require 'ansi-color )
71
72
(require 'cl-lib )
72
73
(require 'subr-x )
74
+ (require 'project )
73
75
74
76
(defvar inf-clojure-startup-forms '((lein . " lein repl" )
75
77
(boot . " boot repl" )
@@ -193,10 +195,10 @@ either `setq-local` or an entry in `.dir-locals.el`." )
193
195
MULTIPLE PROCESS SUPPORT
194
196
===========================================================================
195
197
To run multiple Clojure processes, you start the first up
196
- with \\ [inf-clojure]. It will be in a buffer named ` *inf-clojure*' .
198
+ with \\ [inf-clojure]. It will be in a buffer named *inf-clojure*.
197
199
Rename this buffer with \\ [rename-buffer]. You may now start up a new
198
200
process with another \\ [inf-clojure]. It will be in a new buffer,
199
- named ` *inf-clojure*' . You can switch between the different process
201
+ named *inf-clojure*. You can switch between the different process
200
202
buffers with \\ [switch-to-buffer].
201
203
202
204
Commands that send text from source buffers to Clojure processes --
@@ -205,7 +207,7 @@ process to send to, when you have more than one Clojure process around. This
205
207
is determined by the global variable `inf-clojure-buffer' . Suppose you
206
208
have three inferior Clojures running:
207
209
Buffer Process
208
- foo inf-clojure
210
+ foo ` inf-clojure'
209
211
bar inf-clojure<2>
210
212
*inf-clojure* inf-clojure<3>
211
213
If you do a \\ [inf-clojure-eval-defun] command on some Clojure source code,
@@ -269,7 +271,7 @@ has been found. See also variable `inf-clojure-buffer'."
269
271
(error " No Clojure subprocess; see variable `inf-clojure-buffer' " ))))
270
272
271
273
(defun inf-clojure-repl-p (&optional buf )
272
- " Indicates if BUF is an inf-clojure REPL.
274
+ " Indicates if BUF is an ` inf-clojure' REPL.
273
275
If BUF is nil then defaults to the current buffer.
274
276
Checks the mode and that there is a live process."
275
277
(let ((buf (or buf (current-buffer ))))
@@ -278,35 +280,35 @@ Checks the mode and that there is a live process."
278
280
(process-live-p (get-buffer-process buf)))))
279
281
280
282
(defun inf-clojure-repls ()
281
- " Return a list of all inf-clojure REPL buffers."
283
+ " Return a list of all ` inf-clojure' REPL buffers."
282
284
(let (repl-buffers)
283
285
(dolist (b (buffer-list ))
284
286
(when (inf-clojure-repl-p b)
285
287
(push (buffer-name b) repl-buffers)))
286
288
repl-buffers))
287
289
288
290
(defun inf-clojure--prompt-repl-buffer (prompt )
289
- " Prompt the user to select an inf-clojure repl buffer.
291
+ " Prompt the user to select an ` inf-clojure' repl buffer.
290
292
PROMPT is a string to prompt the user.
291
293
Returns nil when no buffer is selected."
292
294
(let ((repl-buffers (inf-clojure-repls)))
293
295
(if (> (length repl-buffers) 0 )
294
- (when-let ((repl-buffer (completing-read prompt repl-buffers nil t )))
296
+ (when-let* ((repl-buffer (completing-read prompt repl-buffers nil t )))
295
297
(get-buffer repl-buffer))
296
298
(user-error " No buffers have an inf-clojure process" ))))
297
299
298
300
(defun inf-clojure-set-repl (always-ask )
299
- " Set an inf-clojure buffer as the active (default) REPL.
301
+ " Set an ` inf-clojure' buffer as the active (default) REPL.
300
302
If in a REPL buffer already, use that unless a prefix is used (or
301
- ALWAYS-ASK). Otherwise get a list of all active inf-clojure
303
+ ALWAYS-ASK). Otherwise get a list of all active ` inf-clojure'
302
304
REPLS and offer a choice. It's recommended to rename REPL
303
305
buffers after they are created with `rename-buffer' ."
304
306
(interactive " P" )
305
- (when-let ((new-repl-buffer
306
- (if (or always-ask
307
- (not (inf-clojure-repl-p)))
308
- (inf-clojure--prompt-repl-buffer " Select default REPL: " )
309
- (current-buffer ))))
307
+ (when-let* ((new-repl-buffer
308
+ (if (or always-ask
309
+ (not (inf-clojure-repl-p)))
310
+ (inf-clojure--prompt-repl-buffer " Select default REPL: " )
311
+ (current-buffer ))))
310
312
(setq inf-clojure-buffer new-repl-buffer)
311
313
(message " Current inf-clojure REPL set to %s " new-repl-buffer)))
312
314
@@ -349,6 +351,14 @@ mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword
349
351
\( as in :a, :c, etc.)"
350
352
:type 'regexp )
351
353
354
+ (defcustom inf-clojure-source-modes '(clojure-ts-mode clojure-mode)
355
+ " Used to determine if a buffer contains Clojure source code.
356
+
357
+ Any buffer with one of these major modes, it's considered a Clojure
358
+ source file by all `inf-clojure' commands."
359
+ :type '(repeat symbol)
360
+ :safe #'symbolp )
361
+
352
362
(defun inf-clojure--modeline-info ()
353
363
" Return modeline info for `inf-clojure-minor-mode' .
354
364
Either \" no process\" or \" buffer-name(repl-type)\" "
@@ -453,7 +463,7 @@ The value of this variable is a mode line template as in
453
463
`mode-line-format' . See Info Node `(elisp)Mode Line Format' for details
454
464
about mode line templates.
455
465
456
- Customize this variable to change how inf-clojure-minor-mode
466
+ Customize this variable to change how ` inf-clojure-minor-mode'
457
467
displays its status in the mode line. The default value displays
458
468
the current REPL. Set this variable to nil to disable the
459
469
mode line entirely."
@@ -609,24 +619,35 @@ This should usually be a combination of `inf-clojure-prompt' and
609
619
:package-version '(inf-clojure . " 2.0.0" ))
610
620
611
621
(defcustom inf-clojure-auto-mode t
612
- " Automatically enable inf-clojure-minor-mode.
622
+ " Automatically enable ` inf-clojure-minor-mode' .
613
623
All buffers in `clojure-mode' will automatically be in
614
624
`inf-clojure-minor-mode' unless set to nil."
615
625
:type 'boolean
616
626
:safe #'booleanp
617
627
:package-version '(inf-clojure . " 3.1.0" ))
618
628
629
+ (defun inf-clojure--get-preferred-major-modes ()
630
+ " Return list of preferred major modes that are actually available."
631
+ (cl-remove-if-not (lambda (mode ) (featurep mode))
632
+ inf-clojure-source-modes))
633
+
634
+ (defun inf-clojure--clojure-buffer-p ()
635
+ " Return TRUE if the current buffer is a Clojure buffer."
636
+ (derived-mode-p (inf-clojure--get-preferred-major-modes)))
637
+
619
638
(defun inf-clojure--clojure-buffers ()
620
639
" Return a list of all existing `clojure-mode' buffers."
621
- (cl-remove-if-not
622
- (lambda (buffer ) (with-current-buffer buffer (derived-mode-p 'clojure-mode )))
623
- (buffer-list )))
640
+ (cl-remove-if-not (lambda (buffer )
641
+ (with-current-buffer buffer
642
+ (inf-clojure--clojure-buffer-p)))
643
+ (buffer-list )))
624
644
625
645
(defun inf-clojure-enable-on-existing-clojure-buffers ()
626
646
" Enable inf-clojure's minor mode on existing Clojure buffers.
627
647
See command `inf-clojure-minor-mode' ."
628
648
(interactive )
629
- (add-hook 'clojure-mode-hook #'inf-clojure-minor-mode )
649
+ (dolist (mode (inf-clojure--get-preferred-major-modes))
650
+ (add-hook (derived-mode-hook-name mode) #'inf-clojure-minor-mode ))
630
651
(dolist (buffer (inf-clojure--clojure-buffers))
631
652
(with-current-buffer buffer
632
653
(inf-clojure-minor-mode +1 ))))
@@ -688,6 +709,8 @@ If `comint-use-prompt-regexp' is nil (the default), \\[comint-insert-input] on
688
709
(setq comint-input-sender 'inf-clojure--send-string )
689
710
(setq comint-prompt-regexp inf-clojure-comint-prompt-regexp)
690
711
(setq mode-line-process '(" :%s" ))
712
+ ; ; NOTE: Using Tree-sitter based syntax highlighting in comint
713
+ ; ; buffer is currently not possible.
691
714
(clojure-mode-variables)
692
715
(clojure-font-lock-setup)
693
716
(when inf-clojure-enable-eldoc
@@ -799,10 +822,24 @@ to suppress the usage of the target buffer discovery logic."
799
822
The name is simply the final segment of the path."
800
823
(file-name-nondirectory (directory-file-name dir)))
801
824
825
+ (defun inf-clojure--project-dir ()
826
+ " Return current Clojure project root."
827
+ (let ((project-vc-extra-root-markers '(" project.clj" ; Leiningen
828
+ " build.boot" ; Boot
829
+ " build.gradle" ; Gradle
830
+ " build.gradle.kts" ; Gradle
831
+ " deps.edn" ; Clojure CLI (a.k.a. tools.deps)
832
+ " shadow-cljs.edn" ; shadow-cljs
833
+ " bb.edn" ; babashka
834
+ " nbb.edn" ; nbb
835
+ " basilisp.edn" ; Basilisp (Python)
836
+ )))
837
+ (project-root (project-current ))))
838
+
802
839
;;;### autoload
803
840
(defun inf-clojure (cmd &optional suppress-message )
804
- " Run an inferior Clojure process, input and output via buffer ` *inf-clojure*' .
805
- If there is a process already running in ` *inf-clojure*' , just
841
+ " Run an inferior Clojure process, input and output via buffer *inf-clojure*.
842
+ If there is a process already running in *inf-clojure*, just
806
843
switch to that buffer.
807
844
808
845
CMD is a string which serves as the startup command or a cons of
@@ -826,7 +863,7 @@ process buffer for a list of commands.)"
826
863
(mapcar #'cdr inf-clojure-startup-forms)
827
864
nil
828
865
'confirm-after-completion ))))
829
- (let* ((project-dir (clojure-project-dir))
866
+ (let* ((project-dir (inf- clojure- -project-dir))
830
867
(process-buffer-name (or
831
868
inf-clojure-custom-repl-name
832
869
(if project-dir
@@ -850,7 +887,9 @@ process buffer for a list of commands.)"
850
887
(with-current-buffer (apply #'make-comint
851
888
process-buffer-name (car cmdlist) nil (cdr cmdlist))
852
889
(inf-clojure-mode)
853
- (set-syntax-table clojure-mode-syntax-table)
890
+ (set-syntax-table (pcase (car (inf-clojure--get-preferred-major-modes))
891
+ ('clojure-ts-mode clojure-ts-mode-syntax-table)
892
+ (_ clojure-mode-syntax-table)))
854
893
(setq-local inf-clojure-repl-type repl-type)
855
894
(hack-dir-local-variables-non-file-buffer ))))
856
895
; ; update the default comint buffer and switch to it
@@ -940,7 +979,7 @@ defaults provided in `inf-clojure-socket-repl-startup-forms'."
940
979
'confirm-after-completion ))))
941
980
(let* ((host " localhost" )
942
981
(port (or inf-clojure-socket-repl-port (+ 5500 (random 500 ))))
943
- (project-dir (clojure-project-dir))
982
+ (project-dir (inf- clojure- -project-dir))
944
983
(repl-type (or (unless prefix-arg
945
984
inf-clojure-custom-repl-type)
946
985
(car (rassoc cmd inf-clojure-socket-repl-startup-forms))
@@ -978,16 +1017,19 @@ of forms."
978
1017
(condition-case nil
979
1018
(with-temp-buffer
980
1019
(progn
981
- (clojurec-mode)
1020
+ ; ; Activate preferred major mode.
1021
+ (funcall (car (inf-clojure--get-preferred-major-modes)))
982
1022
(insert str)
983
1023
(whitespace-cleanup )
984
1024
(goto-char (point-min ))
985
1025
(while (not (eobp ))
986
1026
(while (looking-at " \n " )
987
1027
(delete-char 1 ))
988
1028
(unless (eobp )
989
- (clojure-forward-logical-sexp))
990
- (unless (eobp )
1029
+ ; ; NOTE: There is no special API for that in
1030
+ ; ; `clojure-ts-mode' , so probably for now lets keep this
1031
+ ; ; `clojure-mode' function.
1032
+ (clojure-forward-logical-sexp)
991
1033
(forward-char )))
992
1034
(buffer-substring-no-properties (point-min ) (point-max ))))
993
1035
(scan-error str)))
@@ -1105,13 +1147,6 @@ START and END are the beginning and end positions in the buffer to send."
1105
1147
This holds a cons cell of the form `(DIRECTORY . FILE)'
1106
1148
describing the last `inf-clojure-load-file' command." )
1107
1149
1108
- (defcustom inf-clojure-source-modes '(clojure-mode)
1109
- " Used to determine if a buffer contains Clojure source code.
1110
- If it's loaded into a buffer that is in one of these major modes, it's
1111
- considered a Clojure source file by `inf-clojure-load-file' .
1112
- Used by this command to determine defaults."
1113
- :type '(repeat symbol))
1114
-
1115
1150
(defun inf-clojure-load-file (&optional switch-to-repl file-name )
1116
1151
" Load a Clojure file into the inferior Clojure process.
1117
1152
@@ -1123,7 +1158,7 @@ is present it will be used instead of the current file."
1123
1158
(file-name (or file-name
1124
1159
(car (comint-get-source " Load Clojure file: " inf-clojure-prev-l/c-dir/file
1125
1160
; ; nil because doesn't need an exact name
1126
- inf-clojure-source- modes nil ))))
1161
+ ( inf-clojure--get-preferred-major- modes) nil ))))
1127
1162
(load-form (inf-clojure-get-feature proc 'load )))
1128
1163
(comint-check-source file-name) ; Check to see if buffer needs saved.
1129
1164
(setq inf-clojure-prev-l/c-dir/file (cons (file-name-directory file-name)
@@ -1132,23 +1167,32 @@ is present it will be used instead of the current file."
1132
1167
(when switch-to-repl
1133
1168
(inf-clojure-switch-to-repl t ))))
1134
1169
1170
+ (defun inf-clojure--find-ns ()
1171
+ " Return the namespace of the current Clojure buffer.
1172
+
1173
+ This function delegates its job to an appropritate function, considering
1174
+ `inf-clojure-source-modes' ."
1175
+ (pcase (car (inf-clojure--get-preferred-major-modes))
1176
+ ('clojure-ts-mode (clojure-ts-find-ns))
1177
+ (_ (clojure-find-ns))))
1178
+
1135
1179
(defun inf-clojure-reload (arg )
1136
1180
" Send a query to the inferior Clojure for reloading the namespace.
1137
- See variable `inf-clojure-reload-form' and
1181
+ See variable `inf-clojure-reload-form' and variable
1138
1182
`inf-clojure-reload-all-form' .
1139
1183
1140
1184
The prefix argument ARG can change the behavior of the command:
1141
1185
1142
- - C-u M-x ` inf-clojure-reload' : prompts for a namespace name.
1143
- - M-- M-x ` inf-clojure-reload' : executes (require ... :reload-all).
1144
- - M-- C-u M-x ` inf-clojure-reload' : reloads all AND prompts."
1186
+ - \\ ` C-u' \\ [ inf-clojure-reload] : prompts for a namespace name.
1187
+ - \\ ` M--' \\ [ inf-clojure-reload] : executes (require ... :reload-all).
1188
+ - \\ ` M--' \\ ` C-u' \\ [ inf-clojure-reload] : reloads all AND prompts."
1145
1189
(interactive " P" )
1146
1190
(let* ((proc (inf-clojure-proc))
1147
1191
(reload-all-p (or (equal arg '- ) (equal arg '(-4 ))))
1148
1192
(prompt-p (or (equal arg '(4 )) (equal arg '(-4 ))))
1149
1193
(ns (if prompt-p
1150
- (car (inf-clojure-symprompt " Namespace" (clojure-find-ns)))
1151
- (clojure-find-ns)))
1194
+ (car (inf-clojure-symprompt " Namespace" (inf- clojure- -find-ns)))
1195
+ (inf- clojure- -find-ns)))
1152
1196
(form (if (not reload-all-p)
1153
1197
(inf-clojure-reload-form proc)
1154
1198
(inf-clojure-reload-all-form proc))))
@@ -1249,7 +1293,7 @@ STRING if present."
1249
1293
(prin1-to-string (substring-no-properties string))))
1250
1294
nil
1251
1295
(expand-file-name inf-clojure--log-file-name
1252
- (clojure-project-dir))
1296
+ (inf- clojure- -project-dir))
1253
1297
'append
1254
1298
'no-annoying-write-file-in-minibuffer )))
1255
1299
@@ -1357,11 +1401,11 @@ for evaluation, therefore FORM should not include it."
1357
1401
(defun inf-clojure-arglists (fn )
1358
1402
" Send a query to the inferior Clojure for the arglists for function FN.
1359
1403
See variable `inf-clojure-arglists-form' ."
1360
- (when-let ((proc (inf-clojure-proc 'no-error ) ))
1361
- ( when-let ( (arglists-form (inf-clojure-get-feature proc 'arglists )))
1362
- (thread-first (format arglists-form fn)
1363
- (inf-clojure--process-response proc " (" " )" )
1364
- (inf-clojure--some) ))))
1404
+ (when-let* ((proc (inf-clojure-proc 'no-error ))
1405
+ (arglists-form (inf-clojure-get-feature proc 'arglists )))
1406
+ (thread-first (format arglists-form fn)
1407
+ (inf-clojure--process-response proc " (" " )" )
1408
+ (inf-clojure--some))))
1365
1409
1366
1410
(defun inf-clojure-show-arglists (prompt-for-symbol )
1367
1411
" Show the arglists for function FN in the mini-buffer.
@@ -1383,8 +1427,8 @@ prefix argument PROMPT-FOR-NS, it prompts for a namespace name."
1383
1427
(interactive " P" )
1384
1428
(let* ((proc (inf-clojure-proc))
1385
1429
(ns (if prompt-for-ns
1386
- (car (inf-clojure-symprompt " Ns vars" (clojure-find-ns)))
1387
- (clojure-find-ns)))
1430
+ (car (inf-clojure-symprompt " Ns vars" (inf- clojure- -find-ns)))
1431
+ (inf- clojure- -find-ns)))
1388
1432
(ns-vars-form (inf-clojure-get-feature proc 'ns-vars )))
1389
1433
(inf-clojure--send-string proc (format ns-vars-form ns))))
1390
1434
@@ -1396,8 +1440,8 @@ PROMPT-FOR-NS, it prompts for a namespace name."
1396
1440
(interactive " P" )
1397
1441
(let* ((proc (inf-clojure-proc))
1398
1442
(ns (if prompt-for-ns
1399
- (car (inf-clojure-symprompt " Set ns to" (clojure-find-ns)))
1400
- (clojure-find-ns)))
1443
+ (car (inf-clojure-symprompt " Set ns to" (inf- clojure- -find-ns)))
1444
+ (inf- clojure- -find-ns)))
1401
1445
(set-ns-form (inf-clojure-get-feature proc 'set-ns )))
1402
1446
(when (or (not ns) (equal ns " " ))
1403
1447
(user-error " No namespace selected" ))
0 commit comments