summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitalie Spinu <spinuvit@gmail.com>2014-08-13 13:50:25 -0700
committerVitalie Spinu <spinuvit@gmail.com>2014-08-25 12:02:51 -0700
commit09dcec951125300274eea6e0b5f591be1d57bb5e (patch)
tree41f678af60d204b3172b88a430eae05416c57397
parentb58ba0ac546fc6a4c9228cb18f552067741a060d (diff)
Use repl buffer as connection buffer
Ancillary changes: - new functions `nrepl-start-client-process' and `nrepl-start-server-process'. - `cider-init-repl-buffer' and `cider-create-repl-buffer' have clear cut separation of functionality - `nrepl-make-buffer-name` and all `cider-create-xxx-buffer-name` take explicit dir, port and host variables. - increase `nrepl-decode-timeout` to 0.025 for greater reliability - merge `nrepl--handle-process-output` into client process filter - remove `nrepl-connect' in favor of `nrepl-start-client-process'
-rw-r--r--CHANGELOG.md4
-rw-r--r--cider-interaction.el4
-rw-r--r--cider-repl.el98
-rw-r--r--cider-selector.el6
-rw-r--r--cider.el36
-rw-r--r--nrepl-client.el257
-rw-r--r--test/cider-tests.el14
7 files changed, 229 insertions, 190 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fcd27fb..611a030a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,10 @@ are used to translate filenames from/to the nREPL server (default Cygwin impleme
### Changes
+* REPL buffers are now connection buffers for REPL client connections.
+* Server and client cranking were isolated into `nrepl-start-server-process` and
+ `nrepl-start-client-process`.
+
* nrepl-client.el refactoring:
- `nrepl-send-request-sync` was renamed into `nrepl-send-sync-request` to comply
diff --git a/cider-interaction.el b/cider-interaction.el
index 0c1cda15..9a1ae8e8 100644
--- a/cider-interaction.el
+++ b/cider-interaction.el
@@ -156,7 +156,7 @@ Signal an error if it is not supported."
(unless (nrepl-op-supported-p op)
(error "Can't find nREPL middleware providing op \"%s\". Please, install (or update) cider-nrepl %s and restart CIDER" op cider-version)))
-(defun cider-verify-required-nrepl-ops ()
+(defun cider--check-required-nrepl-ops ()
"Check whether all required nREPL ops are present."
(let ((missing-ops (-remove 'nrepl-op-supported-p cider-required-nrepl-ops)))
(when missing-ops
@@ -317,7 +317,7 @@ of the namespace in the Clojure source buffer."
(let ((buffer (current-buffer)))
(when (eq 4 arg)
(cider-repl-set-ns (cider-current-ns)))
- (pop-to-buffer (cider-find-or-create-repl-buffer))
+ (pop-to-buffer (cider-get-repl-buffer))
(cider-remember-clojure-buffer buffer)
(goto-char (point-max))))
diff --git a/cider-repl.el b/cider-repl.el
index 07139b58..03c8eaac 100644
--- a/cider-repl.el
+++ b/cider-repl.el
@@ -43,6 +43,7 @@
(defvar paredit-version)
(defvar paredit-space-for-delimiter-predicates))
+
(defgroup cider-repl nil
"Interaction with the REPL."
:prefix "cider-repl-"
@@ -115,6 +116,7 @@ you'd like to use the default Emacs behavior use
:type 'symbol
:group 'cider-repl)
+
;;;; REPL buffer local variables
(defvar-local cider-repl-input-start-mark nil)
@@ -151,31 +153,42 @@ joined together.")
(set markname (make-marker))
(set-marker (symbol-value markname) (point))))
+
;;; REPL init
-(defun cider-repl-buffer-name ()
- "Generate a REPL buffer name based on current connection buffer."
- (with-current-buffer (get-buffer (nrepl-current-connection-buffer))
- (nrepl-make-buffer-name nrepl-repl-buffer-name-template)))
-
-(defun cider-create-repl-buffer ()
- "Create a REPL buffer."
- (cider-init-repl-buffer
- (let ((buffer-name (cider-repl-buffer-name)))
- (if cider-repl-display-in-current-window
- (add-to-list 'same-window-buffer-names buffer-name))
- (if cider-repl-pop-to-buffer-on-connect
- (pop-to-buffer buffer-name)
- (generate-new-buffer buffer-name))
- buffer-name)))
-
-(defun cider-make-repl (process)
- "Make a REPL for the connection PROCESS."
- (let ((connection-buffer (process-buffer process))
- (repl-buffer (cider-create-repl-buffer)))
- (with-current-buffer repl-buffer
- (setq nrepl-connection-buffer (buffer-name connection-buffer)))
- (with-current-buffer connection-buffer
- (setq nrepl-repl-buffer (buffer-name repl-buffer)))))
+(defun cider-repl-buffer-name (&optional project-dir host port)
+ "Generate a REPL buffer name based on current connection buffer.
+PROJECT-DIR, PORT and HOST are as in `nrepl-make-buffer-name'."
+ (with-current-buffer (or (get-buffer (nrepl-current-connection-buffer))
+ (current-buffer))
+ (nrepl-make-buffer-name nrepl-repl-buffer-name-template project-dir host port)))
+
+(defun cider-repl-create (&optional project-dir host port)
+ "Create a REPL buffer and install `cider-repl-mode'.
+PROJECT-DIR, PORT and HOST are as in `nrepl-make-buffer-name'."
+ ;; Connection might not have been set as yet. Please don't send requests here.
+ (let ((buf (nrepl-make-buffer-name nrepl-repl-buffer-name-template
+ project-dir host port)))
+ (with-current-buffer (get-buffer-create buf)
+ (unless (derived-mode-p 'cider-repl-mode)
+ (cider-repl-mode))
+ (cider-repl-reset-markers))
+ buf))
+
+(defun cider-repl-init (buffer &optional no-banner)
+ "Initialize the REPL in BUFFER.
+BUFFER must be a REPL buffer with `cider-repl-mode' and a running
+clienprocessL connection. Unless NO-BANNER is non-nil, insert a banner."
+ (with-current-buffer buffer
+ ;; honor :init-ns from lein's :repl-options on startup
+ (setq nrepl-buffer-ns (cider-eval-and-get-value "(str *ns*)"))
+ (unless no-banner
+ (cider-repl--insert-banner-and-prompt nrepl-buffer-ns))
+ (when cider-repl-display-in-current-window
+ (add-to-list 'same-window-buffer-names buf))
+ (when cider-repl-pop-to-buffer-on-connect
+ (pop-to-buffer buffer))
+ (cider-remember-clojure-buffer cider-current-clojure-buffer)
+ buffer))
(defun cider-repl--banner ()
"Generate the welcome REPL buffer banner."
@@ -194,33 +207,14 @@ joined together.")
(cider-repl--mark-input-start)
(cider-repl--insert-prompt ns))
-(defun cider-init-repl-buffer (buffer &optional noprompt)
- "Initialize the REPL in BUFFER.
-Insert a banner, unless NOPROMPT is non-nil."
- (with-current-buffer buffer
- (unless (eq major-mode 'cider-repl-mode)
- (cider-repl-mode))
- (cider-repl-reset-markers)
- (unless noprompt
- (cider-repl--insert-banner-and-prompt nrepl-buffer-ns))
- (cider-remember-clojure-buffer cider-current-clojure-buffer)
- (current-buffer)))
-
-(defun cider-find-or-create-repl-buffer ()
- "Return the REPL buffer, create it if necessary."
- (let ((buffer (cider-current-repl-buffer)))
- (if (null buffer)
- (error "No active nREPL connection")
- (let ((buffer (get-buffer buffer)))
- (or (when (buffer-live-p buffer) buffer)
- (let ((buffer (nrepl-current-connection-buffer)))
- (if (null buffer)
- (error "No active nREPL connection")
- (cider-init-repl-buffer
- (get-process buffer)
- (get-buffer-create
- (cider-repl-buffer-name))))))))))
+(defun cider-get-repl-buffer ()
+ "Return the REPL buffer for current connection."
+ (let ((buffer (get-buffer-create (cider-current-repl-buffer))))
+ (if (buffer-live-p buffer)
+ buffer
+ (error "No active REPL"))))
+
;;; REPL interaction
(defun cider-repl--in-input-area-p ()
@@ -685,6 +679,7 @@ namespace to switch to."
(cider-repl-handler (current-buffer))))
(error "Cannot determine the current namespace")))
+
;;;;; History
(defcustom cider-repl-wrap-history nil
@@ -904,6 +899,7 @@ constructs."
(append (cl-subseq session-hist 0 n-added-items)
file-hist))
+
;;; REPL shortcuts
(defcustom cider-repl-shortcut-dispatch-char ?\,
"Character used to distinguish REPL commands from Lisp forms."
@@ -952,7 +948,7 @@ constructs."
(call-interactively (gethash command cider-repl-shortcuts))
(error "No command selected")))))
-
+
;;;;; CIDER REPL mode
;;; Prevent paredit from inserting some inappropriate spaces.
diff --git a/cider-selector.el b/cider-selector.el
index 308e8ccc..070f1b4f 100644
--- a/cider-selector.el
+++ b/cider-selector.el
@@ -32,7 +32,7 @@
(require 'cider-client)
(require 'cider-interaction)
-(require 'cider-repl) ; for cider-find-or-create-repl-buffer
+(require 'cider-repl) ; for cider-get-repl-buffer
(defconst cider-selector-help-buffer "*Selector Help*"
"The name of the selector's help buffer.")
@@ -135,7 +135,7 @@ is chosen. The returned buffer is selected with
(def-cider-selector-method ?r
"Current REPL buffer."
- (cider-find-or-create-repl-buffer))
+ (cider-get-repl-buffer))
(def-cider-selector-method ?n
"Connections browser buffer."
@@ -153,7 +153,7 @@ is chosen. The returned buffer is selected with
(def-cider-selector-method ?s
"Cycle to the next CIDER connection's REPL."
(cider-rotate-connection)
- (cider-find-or-create-repl-buffer))
+ (cider-get-repl-buffer))
(provide 'cider-selector)
diff --git a/cider.el b/cider.el
index 86566d04..a304669c 100644
--- a/cider.el
+++ b/cider.el
@@ -117,28 +117,17 @@ start the server."
(let* ((project (when prompt-project
(read-directory-name "Project: ")))
(project-dir (nrepl-project-directory-for
- (or project (nrepl-current-dir)))))
+ (or project (nrepl-current-dir))))
+ (lein-params (if prompt-project
+ (read-string (format "nREPL server command: %s "
+ cider-lein-command)
+ cider-lein-parameters)
+ cider-lein-parameters))
+ (cmd (format "%s %s" cider-lein-command lein-params)))
(when (nrepl-check-for-repl-buffer nil project-dir)
- (let* ((nrepl-project-dir project-dir)
- (lein-params (if prompt-project
- (read-string (format "nREPL server command: %s " cider-lein-command) cider-lein-parameters)
- cider-lein-parameters))
- (cmd (format "%s %s" cider-lein-command lein-params))
- (default-directory (or project-dir default-directory))
- (serv-buf-name (generate-new-buffer-name (nrepl-server-buffer-name)))
- (process
- (progn
- ;; the buffer has to be created before the proc:
- (get-buffer-create serv-buf-name)
- (start-file-process-shell-command "nrepl-server" serv-buf-name cmd))))
- (set-process-filter process 'nrepl-server-filter)
- (set-process-sentinel process 'nrepl-server-sentinel)
- (set-process-coding-system process 'utf-8-unix 'utf-8-unix)
- (with-current-buffer (process-buffer process)
- (setq nrepl-project-dir project-dir))
- (message "Starting nREPL server via %s..."
- (propertize cmd 'face 'font-lock-keyword-face)))))
- (message "The %s executable (specified by `cider-lein-command') isn't on your exec-path" cider-lein-command)))
+ (nrepl-start-server-process project-dir cmd)))
+ (message "The %s executable (specified by `cider-lein-command') isn't on your exec-path"
+ cider-lein-command)))
(defun cider-known-endpoint-candidates ()
"Known endpoint candidates for establishing an nREPL connection.
@@ -162,7 +151,8 @@ The returned endpoint has the label removed."
;;;###autoload
(defun cider-connect (host port)
- "Connect to an nREPL server identified by HOST and PORT."
+ "Connect to an nREPL server identified by HOST and PORT.
+Create REPL buffer and start an nREPL client connection."
(interactive (let ((known-endpoint (when cider-known-endpoints
(cider-select-known-endpoint))))
(list (or (car known-endpoint)
@@ -171,7 +161,7 @@ The returned endpoint has the label removed."
(read-string "Port: " port nil port))))))
(setq cider-current-clojure-buffer (current-buffer))
(when (nrepl-check-for-repl-buffer `(,host ,port) nil)
- (nrepl-connect host port)))
+ (nrepl-start-client-process default-directory host port t)))
(define-obsolete-function-alias
'cider
diff --git a/nrepl-client.el b/nrepl-client.el
index 104c0892..9ac2ea64 100644
--- a/nrepl-client.el
+++ b/nrepl-client.el
@@ -148,6 +148,7 @@ buffer will be hidden."
(defconst nrepl-connection-buffer-name-template "*nrepl-connection%s*")
(defconst nrepl-server-buffer-name-template "*nrepl-server%s*")
(defconst nrepl-on-connection-buffer-name-template "*nrepl-on-connection%s*")
+(defconst nrepl-decoder-buffer-name-template "*nrepl-decoder%s*")
(defun nrepl-format-buffer-name-template (buffer-name-template designation)
"Apply the DESIGNATION to the corresponding BUFFER-NAME-TEMPLATE."
@@ -156,18 +157,21 @@ buffer will be hidden."
(concat nrepl-buffer-name-separator designation)
"")))
-(defun nrepl-make-buffer-name (buffer-name-template)
+(defun nrepl-make-buffer-name (buffer-name-template &optional project-dir host port)
"Generate a buffer name using BUFFER-NAME-TEMPLATE.
-The name will include the project name if available or the
-endpoint host if it is not. The name will also include the
-connection port if `nrepl-buffer-name-show-port' is true."
+If not supplied PROJECT-DIR, PORT and HOST default to the buffer local value of the
+`nrepl-project-dir' and `nrepl-endpoint'.
+
+The name will include the project name if available or the endpoint host if
+it is not. The name will also include the connection port if
+`nrepl-buffer-name-show-port' is true."
(generate-new-buffer-name
- (let ((project-name (nrepl--project-name nrepl-project-dir))
- (nrepl-proj-port (cadr nrepl-endpoint)))
+ (let ((project-name (nrepl--project-name (or project-dir nrepl-project-dir)))
+ (nrepl-proj-port (or port (cadr nrepl-endpoint))))
(nrepl-format-buffer-name-template
buffer-name-template
- (concat (if project-name project-name (car nrepl-endpoint))
+ (concat (if project-name project-name (or host (car nrepl-endpoint)))
(if (and nrepl-proj-port nrepl-buffer-name-show-port)
(format ":%s" nrepl-proj-port) ""))))))
@@ -175,21 +179,34 @@ connection port if `nrepl-buffer-name-show-port' is true."
"Apply a prefix to BUFFER-NAME that will hide the buffer."
(concat (if nrepl-hide-special-buffers " " "") buffer-name))
-(defun nrepl-connection-buffer-name ()
- "Return the name of the connection buffer."
+(defun nrepl-connection-buffer-name (&optional project-dir host port)
+ "Return the name of the connection buffer.
+PROJECT-DIR, PORT and HOST are as in `/nrepl-make-buffer-name'."
(nrepl--make-hidden-name
- (nrepl-make-buffer-name nrepl-connection-buffer-name-template)))
+ (nrepl-make-buffer-name nrepl-connection-buffer-name-template
+ project-dir host port)))
-(defun nrepl-server-buffer-name ()
- "Return the name of the server buffer."
+(defun nrepl-server-buffer-name (&optional project-dir host port)
+ "Return the name of the server buffer.
+PROJECT-DIR, PORT and HOST are as in `nrepl-make-buffer-name'."
(nrepl--make-hidden-name
- (nrepl-make-buffer-name nrepl-server-buffer-name-template)))
+ (nrepl-make-buffer-name nrepl-server-buffer-name-template
+ project-dir host port)))
-(defun nrepl-on-connection-buffer-name ()
- "Return the name of the on-connection buffer."
+(defun nrepl-on-connection-buffer-name (&optional project-dir host port)
+ "Return the name of the on-connection buffer.
+PROJECT-DIR, PORT and HOST are as in `nrepl-make-buffer-name'."
(nrepl--make-hidden-name
- (nrepl-make-buffer-name nrepl-on-connection-buffer-name-template)))
+ (nrepl-make-buffer-name nrepl-on-connection-buffer-name-template
+ project-dir host port)))
+(defun nrepl-decoder-buffer-name (&optional project-dir host port)
+ "Return the name of the buffer used for bencode decoding.
+PROJECT-DIR, PORT and HOST are as in `nrepl-make-buffer-name'."
+ ;; this might go away if bdecode is rewriten by direct decoding of the sring
+ (nrepl--make-hidden-name
+ (nrepl-make-buffer-name nrepl-decoder-buffer-name-template
+ project-dir host port)))
;;; Buffer Local Declarations
@@ -198,6 +215,7 @@ connection port if `nrepl-buffer-name-show-port' is true."
(defvar-local nrepl-connection-buffer nil)
(defvar-local nrepl-server-buffer nil)
(defvar-local nrepl-repl-buffer nil)
+(defvar-local nrepl-decoder-buffer nil)
(defvar-local nrepl-endpoint nil)
(defvar-local nrepl-project-dir nil)
(defvar-local nrepl-on-connection-buffer nil)
@@ -315,29 +333,25 @@ Remove the processed data from the buffer if the decode successful."
;; Decoding and dispatching of the server responses happens in
;; `nrepl-client-filter'.
-(defvar nrepl-decode-timeout 0.01
+(defvar nrepl-decode-timeout 0.025
"Seconds to wait before decoding nREPL output.")
(defun nrepl-client-filter (process string)
"Decode the message(s) from PROCESS contained in STRING and dispatch."
- (with-current-buffer (process-buffer process)
+ (with-current-buffer (get-buffer-create
+ (buffer-local-value 'nrepl-decoder-buffer
+ (process-buffer process)))
(goto-char (point-max))
- (insert string))
- ;; end of the dict maybe?
- (when (eq ?e (aref string (1- (length string))))
- ;; wait a bit to make sure we are at the real end
- (unless (accept-process-output process nrepl-decode-timeout)
- (nrepl--handle-process-output process))))
-
-(defun nrepl--handle-process-output (process)
- "Handle all complete messages from PROCESS."
- (with-current-buffer (process-buffer process)
- (let ((nrepl-connection-dispatch (current-buffer)))
- ;; FIXME: An ugly fix for https://github.com/clojure-emacs/cider/issues/583
- (while (and (not (derived-mode-p 'cider-repl-mode)) (> (buffer-size) 1))
+ (insert string)
+ ;; at the end of the dict?
+ (when (eq ?e (aref string (1- (length string))))
+ ;; we are good to go if no new output came within the timeout
+ (unless (accept-process-output process nrepl-decode-timeout)
(let ((responses (nrepl-decode-current-buffer)))
- (dolist (r responses)
- (nrepl--dispatch-response r)))))))
+ ;; callbacks are executed in the connection buffer
+ (with-current-buffer (process-buffer process)
+ (dolist (r responses)
+ (nrepl--dispatch-response r))))))))
(defun nrepl--dispatch-response (response)
"Dispatch the RESPONSE to associated callback.
@@ -360,7 +374,8 @@ process buffer and run the hook `nrepl-disconnected-hook'."
(if (equal (process-status process) 'closed)
(progn
(with-current-buffer (process-buffer process)
- (when (get-buffer nrepl-repl-buffer)
+ (when (and nrepl-repl-buffer
+ (get-buffer nrepl-repl-buffer))
(kill-buffer nrepl-repl-buffer))
(kill-buffer (current-buffer)))
(run-hooks 'nrepl-disconnected-hook))))
@@ -368,60 +383,87 @@ process buffer and run the hook `nrepl-disconnected-hook'."
;;; Client: Initialization
-;; `nrepl-connect' is called from `nrepl-server-filter' and starts the client
-;; process described by `nrepl-client-filter' and `nrepl-client-sentinel'.
-(defun nrepl-connect (host port)
- "Connect to a running nREPL server running on HOST and PORT."
- (message "Connecting to nREPL server on %s:%s..." host port)
- (let* ((nrepl-endpoint `(,host ,port))
- (process (open-network-stream "nrepl"
- (nrepl-make-connection-buffer)
- host
- port)))
- (set-process-filter process 'nrepl-client-filter)
- (set-process-sentinel process 'nrepl-client-sentinel)
- (set-process-coding-system process 'utf-8-unix 'utf-8-unix)
- (with-current-buffer (process-buffer process)
- (setq nrepl-endpoint `(,host ,port)))
- (let ((nrepl-connection-dispatch (buffer-name (process-buffer process))))
- (nrepl-init-client-sessions process)
- (nrepl-request:describe (nrepl--make-describe-handler (process-buffer process))))
- process))
-
-(defun nrepl--make-describe-handler (process-buffer)
- "Return a handler to describe into PROCESS-BUFFER."
+;; `nrepl-start-client-process' is called from `nrepl-server-filter'. It
+;; starts the client process described by `nrepl-client-filter' and
+;; `nrepl-client-sentinel'.
+(defun nrepl-start-client-process (&optional directory host port replp server-proc)
+ "Create new client process identified by DIRECTORY, HOST and PORT.
+If DIRECTORY is nil, use `default-directory'. If eitehr HOST or PORT are
+nil, pick them from the value returned by `nrepl-connection-endpoint'. If
+REPLP is non-nil create a client connection which is associated with a repl
+buffer. When non-nil, SERVER-PROC must be a running nrepl server process
+within emacs. Return the newly created client connection process."
+ (let* ((endpoint (if (functionp nrepl-connection-endpoint)
+ (funcall nrepl-connection-endpoint directory port)
+ (nrepl--default-endpoint directory port)))
+ (directory (or directory default-directory))
+ (host (or host (plist-get endpoint :hostname)))
+ (port (or port (plist-get endpoint :port)))
+ (proc-buffer-name (plist-get endpoint :proc-buffer-name))
+ (server-buf (and server-proc
+ (buffer-name (process-buffer server-proc))))
+ (client-buf (if replp
+ (cider-repl-create directory host port)
+ (nrepl-create-connection-buffer directory host port)))
+ (client-proc (open-network-stream "nrepl" client-buf host port))
+ (nrepl-connection-dispatch client-buf))
+
+ (set-process-filter client-proc 'nrepl-client-filter)
+ (set-process-sentinel client-proc 'nrepl-client-sentinel)
+ (set-process-coding-system client-proc 'utf-8-unix 'utf-8-unix)
+
+ (with-current-buffer client-buf
+ (when server-buf
+ (setq nrepl-project-dir (buffer-local-value 'nrepl-project-dir
+ (get-buffer server-buf))
+ nrepl-server-buffer server-buf))
+ (setq nrepl-endpoint `(,host ,port)
+ ;; fixme: repl and connection buffers are the same thing
+ nrepl-connection-buffer client-buf
+ nrepl-repl-buffer (when replp client-buf)
+ nrepl-on-connection-buffer proc-buffer-name
+ nrepl-decoder-buffer (nrepl-decoder-buffer-name directory host port)))
+
+ ;; Everything is set. We are ready to send requests.
+ (nrepl-request:clone (nrepl--new-tooling-session-handler client-proc))
+ (nrepl-request:clone (nrepl--new-session-handler client-proc))
+ (when replp
+ (nrepl-request:describe (nrepl--init-repl-handler client-buf t)))
+ client-proc))
+
+(defun nrepl--init-repl-handler (connection-buffer replp)
+ "Return a handler to describe into CONNECTION-BUFFER."
(lambda (response)
(nrepl-dbind-response response (ops versions)
- (with-current-buffer process-buffer
+ (with-current-buffer connection-buffer
(setq nrepl-ops ops)
(setq nrepl-versions versions)))
- (cider-make-repl (get-buffer-process process-buffer))
- (nrepl-make-repl-connection-default process-buffer)
- (cider-verify-required-nrepl-ops)
+ (when replp
+ (cider-repl-init connection-buffer))
+ (nrepl-make-connection-default connection-buffer)
+ (cider--check-required-nrepl-ops)
(cider--check-middleware-compatibility)))
(defun nrepl--new-session-handler (process)
"Create a new session handler for PROCESS."
(lambda (response)
- (nrepl-dbind-response response (id new-session)
+ (nrepl-dbind-response response (id new-session err)
(remhash id nrepl-pending-requests)
- (let ((connection-buffer (process-buffer process)))
- (setq nrepl-session new-session
- nrepl-connection-buffer connection-buffer)
- (run-hooks 'nrepl-connected-hook)))))
+ (if new-session
+ (with-current-buffer (process-buffer process)
+ (setq nrepl-session new-session))
+ (error "Could not create new session (%s)" err))
+ (run-hooks 'nrepl-connected-hook))))
(defun nrepl--new-tooling-session-handler (process)
"Create a new tooling session handler for PROCESS."
(lambda (response)
- (nrepl-dbind-response response (id new-session)
- (with-current-buffer (process-buffer process)
- (setq nrepl-tooling-session new-session)
- (remhash id nrepl-pending-requests)))))
-
-(defun nrepl-init-client-sessions (process)
- "Initialize client sessions for PROCESS."
- (nrepl-request:clone (nrepl--new-session-handler process))
- (nrepl-request:clone (nrepl--new-tooling-session-handler process)))
+ (nrepl-dbind-response response (id new-session err)
+ (if new-session
+ (with-current-buffer (process-buffer process)
+ (remhash id nrepl-pending-requests)
+ (setq nrepl-tooling-session new-session))
+ (error "Could not create new tooling session (%s)")))))
(defun nrepl--port-from-file (file)
"Attempts to read port from a file named by FILE."
@@ -628,13 +670,12 @@ The result is a plist with keys :value, :stderr and :stdout."
(nrepl-send-request request (nrepl-sync-request-handler (current-buffer)))
(while (or (null nrepl-last-sync-response)
(null (plist-get nrepl-last-sync-response :done)))
- (accept-process-output nil 0.005)
+ (accept-process-output nil 0.01)
;; break out in case we don't receive a response for a while
(when nrepl-sync-request-timeout
(let ((seconds-ellapsed (cadr (time-subtract (current-time) nrepl-last-sync-request-timestamp))))
(when (> seconds-ellapsed nrepl-sync-request-timeout)
- (error "Sync nREPL request %s timed out" request)
- (keyboard-quit)))))
+ (error "nREPL sync request timed out %s" request)))))
nrepl-last-sync-response))
(defun nrepl-sync-request:eval (input &optional ns session)
@@ -646,11 +687,29 @@ If NS is non-nil, include it in the request. SESSION defaults to current session
;;; Server
-;; The server side process is started by `cider-jack-in' and has a very simple
-;; filter that pipes its output directly into its process buffer
+;; The server side process is started by `nrepl-start-server-process' and has a
+;; very simple filter that pipes its output directly into its process buffer
;; (*nrepl-server*). The main purpose of this process is to start the actual
-;; nrepl communication client (`nrepl-client-filter') once the message "nREPL
+;; nrepl communication client (`nrepl-client-filter') when the message "nREPL
;; server started on port ..." is detected.
+
+(defun nrepl-start-server-process (directory cmd)
+ "Start nREPL server process in DIRECTORY using shell command CMD.
+Return a newly created process."
+ (let* ((default-directory (or directory default-directory))
+ (serv-buf (get-buffer-create (generate-new-buffer-name
+ (nrepl-server-buffer-name directory))))
+ (serv-proc (start-file-process-shell-command
+ "nrepl-server" serv-buf cmd)))
+ (set-process-filter serv-proc 'nrepl-server-filter)
+ (set-process-sentinel serv-proc 'nrepl-server-sentinel)
+ (set-process-coding-system serv-proc 'utf-8-unix 'utf-8-unix)
+ (with-current-buffer serv-buf
+ (setq nrepl-project-dir directory))
+ (message "Starting nREPL server via %s..."
+ (propertize cmd 'face 'font-lock-keyword-face))
+ serv-proc))
+
(defun nrepl-server-filter (process output)
"Process nREPL server output from PROCESS contained in OUTPUT."
(with-current-buffer (process-buffer process)
@@ -661,21 +720,11 @@ If NS is non-nil, include it in the request. SESSION defaults to current session
(let ((port (string-to-number (match-string 1 output))))
(message (format "nREPL server started on %s" port))
(with-current-buffer (process-buffer process)
- (let* ((endpoint (if (functionp nrepl-connection-endpoint)
- (funcall nrepl-connection-endpoint
- default-directory port)
- (nrepl--default-endpoint default-directory port)))
- (hostname (plist-get endpoint :hostname))
- (port (plist-get endpoint :port))
- (proc-buffer-name (plist-get endpoint :proc-buffer-name)))
- (let ((nrepl-process (nrepl-connect hostname port)))
- (setq nrepl-connection-buffer
- (buffer-name (process-buffer nrepl-process)))
- (with-current-buffer (process-buffer nrepl-process)
- (setq nrepl-server-buffer (buffer-name (process-buffer process))
- nrepl-project-dir (buffer-local-value
- 'nrepl-project-dir (process-buffer process))
- nrepl-on-connection-buffer proc-buffer-name))))))))
+ (let ((client-proc (nrepl-start-client-process
+ default-directory nil port t process)))
+ ;; fixme: Bad connection tracking system. There can be multiple client
+ ;; connections per server
+ (setq nrepl-connection-buffer (buffer-name (process-buffer client-proc))))))))
(defun nrepl-server-sentinel (process event)
"Handle nREPL server PROCESS EVENT."
@@ -877,9 +926,10 @@ This is bound for the duration of the handling of that message")
tramp-current-host
nrepl-host))
-(defun nrepl-make-connection-buffer ()
- "Create an nREPL connection buffer."
- (let ((buffer (generate-new-buffer (nrepl-connection-buffer-name))))
+(defun nrepl-create-connection-buffer (&optional project-dir host port)
+ "Create an nREPL connection buffer.
+PROJECT-DIR, PORT and HOST are as in `nrepl-make-buffer-name'."
+ (let ((buffer (generate-new-buffer (nrepl-connection-buffer-name project-dir host port))))
(with-current-buffer buffer
(buffer-disable-undo)
(setq-local kill-buffer-query-functions nil))
@@ -902,7 +952,7 @@ Purge the dead buffers from the `nrepl-connection-list' beforehand."
;; VS[06-08-2014]: FIXME: Bad user api; don't burden users with management of
;; the connection list, same holds for `cider-rotate-connection'.
-(defun nrepl-make-repl-connection-default (connection-buffer)
+(defun nrepl-make-connection-default (connection-buffer)
"Make the nREPL CONNECTION-BUFFER the default connection.
Moves CONNECITON-BUFFER to the front of `nrepl-connection-list'."
(interactive (list nrepl-connection-buffer))
@@ -922,10 +972,9 @@ Also closes associated REPL and server buffers."
(setq nrepl-connection-list
(delq (buffer-name buffer) nrepl-connection-list))
(when (buffer-live-p buffer)
- (dolist (buf-name `(,(buffer-local-value 'nrepl-repl-buffer buffer)
- ,(buffer-local-value 'nrepl-server-buffer buffer)
- ,(buffer-local-value
- 'nrepl-on-connection-buffer buffer)
+ (dolist (buf-name `(,(buffer-local-value 'nrepl-server-buffer buffer)
+ ,(buffer-local-value 'nrepl-on-connection-buffer buffer)
+ ,(buffer-local-value 'nrepl-decoder-buffer buffer)
,buffer))
(when buf-name
(cider--close-buffer buf-name)))))))
@@ -1039,7 +1088,7 @@ F is a function of two arguments, the ewoc and the data at point."
"Make the connection in EWOC specified by DATA default.
Refreshes EWOC."
(interactive)
- (nrepl-make-repl-connection-default data)
+ (nrepl-make-connection-default data)
(ewoc-refresh ewoc))
(defun nrepl-connections-close-connection ()
diff --git a/test/cider-tests.el b/test/cider-tests.el
index d85272b2..b7fc131f 100644
--- a/test/cider-tests.el
+++ b/test/cider-tests.el
@@ -96,19 +96,19 @@
,@body
(mapc 'kill-buffer (list ,@buffer-names))))))
-(ert-deftest test-nrepl-make-repl-connection-default ()
+(ert-deftest test-nrepl-make-connection-default ()
(let ((connections (nrepl-connection-buffers)))
(cider-test-with-buffers
(a b)
(should (get-buffer a))
(should (get-buffer b))
;; Add one connection
- (nrepl-make-repl-connection-default a)
+ (nrepl-make-connection-default a)
(should (equal (append (list (buffer-name a)) connections)
(nrepl-connection-buffers)))
(should (equal (buffer-name a) (nrepl-current-connection-buffer)))
;; Add second connection
- (nrepl-make-repl-connection-default b)
+ (nrepl-make-connection-default b)
(should (equal (append (list (buffer-name b) (buffer-name a)) connections)
(nrepl-connection-buffers)))
(should (equal (buffer-name b) (nrepl-current-connection-buffer))))))
@@ -117,8 +117,8 @@
(let ((connections (nrepl-connection-buffers)))
(cider-test-with-buffers
(a b)
- (nrepl-make-repl-connection-default a)
- (nrepl-make-repl-connection-default b)
+ (nrepl-make-connection-default a)
+ (nrepl-make-connection-default b)
;; killing a buffer should see it purged from the connection list
(kill-buffer a)
(should (equal (append (list (buffer-name b)) connections)
@@ -168,8 +168,8 @@
(let ((connections (nrepl-connection-buffers)))
(cider-test-with-buffers
(a b)
- (nrepl-make-repl-connection-default a)
- (nrepl-make-repl-connection-default b)
+ (nrepl-make-connection-default a)
+ (nrepl-make-connection-default b)
;; closing a buffer should see it removed from the connection list
(nrepl-close a)
(should (not (buffer-live-p a)))