diff --git a/README.md b/README.md index c43438ab4..4118915ef 100644 --- a/README.md +++ b/README.md @@ -921,6 +921,10 @@ Keyboard shortcut | Description l | List local variables q | Quit execution +In addition, all the usual evaluation commands (such as C-x C-e or +C-c M-:) will use the current lexical context (local variables) while +the debugger is active. + ### Managing multiple sessions You can connect to multiple nREPL servers using M-x diff --git a/cider-debug.el b/cider-debug.el index 807651925..6c1000c56 100644 --- a/cider-debug.el +++ b/cider-debug.el @@ -178,6 +178,18 @@ Each element of LOCALS should be a list of at least two elements." (setq cider--debug-display-locals (not cider--debug-display-locals)) (cider--debug-mode-redisplay)) +(defun cider--debug-lexical-eval (key form &optional callback _point) + "Eval FORM in the lexical context of debug session given by KEY. +Do nothing if CALLBACK is provided. +Designed to be used as `cider-interactive-eval-override' and called instead +of `cider-interactive-eval' in debug sessions." + ;; The debugger uses its own callback, so if the caller is passing a callback + ;; we return nil and let `cider-interactive-eval' do its thing. + (unless callback + (cider-debug-mode-send-reply (format "{:response :eval, :code %s}" form) + key) + t)) + (defvar cider--debug-mode-map) (define-minor-mode cider--debug-mode @@ -190,6 +202,10 @@ In order to work properly, this mode must be activated by (nrepl-dbind-response cider--debug-mode-response (input-type) (unless (consp input-type) (error "debug-mode activated on a message not asking for commands: %s" cider--debug-mode-response)) + ;; Integrate with eval commands. + (setq cider-interactive-eval-override + (apply-partially #'cider--debug-lexical-eval + (nrepl-dict-get cider--debug-mode-response "key"))) ;; Set the keymap. (let ((alist `((?\C-g . ":quit") ,@(mapcar (lambda (k) (cons (string-to-char k) (concat ":" k))) @@ -206,6 +222,7 @@ In order to work properly, this mode must be activated by (setq buffer-read-only nil) (remove-overlays nil nil 'cider-type 'debug-result) (remove-overlays nil nil 'cider-type 'debug-code) + (setq cider-interactive-eval-override nil) (setq cider--debug-mode-commands-alist nil) (setq cider--debug-mode-response nil))) diff --git a/cider-interaction.el b/cider-interaction.el index 6cb4397de..116ccbc8b 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -1640,21 +1640,30 @@ Clears any compilation highlights and kills the error window." (cider-eval-ns-form) (cider--cache-ns-form)))) +(defvar-local cider-interactive-eval-override nil + "Function to call instead of `cider-interactive-eval'.") + (defun cider-interactive-eval (form &optional callback point) "Evaluate FORM and dispatch the response to CALLBACK. This function is the main entry point in CIDER's interactive evaluation API. Most other interactive eval functions should rely on this function. If CALLBACK is nil use `cider-interactive-eval-handler'. -POINT, if non-nil, is the position of FORM in its buffer." - (cider--prep-interactive-eval form) - (nrepl-request:eval - form - (or callback (cider-interactive-eval-handler)) - ;; always eval ns forms in the user namespace - ;; otherwise trying to eval ns form for the first time will produce an error - (if (cider-ns-form-p form) "user" (cider-current-ns)) - nil - point)) +POINT, if non-nil, is the position of FORM in its buffer. + +If `cider-interactive-eval-override' is a function, call it with the same +arguments and only proceed with evaluation if it returns nil." + (unless (and cider-interactive-eval-override + (functionp cider-interactive-eval-override) + (funcall cider-interactive-eval-override form callback point)) + (cider--prep-interactive-eval form) + (nrepl-request:eval + form + (or callback (cider-interactive-eval-handler)) + ;; always eval ns forms in the user namespace + ;; otherwise trying to eval ns form for the first time will produce an error + (if (cider-ns-form-p form) "user" (cider-current-ns)) + nil + point))) (defun cider-interactive-pprint-eval (form &optional callback right-margin) "Evaluate FORM and dispatch the response to CALLBACK. @@ -1752,6 +1761,7 @@ command `cider-debug-defun-at-point'." "Read a sexp from the minibuffer and output its result to the echo area." (interactive) (let* ((form (cider-read-from-minibuffer "CIDER Eval: ")) + (override cider-interactive-eval-override) (ns-form (if (cider-ns-form-p form) "" (format "(ns %s)" (cider-current-ns))))) (with-current-buffer (get-buffer-create cider-read-eval-buffer) (erase-buffer) @@ -1759,7 +1769,8 @@ command `cider-debug-defun-at-point'." (unless (string= "" ns-form) (insert ns-form "\n\n")) (insert form) - (cider-interactive-eval form)))) + (let ((cider-interactive-eval-override override)) + (cider-interactive-eval form))))) ;; Connection and REPL