44
44
(require 'thingatpt )
45
45
(require 'ansi-color )
46
46
(require 'cl-lib )
47
+ (require 'subr-x )
47
48
48
49
49
50
(defgroup inf-clojure nil
@@ -148,6 +149,7 @@ The following commands are available:
148
149
149
150
\\ {inf-clojure-minor-mode-map}"
150
151
:lighter " " :keymap inf-clojure-minor-mode-map
152
+ (setq comint-input-sender 'inf-clojure--send-string )
151
153
(inf-clojure-eldoc-setup)
152
154
(make-local-variable 'completion-at-point-functions )
153
155
(add-to-list 'completion-at-point-functions
@@ -183,6 +185,30 @@ often connecting to a remote REPL process."
183
185
:type '(choice (string )
184
186
(cons string integer)))
185
187
188
+ (defvar-local inf-clojure-repl-type nil
189
+ " Symbol to define your REPL type.
190
+ Its root binding is nil and it can be further customized using
191
+ either `setq-local` or an entry in `.dir-locals.el`." )
192
+
193
+ (defun inf-clojure--detect-type (proc )
194
+ " Identifies the current REPL type for PROC."
195
+ (cond
196
+ ((inf-clojure--lumo-p proc) 'lumo )
197
+ (t 'clojure )))
198
+
199
+ (defun inf-clojure--set-repl-type (proc )
200
+ " Set the REPL type if has not already been set."
201
+ (when (not inf-clojure-repl-type)
202
+ (setq inf-clojure-repl-type (inf-clojure--detect-type proc))))
203
+
204
+ (defun inf-clojure--send-string (proc string )
205
+ " A custom `comint-input-sender` / `comint-send-string`.
206
+ Perform the required side effects on every send for PROC and
207
+ STRING (for example set the buffer local REPL type). It should
208
+ be used instead of `comint-send-string`."
209
+ (inf-clojure--set-repl-type proc)
210
+ (comint-simple-send proc string))
211
+
186
212
(defcustom inf-clojure-load-command " (clojure.core/load-file \" %s\" )\n "
187
213
" Format-string for building a Clojure expression to load a file.
188
214
This format string should use `%s' to substitute a file name
@@ -296,6 +322,7 @@ If `comint-use-prompt-regexp' is nil (the default), \\[comint-insert-input] on o
296
322
Paragraphs are separated only by blank lines. Semicolons start comments.
297
323
If you accidentally suspend your process, use \\ [comint-continue-subjob]
298
324
to continue it."
325
+ (setq comint-input-sender 'inf-clojure--send-string )
299
326
(setq comint-prompt-regexp inf-clojure-comint-prompt-regexp)
300
327
(setq mode-line-process '(" :%s" ))
301
328
(clojure-mode-variables)
@@ -408,12 +435,12 @@ Prefix argument AND-GO means switch to the Clojure buffer afterwards."
408
435
(let ((str (replace-regexp-in-string
409
436
" [\n ]*\\ '" " \n "
410
437
(buffer-substring-no-properties start end))))
411
- (comint -send-string (inf-clojure-proc) str))
438
+ (inf-clojure- -send-string (inf-clojure-proc) str))
412
439
(if and-go (inf-clojure-switch-to-repl t )))
413
440
414
441
(defun inf-clojure-eval-string (code )
415
442
" Send the string CODE to the inferior Clojure process to be executed."
416
- (comint -send-string (inf-clojure-proc) (concat code " \n " )))
443
+ (inf-clojure- -send-string (inf-clojure-proc) (concat code " \n " )))
417
444
418
445
(defun inf-clojure-eval-defun (&optional and-go )
419
446
" Send the current defun to the inferior Clojure process.
@@ -504,8 +531,8 @@ The prefix argument SWITCH-TO-REPL controls whether to switch to REPL after the
504
531
(comint-check-source file-name) ; Check to see if buffer needs saved.
505
532
(setq inf-clojure-prev-l/c-dir/file (cons (file-name-directory file-name)
506
533
(file-name-nondirectory file-name)))
507
- (comint -send-string (inf-clojure-proc)
508
- (format inf-clojure-load-command file-name))
534
+ (inf-clojure- -send-string (inf-clojure-proc)
535
+ (format inf-clojure-load-command file-name))
509
536
(when switch-to-repl
510
537
(inf-clojure-switch-to-repl t ))))
511
538
@@ -526,6 +553,19 @@ The prefix argument SWITCH-TO-REPL controls whether to switch to REPL after the
526
553
" Command to query inferior Clojure for a var's documentation."
527
554
:type 'string )
528
555
556
+ (defcustom inf-clojure-var-doc-command-lumo
557
+ " (lumo.repl/doc %s)\n "
558
+ " Lumo command to query inferior Clojure for a var's documentation."
559
+ :type 'string )
560
+
561
+ (defun inf-clojure-var-doc-form ()
562
+ " Return the form to query inferior Clojure for a var's documentation.
563
+ If you are using REPL types, it will pickup the most approapriate
564
+ `inf-clojure-var-doc-form` variant."
565
+ (pcase inf-clojure-repl-type
566
+ (lumo inf-clojure-var-doc-form-lumo)
567
+ (_ inf-clojure-var-doc-form)))
568
+
529
569
(defcustom inf-clojure-var-source-command
530
570
" (clojure.repl/source %s)\n "
531
571
" Command to query inferior Clojure for a var's source."
@@ -546,6 +586,19 @@ The prefix argument SWITCH-TO-REPL controls whether to switch to REPL after the
546
586
" Command to query inferior Clojure for completion candidates."
547
587
:type 'string )
548
588
589
+ (defcustom inf-clojure-completion-form-lumo
590
+ " (doall (map str (lumo.repl/get-completions \" %s\" )))\n "
591
+ " Lumo form to query inferior Clojure for completion candidates."
592
+ :type 'string )
593
+
594
+ (defun inf-clojure-completion-form ()
595
+ " Return the form to query inferior Clojure for a var's documentation.
596
+ If you are using REPL types, it will pickup the most approapriate
597
+ `inf-clojure-completion-form` variant."
598
+ (pcase inf-clojure-repl-type
599
+ (lumo inf-clojure-completion-form-lumo)
600
+ (_ inf-clojure-completion-form)))
601
+
549
602
(defcustom inf-clojure-ns-vars-command
550
603
" (clojure.repl/dir %s)\n "
551
604
" Command to show the public vars in a namespace."
@@ -618,9 +671,9 @@ The value is nil if it can't find one."
618
671
619
672
(defun inf-clojure-show-var-documentation (var )
620
673
" Send a command to the inferior Clojure to give documentation for VAR.
621
- See variable `inf-clojure-var-doc-command ' ."
674
+ See function `inf-clojure-var-doc-form ' ."
622
675
(interactive (inf-clojure-symprompt " Var doc" (inf-clojure-var-at-pt)))
623
- (comint-proc-query (inf-clojure-proc) (format inf-clojure-var-doc-command var)))
676
+ (comint-proc-query (inf-clojure-proc) (format ( inf-clojure-var-doc-form) var)))
624
677
625
678
(defun inf-clojure-show-var-source (var )
626
679
" Send a command to the inferior Clojure to give source for VAR.
@@ -683,7 +736,7 @@ See variable `inf-clojure-macroexpand-command'.
683
736
With a prefix arg MACRO-1 uses `inf-clojure-macroexpand-1-command' ."
684
737
(interactive " P" )
685
738
(let ((last-sexp (buffer-substring-no-properties (save-excursion (backward-sexp ) (point )) (point ))))
686
- (comint -send-string
739
+ (inf-clojure- -send-string
687
740
(inf-clojure-proc)
688
741
(format (if macro-1
689
742
inf-clojure-macroexpand-1-command
@@ -710,7 +763,7 @@ See variable `inf-clojure-buffer'."
710
763
(unwind-protect
711
764
(let ((completion-snippet
712
765
(format
713
- inf-clojure-completion-command (substring-no-properties expr))))
766
+ ( inf-clojure-completion-form) (substring-no-properties expr))))
714
767
(process-send-string proc completion-snippet)
715
768
(while (and (not (string-match inf-clojure-prompt kept))
716
769
(accept-process-output proc 2 )))
@@ -876,6 +929,39 @@ to suppress the usage of the target buffer discovery logic."
876
929
(inf-clojure (inf-clojure-cmd (inf-clojure-project-type)))
877
930
(rename-buffer target-buffer-name)))
878
931
879
- (provide 'inf-clojure )
932
+ (defun inf-clojure--response-match-p (form match-p proc )
933
+ " Return MATCH-P on the result of sending FORM to PROC.
934
+ Note that this function will add a \n to the end of the string
935
+ for evaluation, therefore FORM should not include it."
936
+ (let* ((kept " " )
937
+ (is-matching nil )
938
+ (prev-filter (process-filter proc)))
939
+ (set-process-filter proc (lambda (_ string ) (setq kept (concat kept string))))
940
+ (unwind-protect
941
+ ; ; use the real comind-send-string in order to avoid stack overflows
942
+ (comint-send-string proc (concat form " \n " ))
943
+ ; ; yey, loads of procedural code again
944
+ (while (and (not is-matching)
945
+ (not (string-match inf-clojure-prompt kept))
946
+ (accept-process-output proc 2 ))
947
+ (setq is-matching (funcall match-p kept)))
948
+ (set-process-filter proc prev-filter))
949
+ is-matching))
950
+
951
+ ; ;;; Lumo
952
+ ; ;;; ====
953
+
954
+ (defcustom inf-clojure--lumo-repl-form
955
+ " (js/global.hasOwnProperty \" $$LUMO_GLOBALS\" )"
956
+ " Form to invoke in order to verify that we launched a Lumo REPL."
957
+ :type 'string )
958
+
959
+ (defalias 'inf-clojure--lumo-p
960
+ (apply-partially 'inf-clojure--response-match-p
961
+ inf-clojure--lumo-repl-form
962
+ (lambda (string )
963
+ (string-match-p (concat inf-clojure--lumo-repl-form " \\ Ca*true\\ Ca*" ) string)))
964
+ " Ascertain that PROC is a Lumo REPL." )
880
965
966
+ (provide 'inf-clojure )
881
967
; ;; inf-clojure.el ends here
0 commit comments