8
8
; ; URL: http://github.com/clojure-emacs/inf-clojure
9
9
; ; Keywords: processes, comint, clojure
10
10
; ; Version: 3.2.1
11
- ; ; Package-Requires: ((emacs "25.1 ") (clojure-mode "5.11"))
11
+ ; ; Package-Requires: ((emacs "26.2 ") (clojure-mode "5.11"))
12
12
13
13
; ; This file is not part of GNU Emacs.
14
14
74
74
(defvar inf-clojure-startup-forms '((lein . " lein repl" )
75
75
(boot . " boot repl" )
76
76
(clojure . " clojure" )
77
- (cljs . " clojure -m cljs.main -r" )
77
+ (cljs . " clojure -M - m cljs.main -r" )
78
78
(lein-clr . " lein clr repl" )
79
79
(planck . " planck -d" )
80
80
(babashka . " bb" )
81
+ (node-babashka . " nbb" )
81
82
(lumo . " lumo -d" )
82
83
(joker . " joker" )))
83
84
140
141
(set-ns . " (clojure.core/in-ns '%s)" )
141
142
(macroexpand . " (clojure.core/macroexpand '%s)" )
142
143
(macroexpand-1 . " (clojure.core/macroexpand-1 '%s)" )))
144
+ (node-babashka . ((load . " (clojure.core/load-file \" %s\" )" )
145
+ (doc . " (clojure.repl/doc %s)" )
146
+ (source . " (clojure.repl/source %s)" )
147
+ (arglists .
148
+ " (try (-> '%s clojure.core/resolve clojure.core/meta :arglists)
149
+ (catch Throwable e nil))" )
150
+ (apropos . " (doseq [var (sort (clojure.repl/apropos \" %s\" ))] (println (str var)))" )
151
+ (ns-vars . " (clojure.repl/dir %s)" )
152
+ (set-ns . " (clojure.core/in-ns '%s)" )
153
+ (macroexpand . " (clojure.core/macroexpand '%s)" )
154
+ (macroexpand-1 . " (clojure.core/macroexpand-1 '%s)" )))
143
155
(clojure . ((load . " (clojure.core/load-file \" %s\" )" )
144
156
(doc . " (clojure.repl/doc %s)" )
145
157
(source . " (clojure.repl/source %s)" )
@@ -641,33 +653,34 @@ Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
641
653
642
654
You can send text to the inferior Clojure process from other buffers containing
643
655
Clojure source.
644
- `inf-clojure-switch-to-repl' switches the current buffer to the Clojure process buffer.
656
+ `inf-clojure-switch-to-repl' switches the current buffer to the Clojure
657
+ process buffer.
645
658
`inf-clojure-eval-defun' sends the current defun to the Clojure process.
646
659
`inf-clojure-eval-region' sends the current region to the Clojure process.
647
660
648
661
Prefixing the inf-clojure-eval/defun/region commands with
649
- a \\ [universal-argument] causes a switch to the Clojure process buffer after sending
650
- the text.
662
+ a \\ [universal-argument] causes a switch to the Clojure process buffer after
663
+ sending the text.
651
664
652
665
Commands:\\ <inf-clojure-mode-map>
653
- \\ [comint-send-input] after the end of the process' output sends the text from the
654
- end of process to point.
655
- \\ [comint-send-input] before the end of the process' output copies the sexp ending at point
656
- to the end of the process' output, and sends it.
657
- \\ [comint-copy-old-input] copies the sexp ending at point to the end of the process' output,
658
- allowing you to edit it before sending it.
659
- If `comint-use-prompt-regexp' is nil (the default), \\ [comint-insert-input] on old input
660
- copies the entire old input to the end of the process' output, allowing
661
- you to edit it before sending it. When not used on old input, or if
662
- `comint-use-prompt-regexp' is non-nil, \\ [comint-insert-input] behaves according to
663
- its global binding.
666
+ \\ [comint-send-input] after the end of the process' output sends the text from
667
+ the end of process to point.
668
+ \\ [comint-send-input] before the end of the process' output copies the sexp
669
+ ending at point to the end of the process' output, and sends it.
670
+ \\ [comint-copy-old-input] copies the sexp ending at point to the end of the
671
+ process' output, allowing you to edit it before sending it.
672
+ If `comint-use-prompt-regexp' is nil (the default), \\ [comint-insert-input] on
673
+ old input copies the entire old input to the end of the process' output,
674
+ allowing you to edit it before sending it. When not used on old input, or if
675
+ `comint-use-prompt-regexp' is non-nil, \\ [comint-insert-input] behaves
676
+ according to its global binding.
664
677
\\ [backward-delete-char-untabify] converts tabs to spaces as it moves back.
665
678
\\ [clojure-indent-line] indents for Clojure; with argument, shifts rest
666
679
of expression rigidly with the current line.
667
- \\ [indent-sexp] does \\ [clojure-indent-line] on each line starting within following expression.
668
- Paragraphs are separated only by blank lines. Semicolons start comments .
669
- If you accidentally suspend your process, use \\ [comint-continue-subjob]
670
- to continue it."
680
+ \\ [indent-sexp] does \\ [clojure-indent-line] on each line starting within
681
+ following expression. Paragraphs are separated only by blank lines.
682
+ Semicolons start comments. If you accidentally suspend your process,
683
+ use \\ [comint-continue-subjob] to continue it."
671
684
(setq comint-input-sender 'inf-clojure--send-string )
672
685
(setq comint-prompt-regexp inf-clojure-comint-prompt-regexp)
673
686
(setq mode-line-process '(" :%s" ))
@@ -807,9 +820,11 @@ process buffer for a list of commands.)"
807
820
nil
808
821
'confirm-after-completion ))))
809
822
(let* ((project-dir (clojure-project-dir))
810
- (process-buffer-name (if project-dir
811
- (format " inf-clojure %s " (inf-clojure--project-name project-dir))
812
- " inf-clojure" ))
823
+ (process-buffer-name (or
824
+ inf-clojure-custom-repl-name
825
+ (if project-dir
826
+ (format " inf-clojure %s " (inf-clojure--project-name project-dir))
827
+ " inf-clojure" )))
813
828
; ; comint adds the asterisks to both sides
814
829
(repl-buffer-name (format " *%s * " process-buffer-name)))
815
830
; ; Create a new comint buffer if needed
@@ -819,10 +834,11 @@ process buffer for a list of commands.)"
819
834
(cmdlist (if (consp cmd)
820
835
(list cmd)
821
836
(split-string-and-unquote cmd)))
822
- (repl-type (or (unless prefix-arg
837
+ (repl-type (or inf-clojure-socket-repl-type
838
+ (unless prefix-arg
823
839
inf-clojure-custom-repl-type)
824
- (car (rassoc cmd inf-clojure-startup-forms))
825
- (inf-clojure--prompt-repl-type))))
840
+ (car (rassoc cmd inf-clojure-startup-forms))
841
+ (inf-clojure--prompt-repl-type))))
826
842
(message " Starting Clojure REPL via `%s' ... " cmd)
827
843
(with-current-buffer (apply #'make-comint
828
844
process-buffer-name (car cmdlist) nil (cdr cmdlist))
@@ -843,6 +859,121 @@ HOST is the host the process is running on, PORT is where it's listening."
843
859
(interactive " shost: \n nport: " )
844
860
(inf-clojure (cons host port)))
845
861
862
+ (defvar-local inf-clojure-socket-callback nil
863
+ " Used to transfer state between the socket process buffer & REPL buffer." )
864
+
865
+ (defvar-local inf-clojure-socket-buffer nil
866
+ " Used to kill the associated socket buffer when it's REPL buffer is killed." )
867
+
868
+ (defvar inf-clojure-socket-repl-startup-message " Socket REPL listening"
869
+ " Used to detect when nbb socket REPL has started since it does not print `=>' ." )
870
+
871
+ (defun inf-clojure-socket-filter (process output )
872
+ " A filter that gets triggered each time the socket receives new OUTPUT.
873
+ This function prints out the output received but also
874
+ watches for a prompt using the `inf-clojure-prompt' regexp, once
875
+ this happens a callback is triggered if available. The callback
876
+ is intended to be used to trigger a `inf-clojure-connect' once we
877
+ can determine that a socket REPL is ready to receive a
878
+ connection.
879
+
880
+ PROCESS is the process object that is being filtered.
881
+
882
+ OUTPUT is the latest data received from the process"
883
+ (let ((server-buffer (process-buffer process)))
884
+ (when (buffer-live-p server-buffer)
885
+ (with-current-buffer server-buffer
886
+ (insert output)))
887
+ (let ((prompt-displayed (string-match inf-clojure-prompt output))
888
+ (startup-displayed (string-match inf-clojure-socket-repl-startup-message output)))
889
+ (when (or prompt-displayed startup-displayed)
890
+ (message (format " Socket REPL startup detected for %s " (process-name process)))
891
+ (with-current-buffer server-buffer
892
+ (when inf-clojure-socket-callback
893
+ (funcall inf-clojure-socket-callback)))))))
894
+
895
+ (defun inf-clojure-socket-repl-sentinel (process event )
896
+ " Ensures socket REPL are cleaned up when the REPL buffer is closed.
897
+
898
+ PROCESS is the process object that is connected to a socket REPL.
899
+
900
+ EVENT is the event that triggered this function to be called."
901
+ (when (not (process-live-p process))
902
+ (let ((repl-buffer (process-buffer process)))
903
+ (with-current-buffer repl-buffer
904
+ (when inf-clojure-socket-buffer
905
+ (kill-buffer inf-clojure-socket-buffer))))))
906
+
907
+ (defvar inf-clojure-socket-repl-startup-forms
908
+ '((lein . " JVM_OPTS='-Dclojure.server.repl={:port %d :accept clojure.core.server/repl}' lein repl" )
909
+ (boot . " export BOOT_JVM_OPTIONS='-Dclojure.server.repl=\" {:port %d :accept clojure.core.server/repl}\" ' boot repl" )
910
+ (clojure . " clojure -J-Dclojure.server.repl=\" {:port %d :accept clojure.core.server/repl}\" " )
911
+ (cljs . " clojure -J-Dclojure.server.repl=\" {:port %d :accept cljs.server.browser/repl}\" " )
912
+ (lein-clr . " JVM_OPTS='-Dclojure.server.repl={:port %d :accept clojure.core.server/repl}' lein clr repl" )
913
+ (planck . " planck -n %d" )
914
+ (babashka . " bb socket-repl %d" )
915
+ (node-babashka . " nbb socket-repl :port %d" )))
916
+
917
+ (defcustom inf-clojure-socket-repl-port
918
+ nil
919
+ " Port to be used when creating a socket REPL via `inf-clojure-socket-repl' .
920
+ If left as nil a random port will be selected between 5500-6000."
921
+ :type '(choice integer (const nil ))
922
+ :package-version '(inf-clojure . " 3.2.1" ))
923
+
924
+ ;;;### autoload
925
+ (defun inf-clojure-socket-repl (cmd )
926
+ " Start a socket REPL server and connect to it via `inf-clojure' .
927
+ CMD is the command line used to start the socket REPL, if this
928
+ isn't provided you will be prompted to select from the defaults
929
+ provided in `inf-clojure-socket-repl-startup-forms' or
930
+ `inf-clojure-custom-startup' if this is defined."
931
+ (interactive (list (or (unless current-prefix-arg
932
+ inf-clojure-custom-startup)
933
+ (completing-read " Select Clojure socket REPL startup command: "
934
+ (mapcar #'cdr inf-clojure-socket-repl-startup-forms)
935
+ nil
936
+ 'confirm-after-completion ))))
937
+ (let* ((host " localhost" )
938
+ (port (or inf-clojure-socket-repl-port (+ 5500 (random 500 ))))
939
+ (project-dir (clojure-project-dir))
940
+ (repl-type (or (unless prefix-arg
941
+ inf-clojure-custom-repl-type)
942
+ (car (rassoc cmd inf-clojure-socket-repl-startup-forms))
943
+ (inf-clojure--prompt-repl-type)))
944
+ (project-name (inf-clojure--project-name (or project-dir " standalone" )))
945
+ (socket-process-name (format " *%s -%s -socket-server* " project-name repl-type))
946
+ (socket-buffer-name (format " *%s -%s -socket* " project-name repl-type))
947
+ (socket-buffer (get-buffer-create socket-buffer-name))
948
+ (repl-buffer-name (format " %s -%s -repl" project-name repl-type))
949
+ (socket-form (or (cdr (assoc repl-type inf-clojure-socket-repl-startup-forms))
950
+ inf-clojure-custom-startup
951
+ cmd))
952
+ (socket-cmd (format socket-form port))
953
+ (sock (let ((default-directory (or project-dir default-directory)))
954
+ (start-file-process-shell-command
955
+ socket-process-name socket-buffer
956
+ socket-cmd))))
957
+ (with-current-buffer socket-buffer
958
+ (setq-local
959
+ inf-clojure-socket-callback
960
+ (lambda ()
961
+ (setq inf-clojure-socket-repl-type
962
+ repl-type
963
+ inf-clojure-custom-repl-name
964
+ repl-buffer-name
965
+ repl-buffer
966
+ (get-buffer-create repl-buffer-name))
967
+ (inf-clojure-connect host port)
968
+ (with-current-buffer (concat " *" repl-buffer-name " *" )
969
+ (setq inf-clojure-socket-buffer socket-buffer))
970
+ (set-process-sentinel
971
+ (get-buffer-process (get-buffer (concat " *" repl-buffer-name " *" )))
972
+ #'inf-clojure-socket-repl-sentinel ))))
973
+ (set-process-filter sock #'inf-clojure-socket-filter )
974
+ (message " Starting %s socket REPL server at %s :%d with %s " repl-type host port socket-cmd)))
975
+
976
+
846
977
(defun inf-clojure--forms-without-newlines (str )
847
978
" Remove newlines between toplevel forms.
848
979
STR is a string of contents to be evaluated. When sending
0 commit comments