diff --git a/CHANGELOG.md b/CHANGELOG.md index 14da1630f..80250007c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,14 @@ ## master (unreleased) +### New features + +- [#3354](https://github.com/clojure-emacs/cider/issues/3354): Add new customization variable `cider-reuse-dead-repls` to control how dead REPL buffers are reused on new connections. + ### Bugs fixed - [#3341](https://github.com/clojure-emacs/cider/issues/3341): Escape clojure-cli args on MS-Windows on non powershell invocations. +- [#3353](https://github.com/clojure-emacs/cider/issues/3353): Fix regression which caused new connections to prompt for reusing dead REPLs. ## 1.7.0 (2023-03-23) diff --git a/cider-connection.el b/cider-connection.el index 5b4a668d5..9d0aad8fd 100644 --- a/cider-connection.el +++ b/cider-connection.el @@ -61,7 +61,6 @@ available) and the matching REPL buffer." :safe #'booleanp :package-version '(cider . "0.9.0")) -;;;###autoload (defcustom cider-merge-sessions nil "Controls session combination behaviour. @@ -69,11 +68,33 @@ Symbol `host' combines all sessions of a project associated with the same host. Symbol `project' combines all sessions of a project. All other values do not combine any sessions." - :type 'symbol + :type '(choice (const :tag "Combine all sessions with the same host" host) + (const :tag "Combine all sessions from the same project" project) + (other :tag "Do not combine any sessions")) :group 'cider :safe #'symbolp :package-version '(cider . "1.5")) +(defcustom cider-reuse-dead-repls 'prompt + "How to deal with existing dead REPL buffers when initializing a connection. + +Possible choices are `prompt', `auto', `any', and nil. +- `prompt' means to always ask the user for a decision. +- `auto' means to automatically reuse a dead REPL without prompting the user + if it is the only available option. When there are multiple buffers to + choose from, the user is is prompted for a choice. +- `any' (or any other non-nil value) means to reuse any dead REPL buffer + available, by default the most relevant according to various heuristics, + and never prompt the user. +- nil means to start a new REPL each time, ignoring existing buffers." + :type '(choice (const :tag "Always prompt for what to do with dead REPLs" prompt) + (const :tag "Reuse dead REPL, prompting only for multiple choice" auto) + (const :tag "Reuse any available dead REPL and never prompt" any) + (const :tag "Never reuse dead REPLs" nil)) + :group 'cider + :safe #'symbolp + :package-version '(cider . "1.8")) + (defconst cider-required-nrepl-version "0.6.0" "The minimum nREPL version that's known to work properly with CIDER.") @@ -819,28 +840,27 @@ PARAMS is a plist as received by `cider-repl-create'." (let* ((proj-dir (plist-get params :project-dir)) (host (plist-get params :host)) (port (plist-get params :port)) - (cljsp (eq (plist-get params :repl-type) 'cljs)) + (type (plist-get params :repl-type)) (scored-repls - (delq nil - (mapcar (lambda (b) - (let ((bparams (cider--gather-connect-params nil b))) - (when (and cljsp - (eq (plist-get bparams :repl-type) - '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)))))))) + (mapcar (lambda (b) + (let ((bparams (cider--gather-connect-params nil b))) + (when (eq type (plist-get bparams :repl-type)) + (cons 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)) + (sorted-repls (mapcar #'car (seq-sort-by #'cdr #'> (delq nil scored-repls))))) + (when sorted-repls + (cond ((eq 'any cider-reuse-dead-repls) + (car sorted-repls)) + ((= 1 (length sorted-repls)) + (when (or (eq 'auto cider-reuse-dead-repls) + (y-or-n-p (format "A dead REPL %s exists. Reuse buffer? " (car sorted-repls)))) + (car sorted-repls))) + ((y-or-n-p "Dead REPL buffers exist. Select one to reuse? ") + (get-buffer (completing-read "REPL buffer to reuse: " (mapcar #'buffer-name sorted-repls) + nil t nil nil (car sorted-repls))))))))) (declare-function cider-default-err-handler "cider-eval") (declare-function cider-repl-mode "cider-repl") @@ -858,7 +878,8 @@ 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) + (and cider-reuse-dead-repls + (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)))) diff --git a/doc/modules/ROOT/pages/usage/managing_connections.adoc b/doc/modules/ROOT/pages/usage/managing_connections.adoc index 9b46b1340..73b6907a5 100644 --- a/doc/modules/ROOT/pages/usage/managing_connections.adoc +++ b/doc/modules/ROOT/pages/usage/managing_connections.adoc @@ -192,3 +192,18 @@ name and the REPL type specification post-fix You can customize session names with `cider-session-name-template` and REPL names with `nrepl-repl-buffer-name-template`. See also `cider-format-connection-params` for available formats. + +== Reusing dead REPLs + +Under normal circumstances, CIDER automatically kills the REPL buffers and cleans up after itself when ending a session. +However, when a session is terminated unexpectedly, e.g. when it crashes or is disconnected from an external server process, the REPL buffer is left without an active connection and outputs a log: + +[source] +---- +*** Closed on < date/time > *** +---- + +Upon starting a new connection, CIDER can detect these "dead REPLs" and offer to reuse the buffer for the new connection. +By default, it prompts for confirmation whenever a dead REPL buffer is available for reuse, but you can customize this behaviour via the variable `cider-reuse-dead-repls`. +Setting it to `auto` reuses a dead REPL buffer automatically, and only displays a prompt when there are multiple options to choose from. +To suppress the prompt entirely, set it to `nil` to always start a new REPL buffer, or `any` to reuse the most relevant dead REPL.