Function: nrepl-sync-request

nrepl-sync-request is a byte-compiled function defined in nrepl-client.el.

Signature

(nrepl-sync-request REQUEST CONNECTION &key ABORT-ON-INPUT TOOLING CALLBACK)

Documentation

Send REQUEST to the nREPL server synchronously using CONNECTION.

Hold till final "done" message has arrived and join all response messages of the same "op" that came along. If ABORT-ON-INPUT is non-nil, the function will return nil at the first sign of user input, so as not to hang the interface. If TOOLING, use the tooling session rather than the standard session.

If CALLBACK is non-nil, it will additionally be called on all received messages. This shouldn't be used this for any control logic - use the asynchronous nrepl-send-request directly for that. CALLBACK here should be used to react to some intermediate events in an otherwise synchronous command and e.g. notify the user about them.

This is the keyword-argument form; nrepl-send-sync-request is the legacy positional shim retained for backward compatibility.

Source Code

;; Defined in ~/.emacs.d/elpa/cider-20260822.1520/nrepl-client.el
(cl-defun nrepl-sync-request (request connection &key abort-on-input
                                      tooling callback)
  "Send REQUEST to the nREPL server synchronously using CONNECTION.
Hold till final \"done\" message has arrived and join all response messages
of the same \"op\" that came along.
If ABORT-ON-INPUT is non-nil, the function will return nil at the first
sign of user input, so as not to hang the interface.
If TOOLING, use the tooling session rather than the standard session.

If CALLBACK is non-nil, it will additionally be called on all received
messages.  This shouldn't be used this for any control logic - use the
asynchronous `nrepl-send-request' directly for that.  CALLBACK here should
be used to react to some intermediate events in an otherwise synchronous
command and e.g. notify the user about them.

This is the keyword-argument form; `nrepl-send-sync-request' is the legacy
positional shim retained for backward compatibility."
  (let* ((time0 (current-time))
         (response (cons 'dict nil))
         (nrepl-ongoing-sync-request t)
         (cb (lambda (resp)
               ;; If caller has provided `callback', call it on the response.
               (when callback
                 (funcall callback resp))
               (nrepl--merge response resp)))
         status
         (id (nrepl-send-request request cb connection tooling)))
    (unwind-protect
        (progn
          (while (and (not (member "done" status))
                      (not (and abort-on-input
                                (input-pending-p))))
            (setq status (nrepl-dict-get response "status"))
            ;; On a need-input response the eval is blocked reading stdin and
            ;; won't finish on its own, so forward it to the user (who provides
            ;; input or cancels) instead of waiting for the timeout.
            (if (and (member "need-input" status)
                     nrepl-need-input-handler-function)
                (progn (funcall nrepl-need-input-handler-function (current-buffer) response)
                       ;; If the user took a few seconds to respond, we might
                       ;; unnecessarily timeout, so let's reset the timer.
                       (setq time0 (current-time)))
              ;; break out in case we don't receive a response for a while
              (when (and nrepl-sync-request-timeout
                         (time-less-p
                          nrepl-sync-request-timeout
                          (time-subtract nil time0)))
                (error "Sync nREPL request timed out %s after %s secs" request nrepl-sync-request-timeout)))
            ;; Clean up the response, otherwise we might repeatedly ask for input.
            (nrepl-dict-put response "status" (remove "need-input" status))
            (accept-process-output nil 0.01))
          ;; If we couldn't finish, return nil.
          (when (member "done" status)
            (nrepl-dbind-response response (ex err eval-error)
              (when (and ex err eval-error nrepl-err-handler-function)
                (funcall nrepl-err-handler-function connection))
              ;; The op was declined because a ClojureScript REPL is active; abort
              ;; the calling command with a clear message (clojure-emacs/cider#2198).
              (when-let* ((msg (nrepl--clojure-only-error response)))
                (user-error "%s" msg))
              response)))
      ;; Always reap the pending callback -- even on an abort-on-input or
      ;; timeout exit -- so it isn't leaked for the life of the connection.
      (when (buffer-live-p connection)
        (with-current-buffer connection
          (nrepl--mark-id-completed id))))))