summaryrefslogtreecommitdiff
path: root/cider-connection.el
diff options
context:
space:
mode:
Diffstat (limited to 'cider-connection.el')
-rw-r--r--cider-connection.el172
1 files changed, 118 insertions, 54 deletions
diff --git a/cider-connection.el b/cider-connection.el
index 959b78e5..0a727fde 100644
--- a/cider-connection.el
+++ b/cider-connection.el
@@ -1,6 +1,6 @@
;;; cider-connection.el --- Connection and session life-cycle management for CIDER -*- lexical-binding: t -*-
;;
-;; Copyright © 2018 Artur Malabarba, Bozhidar Batsov, Vitalie Spinu and CIDER contributors
+;; Copyright © 2019 Artur Malabarba, Bozhidar Batsov, Vitalie Spinu and CIDER contributors
;;
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
;; Bozhidar Batsov <bozhidar@batsov.com>
@@ -156,7 +156,7 @@ buffer."
;; inform sentinel not to kill the server, if any
(thread-first (get-buffer-process repl)
(process-plist)
- (plist-put :no-server-kill t))))
+ (plist-put :keep-server t))))
(let ((proc (get-buffer-process repl)))
(when (and (process-live-p proc)
(or (not nrepl-server-buffer)
@@ -167,11 +167,7 @@ buffer."
(when-let* ((messages-buffer (and nrepl-log-messages
(nrepl-messages-buffer repl))))
(kill-buffer messages-buffer))
- (if no-kill
- (with-current-buffer repl
- (goto-char (point-max))
- (cider-repl-emit-interactive-stderr
- (format "*** Closed on %s ***\n" (current-time-string))))
+ (unless no-kill
(kill-buffer repl)))
(when repl
(sesman-remove-object 'CIDER nil repl (not no-kill) t)))
@@ -328,7 +324,7 @@ Clojure version. When GENERICP is non-nil, don't provide specific info
about this buffer (like variable `cider-repl-type')."
(with-current-buffer connection-buffer
(format "%s%s@%s:%s (Java %s, Clojure %s, nREPL %s)"
- (if genericp "" (upcase (concat cider-repl-type " ")))
+ (if genericp "" (upcase (concat (symbol-name cider-repl-type) " ")))
(or (cider--project-name nrepl-project-dir) "<no project>")
(plist-get nrepl-endpoint :host)
(plist-get nrepl-endpoint :port)
@@ -421,6 +417,32 @@ REPL defaults to the current REPL."
(cl-defmethod sesman-more-relevant-p ((_system (eql CIDER)) session1 session2)
(sesman-more-recent-p (cdr session1) (cdr session2)))
+(cl-defmethod sesman-friendly-session-p ((_system (eql CIDER)) session)
+ (setcdr session (seq-filter #'buffer-live-p (cdr session)))
+ (when-let* ((repl (cadr session))
+ (proc (get-buffer-process repl))
+ (file (file-truename (or (buffer-file-name) default-directory))))
+ ;; With avfs paths look like /path/to/.avfs/path/to/some.jar#uzip/path/to/file.clj
+ (when (string-match-p "#uzip" file)
+ (let ((avfs-path (directory-file-name (expand-file-name (or (getenv "AVFSBASE") "~/.avfs/")))))
+ (setq file (replace-regexp-in-string avfs-path "" file t t))))
+ (when (process-live-p proc)
+ (let* ((classpath (or (process-get proc :cached-classpath)
+ (let ((cp (with-current-buffer repl
+ (cider-sync-request:classpath))))
+ (process-put proc :cached-classpath cp)
+ cp)))
+ (classpath-roots (or (process-get proc :cached-classpath-roots)
+ (let ((cp (thread-last classpath
+ (seq-filter (lambda (path) (not (string-match-p "\\.jar$" path))))
+ (mapcar #'file-name-directory))))
+ (process-put proc :cached-classpath-roots cp)
+ cp))))
+ (or (seq-find (lambda (path) (string-prefix-p path file))
+ classpath)
+ (seq-find (lambda (path) (string-prefix-p path file))
+ classpath-roots))))))
+
(defvar cider-sesman-browser-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "j q") #'cider-quit)
@@ -532,7 +554,7 @@ removed."
""
host))
(repl-type (or (plist-get params :repl-type) "unknown"))
- (cljs-repl-type (or (and (equal repl-type "cljs")
+ (cljs-repl-type (or (and (eq repl-type 'cljs)
(plist-get params :cljs-repl-type))
""))
(specs `((?h . ,host)
@@ -567,10 +589,10 @@ Session name can be customized with `cider-session-name-template'."
;;; REPL Buffer Init
(defvar-local cider-cljs-repl-type nil
- "The type of the CLJS runtime (Nashorn, Node etc.)")
+ "The type of the ClojureScript runtime (Nashorn, Node etc.)")
(defvar-local cider-repl-type nil
- "The type of this REPL buffer, usually either \"clj\" or \"cljs\".")
+ "The type of this REPL buffer, usually either clj or cljs.")
(defun cider-repl-type (repl-buffer)
"Get REPL-BUFFER's type."
@@ -579,23 +601,23 @@ Session name can be customized with `cider-session-name-template'."
(defun cider-repl-type-for-buffer (&optional buffer)
"Return the matching connection type (clj or cljs) for BUFFER.
BUFFER defaults to the `current-buffer'. In cljc buffers return
-\"multi\". This function infers connection type based on the major mode.
+multi. This function infers connection type based on the major mode.
For the REPL type use the function `cider-repl-type'."
(with-current-buffer (or buffer (current-buffer))
(cond
- ((derived-mode-p 'clojurescript-mode) "cljs")
- ((derived-mode-p 'clojurec-mode) "multi")
- ((derived-mode-p 'clojure-mode) "clj")
+ ((derived-mode-p 'clojurescript-mode) 'cljs)
+ ((derived-mode-p 'clojurec-mode) 'multi)
+ ((derived-mode-p 'clojure-mode) 'clj)
(cider-repl-type))))
(defun cider-set-repl-type (&optional type)
- "Set REPL TYPE to \"clj\" or \"cljs\".
+ "Set REPL TYPE to clj or cljs.
Assume that the current buffer is a REPL."
(interactive)
- (let ((type (or type (completing-read
- (format "Set REPL type (currently `%s') to: "
- cider-repl-type)
- '("clj" "cljs")))))
+ (let ((type (cider-maybe-intern (or type (completing-read
+ (format "Set REPL type (currently `%s') to: "
+ cider-repl-type)
+ '(clj cljs))))))
(when (or (not (equal cider-repl-type type))
(null mode-name))
(setq cider-repl-type type)
@@ -609,6 +631,41 @@ Assume that the current buffer is a REPL."
(with-current-buffer nrepl-messages-buffer
(rename-buffer (nrepl-messages-buffer-name params))))))))
+(defun cider--choose-reusable-repl-buffer (params)
+ "Find connection-less REPL buffer and ask the user for confirmation.
+Return nil if no such buffers exists or the user has chosen not to reuse
+the buffer. If multiple dead REPLs exist, ask the user to choose one.
+PARAMS is a plist as received by `cider-repl-create'."
+ (when-let* ((repls (seq-filter (lambda (b)
+ (with-current-buffer b
+ (and (derived-mode-p 'cider-repl-mode)
+ (not (process-live-p (get-buffer-process b))))))
+ (buffer-list))))
+ (let* ((proj-dir (plist-get params :project-dir))
+ (host (plist-get params :host))
+ (port (plist-get params :port))
+ (cljsp (member (plist-get params :repl-type) '(cljs pending-cljs)))
+ (scored-repls
+ (delq nil
+ (mapcar (lambda (b)
+ (let ((bparams (cider--gather-connect-params nil b)))
+ (when (eq cljsp (member (plist-get bparams :repl-type)
+ '(cljs pending-cljs)))
+ (cons (buffer-name b)
+ (+
+ (if (equal proj-dir (plist-get bparams :project-dir)) 8 0)
+ (if (equal host (plist-get bparams :host)) 4 0)
+ (if (equal port (plist-get bparams :port)) 2 0))))))
+ repls))))
+ (when scored-repls
+ (if (> (length scored-repls) 1)
+ (when (y-or-n-p "Dead REPLs exist. Reuse? ")
+ (let ((sorted-repls (seq-sort (lambda (a b) (> (cdr a) (cdr b))) scored-repls)))
+ (get-buffer (completing-read "REPL to reuse: "
+ (mapcar #'car sorted-repls) nil t nil nil (caar sorted-repls)))))
+ (when (y-or-n-p (format "A dead REPL %s exists. Reuse? " (caar scored-repls)))
+ (get-buffer (caar scored-repls))))))))
+
(declare-function cider-default-err-handler "cider-eval")
(declare-function cider-repl-mode "cider-repl")
(declare-function cider-repl--state-handler "cider-repl")
@@ -624,6 +681,7 @@ function with the repl buffer set as current."
;; Connection might not have been set as yet. Please don't send requests in
;; this function, but use cider--connected-handler instead.
(let ((buffer (or (plist-get params :repl-buffer)
+ (cider--choose-reusable-repl-buffer params)
(get-buffer-create (generate-new-buffer-name "*cider-uninitialized-repl*"))))
(ses-name (or (plist-get params :session-name)
(cider-make-session-name params))))
@@ -645,8 +703,8 @@ function with the repl buffer set as current."
cider-repl-init-function (plist-get params :repl-init-function))
(cider-repl-reset-markers)
(add-hook 'nrepl-response-handler-functions #'cider-repl--state-handler nil 'local)
- (add-hook 'nrepl-connected-hook 'cider--connected-handler nil 'local)
- (add-hook 'nrepl-disconnected-hook 'cider--disconnected-handler nil 'local)
+ (add-hook 'nrepl-connected-hook #'cider--connected-handler nil 'local)
+ (add-hook 'nrepl-disconnected-hook #'cider--disconnected-handler nil 'local)
(current-buffer))))
@@ -655,7 +713,7 @@ function with the repl buffer set as current."
(defun cider--no-repls-user-error (type)
"Throw \"No REPL\" user error customized for TYPE."
(let ((type (cond
- ((equal type "multi")
+ ((or (eq type 'multi) (eq type 'any))
"clj or cljs")
((listp type)
(mapconcat #'identity type " or "))
@@ -665,41 +723,47 @@ function with the repl buffer set as current."
(defun cider-current-repl (&optional type ensure)
"Get the most recent REPL of TYPE from the current session.
-TYPE is either \"clj\", \"cljs\" or \"multi\". When nil, infer the type
-from the current buffer. If ENSURE is non-nil, throw an error if either
-there is no linked session or there is no REPL of TYPE within the current
-session."
- (if (and (derived-mode-p 'cider-repl-mode)
- (or (null type)
- (string= cider-repl-type type)))
- ;; shortcut when in REPL buffer
- (current-buffer)
- (let* ((type (or type (cider-repl-type-for-buffer)))
- (repls (cider-repls type ensure))
- (repl (if (<= (length repls) 1)
- (car repls)
- ;; pick the most recent one
- (seq-find (lambda (b)
- (member b repls))
- (buffer-list)))))
- (if (and ensure (null repl))
- (cider--no-repls-user-error type)
- repl))))
+TYPE is either clj, cljs, multi or any.
+When nil, infer the type from the current buffer.
+If ENSURE is non-nil, throw an error if either there is
+no linked session or there is no REPL of TYPE within the current session."
+ (let ((type (cider-maybe-intern type)))
+ (if (and (derived-mode-p 'cider-repl-mode)
+ (or (null type)
+ (eq 'any type)
+ (eq cider-repl-type type)))
+ ;; shortcut when in REPL buffer
+ (current-buffer)
+ (let* ((type (or type (cider-repl-type-for-buffer)))
+ (repls (cider-repls type ensure))
+ (repl (if (<= (length repls) 1)
+ (car repls)
+ ;; pick the most recent one
+ (seq-find (lambda (b)
+ (member b repls))
+ (buffer-list)))))
+ (if (and ensure (null repl))
+ (cider--no-repls-user-error type)
+ repl)))))
(defun cider--match-repl-type (type buffer)
"Return non-nil if TYPE matches BUFFER's REPL type."
(let ((buffer-repl-type (cider-repl-type buffer)))
(cond ((null buffer-repl-type) nil)
- ((or (null type) (equal type "multi")) t)
+ ((or (null type) (eq type 'multi) (eq type 'any)) t)
((listp type) (member buffer-repl-type type))
(t (string= type buffer-repl-type)))))
(defun cider-repls (&optional type ensure)
"Return cider REPLs of TYPE from the current session.
-If TYPE is nil or \"multi\", return all repls. If TYPE is a list of types,
+If TYPE is nil or multi, return all repls. If TYPE is a list of types,
return only REPLs of type contained in the list. If ENSURE is non-nil,
throw an error if no linked session exists."
- (let ((repls (cdr (if ensure
+ (let ((type (cond
+ ((listp type)
+ (mapcar #'cider-maybe-intern type))
+ ((cider-maybe-intern type))))
+ (repls (cdr (if ensure
(sesman-ensure-session 'CIDER)
(sesman-current-session 'CIDER)))))
(or (seq-filter (lambda (b)
@@ -724,15 +788,15 @@ session."
(declare (indent 1))
(let ((cur-type (cider-repl-type-for-buffer)))
(cl-case which
- (:clj-strict (when (equal cur-type "cljs")
+ (:clj-strict (when (eq cur-type 'cljs)
(user-error "Clojure-only operation requested in a ClojureScript buffer")))
- (:cljs-strict (when (equal cur-type "clj")
+ (:cljs-strict (when (eq cur-type 'clj)
(user-error "ClojureScript-only operation requested in a Clojure buffer"))))
(let* ((type (cl-case which
- ((:clj :clj-strict) "clj")
- ((:cljs :cljs-strict) "cljs")
- (:auto (if (equal cur-type "multi")
- '("clj" "cljs")
+ ((:clj :clj-strict) 'clj)
+ ((:cljs :cljs-strict) 'cljs)
+ (:auto (if (eq cur-type 'multi)
+ '(clj cljs)
cur-type))))
(repls (cider-repls type 'ensure)))
(mapcar function repls))))
@@ -764,11 +828,11 @@ session."
(make-obsolete 'cider-current-messages-buffer nil "0.18")
(make-obsolete 'cider-default-connection "see sesman." "0.18")
(make-obsolete 'cider-extract-designation-from-current-repl-buffer nil "0.18")
-(make-obsolete 'cider-find-connection-buffer-for-project-directory 'sesman-linked-sessions "0.18")
+(make-obsolete 'cider-find-connection-buffer-for-project-directory 'sesman-current-sessions "0.18")
(make-obsolete 'cider-find-reusable-repl-buffer nil "0.18")
(make-obsolete 'cider-make-connection-default "see sesman." "0.18")
(make-obsolete 'cider-other-connection nil "0.18")
-(make-obsolete 'cider-project-connections 'sesman-linked-sessions "0.18")
+(make-obsolete 'cider-project-connections 'sesman-current-sessions "0.18")
(make-obsolete 'cider-project-connections-types nil "0.18")
(make-obsolete 'cider-prompt-for-project-on-connect nil "0.18")
(make-obsolete 'cider-read-connection `sesman-ask-for-session "0.18")