dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

cider-eval.el (71428B)


      1 ;;; cider-eval.el --- Interactive evaluation (compilation) functionality -*- lexical-binding: t -*-
      2 
      3 ;; Copyright © 2012-2013 Tim King, Phil Hagelberg, Bozhidar Batsov
      4 ;; Copyright © 2013-2023 Bozhidar Batsov, Artur Malabarba and CIDER contributors
      5 ;;
      6 ;; Author: Tim King <kingtim@gmail.com>
      7 ;;         Phil Hagelberg <technomancy@gmail.com>
      8 ;;         Bozhidar Batsov <bozhidar@batsov.dev>
      9 ;;         Artur Malabarba <bruce.connor.am@gmail.com>
     10 ;;         Hugo Duncan <hugo@hugoduncan.org>
     11 ;;         Steve Purcell <steve@sanityinc.com>
     12 ;;         Arne Brasseur <arne@arnebraasseur.net>
     13 
     14 ;; This program is free software: you can redistribute it and/or modify
     15 ;; it under the terms of the GNU General Public License as published by
     16 ;; the Free Software Foundation, either version 3 of the License, or
     17 ;; (at your option) any later version.
     18 
     19 ;; This program is distributed in the hope that it will be useful,
     20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     22 ;; GNU General Public License for more details.
     23 
     24 ;; You should have received a copy of the GNU General Public License
     25 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
     26 
     27 ;; This file is not part of GNU Emacs.
     28 
     29 ;;; Commentary:
     30 
     31 ;; This file contains CIDER's interactive evaluation (compilation) functionality.
     32 ;; Although Clojure doesn't really have the concept of evaluation (only
     33 ;; compilation), we're using everywhere in the code the term evaluation for
     34 ;; brevity (and to be in line with the naming employed by other similar modes).
     35 ;;
     36 ;; This files also contains all the logic related to displaying errors and
     37 ;; evaluation warnings.
     38 ;;
     39 ;; Pretty much all of the commands here are meant to be used mostly from
     40 ;; `cider-mode', but some of them might make sense in other contexts as well.
     41 
     42 ;;; Code:
     43 
     44 (require 'ansi-color)
     45 (require 'cl-lib)
     46 (require 'compile)
     47 (require 'map)
     48 (require 'seq)
     49 (require 'subr-x)
     50 
     51 (require 'clojure-mode)
     52 
     53 (require 'cider-client)
     54 (require 'cider-common)
     55 (require 'cider-jar)
     56 (require 'cider-overlays)
     57 (require 'cider-popup)
     58 (require 'cider-repl)
     59 (require 'cider-stacktrace)
     60 (require 'cider-util)
     61 
     62 (defconst cider-read-eval-buffer "*cider-read-eval*")
     63 (defconst cider-result-buffer "*cider-result*")
     64 
     65 (defcustom cider-show-error-buffer t
     66   "Control the popup behavior of cider stacktraces.
     67 The following values are possible t or 'always, 'except-in-repl,
     68 'only-in-repl.  Any other value, including nil, will cause the stacktrace
     69 not to be automatically shown.
     70 
     71 Irrespective of the value of this variable, the `cider-error-buffer' is
     72 always generated in the background.  Use `cider-selector' to
     73 navigate to this buffer."
     74   :type '(choice (const :tag "always" t)
     75                  (const except-in-repl)
     76                  (const only-in-repl)
     77                  (const :tag "never" nil))
     78   :group 'cider)
     79 
     80 (defcustom cider-auto-jump-to-error t
     81   "Control the cursor jump behavior in compilation error buffer.
     82 When non-nil automatically jump to error location during interactive
     83 compilation.  When set to 'errors-only, don't jump to warnings.
     84 When set to nil, don't jump at all."
     85   :type '(choice (const :tag "always" t)
     86                  (const errors-only)
     87                  (const :tag "never" nil))
     88   :group 'cider
     89   :package-version '(cider . "0.7.0"))
     90 
     91 (defcustom cider-auto-select-error-buffer t
     92   "Controls whether to auto-select the error popup buffer."
     93   :type 'boolean
     94   :group 'cider)
     95 
     96 (defcustom cider-auto-track-ns-form-changes t
     97   "Controls whether to auto-evaluate a source buffer's ns form when changed.
     98 When non-nil CIDER will check for ns form changes before each eval command.
     99 When nil the users are expected to take care of the re-evaluating updated
    100 ns forms manually themselves."
    101   :type 'boolean
    102   :group 'cider
    103   :package-version '(cider . "0.15.0"))
    104 
    105 (defcustom cider-auto-inspect-after-eval t
    106   "Controls whether to auto-update the inspector buffer after eval.
    107 Only applies when the *cider-inspect* buffer is currently visible."
    108   :type 'boolean
    109   :group 'cider
    110   :package-version '(cider . "0.25.0"))
    111 
    112 (defcustom cider-save-file-on-load 'prompt
    113   "Controls whether to prompt to save the file when loading a buffer.
    114 If nil, files are not saved.
    115 If 'prompt, the user is prompted to save the file if it's been modified.
    116 If t, save the file without confirmation."
    117   :type '(choice (const prompt :tag "Prompt to save the file if it's been modified")
    118                  (const nil :tag "Don't save the file")
    119                  (const t :tag "Save the file without confirmation"))
    120   :group 'cider
    121   :package-version '(cider . "0.6.0"))
    122 
    123 (defcustom cider-file-loaded-hook nil
    124   "List of functions to call when a load file has completed."
    125   :type 'hook
    126   :group 'cider
    127   :package-version '(cider . "0.1.7"))
    128 
    129 (defconst cider-output-buffer "*cider-out*")
    130 
    131 (defcustom cider-interactive-eval-output-destination 'repl-buffer
    132   "The destination for stdout and stderr produced from interactive evaluation."
    133   :type '(choice (const output-buffer)
    134                  (const repl-buffer))
    135   :group 'cider
    136   :package-version '(cider . "0.7.0"))
    137 
    138 (defface cider-error-highlight-face
    139   '((((supports :underline (:style wave)))
    140      (:underline (:style wave :color "red") :inherit unspecified))
    141     (t (:inherit font-lock-warning-face :underline t)))
    142   "Face used to highlight compilation errors in Clojure buffers."
    143   :group 'cider)
    144 
    145 (defface cider-warning-highlight-face
    146   '((((supports :underline (:style wave)))
    147      (:underline (:style wave :color "yellow") :inherit unspecified))
    148     (t (:inherit font-lock-warning-face :underline (:color "yellow"))))
    149   "Face used to highlight compilation warnings in Clojure buffers."
    150   :group 'cider)
    151 
    152 (defcustom cider-comment-prefix ";; => "
    153   "The prefix to insert before the first line of commented output."
    154   :type 'string
    155   :group 'cider
    156   :package-version '(cider . "0.16.0"))
    157 
    158 (defcustom cider-comment-continued-prefix ";;    "
    159   "The prefix to use on the second and subsequent lines of commented output."
    160   :type 'string
    161   :group 'cider
    162   :package-version '(cider . "0.16.0"))
    163 
    164 (defcustom cider-comment-postfix ""
    165   "The postfix to be appended after the final line of commented output."
    166   :type 'string
    167   :group 'cider
    168   :package-version '(cider . "0.16.0"))
    169 
    170 (defcustom cider-eval-register ?e
    171   "The text register assigned to the most recent evaluation result.
    172 When non-nil, the return value of all CIDER eval commands are
    173 automatically written into this register."
    174   :type '(choice character
    175                  (const nil))
    176   :group 'cider
    177   :package-version '(cider . "1.4.0"))
    178 
    179 
    180 ;;; Utilities
    181 
    182 (defun cider--clear-compilation-highlights ()
    183   "Remove compilation highlights."
    184   (remove-overlays (point-min) (point-max) 'cider-note-p t))
    185 
    186 (defun cider-clear-compilation-highlights (&optional arg)
    187   "Remove compilation highlights.
    188 When invoked with a prefix ARG the command doesn't prompt for confirmation."
    189   (interactive "P")
    190   (when (or arg (y-or-n-p "Are you sure you want to clear the compilation highlights? "))
    191     (cider--clear-compilation-highlights)))
    192 
    193 (defun cider--quit-error-window ()
    194   "Buries the `cider-error-buffer' and quits its containing window."
    195   (when-let* ((error-win (get-buffer-window cider-error-buffer)))
    196     (save-excursion
    197       (quit-window nil error-win))))
    198 
    199 
    200 ;;; Sideloader
    201 ;;
    202 ;; nREPL includes sideloader middleware which provides a Java classloader that
    203 ;; is able to dynamically load classes and resources at runtime by interacting
    204 ;; with the nREPL client (as opposed to using the classpath of the JVM hosting
    205 ;; nREPL server).
    206 ;;
    207 ;; This performs a similar functionality as the load-file
    208 ;; operation, where we can load Clojure namespaces (as source files) or Java
    209 ;; classes (as bytecode) by simply requiring or importing them.
    210 ;;
    211 ;; See https://nrepl.org/nrepl/design/middleware.html#sideloading
    212 
    213 (defcustom cider-sideloader-path nil
    214   "List of directories and jar files to scan for sideloader resources.
    215 When not set the cider-nrepl jar will be added automatically when upgrading
    216 an nREPL connection."
    217   :type 'list
    218   :group 'cider
    219   :package-version '(cider . "1.2.0"))
    220 
    221 (defcustom cider-dynload-cider-nrepl-version nil
    222   "Version of the cider-nrepl jar used for dynamically upgrading a connection.
    223 Defaults to `cider-required-middleware-version'."
    224   :type 'string
    225   :group 'cider
    226   :package-version '(cider . "1.2.0"))
    227 
    228 (defun cider-read-bytes (path)
    229   "Read binary data from PATH.
    230 Return the binary data as unibyte string."
    231   ;; based on f-read-bytes
    232   (with-temp-buffer
    233     (set-buffer-multibyte nil)
    234     (setq buffer-file-coding-system 'binary)
    235     (insert-file-contents-literally path nil)
    236     (buffer-substring-no-properties (point-min) (point-max))))
    237 
    238 (defun cider-retrieve-resource (dirs name)
    239   "Find a resource NAME in a list DIRS of directories or jar files.
    240 Similar to a classpath lookup.  Returns the file contents as a string."
    241   (seq-some
    242    (lambda (path)
    243      (cond
    244       ((file-directory-p path)
    245        (let ((expanded (expand-file-name name path)))
    246          (when (file-exists-p expanded)
    247            (cider-read-bytes expanded))))
    248       ((and (file-exists-p path) (string-suffix-p ".jar" path))
    249        (cider-jar-retrieve-resource path name))))
    250    dirs))
    251 
    252 (defun cider-provide-file (file)
    253   "Provide FILE in a format suitable for sideloading."
    254   (let ((contents (cider-retrieve-resource cider-sideloader-path file)))
    255     (if contents
    256         (base64-encode-string contents 'no-line-breaks)
    257       ;; if we can't find the file we should return an empty string
    258       (base64-encode-string ""))))
    259 
    260 (defun cider-sideloader-lookup-handler ()
    261   "Make a sideloader-lookup handler."
    262   (lambda (response)
    263     (nrepl-dbind-response response (id status type name)
    264       (if status
    265           (when (member "sideloader-lookup" status)
    266             (cider-request:sideloader-provide id type name))))))
    267 
    268 (defun cider-add-middleware-handler (continue)
    269   "Make a add-middleware handler.
    270 CONTINUE is an optional continuation function."
    271   (lambda (response)
    272     (nrepl-dbind-response response (status unresolved-middleware) ;; id middleware
    273       (when unresolved-middleware
    274         (seq-do
    275          (lambda (mw)
    276            (cider-repl-emit-interactive-stderr
    277             (concat "WARNING: middleware " mw " was not found or failed to load.\n")))
    278          unresolved-middleware))
    279       (when (and status (member "done" status) continue)
    280         (funcall continue)))))
    281 
    282 (defun cider-request:sideloader-start (&optional connection tooling)
    283   "Perform the nREPL \"sideloader-start\" op.
    284 If CONNECTION is nil, use `cider-current-repl'.
    285 If TOOLING is truthy then the operation is performed over the tooling
    286 session, rather than the regular session."
    287   (cider-ensure-op-supported "sideloader-start")
    288   (cider-nrepl-send-request `("op" "sideloader-start")
    289                             (cider-sideloader-lookup-handler)
    290                             connection
    291                             tooling))
    292 
    293 (defun cider-request:sideloader-provide (id type file &optional connection)
    294   "Perform the nREPL \"sideloader-provide\" op for ID, TYPE and FILE.
    295 If CONNECTION is nil, use `cider-current-repl'."
    296   (cider-nrepl-send-request `("id" ,id
    297                               "op" "sideloader-provide"
    298                               "type" ,type
    299                               "name" ,file
    300                               "content" ,(cider-provide-file file))
    301                             (cider-sideloader-lookup-handler)
    302                             connection))
    303 
    304 (defun cider-sideloader-start (&optional connection)
    305   "Start nREPL's sideloader.
    306 If CONNECTION is nil, use `cider-current-repl'."
    307   (interactive)
    308   (message "Starting nREPL's sideloader")
    309   (cider-request:sideloader-start connection)
    310   (cider-request:sideloader-start connection 'tooling))
    311 
    312 (defvar cider-nrepl-middlewares
    313   '("cider.nrepl/wrap-apropos"
    314     "cider.nrepl/wrap-classpath"
    315     "cider.nrepl/wrap-clojuredocs"
    316     "cider.nrepl/wrap-complete"
    317     "cider.nrepl/wrap-content-type"
    318     "cider.nrepl/wrap-debug"
    319     "cider.nrepl/wrap-enlighten"
    320     "cider.nrepl/wrap-format"
    321     "cider.nrepl/wrap-info"
    322     "cider.nrepl/wrap-inspect"
    323     "cider.nrepl/wrap-macroexpand"
    324     "cider.nrepl/wrap-ns"
    325     "cider.nrepl/wrap-out"
    326     "cider.nrepl/wrap-slurp"
    327     "cider.nrepl/wrap-profile"
    328     "cider.nrepl/wrap-refresh"
    329     "cider.nrepl/wrap-resource"
    330     "cider.nrepl/wrap-spec"
    331     "cider.nrepl/wrap-stacktrace"
    332     "cider.nrepl/wrap-test"
    333     "cider.nrepl/wrap-trace"
    334     "cider.nrepl/wrap-tracker"
    335     "cider.nrepl/wrap-undef"
    336     "cider.nrepl/wrap-version"
    337     "cider.nrepl/wrap-xref"))
    338 
    339 (defun cider-request:add-middleware (middlewares
    340                                      &optional connection tooling continue)
    341   "Use the nREPL dynamic loader to add MIDDLEWARES to the nREPL session.
    342 
    343 - If CONNECTION is nil, use `cider-current-repl'.
    344 - If TOOLING it truthy, use the tooling session instead of the main session.
    345 - CONTINUE is an optional continuation function, which will be called when the
    346 add-middleware op has finished successfully."
    347   (cider-nrepl-send-request `("op" "add-middleware"
    348                               "middleware" ,middlewares)
    349                             (cider-add-middleware-handler continue)
    350                             connection
    351                             tooling))
    352 
    353 (defun cider-add-cider-nrepl-middlewares (&optional connection)
    354   "Use dynamic loading to add the cider-nrepl middlewares to nREPL.
    355 If CONNECTION is nil, use `cider-current-repl'."
    356   (cider-request:add-middleware
    357    cider-nrepl-middlewares connection nil
    358    (lambda ()
    359      ;; When the main session is done adding middleware, then do the tooling
    360      ;; session. At this point all the namespaces have been sideloaded so this
    361      ;; is faster, we don't want these to race to sideload resources.
    362      (cider-request:add-middleware
    363       cider-nrepl-middlewares connection 'tooling
    364       (lambda ()
    365         ;; Ask nREPL again what its capabilities are, so we know which new
    366         ;; operations are supported.
    367         (nrepl--init-capabilities (or connection (cider-current-repl))))))))
    368 
    369 (defvar cider-required-middleware-version)
    370 (defun cider-upgrade-nrepl-connection (&optional connection)
    371   "Sideload cider-nrepl middleware.
    372 If CONNECTION is nil, use `cider-current-repl'."
    373   (interactive)
    374   (when (not cider-sideloader-path)
    375     (setq cider-sideloader-path (list (cider-jar-find-or-fetch
    376                                        "cider" "cider-nrepl"
    377                                        (or cider-dynload-cider-nrepl-version
    378                                            cider-required-middleware-version)))))
    379   (cider-sideloader-start connection)
    380   (cider-add-cider-nrepl-middlewares connection))
    381 
    382 
    383 ;;; Dealing with compilation (evaluation) errors and warnings
    384 (defun cider-find-property (property &optional backward)
    385   "Find the next text region which has the specified PROPERTY.
    386 If BACKWARD is t, then search backward.
    387 Returns the position at which PROPERTY was found, or nil if not found."
    388   (let ((p (if backward
    389                (previous-single-char-property-change (point) property)
    390              (next-single-char-property-change (point) property))))
    391     (when (and (not (= p (point-min))) (not (= p (point-max))))
    392       p)))
    393 
    394 (defun cider-jump-to-compilation-error (&optional _arg _reset)
    395   "Jump to the line causing the current compilation error.
    396 _ARG and _RESET are ignored, as there is only ever one compilation error.
    397 They exist for compatibility with `next-error'."
    398   (interactive)
    399   (cl-labels ((goto-next-note-boundary
    400                ()
    401                (let ((p (or (cider-find-property 'cider-note-p)
    402                             (cider-find-property 'cider-note-p t))))
    403                  (when p
    404                    (goto-char p)
    405                    (message "%s" (get-char-property p 'cider-note))))))
    406     ;; if we're already on a compilation error, first jump to the end of
    407     ;; it, so that we find the next error.
    408     (when (get-char-property (point) 'cider-note-p)
    409       (goto-next-note-boundary))
    410     (goto-next-note-boundary)))
    411 
    412 (defun cider--show-error-buffer-p ()
    413   "Return non-nil if the error buffer must be shown on error.
    414 Takes into account both the value of `cider-show-error-buffer' and the
    415 currently selected buffer."
    416   (let* ((selected-buffer (window-buffer (selected-window)))
    417          (replp (with-current-buffer selected-buffer (derived-mode-p 'cider-repl-mode))))
    418     (memq cider-show-error-buffer
    419           (if replp
    420               '(t always only-in-repl)
    421             '(t always except-in-repl)))))
    422 
    423 (defun cider-new-error-buffer (&optional mode error-types)
    424   "Return an empty error buffer using MODE.
    425 
    426 When deciding whether to display the buffer, takes into account not only
    427 the value of `cider-show-error-buffer' and the currently selected buffer
    428 but also the ERROR-TYPES of the error, which is checked against the
    429 `cider-stacktrace-suppressed-errors' set.
    430 
    431 When deciding whether to select the buffer, takes into account the value of
    432 `cider-auto-select-error-buffer'."
    433   (if (and (cider--show-error-buffer-p)
    434            (not (cider-stacktrace-some-suppressed-errors-p error-types)))
    435       (cider-popup-buffer cider-error-buffer cider-auto-select-error-buffer mode 'ancillary)
    436     (cider-make-popup-buffer cider-error-buffer mode 'ancillary)))
    437 
    438 (defun cider-emit-into-color-buffer (buffer value)
    439   "Emit into color BUFFER the provided VALUE."
    440   (with-current-buffer buffer
    441     (let ((inhibit-read-only t)
    442           (buffer-undo-list t))
    443       (goto-char (point-max))
    444       (insert (format "%s" value))
    445       (ansi-color-apply-on-region (point-min) (point-max)))
    446     (goto-char (point-min))))
    447 
    448 (defun cider--handle-err-eval-response (response)
    449   "Render eval RESPONSE into a new error buffer.
    450 
    451 Uses the value of the `out' slot in RESPONSE."
    452   (nrepl-dbind-response response (out)
    453     (when out
    454       (let ((error-buffer (cider-new-error-buffer)))
    455         (cider-emit-into-color-buffer error-buffer out)
    456         (with-current-buffer error-buffer
    457           (compilation-minor-mode +1))))))
    458 
    459 (defun cider-default-err-eval-handler ()
    460   "Display the last exception without middleware support."
    461   (cider--handle-err-eval-response
    462    (cider-nrepl-sync-request:eval
    463     "(clojure.stacktrace/print-cause-trace *e)")))
    464 
    465 (defun cider-default-err-eval-print-handler ()
    466   "Display the last exception without middleware support.
    467 When clojure.stracktrace is not present."
    468   (cider--handle-err-eval-response
    469    (cider-nrepl-sync-request:eval
    470     "(println (ex-data *e))")))
    471 
    472 (defun cider--render-stacktrace-causes (causes &optional error-types)
    473   "If CAUSES is non-nil, render its contents into a new error buffer.
    474 Optional argument ERROR-TYPES contains a list which should determine the
    475 op/situation that originated this error."
    476   (when causes
    477     (let ((error-buffer (cider-new-error-buffer #'cider-stacktrace-mode error-types)))
    478       (cider-stacktrace-render error-buffer (reverse causes) error-types))))
    479 
    480 (defun cider--handle-stacktrace-response (response causes)
    481   "Handle stacktrace op RESPONSE, aggregating the result into CAUSES.
    482 If RESPONSE contains a cause, cons it onto CAUSES and return that.  If
    483 RESPONSE is the final message (i.e. it contains a status), render CAUSES
    484 into a new error buffer."
    485   (nrepl-dbind-response response (class msg status type)
    486     (cond ((and (member "notification" status) causes)
    487            (nrepl-notify msg type))
    488           (class (cons response causes))
    489           (status (cider--render-stacktrace-causes causes)))))
    490 
    491 (defun cider-default-err-op-handler ()
    492   "Display the last exception, with middleware support."
    493   ;; Causes are returned as a series of messages, which we aggregate in `causes'
    494   (let (causes)
    495     (cider-nrepl-send-request
    496      (thread-last
    497        (map-merge 'list
    498                   '(("op" "analyze-last-stacktrace"))
    499                   (cider--nrepl-print-request-map fill-column))
    500        (seq-mapcat #'identity))
    501      (lambda (response)
    502        ;; While the return value of `cider--handle-stacktrace-response' is not
    503        ;; meaningful for the last message, we do not need the value of `causes'
    504        ;; after it has been handled, so it's fine to set it unconditionally here
    505        (setq causes (cider--handle-stacktrace-response response causes))))))
    506 
    507 (defun cider-default-err-handler ()
    508   "This function determines how the error buffer is shown.
    509 It delegates the actual error content to the eval or op handler."
    510   (cond ((cider-nrepl-op-supported-p "analyze-last-stacktrace")
    511          (cider-default-err-op-handler))
    512         ((cider-library-present-p "clojure.stacktrace")
    513          (cider-default-err-eval-handler))
    514         (t (cider-default-err-eval-print-handler))))
    515 
    516 
    517 ;; The format of the error messages emitted by Clojure's compiler changed in
    518 ;; Clojure 1.10.  That's why we're trying to match error messages to both the
    519 ;; old and the new format, by utilizing a combination of two different regular
    520 ;; expressions.
    521 
    522 (defconst cider-clojure-1.10-error `(sequence
    523                                      "Syntax error "
    524                                      (minimal-match (zero-or-more anything))
    525                                      "compiling "
    526                                      (minimal-match (zero-or-more anything))
    527                                      "at ("
    528                                      (group-n 2 (minimal-match (zero-or-more anything)))
    529                                      ":"
    530                                      (group-n 3 (one-or-more digit))
    531                                      (optional ":" (group-n 4 (one-or-more digit)))
    532                                      ")."))
    533 
    534 (defconst cider-clojure-1.9-error `(sequence
    535                                     (zero-or-more anything)
    536                                     ", compiling:("
    537                                     (group-n 2 (minimal-match (zero-or-more anything)))
    538                                     ":"
    539                                     (group-n 3 (one-or-more digit))
    540                                     (optional ":" (group-n 4 (one-or-more digit)))
    541                                     ")"))
    542 
    543 (defconst cider-clojure-warning `(sequence
    544                                   (minimal-match (zero-or-more anything))
    545                                   (group-n 1 "warning")
    546                                   ", "
    547                                   (group-n 2 (minimal-match (zero-or-more anything)))
    548                                   ":"
    549                                   (group-n 3 (one-or-more digit))
    550                                   (optional ":" (group-n 4 (one-or-more digit)))
    551                                   " - "))
    552 
    553 
    554 (defconst cider-clojure-compilation-regexp
    555   (eval
    556    `(rx bol (or ,cider-clojure-1.9-error
    557                 ,cider-clojure-warning
    558                 ,cider-clojure-1.10-error))
    559    t))
    560 
    561 
    562 (defvar cider-compilation-regexp
    563   (list cider-clojure-compilation-regexp  2 3 4 '(1))
    564   "Specifications for matching errors and warnings in Clojure stacktraces.
    565 See `compilation-error-regexp-alist' for help on their format.")
    566 
    567 (add-to-list 'compilation-error-regexp-alist-alist
    568              (cons 'cider cider-compilation-regexp))
    569 (add-to-list 'compilation-error-regexp-alist 'cider)
    570 
    571 (defun cider-extract-error-info (regexp message)
    572   "Extract error information with REGEXP against MESSAGE."
    573   (let ((file (nth 1 regexp))
    574         (line (nth 2 regexp))
    575         (col (nth 3 regexp))
    576         (type (nth 4 regexp))
    577         (pat (car regexp)))
    578     (when (string-match pat message)
    579       ;; special processing for type (1.2) style
    580       (setq type (if (consp type)
    581                      (or (and (car type) (match-end (car type)) 1)
    582                          (and (cdr type) (match-end (cdr type)) 0)
    583                          2)))
    584       (list
    585        (when file
    586          (let ((val (match-string-no-properties file message)))
    587            (unless (string= val "NO_SOURCE_PATH") val)))
    588        (when line (string-to-number (match-string-no-properties line message)))
    589        (when col
    590          (let ((val (match-string-no-properties col message)))
    591            (when (and val (not (string-blank-p val))) (string-to-number val))))
    592        (aref [cider-warning-highlight-face
    593               cider-warning-highlight-face
    594               cider-error-highlight-face]
    595              (or type 2))
    596        message))))
    597 
    598 (defun cider--goto-expression-start ()
    599   "Go to the beginning a list, vector, map or set outside of a string.
    600 We do so by starting and the current position and proceeding backwards
    601 until we find a delimiters that's not inside a string."
    602   (if (and (looking-back "[])}]" (line-beginning-position))
    603            (null (nth 3 (syntax-ppss))))
    604       (backward-sexp)
    605     (while (or (not (looking-at-p "[({[]"))
    606                (nth 3 (syntax-ppss)))
    607       (backward-char))))
    608 
    609 (defun cider--find-last-error-location (message)
    610   "Return the location (begin end buffer) from the Clojure error MESSAGE.
    611 If location could not be found, return nil."
    612   (save-excursion
    613     (let ((info (cider-extract-error-info cider-compilation-regexp message)))
    614       (when info
    615         (let ((file (nth 0 info))
    616               (line (nth 1 info))
    617               (col (nth 2 info)))
    618           (unless (or (not (stringp file))
    619                       (cider--tooling-file-p file))
    620             (when-let* ((buffer (cider-find-file file)))
    621               (with-current-buffer buffer
    622                 (save-excursion
    623                   (save-restriction
    624                     (widen)
    625                     (goto-char (point-min))
    626                     (forward-line (1- line))
    627                     (move-to-column (or col 0))
    628                     (let ((begin (progn (if col (cider--goto-expression-start) (back-to-indentation))
    629                                         (point)))
    630                           (end (progn (if col (forward-list) (move-end-of-line nil))
    631                                       (point))))
    632                       (list begin end buffer))))))))))))
    633 
    634 (defun cider-handle-compilation-errors (message eval-buffer)
    635   "Highlight and jump to compilation error extracted from MESSAGE.
    636 EVAL-BUFFER is the buffer that was current during user's interactive
    637 evaluation command.  Honor `cider-auto-jump-to-error'."
    638   (when-let* ((loc (cider--find-last-error-location message))
    639               (overlay (make-overlay (nth 0 loc) (nth 1 loc) (nth 2 loc)))
    640               (info (cider-extract-error-info cider-compilation-regexp message)))
    641     (let* ((face (nth 3 info))
    642            (note (nth 4 info))
    643            (auto-jump (if (eq cider-auto-jump-to-error 'errors-only)
    644                           (not (or (eq face 'cider-warning-highlight-face)
    645                                    (string-match-p "warning" note)))
    646                         cider-auto-jump-to-error)))
    647       (overlay-put overlay 'cider-note-p t)
    648       (overlay-put overlay 'font-lock-face face)
    649       (overlay-put overlay 'cider-note note)
    650       (overlay-put overlay 'help-echo note)
    651       (overlay-put overlay 'modification-hooks
    652                    (list (lambda (o &rest _args) (delete-overlay o))))
    653       (when auto-jump
    654         (with-current-buffer eval-buffer
    655           (push-mark)
    656           ;; At this stage selected window commonly is *cider-error* and we need to
    657           ;; re-select the original user window. If eval-buffer is not
    658           ;; visible it was probably covered as a result of a small screen or user
    659           ;; configuration (https://github.com/clojure-emacs/cider/issues/847). In
    660           ;; that case we don't jump at all in order to avoid covering *cider-error*
    661           ;; buffer.
    662           (when-let* ((win (get-buffer-window eval-buffer)))
    663             (with-selected-window win
    664               (cider-jump-to (nth 2 loc) (car loc)))))))))
    665 
    666 
    667 ;;; Interactive evaluation handlers
    668 (defun cider-insert-eval-handler (&optional buffer)
    669   "Make an nREPL evaluation handler for the BUFFER.
    670 The handler simply inserts the result value in BUFFER."
    671   (let ((eval-buffer (current-buffer))
    672         (res ""))
    673     (nrepl-make-response-handler (or buffer eval-buffer)
    674                                  (lambda (_buffer value)
    675                                    (with-current-buffer buffer
    676                                      (insert value))
    677                                    (when cider-eval-register
    678                                      (setq res (concat res value))))
    679                                  (lambda (_buffer out)
    680                                    (cider-repl-emit-interactive-stdout out))
    681                                  (lambda (_buffer err)
    682                                    (cider-handle-compilation-errors err eval-buffer))
    683                                  (lambda (_buffer)
    684                                    (when cider-eval-register
    685                                      (set-register cider-eval-register res))))))
    686 
    687 (defun cider--emit-interactive-eval-output (output repl-emit-function)
    688   "Emit output resulting from interactive code evaluation.
    689 The OUTPUT can be sent to either a dedicated output buffer or the current
    690 REPL buffer.  This is controlled by `cider-interactive-eval-output-destination'.
    691 REPL-EMIT-FUNCTION emits the OUTPUT."
    692   (pcase cider-interactive-eval-output-destination
    693     (`output-buffer (let ((output-buffer (or (get-buffer cider-output-buffer)
    694                                              (cider-popup-buffer cider-output-buffer t))))
    695                       (cider-emit-into-popup-buffer output-buffer output)
    696                       (pop-to-buffer output-buffer)))
    697     (`repl-buffer (funcall repl-emit-function output))
    698     (_ (error "Unsupported value %s for `cider-interactive-eval-output-destination'"
    699               cider-interactive-eval-output-destination))))
    700 
    701 (defun cider-emit-interactive-eval-output (output)
    702   "Emit OUTPUT resulting from interactive code evaluation.
    703 The output can be send to either a dedicated output buffer or the current
    704 REPL buffer.  This is controlled via
    705 `cider-interactive-eval-output-destination'."
    706   (cider--emit-interactive-eval-output output 'cider-repl-emit-interactive-stdout))
    707 
    708 (defun cider-emit-interactive-eval-err-output (output)
    709   "Emit err OUTPUT resulting from interactive code evaluation.
    710 The output can be send to either a dedicated output buffer or the current
    711 REPL buffer.  This is controlled via
    712 `cider-interactive-eval-output-destination'."
    713   (cider--emit-interactive-eval-output output 'cider-repl-emit-interactive-stderr))
    714 
    715 (defun cider--make-fringe-overlays-for-region (beg end)
    716   "Place eval indicators on all sexps between BEG and END."
    717   (with-current-buffer (if (markerp end)
    718                            (marker-buffer end)
    719                          (current-buffer))
    720     (save-excursion
    721       (goto-char beg)
    722       (remove-overlays beg end 'category 'cider-fringe-indicator)
    723       (condition-case nil
    724           (while (progn (clojure-forward-logical-sexp)
    725                         (and (<= (point) end)
    726                              (not (eobp))))
    727             (cider--make-fringe-overlay (point)))
    728         (scan-error nil)))))
    729 
    730 (declare-function cider-inspect-last-result "cider-inspector")
    731 (defun cider-interactive-eval-handler (&optional buffer place)
    732   "Make an interactive eval handler for BUFFER.
    733 PLACE is used to display the evaluation result.
    734 If non-nil, it can be the position where the evaluated sexp ends,
    735 or it can be a list with (START END) of the evaluated region.
    736 Update the cider-inspector buffer with the evaluation result
    737 when `cider-auto-inspect-after-eval' is non-nil."
    738 
    739   (let* ((eval-buffer (current-buffer))
    740          (beg (car-safe place))
    741          (end (or (car-safe (cdr-safe place)) place))
    742          (beg (when beg (copy-marker beg)))
    743          (end (when end (copy-marker end)))
    744          (fringed nil)
    745          (res ""))
    746     (nrepl-make-response-handler (or buffer eval-buffer)
    747                                  (lambda (_buffer value)
    748                                    (setq res (concat res value))
    749                                    (cider--display-interactive-eval-result res end))
    750                                  (lambda (_buffer out)
    751                                    (cider-emit-interactive-eval-output out))
    752                                  (lambda (_buffer err)
    753                                    (cider-emit-interactive-eval-err-output err)
    754 
    755                                    (when (or (not cider-show-error-buffer)
    756                                              (not (cider-connection-has-capability-p 'jvm-compilation-errors)))
    757 
    758                                      ;; Display errors as temporary overlays
    759                                      (let ((cider-result-use-clojure-font-lock nil))
    760                                        (cider--display-interactive-eval-result
    761                                         err end 'cider-error-overlay-face)))
    762                                    (cider-handle-compilation-errors err eval-buffer))
    763                                  (lambda (buffer)
    764                                    (if beg
    765                                        (unless fringed
    766                                          (cider--make-fringe-overlays-for-region beg end)
    767                                          (setq fringed t))
    768                                      (cider--make-fringe-overlay end))
    769                                    (when (and cider-auto-inspect-after-eval
    770                                               (boundp 'cider-inspector-buffer)
    771                                               (windowp (get-buffer-window cider-inspector-buffer 'visible)))
    772                                      (cider-inspect-last-result)
    773                                      (select-window (get-buffer-window buffer)))
    774                                    (when cider-eval-register
    775                                      (set-register cider-eval-register res))))))
    776 
    777 
    778 (defun cider-load-file-handler (&optional buffer done-handler)
    779   "Make a load file handler for BUFFER.
    780 Optional argument DONE-HANDLER lambda will be run once load is complete."
    781   (let ((eval-buffer (current-buffer))
    782         (res ""))
    783     (nrepl-make-response-handler (or buffer eval-buffer)
    784                                  (lambda (buffer value)
    785                                    (cider--display-interactive-eval-result value)
    786                                    (when cider-eval-register
    787                                      (setq res (concat res value)))
    788                                    (when (buffer-live-p buffer)
    789                                      (with-current-buffer buffer
    790                                        (cider--make-fringe-overlays-for-region (point-min) (point-max))
    791                                        (run-hooks 'cider-file-loaded-hook))))
    792                                  (lambda (_buffer value)
    793                                    (cider-emit-interactive-eval-output value))
    794                                  (lambda (_buffer err)
    795                                    (cider-emit-interactive-eval-err-output err)
    796                                    (cider-handle-compilation-errors err eval-buffer))
    797                                  (lambda (buffer)
    798                                    (when cider-eval-register
    799                                      (set-register cider-eval-register res))
    800                                    (when done-handler
    801                                      (funcall done-handler buffer)))
    802                                  (lambda ()
    803                                    (funcall nrepl-err-handler)))))
    804 
    805 (defun cider-eval-print-handler (&optional buffer)
    806   "Make a handler for evaluating and printing result in BUFFER."
    807   ;; NOTE: cider-eval-register behavior is not implemented here for performance reasons.
    808   ;; See https://github.com/clojure-emacs/cider/pull/3162
    809   (nrepl-make-response-handler (or buffer (current-buffer))
    810                                (lambda (buffer value)
    811                                  (with-current-buffer buffer
    812                                    (insert
    813                                     (if (derived-mode-p 'cider-clojure-interaction-mode)
    814                                         (format "\n%s\n" value)
    815                                       value))))
    816                                (lambda (_buffer out)
    817                                  (cider-emit-interactive-eval-output out))
    818                                (lambda (_buffer err)
    819                                  (cider-emit-interactive-eval-err-output err))
    820                                ()))
    821 
    822 (defun cider-eval-print-with-comment-handler (buffer location comment-prefix)
    823   "Make a handler for evaluating and printing commented results in BUFFER.
    824 LOCATION is the location marker at which to insert.  COMMENT-PREFIX is the
    825 comment prefix to use."
    826   (let ((res ""))
    827     (nrepl-make-response-handler buffer
    828                                  (lambda (_buffer value)
    829                                    (setq res (concat res value)))
    830                                  (lambda (_buffer out)
    831                                    (cider-emit-interactive-eval-output out))
    832                                  (lambda (_buffer err)
    833                                    (cider-emit-interactive-eval-err-output err))
    834                                  (lambda (buffer)
    835                                    (with-current-buffer buffer
    836                                      (save-excursion
    837                                        (goto-char (marker-position location))
    838                                        (insert (concat comment-prefix
    839                                                        res "\n"))))
    840                                    (when cider-eval-register
    841                                      (set-register cider-eval-register res))))))
    842 
    843 (defun cider-maybe-insert-multiline-comment (result comment-prefix continued-prefix comment-postfix)
    844   "Insert eval RESULT at current location if RESULT is not empty.
    845 RESULT will be preceded by COMMENT-PREFIX.
    846 CONTINUED-PREFIX is inserted for each additional line of output.
    847 COMMENT-POSTFIX is inserted after final text output."
    848   (unless (string= result "")
    849     (clojure-indent-line)
    850     (let ((lines (split-string result "[\n]+" t))
    851           (beg (point))
    852           (col (current-indentation)))
    853       ;; only the first line gets the normal comment-prefix
    854       (insert (concat comment-prefix (pop lines)))
    855       (dolist (elem lines)
    856         (insert (concat "\n" continued-prefix elem)))
    857       (indent-rigidly beg (point) col)
    858       (unless (string= comment-postfix "")
    859         (insert comment-postfix)))))
    860 
    861 (defun cider-eval-pprint-with-multiline-comment-handler (buffer location comment-prefix continued-prefix comment-postfix)
    862   "Make a handler for evaluating and inserting results in BUFFER.
    863 The inserted text is pretty-printed and region will be commented.
    864 LOCATION is the location marker at which to insert.
    865 COMMENT-PREFIX is the comment prefix for the first line of output.
    866 CONTINUED-PREFIX is the comment prefix to use for the remaining lines.
    867 COMMENT-POSTFIX is the text to output after the last line."
    868   (let ((res ""))
    869     (nrepl-make-response-handler
    870      buffer
    871      (lambda (_buffer value)
    872        (setq res (concat res value)))
    873      nil
    874      (lambda (_buffer err)
    875        (setq res (concat res err)))
    876      (lambda (buffer)
    877        (with-current-buffer buffer
    878          (save-excursion
    879            (goto-char (marker-position location))
    880            ;; edge case: defun at eob
    881            (unless (bolp) (insert "\n"))
    882            (cider-maybe-insert-multiline-comment res comment-prefix continued-prefix comment-postfix)))
    883        (when cider-eval-register
    884          (set-register cider-eval-register res)))
    885      nil
    886      nil
    887      (lambda (_buffer warning)
    888        (setq res (concat res warning))))))
    889 
    890 (defun cider-popup-eval-handler (&optional buffer)
    891   "Make a handler for printing evaluation results in popup BUFFER.
    892 This is used by pretty-printing commands."
    893   ;; NOTE: cider-eval-register behavior is not implemented here for performance reasons.
    894   ;; See https://github.com/clojure-emacs/cider/pull/3162
    895   (nrepl-make-response-handler
    896    (or buffer (current-buffer))
    897    (lambda (buffer value)
    898      (cider-emit-into-popup-buffer buffer (ansi-color-apply value) nil t))
    899    (lambda (_buffer out)
    900      (cider-emit-interactive-eval-output out))
    901    (lambda (_buffer err)
    902      (cider-emit-interactive-eval-err-output err))
    903    nil
    904    nil
    905    nil
    906    (lambda (buffer warning)
    907      (cider-emit-into-popup-buffer buffer warning 'font-lock-warning-face t))))
    908 
    909 
    910 ;;; Interactive valuation commands
    911 
    912 (defvar cider-to-nrepl-filename-function
    913   (with-no-warnings
    914     (lambda (path)
    915       (let ((path* (if (eq system-type 'cygwin)
    916                        (cygwin-convert-file-name-to-windows path)
    917                      path)))
    918         (or (cider--translate-path-to-nrepl path*) path*))))
    919   "Function to translate Emacs filenames to nREPL namestrings.")
    920 
    921 (defun cider--prep-interactive-eval (form connection)
    922   "Prepare the environment for an interactive eval of FORM in CONNECTION.
    923 Ensure the current ns declaration has been evaluated (so that the ns
    924 containing FORM exists).  Cache ns-form in the current buffer unless FORM is
    925 ns declaration itself.  Clear any compilation highlights and kill the error
    926 window."
    927   (cider--clear-compilation-highlights)
    928   (cider--quit-error-window)
    929   (let ((cur-ns-form (cider-ns-form)))
    930     (when (and cur-ns-form
    931                (not (cider-ns-form-p form))
    932                (cider-repl--ns-form-changed-p cur-ns-form connection))
    933       (when cider-auto-track-ns-form-changes
    934         ;; The first interactive eval on a file can load a lot of libs. This can
    935         ;; easily lead to more than 10 sec.
    936         (let ((nrepl-sync-request-timeout 30))
    937           ;; TODO: check for evaluation errors
    938           (cider-nrepl-sync-request:eval cur-ns-form connection)))
    939       ;; cache at the end, in case of errors
    940       (cider-repl--cache-ns-form cur-ns-form connection))))
    941 
    942 (defvar-local cider-interactive-eval-override nil
    943   "Function to call instead of `cider-interactive-eval'.")
    944 
    945 (defun cider-interactive-eval (form &optional callback bounds additional-params)
    946   "Evaluate FORM and dispatch the response to CALLBACK.
    947 If the code to be evaluated comes from a buffer, it is preferred to use a
    948 nil FORM, and specify the code via the BOUNDS argument instead.
    949 
    950 This function is the main entry point in CIDER's interactive evaluation
    951 API.  Most other interactive eval functions should rely on this function.
    952 If CALLBACK is nil use `cider-interactive-eval-handler'.
    953 BOUNDS, if non-nil, is a list of two numbers marking the start and end
    954 positions of FORM in its buffer.
    955 ADDITIONAL-PARAMS is a map to be merged into the request message.
    956 
    957 If `cider-interactive-eval-override' is a function, call it with the same
    958 arguments and only proceed with evaluation if it returns nil."
    959   (let ((form  (or form (apply #'buffer-substring-no-properties bounds)))
    960         (start (car-safe bounds))
    961         (end   (car-safe (cdr-safe bounds))))
    962     (when (and start end)
    963       ;; NOTE: don't use `remove-overlays' as it splits and leaves behind
    964       ;; partial overlays, leading to duplicate eval results in some situations.
    965       (dolist (ov (overlays-in start end))
    966         (when (eq (overlay-get ov 'cider-temporary) t)
    967           (delete-overlay ov))))
    968     (unless (and cider-interactive-eval-override
    969                  (functionp cider-interactive-eval-override)
    970                  (funcall cider-interactive-eval-override form callback bounds))
    971       (cider-map-repls :auto
    972         (lambda (connection)
    973           (cider--prep-interactive-eval form connection)
    974           (cider-nrepl-request:eval
    975            form
    976            (or callback (cider-interactive-eval-handler nil bounds))
    977            ;; always eval ns forms in the user namespace
    978            ;; otherwise trying to eval ns form for the first time will produce an error
    979            (if (cider-ns-form-p form) "user" (cider-current-ns))
    980            (when start (line-number-at-pos start))
    981            (when start (cider-column-number-at-pos start))
    982            (seq-mapcat #'identity additional-params)
    983            connection))))))
    984 
    985 (defun cider-eval-region (start end)
    986   "Evaluate the region between START and END."
    987   (interactive "r")
    988   (cider-interactive-eval nil
    989                           nil
    990                           (list start end)
    991                           (cider--nrepl-pr-request-map)))
    992 
    993 (defun cider-eval-last-sexp (&optional output-to-current-buffer)
    994   "Evaluate the expression preceding point.
    995 If invoked with OUTPUT-TO-CURRENT-BUFFER, print the result in the current
    996 buffer."
    997   (interactive "P")
    998   (cider-interactive-eval nil
    999                           (when output-to-current-buffer (cider-eval-print-handler))
   1000                           (cider-last-sexp 'bounds)
   1001                           (cider--nrepl-pr-request-map)))
   1002 
   1003 (defun cider-eval-last-sexp-and-replace ()
   1004   "Evaluate the expression preceding point and replace it with its result."
   1005   (interactive)
   1006   (let ((last-sexp (cider-last-sexp)))
   1007     ;; we have to be sure the evaluation won't result in an error
   1008     (cider-nrepl-sync-request:eval last-sexp)
   1009     ;; seems like the sexp is valid, so we can safely kill it
   1010     (let ((opoint (point)))
   1011       (clojure-backward-logical-sexp)
   1012       (kill-region (point) opoint))
   1013     (cider-interactive-eval last-sexp
   1014                             (cider-eval-print-handler)
   1015                             nil
   1016                             (cider--nrepl-pr-request-map))))
   1017 
   1018 (defun cider-eval-list-at-point (&optional output-to-current-buffer)
   1019   "Evaluate the list (eg.  a function call, surrounded by parens) around point.
   1020 If invoked with OUTPUT-TO-CURRENT-BUFFER, output the result to current buffer."
   1021   (interactive "P")
   1022   (save-excursion
   1023     (goto-char (cadr (cider-list-at-point 'bounds)))
   1024     (cider-eval-last-sexp output-to-current-buffer)))
   1025 
   1026 (defun cider-eval-sexp-at-point (&optional output-to-current-buffer)
   1027   "Evaluate the expression around point.
   1028 If invoked with OUTPUT-TO-CURRENT-BUFFER, output the result to current buffer."
   1029   (interactive "P")
   1030   (save-excursion
   1031     (goto-char (cadr (cider-sexp-at-point 'bounds)))
   1032     (cider-eval-last-sexp output-to-current-buffer)))
   1033 
   1034 (defun cider-tap-last-sexp (&optional output-to-current-buffer)
   1035   "Evaluate and tap the expression preceding point.
   1036 If invoked with OUTPUT-TO-CURRENT-BUFFER, print the result in the current
   1037 buffer."
   1038   (interactive "P")
   1039   (let ((tapped-form (concat "(clojure.core/doto " (cider-last-sexp) " (clojure.core/tap>))")))
   1040     (cider-interactive-eval tapped-form
   1041                             (when output-to-current-buffer (cider-eval-print-handler))
   1042                             nil
   1043                             (cider--nrepl-pr-request-map))))
   1044 
   1045 (defun cider-tap-sexp-at-point (&optional output-to-current-buffer)
   1046   "Evaluate and tap the expression around point.
   1047 If invoked with OUTPUT-TO-CURRENT-BUFFER, output the result to current buffer."
   1048   (interactive "P")
   1049   (save-excursion
   1050     (goto-char (cadr (cider-sexp-at-point 'bounds)))
   1051     (cider-tap-last-sexp output-to-current-buffer)))
   1052 
   1053 (defvar-local cider-previous-eval-context nil
   1054   "The previous evaluation context if any.
   1055 That's set by commands like `cider-eval-last-sexp-in-context'.")
   1056 
   1057 
   1058 (defun cider--guess-eval-context ()
   1059   "Return context for `cider--eval-in-context'.
   1060 This is done by extracting all parent let bindings."
   1061   (save-excursion
   1062     (let ((res ""))
   1063       (condition-case nil
   1064           (while t
   1065             (backward-up-list)
   1066             (when (looking-at (rx "(" (or "when-let" "if-let" "let") (opt "*")
   1067                                   symbol-end (* space)
   1068                                   (group "["))) ;; binding vector
   1069               (let ((beg (match-end 1))
   1070                     (end (save-excursion
   1071                            (goto-char (match-beginning 1))
   1072                            (forward-sexp 1)
   1073                            (1- (point)))))
   1074                 (setq res (concat (buffer-substring-no-properties beg end) ", " res)))))
   1075         (scan-error res)))))
   1076 
   1077 (defun cider--eval-in-context (bounds &optional guess)
   1078   "Evaluate code at BOUNDS in user-provided evaluation context.
   1079 When GUESS is non-nil, attempt to extract the context from parent let-bindings."
   1080   (let* ((code (string-trim-right
   1081                 (buffer-substring-no-properties (car bounds) (cadr bounds))))
   1082          (eval-context
   1083           (minibuffer-with-setup-hook (if guess #'beginning-of-buffer #'ignore)
   1084             (read-string "Evaluation context (let-style): "
   1085                          (if guess (cider--guess-eval-context)
   1086                            cider-previous-eval-context))))
   1087          (code (concat "(let [" eval-context "]\n  " code ")")))
   1088     (setq-local cider-previous-eval-context eval-context)
   1089     (cider-interactive-eval code
   1090                             nil
   1091                             bounds
   1092                             (cider--nrepl-pr-request-map))))
   1093 
   1094 (defun cider-eval-last-sexp-in-context (guess)
   1095   "Evaluate the preceding sexp in user-supplied context.
   1096 The context is just a let binding vector (without the brackets).
   1097 The context is remembered between command invocations.
   1098 
   1099 When GUESS is non-nil, or called interactively with \\[universal-argument],
   1100 attempt to extract the context from parent let-bindings."
   1101   (interactive "P")
   1102   (cider--eval-in-context (cider-last-sexp 'bounds) guess))
   1103 
   1104 (defun cider-eval-sexp-at-point-in-context (guess)
   1105   "Evaluate the sexp around point in user-supplied context.
   1106 
   1107 The context is just a let binding vector (without the brackets).
   1108 The context is remembered between command invocations.
   1109 
   1110 When GUESS is non-nil, or called interactively with \\[universal-argument],
   1111 attempt to extract the context from parent let-bindings."
   1112   (interactive "P")
   1113   (cider--eval-in-context (cider-sexp-at-point 'bounds) guess))
   1114 
   1115 (defun cider-eval-defun-to-comment (&optional insert-before)
   1116   "Evaluate the \"top-level\" form and insert result as comment.
   1117 
   1118 The formatting of the comment is defined in `cider-comment-prefix'
   1119 which, by default, is \";; => \" and can be customized.
   1120 
   1121 With the prefix arg INSERT-BEFORE, insert before the form, otherwise afterwards."
   1122   (interactive "P")
   1123   (let* ((bounds (cider-defun-at-point 'bounds))
   1124          (insertion-point (nth (if insert-before 0 1) bounds)))
   1125     (cider-interactive-eval nil
   1126                             (cider-eval-print-with-comment-handler
   1127                              (current-buffer)
   1128                              (set-marker (make-marker) insertion-point)
   1129                              cider-comment-prefix)
   1130                             bounds
   1131                             (cider--nrepl-pr-request-map))))
   1132 
   1133 (defun cider-pprint-form-to-comment (form-fn insert-before)
   1134   "Evaluate the form selected by FORM-FN and insert result as comment.
   1135 FORM-FN can be either `cider-last-sexp' or `cider-defun-at-point'.
   1136 
   1137 The formatting of the comment is controlled via three options:
   1138     `cider-comment-prefix'           \";; => \"
   1139     `cider-comment-continued-prefix' \";;    \"
   1140     `cider-comment-postfix'          \"\"
   1141 
   1142 so that with customization you can optionally wrap the output
   1143 in the reader macro \"#_( .. )\", or \"(comment ... )\", or any
   1144 other desired formatting.
   1145 
   1146 If INSERT-BEFORE is non-nil, insert before the form, otherwise afterwards."
   1147   (let* ((bounds (funcall form-fn 'bounds))
   1148          (insertion-point (nth (if insert-before 0 1) bounds))
   1149          ;; when insert-before, we need a newline after the output to
   1150          ;; avoid commenting the first line of the form
   1151          (comment-postfix (concat cider-comment-postfix
   1152                                   (if insert-before "\n" ""))))
   1153     (cider-interactive-eval nil
   1154                             (cider-eval-pprint-with-multiline-comment-handler
   1155                              (current-buffer)
   1156                              (set-marker (make-marker) insertion-point)
   1157                              cider-comment-prefix
   1158                              cider-comment-continued-prefix
   1159                              comment-postfix)
   1160                             bounds
   1161                             (cider--nrepl-print-request-map fill-column))))
   1162 
   1163 (defun cider-pprint-eval-last-sexp-to-comment (&optional insert-before)
   1164   "Evaluate the last sexp and insert result as comment.
   1165 
   1166 The formatting of the comment is controlled via three options:
   1167     `cider-comment-prefix'           \";; => \"
   1168     `cider-comment-continued-prefix' \";;    \"
   1169     `cider-comment-postfix'          \"\"
   1170 
   1171 so that with customization you can optionally wrap the output
   1172 in the reader macro \"#_( .. )\", or \"(comment ... )\", or any
   1173 other desired formatting.
   1174 
   1175 If INSERT-BEFORE is non-nil, insert before the form, otherwise afterwards."
   1176   (interactive "P")
   1177   (cider-pprint-form-to-comment 'cider-last-sexp insert-before))
   1178 
   1179 (defun cider-pprint-eval-defun-to-comment (&optional insert-before)
   1180   "Evaluate the \"top-level\" form and insert result as comment.
   1181 
   1182 The formatting of the comment is controlled via three options:
   1183     `cider-comment-prefix'           \";; => \"
   1184     `cider-comment-continued-prefix' \";;    \"
   1185     `cider-comment-postfix'          \"\"
   1186 
   1187 so that with customization you can optionally wrap the output
   1188 in the reader macro \"#_( .. )\", or \"(comment ... )\", or any
   1189 other desired formatting.
   1190 
   1191 If INSERT-BEFORE is non-nil, insert before the form, otherwise afterwards."
   1192   (interactive "P")
   1193   (cider-pprint-form-to-comment 'cider-defun-at-point insert-before))
   1194 
   1195 (declare-function cider-switch-to-repl-buffer "cider-mode")
   1196 
   1197 (defun cider-eval-last-sexp-to-repl (&optional prefix)
   1198   "Evaluate the expression preceding point and insert its result in the REPL.
   1199 If invoked with a PREFIX argument, switch to the REPL buffer."
   1200   (interactive "P")
   1201   (cider-interactive-eval nil
   1202                           (cider-insert-eval-handler (cider-current-repl))
   1203                           (cider-last-sexp 'bounds)
   1204                           (cider--nrepl-pr-request-map))
   1205   (when prefix
   1206     (cider-switch-to-repl-buffer)))
   1207 
   1208 (defun cider-pprint-eval-last-sexp-to-repl (&optional prefix)
   1209   "Evaluate expr before point and insert its pretty-printed result in the REPL.
   1210 If invoked with a PREFIX argument, switch to the REPL buffer."
   1211   (interactive "P")
   1212   (cider-interactive-eval nil
   1213                           (cider-insert-eval-handler (cider-current-repl))
   1214                           (cider-last-sexp 'bounds)
   1215                           (cider--nrepl-print-request-map fill-column))
   1216   (when prefix
   1217     (cider-switch-to-repl-buffer)))
   1218 
   1219 (defun cider-eval-print-last-sexp (&optional pretty-print)
   1220   "Evaluate the expression preceding point.
   1221 Print its value into the current buffer.
   1222 With an optional PRETTY-PRINT prefix it pretty-prints the result."
   1223   (interactive "P")
   1224   (cider-interactive-eval nil
   1225                           (cider-eval-print-handler)
   1226                           (cider-last-sexp 'bounds)
   1227                           (if pretty-print
   1228                               (cider--nrepl-print-request-map fill-column)
   1229                             (cider--nrepl-pr-request-map))))
   1230 
   1231 (defun cider--pprint-eval-form (form)
   1232   "Pretty print FORM in popup buffer."
   1233   (let* ((buffer (current-buffer))
   1234          (result-buffer (cider-popup-buffer cider-result-buffer nil 'clojure-mode 'ancillary))
   1235          (handler (cider-popup-eval-handler result-buffer)))
   1236     (with-current-buffer buffer
   1237       (cider-interactive-eval (when (stringp form) form)
   1238                               handler
   1239                               (when (consp form) form)
   1240                               (cider--nrepl-print-request-map fill-column)))))
   1241 
   1242 (defun cider-pprint-eval-last-sexp (&optional output-to-current-buffer)
   1243   "Evaluate the sexp preceding point and pprint its value.
   1244 If invoked with OUTPUT-TO-CURRENT-BUFFER, insert as comment in the current
   1245 buffer, else display in a popup buffer."
   1246   (interactive "P")
   1247   (if output-to-current-buffer
   1248       (cider-pprint-eval-last-sexp-to-comment)
   1249     (cider--pprint-eval-form (cider-last-sexp 'bounds))))
   1250 
   1251 (defun cider--prompt-and-insert-inline-dbg ()
   1252   "Insert a #dbg button at the current sexp."
   1253   (save-excursion
   1254     (let ((beg))
   1255       (skip-chars-forward "\r\n[:blank:]")
   1256       (unless (looking-at-p "(")
   1257         (ignore-errors (backward-up-list)))
   1258       (setq beg (point))
   1259       (let* ((cond (cider-read-from-minibuffer "Condition for debugging (leave empty for \"always\"): "))
   1260              (button (propertize (concat "#dbg"
   1261                                          (unless (equal cond "")
   1262                                            (format " ^{:break/when %s}" cond)))
   1263                                  'font-lock-face 'cider-fragile-button-face)))
   1264         (when (> (current-column) 30)
   1265           (insert "\n")
   1266           (indent-according-to-mode))
   1267         (insert button)
   1268         (when (> (current-column) 40)
   1269           (insert "\n")
   1270           (indent-according-to-mode)))
   1271       (make-button beg (point)
   1272                    'help-echo "Breakpoint. Reevaluate this form to remove it."
   1273                    :type 'cider-fragile))))
   1274 
   1275 (defun cider-eval-defun-at-point (&optional debug-it)
   1276   "Evaluate the current toplevel form, and print result in the minibuffer.
   1277 With DEBUG-IT prefix argument, also debug the entire form as with the
   1278 command `cider-debug-defun-at-point'."
   1279   (interactive "P")
   1280   (let ((inline-debug (eq 16 (car-safe debug-it))))
   1281     (when debug-it
   1282       (when (derived-mode-p 'clojurescript-mode)
   1283         (when (y-or-n-p (concat "The debugger doesn't support ClojureScript yet, and we need help with that."
   1284                                 "  \nWould you like to read the Feature Request?"))
   1285           (browse-url "https://github.com/clojure-emacs/cider/issues/1416"))
   1286         (user-error "The debugger does not support ClojureScript"))
   1287       (when inline-debug
   1288         (cider--prompt-and-insert-inline-dbg)))
   1289     (cider-interactive-eval (when (and debug-it (not inline-debug))
   1290                               (concat "#dbg\n" (cider-defun-at-point)))
   1291                             nil
   1292                             (cider-defun-at-point 'bounds)
   1293                             (cider--nrepl-pr-request-map))))
   1294 
   1295 (defun cider--insert-closing-delimiters (code)
   1296   "Closes all open parenthesized or bracketed expressions of CODE."
   1297   (with-temp-buffer
   1298     (insert code)
   1299     (goto-char (point-max))
   1300     (let ((matching-delimiter nil))
   1301       (while (ignore-errors
   1302                (save-excursion
   1303                  (backward-up-list 1)
   1304                  (setq matching-delimiter (cdr (syntax-after (point)))))
   1305                t)
   1306         (insert-char matching-delimiter)))
   1307     (buffer-string)))
   1308 
   1309 (defun cider-eval-defun-up-to-point (&optional output-to-current-buffer)
   1310   "Evaluate the current toplevel form up to point.
   1311 If invoked with OUTPUT-TO-CURRENT-BUFFER, print the result in the current
   1312 buffer.  It constructs an expression to eval in the following manner:
   1313 
   1314 - It find the code between the point and the start of the toplevel expression;
   1315 - It balances this bit of code by closing all open expressions;
   1316 - It evaluates the resulting code using `cider-interactive-eval'."
   1317   (interactive "P")
   1318   (let* ((beg-of-defun (save-excursion (beginning-of-defun) (point)))
   1319          (code (buffer-substring-no-properties beg-of-defun (point)))
   1320          (code (cider--insert-closing-delimiters code)))
   1321     (cider-interactive-eval code
   1322                             (when output-to-current-buffer
   1323                               (cider-eval-print-handler))
   1324                             (list beg-of-defun (point))
   1325                             (cider--nrepl-pr-request-map))))
   1326 
   1327 (defun cider--matching-delimiter (delimiter)
   1328   "Get the matching (opening/closing) delimiter for DELIMITER."
   1329   (pcase delimiter
   1330     (?\( ?\))
   1331     (?\[ ?\])
   1332     (?\{ ?\})
   1333     (?\) ?\()
   1334     (?\] ?\[)
   1335     (?\} ?\{)))
   1336 
   1337 (defun cider-eval-sexp-up-to-point (&optional  output-to-current-buffer)
   1338   "Evaluate the current sexp form up to point.
   1339 If invoked with OUTPUT-TO-CURRENT-BUFFER, print the result in the current
   1340 buffer.  It constructs an expression to eval in the following manner:
   1341 
   1342 - It finds the code between the point and the start of the sexp expression;
   1343 - It balances this bit of code by closing the expression;
   1344 - It evaluates the resulting code using `cider-interactive-eval'."
   1345   (interactive "P")
   1346   (let* ((beg-of-sexp (save-excursion (up-list) (backward-list) (point)))
   1347          (beg-delimiter (save-excursion (up-list) (backward-list) (char-after)))
   1348          (beg-set?  (save-excursion (up-list) (backward-list) (char-before)))
   1349          (code (buffer-substring-no-properties beg-of-sexp (point)))
   1350          (code (if (= beg-set? ?#) (concat (list beg-set?) code) code))
   1351          (code (concat code (list (cider--matching-delimiter beg-delimiter)))))
   1352     (cider-interactive-eval code
   1353                             (when output-to-current-buffer
   1354                               (cider-eval-print-handler))
   1355                             (list beg-of-sexp (point))
   1356                             (cider--nrepl-pr-request-map))))
   1357 
   1358 (defun cider-pprint-eval-defun-at-point (&optional output-to-current-buffer)
   1359   "Evaluate the \"top-level\" form at point and pprint its value.
   1360 If invoked with OUTPUT-TO-CURRENT-BUFFER, insert as comment in the current
   1361 buffer, else display in a popup buffer."
   1362   (interactive "P")
   1363   (if output-to-current-buffer
   1364       (cider-pprint-eval-defun-to-comment)
   1365     (cider--pprint-eval-form (cider-defun-at-point 'bounds))))
   1366 
   1367 (defun cider-eval-ns-form (&optional undef-all)
   1368   "Evaluate the current buffer's namespace form.
   1369 When UNDEF-ALL is non-nil, unmap all symbols and aliases first."
   1370   (interactive "P")
   1371   (when-let ((ns (clojure-find-ns)))
   1372     (save-excursion
   1373       (goto-char (match-beginning 0))
   1374       (when undef-all
   1375         (cider-undef-all ns))
   1376       (cider-eval-defun-at-point))))
   1377 
   1378 (defun cider-read-and-eval (&optional value)
   1379   "Read a sexp from the minibuffer and output its result to the echo area.
   1380 If VALUE is non-nil, it is inserted into the minibuffer as initial input."
   1381   (interactive)
   1382   (let* ((form (cider-read-from-minibuffer "Clojure Eval: " value))
   1383          (override cider-interactive-eval-override)
   1384          (ns-form (if (cider-ns-form-p form) "" (format "(ns %s)" (cider-current-ns)))))
   1385     (with-current-buffer (get-buffer-create cider-read-eval-buffer)
   1386       (erase-buffer)
   1387       (clojure-mode)
   1388       (unless (string= "" ns-form)
   1389         (insert ns-form "\n\n"))
   1390       (insert form)
   1391       (let ((cider-interactive-eval-override override))
   1392         (cider-interactive-eval form
   1393                                 nil
   1394                                 nil
   1395                                 (cider--nrepl-pr-request-map))))))
   1396 
   1397 (defun cider-read-and-eval-defun-at-point ()
   1398   "Insert the toplevel form at point in the minibuffer and output its result.
   1399 The point is placed next to the function name in the minibuffer to allow
   1400 passing arguments."
   1401   (interactive)
   1402   (let* ((fn-name (cadr (split-string (cider-defun-at-point))))
   1403          (form (format "(%s)" fn-name)))
   1404     (cider-read-and-eval (cons form (length form)))))
   1405 
   1406 (defun cider-kill-last-result ()
   1407   "Save the last evaluated result into the kill ring."
   1408   (interactive)
   1409   (kill-new
   1410    (nrepl-dict-get (cider-nrepl-sync-request:eval "*1") "value")))
   1411 
   1412 (defun cider-undef ()
   1413   "Undefine a symbol from the current ns."
   1414   (interactive)
   1415   (cider-ensure-op-supported "undef")
   1416   (cider-read-symbol-name
   1417    "Undefine symbol: "
   1418    (lambda (sym)
   1419      (cider-nrepl-send-request
   1420       `("op" "undef"
   1421         "ns" ,(cider-current-ns)
   1422         "sym" ,sym)
   1423       (cider-interactive-eval-handler (current-buffer))))))
   1424 
   1425 (defun cider-undef-all (&optional ns)
   1426   "Undefine all symbols and aliases from the namespace NS."
   1427   (interactive)
   1428   (cider-ensure-op-supported "undef-all")
   1429   (cider-nrepl-send-sync-request
   1430    `("op" "undef-all"
   1431      "ns" ,(or ns (cider-current-ns)))))
   1432 
   1433 ;; Eval keymaps
   1434 (defvar cider-eval-pprint-commands-map
   1435   (let ((map (define-prefix-command 'cider-eval-pprint-commands-map)))
   1436     ;; single key bindings defined last for display in menu
   1437     (define-key map (kbd "e") #'cider-pprint-eval-last-sexp)
   1438     (define-key map (kbd "d") #'cider-pprint-eval-defun-at-point)
   1439     (define-key map (kbd "c e") #'cider-pprint-eval-last-sexp-to-comment)
   1440     (define-key map (kbd "c d") #'cider-pprint-eval-defun-to-comment)
   1441 
   1442     ;; duplicates with C- for convenience
   1443     (define-key map (kbd "C-e") #'cider-pprint-eval-last-sexp)
   1444     (define-key map (kbd "C-d") #'cider-pprint-eval-defun-at-point)
   1445     (define-key map (kbd "C-c e") #'cider-pprint-eval-last-sexp-to-comment)
   1446     (define-key map (kbd "C-c C-e") #'cider-pprint-eval-last-sexp-to-comment)
   1447     (define-key map (kbd "C-c d") #'cider-pprint-eval-defun-to-comment)
   1448     (define-key map (kbd "C-c C-d") #'cider-pprint-eval-defun-to-comment)
   1449     map))
   1450 
   1451 (defvar cider-eval-commands-map
   1452   (let ((map (define-prefix-command 'cider-eval-commands-map)))
   1453     ;; single key bindings defined last for display in menu
   1454     (define-key map (kbd "w") #'cider-eval-last-sexp-and-replace)
   1455     (define-key map (kbd "r") #'cider-eval-region)
   1456     (define-key map (kbd "n") #'cider-eval-ns-form)
   1457     (define-key map (kbd "d") #'cider-eval-defun-at-point)
   1458     (define-key map (kbd "e") #'cider-eval-last-sexp)
   1459     (define-key map (kbd "q") #'cider-tap-last-sexp)
   1460     (define-key map (kbd "l") #'cider-eval-list-at-point)
   1461     (define-key map (kbd "v") #'cider-eval-sexp-at-point)
   1462     (define-key map (kbd "t") #'cider-tap-sexp-at-point)
   1463     (define-key map (kbd "o") #'cider-eval-sexp-up-to-point)
   1464     (define-key map (kbd ".") #'cider-read-and-eval-defun-at-point)
   1465     (define-key map (kbd "z") #'cider-eval-defun-up-to-point)
   1466     (define-key map (kbd "c") #'cider-eval-last-sexp-in-context)
   1467     (define-key map (kbd "b") #'cider-eval-sexp-at-point-in-context)
   1468     (define-key map (kbd "k") #'cider-kill-last-result)
   1469     (define-key map (kbd "f") 'cider-eval-pprint-commands-map)
   1470 
   1471     ;; duplicates with C- for convenience
   1472     (define-key map (kbd "C-w") #'cider-eval-last-sexp-and-replace)
   1473     (define-key map (kbd "C-r") #'cider-eval-region)
   1474     (define-key map (kbd "C-n") #'cider-eval-ns-form)
   1475     (define-key map (kbd "C-d") #'cider-eval-defun-at-point)
   1476     (define-key map (kbd "C-e") #'cider-eval-last-sexp)
   1477     (define-key map (kbd "C-q") #'cider-tap-last-sexp)
   1478     (define-key map (kbd "C-l") #'cider-eval-list-at-point)
   1479     (define-key map (kbd "C-v") #'cider-eval-sexp-at-point)
   1480     (define-key map (kbd "C-t") #'cider-tap-sexp-at-point)
   1481     (define-key map (kbd "C-o") #'cider-eval-sexp-up-to-point)
   1482     (define-key map (kbd "C-.") #'cider-read-and-eval-defun-at-point)
   1483     (define-key map (kbd "C-z") #'cider-eval-defun-up-to-point)
   1484     (define-key map (kbd "C-c") #'cider-eval-last-sexp-in-context)
   1485     (define-key map (kbd "C-b") #'cider-eval-sexp-at-point-in-context)
   1486     (define-key map (kbd "C-k") #'cider-kill-last-result)
   1487     (define-key map (kbd "C-f") 'cider-eval-pprint-commands-map)
   1488     map))
   1489 
   1490 (defun cider--file-string (file)
   1491   "Read the contents of a FILE and return as a string."
   1492   (with-current-buffer (find-file-noselect file)
   1493     (save-restriction
   1494       (widen)
   1495       (substring-no-properties (buffer-string)))))
   1496 
   1497 (defun cider-load-buffer (&optional buffer callback undef-all)
   1498   "Load (eval) BUFFER's file in nREPL.
   1499 If no buffer is provided the command acts on the current buffer.  If the
   1500 buffer is for a cljc file, and both a Clojure and ClojureScript REPL exists
   1501 for the project, it is evaluated in both REPLs.
   1502 Optional argument CALLBACK will override the default ‘cider-load-file-handler’.
   1503 When UNDEF-ALL is non-nil or called with \\[universal-argument], removes
   1504 all ns aliases and var mappings from the namespace before reloading it."
   1505   (interactive (list (current-buffer) nil (equal current-prefix-arg '(4))))
   1506   (setq buffer (or buffer (current-buffer)))
   1507   ;; When cider-load-buffer or cider-load-file are called in programs the
   1508   ;; current context might not match the buffer's context. We use the caller
   1509   ;; context instead of the buffer's context because that's the common use
   1510   ;; case. For the other use case just let-bind the default-directory.
   1511   (let ((orig-default-directory default-directory))
   1512     (with-current-buffer buffer
   1513       (check-parens)
   1514       (let ((default-directory orig-default-directory))
   1515         (unless buffer-file-name
   1516           (user-error "Buffer `%s' is not associated with a file" (current-buffer)))
   1517         (when (and cider-save-file-on-load
   1518                    (buffer-modified-p)
   1519                    (or (eq cider-save-file-on-load t)
   1520                        (y-or-n-p (format "Save file %s? " buffer-file-name))))
   1521           (save-buffer))
   1522         (remove-overlays nil nil 'cider-temporary t)
   1523         (when undef-all
   1524           (cider-undef-all (cider-current-ns)))
   1525         (cider--clear-compilation-highlights)
   1526         (cider--quit-error-window)
   1527         (let ((filename (buffer-file-name buffer))
   1528               (ns-form  (cider-ns-form)))
   1529           (cider-map-repls :auto
   1530             (lambda (repl)
   1531               (when ns-form
   1532                 (cider-repl--cache-ns-form ns-form repl))
   1533               (cider-request:load-file (cider--file-string filename)
   1534                                        (funcall cider-to-nrepl-filename-function
   1535                                                 (cider--server-filename filename))
   1536                                        (file-name-nondirectory filename)
   1537                                        repl
   1538                                        callback)))
   1539           (message "Loading %s..." filename))))))
   1540 
   1541 (defun cider-load-file (filename &optional undef-all)
   1542   "Load (eval) the Clojure file FILENAME in nREPL.
   1543 If the file is a cljc file, and both a Clojure and ClojureScript REPL
   1544 exists for the project, it is evaluated in both REPLs.  The heavy lifting
   1545 is done by `cider-load-buffer'.
   1546 When UNDEF-ALL is non-nil or called with \\[universal-argument], removes
   1547 all ns aliases and var mappings from the namespace before reloading it."
   1548   (interactive (list
   1549                 (read-file-name "Load file: " nil nil nil
   1550                                 (when (buffer-file-name)
   1551                                   (file-name-nondirectory
   1552                                    (buffer-file-name))))
   1553                 (equal current-prefix-arg '(4))))
   1554   (if-let* ((buffer (find-buffer-visiting filename)))
   1555       (cider-load-buffer buffer nil undef-all)
   1556     (cider-load-buffer (find-file-noselect filename) nil undef-all)))
   1557 
   1558 (defun cider-load-all-files (directory undef-all)
   1559   "Load all files in DIRECTORY (recursively).
   1560 Useful when the running nREPL on remote host.
   1561 When UNDEF-ALL is non-nil or called with \\[universal-argument], removes
   1562 all ns aliases and var mappings from the namespaces being reloaded"
   1563   (interactive "DLoad files beneath directory: \nP")
   1564   (mapcar (lambda (file) (cider-load-file file undef-all))
   1565           (directory-files-recursively directory "\\.clj[cs]?$")))
   1566 
   1567 (defalias 'cider-eval-file #'cider-load-file
   1568   "A convenience alias as some people are confused by the load-* names.")
   1569 
   1570 (defalias 'cider-eval-all-files #'cider-load-all-files
   1571   "A convenience alias as some people are confused by the load-* names.")
   1572 
   1573 (defalias 'cider-eval-buffer #'cider-load-buffer
   1574   "A convenience alias as some people are confused by the load-* names.")
   1575 
   1576 (defun cider-load-all-project-ns ()
   1577   "Load all namespaces in the current project."
   1578   (interactive)
   1579   (cider-ensure-connected)
   1580   (cider-ensure-op-supported "ns-load-all")
   1581   (when (y-or-n-p "Are you sure you want to load all namespaces in the project? ")
   1582     (message "Loading all project namespaces...")
   1583     (let ((loaded-ns-count (length (cider-sync-request:ns-load-all))))
   1584       (message "Loaded %d namespaces" loaded-ns-count))))
   1585 
   1586 (provide 'cider-eval)
   1587 
   1588 ;;; cider-eval.el ends here