clojure-emacs / inf-clojure

Basic interaction with a Clojure subprocess
251 stars 45 forks source link

Feature: include helper function for starting socket repls #209

Open mikepjb opened 1 year ago

mikepjb commented 1 year ago

Hi guys,

Just started using inf-clojure and it's great as a simple tool.

I wrote a helper function for my personal use that I think may be useful to include in inf-clojure - let me know what you think, I'd like to improve & contribute this myself if you think it's worth including.

The code itself is loosely based on how cider does it's jack-in/spawning processes, I used the code there as a reference.

(also please excuse the elisp, I'm a long time vim user πŸ˜‰)

  ;; used to transfer state between the connection fns and
  ;; socket-filter.
  (defvar-local repl-setup-callback nil)

  (defun config/socket-filter (process output)
    (let ((server-buffer (process-buffer process)))
      (when (buffer-live-p server-buffer)
    (with-current-buffer server-buffer
          (insert output)))
      (let ((prompt-displayed (string-match "=>" output)))
    (when prompt-displayed
      (message (format "REPL prompt found for %s" (process-name process)))
      (with-current-buffer server-buffer
        (when repl-setup-callback
          (funcall repl-setup-callback)))))))

  (defun config/create-repl-setup (port repl-type)
    (lambda ()
      (setq-default inf-clojure-repl-type (intern repl-type)) ;; doesn't work, still getting repl selection prompt!
      (inf-clojure-connect "localhost" port)))

  (defun config/start-repl (repl-type port)
    (let* ((socket-process-name "socket-server")
       (socket-buffer-name "*test-socket-buffer*")
       (socket-buffer (get-buffer-create socket-buffer-name))
       (sock (start-file-process-shell-command
          socket-process-name socket-buffer
          (concat "clojure"
              " -J-Dclojure.server.repl=\"{:port "
              (number-to-string port)
              " :accept clojure.core.server/repl}\" -Mdev"))))
      (with-current-buffer socket-buffer
    (setq-local repl-setup-callback (config/create-repl-setup port repl-type)))
      (set-process-filter sock #'config/socket-filter)
      (message (format "Socket server started on port: %s" port))
      sock))

  (defun config/clj-repl ()
    (interactive)
    (config/start-repl "clojure" 5555))

  (defun config/cljs-repl ()
    (interactive)
    (config/start-repl "cljs" 5556))
bbatsov commented 1 year ago

(also please excuse the elisp, I'm a long time vim user πŸ˜‰)

Nobody's perfect. πŸ˜‰

I guess it'd be useful to add an option to start a socket REPL straight from Emacs, so feel free to convert this to a PR and we can discuss the code there in more details.