|
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-flavor nil |
| 189 | + "Symbol to define your REPL flavor. |
| 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--probe-flavor (proc) |
| 194 | + "Identifies the current REPL flavor for PROC." |
| 195 | + (cond |
| 196 | + ((inf-clojure--lumo-p proc) 'lumo) |
| 197 | + (t 'clojure))) |
| 198 | + |
| 199 | +(defun inf-clojure--set-flavor (proc) |
| 200 | + "Set the flavor if has not already been set." |
| 201 | + (when (not inf-clojure-repl-flavor) |
| 202 | + (setq inf-clojure-repl-flavor (inf-clojure--probe-flavor 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 flavor). It should |
| 208 | +be used instead of `comint-send-string`." |
| 209 | + (inf-clojure--set-flavor 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 |
|
@@ -683,7 +710,7 @@ See variable `inf-clojure-macroexpand-command'.
|
683 | 710 | With a prefix arg MACRO-1 uses `inf-clojure-macroexpand-1-command'."
|
684 | 711 | (interactive "P")
|
685 | 712 | (let ((last-sexp (buffer-substring-no-properties (save-excursion (backward-sexp) (point)) (point))))
|
686 |
| - (comint-send-string |
| 713 | + (inf-clojure--send-string |
687 | 714 | (inf-clojure-proc)
|
688 | 715 | (format (if macro-1
|
689 | 716 | inf-clojure-macroexpand-1-command
|
@@ -876,6 +903,39 @@ to suppress the usage of the target buffer discovery logic."
|
876 | 903 | (inf-clojure (inf-clojure-cmd (inf-clojure-project-type)))
|
877 | 904 | (rename-buffer target-buffer-name)))
|
878 | 905 |
|
879 |
| -(provide 'inf-clojure) |
| 906 | +(defun inf-clojure--response-match-p (form match-p proc) |
| 907 | + "Return MATCH-P on the result of sending FORM to PROC. |
| 908 | +Note that this function will add a \n to the end of the string |
| 909 | +for evaluation, therefore FORM should not include it." |
| 910 | + (let* ((kept "") |
| 911 | + (is-matching nil) |
| 912 | + (prev-filter (process-filter proc))) |
| 913 | + (set-process-filter proc (lambda (_ string) (setq kept (concat kept string)))) |
| 914 | + (unwind-protect |
| 915 | + ;; use the real comind-send-string in order to avoid stack overflows |
| 916 | + (comint-send-string proc (concat form "\n")) |
| 917 | + ;; yey, loads of procedural code again |
| 918 | + (while (and (not is-matching) |
| 919 | + (not (string-match inf-clojure-prompt kept)) |
| 920 | + (accept-process-output proc 2)) |
| 921 | + (setq is-matching (funcall match-p kept))) |
| 922 | + (set-process-filter proc prev-filter)) |
| 923 | + is-matching)) |
| 924 | + |
| 925 | +;;;; Lumo |
| 926 | +;;;; ==== |
| 927 | + |
| 928 | +(defcustom inf-clojure--lumo-repl-form |
| 929 | + "(js/global.hasOwnProperty \"$$LUMO_GLOBALS\")" |
| 930 | + "Form to invoke in order to verify that we launched a Lumo REPL." |
| 931 | + :type 'string) |
880 | 932 |
|
| 933 | +(defalias 'inf-clojure--lumo-p |
| 934 | + (apply-partially 'inf-clojure--response-match-p |
| 935 | + inf-clojure--lumo-repl-form |
| 936 | + (lambda (string) |
| 937 | + (string-match-p (concat inf-clojure--lumo-repl-form "\\Ca*true\\Ca*") string))) |
| 938 | + "Ascertain that PROC is a Lumo REPL.") |
| 939 | + |
| 940 | +(provide 'inf-clojure) |
881 | 941 | ;;; inf-clojure.el ends here
|
0 commit comments