diff options
Diffstat (limited to 'cider.el')
-rw-r--r-- | cider.el | 506 |
1 files changed, 212 insertions, 294 deletions
@@ -12,7 +12,7 @@ ;; Maintainer: Bozhidar Batsov <bozhidar@batsov.com> ;; URL: http://www.github.com/clojure-emacs/cider ;; Version: 0.18.0-snapshot -;; Package-Requires: ((emacs "24.4") (clojure-mode "5.7.0") (pkg-info "0.4") (queue "0.1.1") (spinner "1.7") (seq "2.16")) +;; Package-Requires: ((emacs "25") (clojure-mode "5.7.0") (pkg-info "0.4") (queue "0.1.1") (spinner "1.7") (seq "2.16")) ;; Keywords: languages, clojure, cider ;; This program is free software: you can redistribute it and/or modify @@ -51,10 +51,13 @@ ;;; Usage: -;; M-x cider-jack-in +;; M-x cider-jack-in-clj ;; M-x cider-jack-in-cljs ;; -;; M-x cider-connect +;; M-x cider-connect-sibling-clj +;; M-x cider-connect-sibling-cljs +;; +;; M-x cider-connect-clj ;; M-x cider-connect-cljs ;;; Code: @@ -67,23 +70,10 @@ :link '(url-link :tag "Online Manual" "https://docs.cider.mx") :link '(emacs-commentary-link :tag "Commentary" "cider")) -(defcustom cider-prompt-for-project-on-connect 'when-needed - "Controls whether to prompt for associated project on `cider-connect'. - -When set to when-needed, the project will be derived from the buffer you're -visiting, when invoking `cider-connect'. -When set to t, you'll always to prompted to select the matching project. -When set to nil, you'll never be prompted to select a project and no -project inference will take place." - :type '(choice (const :tag "always" t) - (const when-needed) - (const :tag "never" nil)) - :group 'cider - :package-version '(cider . "0.10.0")) - (require 'cider-client) (require 'cider-eldoc) (require 'cider-repl) +(require 'cider-connection) (require 'cider-mode) (require 'cider-common) (require 'subr-x) @@ -91,8 +81,8 @@ project inference will take place." (require 'cider-debug) (require 'tramp-sh) (require 'cider-repl-history) - (require 'seq) +(require 'sesman) (defconst cider-version "0.18.0-snapshot" "Fallback version used when it cannot be extracted automatically. @@ -381,9 +371,14 @@ Throws an error if PROJECT-TYPE is unknown. Known types are (cider-add-to-alist 'cider-jack-in-dependencies "org.clojure/tools.nrepl" "0.2.13") +(defvar cider-jack-in-cljs-dependencies nil + "List of dependencies where elements are lists of artifact name and version. +Added to `cider-jack-in-dependencies' when doing `cider-jack-in-cljs'.") +(put 'cider-jack-in-cljs-dependencies 'risky-local-variable t) +(cider-add-to-alist 'cider-jack-in-cljs-dependencies "cider/piggieback" "0.3.5") + (defvar cider-jack-in-dependencies-exclusions nil "List of exclusions for jack in dependencies. - Elements of the list are artifact name and list of exclusions to apply for the artifact.") (put 'cider-jack-in-dependencies-exclusions 'risky-local-variable t) (cider-add-to-alist 'cider-jack-in-dependencies-exclusions @@ -391,7 +386,6 @@ Elements of the list are artifact name and list of exclusions to apply for the a (defcustom cider-jack-in-auto-inject-clojure nil "Version of clojure to auto-inject into REPL. - If nil, do not inject Clojure into the REPL. If `latest', inject `cider-latest-clojure-version', which should approximate to the most recent version of Clojure. If `minimal', inject `cider-minimum-clojure-version', @@ -419,6 +413,12 @@ want to inject some middleware only when within a project context.)") (cider-add-to-alist 'cider-jack-in-lein-plugins "cider/cider-nrepl" (upcase cider-version)) +(defvar cider-jack-in-cljs-lein-plugins nil + "List of Leiningen plugins to be injected at jack-in. +Added to `cider-jack-in-lein-plugins' (which see) when doing +`cider-jack-in-cljs'.") +(put 'cider-jack-in-cljs-lein-plugins 'risky-local-variable t) + (defun cider-jack-in-normalized-lein-plugins () "Return a normalized list of Leiningen plugins to be injected. See `cider-jack-in-lein-plugins' for the format, except that the list @@ -444,6 +444,13 @@ the middlewares should actually be injected.") (put 'cider-jack-in-nrepl-middlewares 'risky-local-variable t) (add-to-list 'cider-jack-in-nrepl-middlewares "cider.nrepl/cider-middleware") +(defvar cider-jack-in-cljs-nrepl-middlewares nil + "List of Clojure variable names. +Added to `cider-jack-in-nrepl-middlewares' (which see) when doing +`cider-jack-in-cljs'.") +(put 'cider-jack-in-cljs-nrepl-middlewares 'risky-local-variable t) +(add-to-list 'cider-jack-in-cljs-nrepl-middlewares "cider.piggieback/wrap-cljs-repl") + (defun cider-jack-in-normalized-nrepl-middlewares () "Return a normalized list of middleware variable names. See `cider-jack-in-nrepl-middlewares' for the format, except that the list @@ -556,7 +563,6 @@ Does so by concatenating GLOBAL-OPTS, DEPENDENCIES finally PARAMS." (defun cider-add-clojure-dependencies-maybe (dependencies) "Return DEPENDENCIES with an added Clojure dependency if requested. - See also `cider-jack-in-auto-inject-clojure'." (if cider-jack-in-auto-inject-clojure (if (consp cider-jack-in-auto-inject-clojure) @@ -615,7 +621,6 @@ dependencies." (defcustom cider-check-cljs-repl-requirements t "When non-nil will run the requirement checks for the different cljs repls. - Generally you should not disable this unless you run into some faulty check." :type 'boolean :safe #'booleanp @@ -674,7 +679,6 @@ Generally you should not disable this unless you run into some faulty check." (defun cider-shadow-cljs-init-form () "Generate the init form for a shadow-cljs REPL. - We have to prompt the user to select a build, that's why this is a command, not just a string." (let ((form "(do (require '[shadow.cljs.devtools.api :as shadow]) (shadow/watch :%s) (shadow/nrepl-select :%s))") @@ -699,7 +703,6 @@ Figwheel for details." (defun cider-custom-cljs-repl-init-form () "Prompt for a form that would start a ClojureScript REPL. - The supplied string will be wrapped in a do form if needed." (let ((form (read-from-minibuffer "Please, provide a form to start a ClojureScript REPL: "))) ;; TODO: We should probably make this more robust (e.g. by using a regexp or @@ -751,7 +754,6 @@ It's intended to be used in your Emacs config." (defcustom cider-default-cljs-repl nil "The default ClojureScript REPL to start. - This affects commands like `cider-jack-in-clojurescript'. Generally it's intended to be set via .dir-locals.el for individual projects, as its relatively unlikely you'd like to use the same type of REPL in each project @@ -788,13 +790,18 @@ you're working on." repl-form) (user-error "No ClojureScript REPL type %s found. Please make sure that `cider-cljs-repl-types' has an entry for it" repl-type))) -(defun cider-verify-cljs-repl-requirements (repl-type) - "Verify that the requirements for REPL-TYPE are met." - (when-let* ((fun (nth 2 (seq-find - (lambda (entry) - (eq (car entry) repl-type)) - cider-cljs-repl-types)))) - (funcall fun))) +(defun cider-verify-cljs-repl-requirements (&optional repl-type) + "Verify that the requirements for REPL-TYPE are met. +Return REPL-TYPE if requirements are met." + (let ((repl-type (or repl-type + cider-default-cljs-repl + (cider-select-cljs-repl)))) + (when-let* ((fun (nth 2 (seq-find + (lambda (entry) + (eq (car entry) repl-type)) + cider-cljs-repl-types)))) + (funcall fun)) + repl-type)) (defun cider--offer-to-open-app-in-browser (server-buffer) "Look for a server address in SERVER-BUFFER and offer to open it." @@ -807,61 +814,6 @@ you're working on." (when (y-or-n-p (format "Visit ‘%s’ in a browser? " url)) (browse-url url))))))) -(defun cider-create-sibling-cljs-repl (client-buffer) - "Create a ClojureScript REPL with the same server as CLIENT-BUFFER. -The new buffer will correspond to the same project as CLIENT-BUFFER, which -should be the regular Clojure REPL started by the server process filter. - -Normally this would prompt for the ClojureScript REPL to start (e.g. Node, -Figwheel, etc), unless you've set `cider-default-cljs-repl'." - (interactive (list (cider-current-connection))) - ;; We can't start a ClojureScript REPL without ClojureScript - (when cider-check-cljs-repl-requirements - (cider-verify-clojurescript-is-present)) - ;; Load variables in .dir-locals.el into the server process buffer, so - ;; cider-default-cljs-repl can be set for each project individually. - (hack-local-variables) - (let* ((cljs-repl-type (or cider-default-cljs-repl - (cider-select-cljs-repl))) - (cljs-repl-form (cider-cljs-repl-form cljs-repl-type))) - (when cider-check-cljs-repl-requirements - (cider-verify-cljs-repl-requirements cljs-repl-type)) - ;; if all the requirements are met we can finally proceed with starting - ;; the ClojureScript REPL for `cljs-repl-type' - (let* ((nrepl-repl-buffer-name-template "*cider-repl%s(cljs)*") - (nrepl-create-client-buffer-function #'cider-repl-create) - (nrepl-use-this-as-repl-buffer 'new) - (client-process-args (with-current-buffer client-buffer - (unless (or nrepl-server-buffer nrepl-endpoint) - (error "This is not a REPL buffer, is there a REPL active?")) - (list (car nrepl-endpoint) - (elt nrepl-endpoint 1) - (when (buffer-live-p nrepl-server-buffer) - (get-buffer-process nrepl-server-buffer))))) - (cljs-proc (apply #'nrepl-start-client-process client-process-args)) - (cljs-buffer (process-buffer cljs-proc))) - (with-current-buffer cljs-buffer - ;; The new connection has now been bumped to the top, but it's still a - ;; Clojure REPL! Additionally, some ClojureScript REPLs can actually take - ;; a while to start (some even depend on the user opening a browser). - ;; Meanwhile, this REPL will gladly receive requests in place of the - ;; original Clojure REPL. Our solution is to bump the original REPL back - ;; up the list, so it takes priority on Clojure requests. - (cider-make-connection-default client-buffer) - (cider-repl-set-type "cljs") - (pcase cider-cljs-repl-types - (`(,name ,_ ,info) - (message "Starting a %s REPL%s" name (or info "")))) - ;; So far we have just another Clojure REPL. It's time to convert it - ;; to a ClojureScript REPL with a magic incantation. - (cider-nrepl-send-request - `("op" "eval" - "ns" ,(cider-current-ns) - "code" ,cljs-repl-form) - (cider-repl-handler (current-buffer))) - (when cider-offer-to-open-cljs-app-in-browser - (cider--offer-to-open-app-in-browser nrepl-server-buffer)))))) - (defun cider--select-zombie-buffer (repl-buffers) "Return a zombie buffer from REPL-BUFFERS, or nil if none exists." (when-let* ((zombie-buffs (seq-remove #'get-buffer-process repl-buffers))) @@ -874,159 +826,204 @@ Figwheel, etc), unless you've set `cider-default-cljs-repl'." (mapcar #'buffer-name zombie-buffs) nil t))))) -(defun cider-find-reusable-repl-buffer (endpoint project-directory) - "Check whether a reusable connection buffer already exists. -Looks for buffers where `nrepl-endpoint' matches ENDPOINT, or -`nrepl-project-dir' matches PROJECT-DIRECTORY. If such a buffer was found, -and has no process, return it. If the process is alive, ask the user for -confirmation and return 'new/nil for y/n answer respectively. If other -REPL buffers with dead process exist, ask the user if any of those should -be reused." - (if-let* ((repl-buffers (cider-repl-buffers)) - (exact-buff (seq-find - (lambda (buff) - (with-current-buffer buff - (or (and endpoint - (equal endpoint nrepl-endpoint)) - (and project-directory - (equal project-directory nrepl-project-dir))))) - repl-buffers))) - (if (get-buffer-process exact-buff) - (when (y-or-n-p (format "REPL buffer already exists (%s). \ -Do you really want to create a new one? " - exact-buff)) - 'new) - exact-buff) - (or (cider--select-zombie-buffer repl-buffers) 'new))) + +;;; Barefoot Connectors -;;;###autoload -(defun cider-jack-in (&optional prompt-project cljs-too) - "Start an nREPL server for the current project and connect to it. -If PROMPT-PROJECT is t, then prompt for the project for which to -start the server. -If CLJS-TOO is non-nil, also start a ClojureScript REPL session with its -own buffer." - (interactive "P") +(defun cider--jack-in (do-prompt on-port-callback) + "Core of all cider-jack-in-xyz functions. +Prompt for the project and nREPL server command when DO-PROMPT is non-nil. +ON-PORT-CALLBACK is passed to `nrepl-start-server-process'." + (declare (indent 1)) (let* ((project-type (cider-project-type)) (command (cider-jack-in-command project-type)) (command-resolved (cider-jack-in-resolve-command project-type)) (command-global-opts (cider-jack-in-global-options project-type)) (command-params (cider-jack-in-params project-type))) (if command-resolved - (let* ((project (when prompt-project + (let* ((project (when do-prompt (read-directory-name "Project: "))) (project-dir (clojure-project-dir (or project (cider-current-dir)))) - (params (if prompt-project - (read-string (format "nREPL server command: %s " - command-params) + (params (if do-prompt + (read-string (format "nREPL server command: %s " command-params) command-params) command-params)) (params (if cider-inject-dependencies-at-jack-in (cider-inject-jack-in-dependencies command-global-opts params project-type) - params)) - - (cmd (format "%s %s" command params))) + params))) (if (or project-dir cider-allow-jack-in-without-project) - (progn - (when (or project-dir - (eq cider-allow-jack-in-without-project t) - (and (null project-dir) - (eq cider-allow-jack-in-without-project 'warn) - (y-or-n-p "Are you sure you want to run `cider-jack-in' without a Clojure project? "))) - (when-let* ((repl-buff (cider-find-reusable-repl-buffer nil project-dir))) - (let ((nrepl-create-client-buffer-function #'cider-repl-create) - (nrepl-use-this-as-repl-buffer repl-buff)) - (nrepl-start-server-process - project-dir cmd - (when cljs-too #'cider-create-sibling-cljs-repl)))))) + (when (or project-dir + (eq cider-allow-jack-in-without-project t) + (and (null project-dir) + (eq cider-allow-jack-in-without-project 'warn) + (y-or-n-p "Are you sure you want to run `cider-jack-in' without a Clojure project? "))) + (let* ((cmd (format "%s %s" command-resolved params))) + (nrepl-start-server-process project-dir cmd on-port-callback))) (user-error "`cider-jack-in' is not allowed without a Clojure project"))) (user-error "The %s executable isn't on your `exec-path'" command)))) -(defvar cider-jack-in-cljs-dependencies nil - "List of dependencies where elements are lists of artifact name and version. -Added to `cider-jack-in-dependencies' when doing `cider-jack-in-cljs'.") -(put 'cider-jack-in-cljs-dependencies 'risky-local-variable t) -(cider-add-to-alist 'cider-jack-in-cljs-dependencies "cider/piggieback" "0.3.6") +(defun cider--check-cljs (&optional repl-type no-error) + "Verify that all cljs requirements are met for cljs REPL-TYPE. +Return REPL-TYPE of requirement are met, and throw an ‘user-error’ otherwise. +When NO-ERROR is non-nil, don't throw an error, issue a message and return +nil." + (if no-error + (condition-case ex + (progn + (cider-verify-clojurescript-is-present) + (cider-verify-cljs-repl-requirements repl-type)) + (error + (message "Invalid CLJS dependency: %S" ex) + nil)) + (cider-verify-clojurescript-is-present) + (cider-verify-cljs-repl-requirements repl-type))) + +(defun cider--cljs-init-hook-builder (cljs-repl-type) + "Create an cljs repl initializer for CLJS-REPL-TYPE." + (lambda () + (cider--check-cljs cljs-repl-type) + (cider-nrepl-send-request + (list "op" "eval" + "ns" (cider-current-ns) + "code" (cider-cljs-repl-form cljs-repl-type)) + (cider-repl-handler (current-buffer))) + (when (and (buffer-live-p nrepl-server-buffer) + cider-offer-to-open-cljs-app-in-browser) + (cider--offer-to-open-app-in-browser nrepl-server-buffer)))) -(defvar cider-jack-in-cljs-lein-plugins nil - "List of Leiningen plugins to be injected at jack-in. -Added to `cider-jack-in-lein-plugins' when doing `cider-jack-in-cljs'. -Each element is a list of artifact name and version, followed optionally by -keyword arguments. The only keyword argument currently accepted is -`:predicate', which should be given a function that takes the list (name, -version, and keyword arguments) and returns non-nil to indicate that the -plugin should actually be injected. (This is useful primarily for packages -that extend CIDER, not for users. For example, a refactoring package might -want to inject some middleware only when within a project context.)") -(put 'cider-jack-in-cljs-lein-plugins 'risky-local-variable t) + +;;; User Level Connectors -(defvar cider-jack-in-cljs-nrepl-middlewares nil - "List of Clojure variable names. -Added to `cider-jack-in-nrepl-middlewares' when doing `cider-jack-in-cljs'. -Each of these Clojure variables should hold a vector of nREPL middlewares. -Instead of a string, an element can be a list containing a string followed -by optional keyword arguments. The only keyword argument currently -accepted is `:predicate', which should be given a function that takes the -list (string and keyword arguments) and returns non-nil to indicate that -the middlewares should actually be injected.") -(put 'cider-jack-in-cljs-nrepl-middlewares 'risky-local-variable t) -(add-to-list 'cider-jack-in-cljs-nrepl-middlewares "cider.piggieback/wrap-cljs-repl") +;;;###autoload +(defun cider-jack-in-clj (&optional do-prompt) + "Start an nREPL server for the current project and connect to it. +Prompt for the project and nREPL server command when DO-PROMPT is non-nil." + (interactive "P") + (cider--jack-in do-prompt + (lambda (server-buffer) + (cider-connect-sibling-clj server-buffer)))) + +;;;###autoload +(defun cider-jack-in-cljs (&optional do-prompt) + "Start an nREPL server for the current project and connect to it. +Prompt for the project and nREPL server command when DO-PROMPT is non-nil." + (interactive "P") + (let ((cider-jack-in-dependencies (append cider-jack-in-dependencies cider-jack-in-cljs-dependencies)) + (cider-jack-in-lein-plugins (append cider-jack-in-lein-plugins cider-jack-in-cljs-lein-plugins)) + (cider-jack-in-nrepl-middlewares (append cider-jack-in-nrepl-middlewares cider-jack-in-cljs-nrepl-middlewares))) + (cider--jack-in do-prompt + (lambda (server-buffer) + (cider-connect-sibling-cljs server-buffer))))) ;;;###autoload -(defun cider-jack-in-clojurescript (&optional prompt-project) - "Start an nREPL server and connect to it both Clojure and ClojureScript REPLs. -If PROMPT-PROJECT is t, then prompt for the project for which to -start the server." +(defun cider-jack-in-cljcljs (&optional do-prompt soft-cljs-start) + "Start an nREPL server and connect with clj and cljs REPLs. +Prompt for the project and nREPL server command when DO-PROMPT is non-nil. +When SOFT-CLJS-START is non-nil, start cljs REPL only when the +ClojureScript dependencies are met." (interactive "P") - ;; We override the standard jack-in deps to inject additional ClojureScript-specific deps (let ((cider-jack-in-dependencies (append cider-jack-in-dependencies cider-jack-in-cljs-dependencies)) (cider-jack-in-lein-plugins (append cider-jack-in-lein-plugins cider-jack-in-cljs-lein-plugins)) (cider-jack-in-nrepl-middlewares (append cider-jack-in-nrepl-middlewares cider-jack-in-cljs-nrepl-middlewares))) - (cider-jack-in prompt-project 'cljs-too))) + (cider--jack-in do-prompt + (lambda (server-buffer) + (let ((clj-repl (cider-connect-sibling-clj server-buffer))) + (if soft-cljs-start + (when-let* ((cider-default-cljs-repl (cider--check-cljs nil 'no-error))) + (cider-connect-sibling-cljs clj-repl)) + (cider-connect-sibling-cljs clj-repl))))))) + +;;;###autoload +(defun cider-connect-sibling-clj (other-repl) + "Create a Clojure REPL with the same server as OTHER-REPL. +OTHER-REPL can also be a server buffer, in which case a new session with a +REPL for that server is created." + (interactive (list (cider-current-repl))) + (cider-nrepl-connect + (let ((ses-name (unless (nrepl-server-p other-repl) + (sesman-session-name-for-object 'CIDER other-repl)))) + (thread-first (cider--gather-connect-params other-repl) + (plist-put :repl-type "clj") + (plist-put :session-name ses-name) + (plist-put :repl-init-function nil))))) ;;;###autoload -(defalias 'cider-jack-in-cljs #'cider-jack-in-clojurescript) +(defun cider-connect-sibling-cljs (other-repl) + "Create a ClojureScript REPL with the same server as OTHER-REPL. +Normally this would prompt for the ClojureScript REPL to start (e.g. Node, +Figwheel, etc), unless you've set `cider-default-cljs-repl'. OTHER-REPL +can also be a server buffer, in which case a new session with a REPL for +that server is created." + (interactive (list (cider-current-repl))) + (let ((cljs-repl-type (or cider-default-cljs-repl + (cider-select-cljs-repl))) + (ses-name (unless (nrepl-server-p other-repl) + (sesman-session-name-for-object 'CIDER other-repl)))) + (cider-nrepl-connect + (thread-first (cider--gather-connect-params other-repl) + (plist-put :repl-type "cljs") + (plist-put :session-name ses-name) + (plist-put :repl-init-function (cider--cljs-init-hook-builder cljs-repl-type)))))) ;;;###autoload -(defun cider-connect (host port &optional project-dir) - "Connect to an nREPL server identified by HOST and PORT. -Create REPL buffer and start an nREPL client connection. +(defun cider-connect-clj (host port) + "Initialize a CLJ connection to an nREPL server at HOST and PORT." + (interactive (cider-select-endpoint)) + (cider-nrepl-connect + (list :host host :port port + :repl-type "clj" + :repl-init-function nil + :session-name nil + :project-dir (or (clojure-project-dir (cider-current-dir)) + default-directory)))) -When the optional param PROJECT-DIR is present, the connection -gets associated with it." +;;;###autoload +(defun cider-connect-cljs (host port) + "Initialize a CLJS connection to an nREPL server at HOST and PORT." (interactive (cider-select-endpoint)) - (when-let* ((repl-buff (cider-find-reusable-repl-buffer `(,host ,port) nil))) - (let* ((nrepl-create-client-buffer-function #'cider-repl-create) - (nrepl-use-this-as-repl-buffer repl-buff) - (conn (process-buffer (nrepl-start-client-process host port)))) - (with-current-buffer conn - (setq cider-connection-created-with 'connect)) - (if project-dir - (cider-assoc-project-with-connection project-dir conn) - (let ((project-dir (clojure-project-dir))) - (cond - ;; associate only if we're in a project - ((and project-dir (null cider-prompt-for-project-on-connect)) (cider-assoc-project-with-connection project-dir conn)) - ;; associate if we're in a project, prompt otherwise - ((eq cider-prompt-for-project-on-connect 'when-needed) (cider-assoc-project-with-connection project-dir conn)) - ;; always prompt - (t (cider-assoc-project-with-connection nil conn))))) - conn))) + (let ((cljs-repl-type (or cider-default-cljs-repl + (cider-select-cljs-repl)))) + (cider-nrepl-connect + (list :host host :port port + :repl-type "cljs" + :repl-init-function (cider--cljs-init-hook-builder cljs-repl-type) + :session-name nil + :project-dir (or (clojure-project-dir (cider-current-dir)) + default-directory))))) ;;;###autoload -(defun cider-connect-clojurescript () - "Connect to a ClojureScript REPL. +(defun cider-connect-cljcljs (host port &optional soft-cljs-start) + "Initialize a CLJ and CLJS connection to an nREPL server at HOST and PORT. +When SOFT-CLJS-START is non-nil, don't start if ClojureScript requirements +are not met." + (interactive (cider-select-endpoint)) + (let ((clj-repl (cider-connect-clj host port))) + (if soft-cljs-start + (when-let* ((cider-default-cljs-repl (cider--check-cljs nil 'no-error))) + (cider-connect-sibling-cljs clj-repl)) + (cider-connect-sibling-cljs clj-repl)))) -It just delegates pretty much everything to `cider-connect' and just sets -the appropriate REPL type in the end." - (interactive) - (when-let* ((conn (call-interactively #'cider-connect))) - (with-current-buffer conn - (cider-repl-set-type "cljs")))) + +;;; Aliases + + ;;;###autoload +(defalias 'cider-jack-in #'cider-jack-in-clj) + ;;;###autoload +(defalias 'cider-jack-in-clojure #'cider-jack-in-clj) +;;;###autoload +(defalias 'cider-jack-in-clojurescript #'cider-jack-in-cljs) + +;;;###autoload +(defalias 'cider-connect #'cider-connect-clj) +;;;###autoload +(defalias 'cider-connect-clojure #'cider-connect-clj) +;;;###autoload +(defalias 'cider-connect-clojurescript #'cider-connect-cljs) ;;;###autoload -(defalias 'cider-connect-cljs #'cider-connect-clojurescript) +(defalias 'cider-connect-sibling-clojure #'cider-connect-sibling-clj) +;;;###autoload +(defalias 'cider-connect-sibling-clojurescript #'cider-connect-sibling-cljs) (defun cider-current-host () "Retrieve the current host." @@ -1034,6 +1031,9 @@ the appropriate REPL type in the end." (file-remote-p buffer-file-name 'host) "localhost")) + +;;; Helpers + (defun cider-select-endpoint () "Interactively select the host and port to connect to." (dolist (endpoint cider-known-endpoints) @@ -1165,106 +1165,24 @@ choose." ;; TODO: Implement a check for command presence over tramp (defun cider--resolve-command (command) "Find COMMAND on `exec-path' if possible, or return nil. - In case `default-directory' is non-local we assume the command is available." (when-let* ((command (or (and (file-remote-p default-directory) command) (executable-find command) (executable-find (concat command ".bat"))))) (shell-quote-argument command))) - -;;; Check that the connection is working well -;; TODO: This is nrepl specific. It should eventually go into some cider-nrepl-client -;; file. -(defun cider--check-required-nrepl-version () - "Check whether we're using a compatible nREPL version." - (if-let* ((nrepl-version (cider--nrepl-version))) - (when (version< nrepl-version cider-required-nrepl-version) - (cider-repl-manual-warning "troubleshooting/#warning-saying-you-have-to-use-nrepl-0212" - "CIDER requires nREPL %s (or newer) to work properly" - cider-required-nrepl-version)) - (cider-repl-manual-warning "troubleshooting/#warning-saying-you-have-to-use-nrepl-0212" - "Can't determine nREPL's version.\nPlease, update nREPL to %s." - cider-required-nrepl-version))) - -(defun cider--check-clojure-version-supported () - "Ensure that we are meeting the minimum supported version of Clojure." - (if-let* ((clojure-version (cider--clojure-version))) - (when (version< clojure-version cider-minimum-clojure-version) - (cider-repl-manual-warning "installation/#prerequisites" - "Clojure version (%s) is not supported (minimum %s). CIDER will not work." - clojure-version cider-minimum-clojure-version)) - (cider-repl-manual-warning "installation/#prerequisites" - "Can't determine Clojure's version. CIDER requires Clojure %s (or newer)." - cider-minimum-clojure-version))) - -(defun cider--check-middleware-compatibility () - "CIDER frontend/backend compatibility check. -Retrieve the underlying connection's CIDER-nREPL version and checks if the -middleware used is compatible with CIDER. If not, will display a warning -message in the REPL area." - (let* ((version-dict (nrepl-aux-info "cider-version" (cider-current-connection))) - (middleware-version (nrepl-dict-get version-dict "version-string" "not installed"))) - (unless (equal cider-version middleware-version) - (cider-repl-manual-warning "troubleshooting/#cider-complains-of-the-cider-nrepl-version" - "CIDER's version (%s) does not match cider-nrepl's version (%s). Things will break!" - cider-version middleware-version)))) - -(defcustom cider-redirect-server-output-to-repl t - "Controls whether nREPL server output would be redirected to the REPL. -When non-nil the output would end up in both the nrepl-server buffer (when -available) and the matching REPL buffer." - :type 'boolean - :group 'cider - :safe #'booleanp - :package-version '(cider . "0.17.0")) - -(defun cider--subscribe-repl-to-server-out () - "Subscribe to the nREPL server's *out*." - (cider-nrepl-send-request '("op" "out-subscribe") - (cider-interactive-eval-handler (current-buffer)))) - -(defun cider--connected-handler () - "Handle CIDER initialization after nREPL connection has been established. -This function is appended to `nrepl-connected-hook' in the client process -buffer." - ;; `nrepl-connected-hook' is run in the connection buffer - - ;; `cider-enlighten-mode' changes eval to include the debugger, so we inhibit - ;; it here as the debugger isn't necessarily initialized yet - (let ((cider-enlighten-mode nil)) - (cider-make-connection-default (current-buffer)) - (cider-repl-init (current-buffer)) - (cider--check-required-nrepl-version) - (cider--check-clojure-version-supported) - (cider--check-middleware-compatibility) - (when cider-redirect-server-output-to-repl - (cider--subscribe-repl-to-server-out)) - (when cider-auto-mode - (cider-enable-on-existing-clojure-buffers)) - ;; Middleware on cider-nrepl's side is deferred until first usage, but - ;; loading middleware concurrently can lead to occasional "require" issues - ;; (likely a Clojure bug). Thus, we load the heavy debug middleware towards - ;; the end, allowing for the faster "server-out" middleware to load - ;; first. - (cider--debug-init-connection) - (run-hooks 'cider-connected-hook))) - -(defun cider--disconnected-handler () - "Cleanup after nREPL connection has been lost or closed. -This function is appended to `nrepl-disconnected-hook' in the client -process buffer." - ;; `nrepl-connected-hook' is run in the connection buffer - (cider-possibly-disable-on-existing-clojure-buffers) - (run-hooks 'cider-disconnected-hook)) - ;;;###autoload (eval-after-load 'clojure-mode '(progn - (define-key clojure-mode-map (kbd "C-c M-j") #'cider-jack-in) - (define-key clojure-mode-map (kbd "C-c M-J") #'cider-jack-in-clojurescript) - (define-key clojure-mode-map (kbd "C-c M-c") #'cider-connect) - (define-key clojure-mode-map (kbd "C-c M-C") #'cider-connect-clojurescript))) + (define-key clojure-mode-map (kbd "C-c M-j") #'cider-jack-in-clj) + (define-key clojure-mode-map (kbd "C-c M-J") #'cider-jack-in-cljs) + (define-key clojure-mode-map (kbd "C-c M-c") #'cider-connect-clj) + (define-key clojure-mode-map (kbd "C-c M-C") #'cider-connect-cljs) + (define-key clojure-mode-map (kbd "C-c M-s") #'cider-connect-sibling-clj) + (define-key clojure-mode-map (kbd "C-c M-S") #'cider-connect-sibling-cljs) + (define-key clojure-mode-map (kbd "C-c C-s") 'sesman-map) + (require 'sesman) + (sesman-install-menu clojure-mode-map))) (provide 'cider) |