diff --git a/CHANGELOG.md b/CHANGELOG.md
index fd149c183..d6864b8af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
### New features
+* [#1545](https://github.com/clojure-emacs/cider/pull/1545): New feature: Enlighten. See the new Readme section for more information.
* [#1169](https://github.com/clojure-emacs/cider/pull/1169): New command `cider-eval-defun-to-comment`.
* Change default value of `cider-overlays-use-font-lock` to `t`. Unlike before, a value of `t`, causes `cider-result-overlay-face` is to be prepended to the font-lock faces (instead of just not being used).
* `cider-result-overlay-face` default value changed to a background and a box, so it can be prepended to other faces without overriding the foreground.
diff --git a/README.md b/README.md
index 234ad3200..518e28732 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,7 @@ specific CIDER release.**
- [Value Inspection](#value-inspection)
- [Running Tests](#running-tests)
- [Navigating Stacktraces](#navigating-stacktraces)
+ - [Enlighten (display local values)](#enlighten-display-local-values)
- [Debugging](#debugging)
- [Code reloading](#code-reloading)
- [Managing multiple connections](#managing-multiple-connections)
@@ -808,6 +809,26 @@ will be used.
(setq cider-stacktrace-fill-column 80)
```
+### Enlighten (display local values)
+
+This feature displays the value of locals in realtime, as your code is being
+executed. This is somewhat akin to one of the features of the Light Table
+editor.
+
+- To turn it on, issue `M-x cider-enlighten-mode`.
+- To use it, evaluate your functions one at a time (e.g., use `C-M-x` or `C-x C-e`, because `C-c C-k` won't work).
+
+That's it! Once your code executes, the regular old buffer on the left will turn
+into the brilliant show of lights on the right.
+
+
+
+
+
+
+You can also trigger this on specific functions (without having to turn on the
+minor mode) by writing `#light` before the `(def` and reevaluating it.
+
### Debugging
The debugger can be invoked in several ways, the simplest one is to type
diff --git a/cider-debug.el b/cider-debug.el
index 81430f5b8..08c5364f0 100644
--- a/cider-debug.el
+++ b/cider-debug.el
@@ -63,6 +63,23 @@
:group 'cider-debug
:package-version '(cider . "0.10.0"))
+(defface cider-enlightened
+ '((((class color) (background light)) :inherit cider-result-overlay-face
+ :box (:color "darkorange" :line-width -1))
+ (((class color) (background dark)) :inherit cider-result-overlay-face
+ ;; "#dd0" is a dimmer yellow.
+ :box (:color "#dd0" :line-width -1)))
+ "Face used to mark enlightened sexps and their return values."
+ :group 'cider-debug
+ :package-version '(cider . "0.11.0"))
+
+(defface cider-enlightened-local
+ '((((class color) (background light)) :weight bold :foreground "darkorange")
+ (((class color) (background dark)) :weight bold :foreground "yellow"))
+ "Face used to mark enlightened locals (not their values)."
+ :group 'cider-debug
+ :package-version '(cider . "0.11.0"))
+
(defcustom cider-debug-prompt 'overlay
"If and where to show the keys while debugging.
If `minibuffer', show it in the minibuffer along with the return value.
@@ -127,6 +144,8 @@ This variable must be set before starting the repl connection."
(defun cider--debug-response-handler (response)
"Handle responses from the cider.debug middleware."
(nrepl-dbind-response response (status id causes)
+ (when (member "enlighten" status)
+ (cider--handle-enlighten response))
(when (or (member "eval-error" status)
(member "stack" status))
;; TODO: Make the error buffer a bit friendlier when we're just printing
@@ -585,6 +604,36 @@ needed. It is expected to contain at least \"key\", \"input-type\", and
(error (cider-debug-mode-send-reply ":quit" key)
(message "Error encountered while handling the debug message: %S" e)))))
+(defun cider--handle-enlighten (response)
+ "Handle an enlighten notification.
+RESPONSE is a message received from the nrepl describing the value and
+coordinates of a sexp. Create an overlay after the specified sexp
+displaying its value."
+ (when-let ((marker (cider--debug-find-source-position response)))
+ (with-current-buffer (marker-buffer marker)
+ (save-excursion
+ (goto-char marker)
+ (clojure-backward-logical-sexp 1)
+ (nrepl-dbind-response response (debug-value erase-previous)
+ (when erase-previous
+ (remove-overlays (point) marker 'cider-type 'enlighten))
+ (when debug-value
+ (if (memq (char-before marker) '(?\) ?\] ?}))
+ ;; Enlightening a sexp looks like a regular return value, except
+ ;; for a different border.
+ (cider--make-result-overlay (cider-font-lock-as-clojure debug-value)
+ :where (cons marker marker)
+ :type 'enlighten
+ :prepend-face 'cider-enlightened)
+ ;; Enlightening a symbol uses a more abbreviated format. The
+ ;; result face is the same as a regular result, but we also color
+ ;; the symbol with `cider-enlightened-local'.
+ (cider--make-result-overlay (cider-font-lock-as-clojure debug-value)
+ :format "%s"
+ :where (cons (point) marker)
+ :type 'enlighten
+ 'face 'cider-enlightened-local))))))))
+
;;; Move here command
;; This is the inverse of `cider--debug-move-point'. However, that algorithm is
diff --git a/cider-mode.el b/cider-mode.el
index 9eaa71d8b..5999e98ce 100644
--- a/cider-mode.el
+++ b/cider-mode.el
@@ -360,14 +360,18 @@ The value can also be t, which means to font-lock as much as possible."
(let ((cider-font-lock-dynamically (if (eq cider-font-lock-dynamically t)
'(function var macro core deprecated)
cider-font-lock-dynamically))
- deprecated
+ deprecated enlightened
macros functions vars instrumented traced)
(when (memq 'core cider-font-lock-dynamically)
(while core-plist
(let ((sym (pop core-plist))
(meta (pop core-plist)))
- (when (nrepl-dict-get meta "cider.nrepl.middleware.util.instrument/breakfunction")
- (push sym instrumented))
+ (pcase (nrepl-dict-get meta "cider.nrepl.middleware.util.instrument/breakfunction")
+ (`nil nil)
+ (`"#'cider.nrepl.middleware.debug/breakpoint-if-interesting"
+ (push sym instrumented))
+ (`"#'cider.nrepl.middleware.enlighten/light-form"
+ (push sym enlightened)))
(when (or (nrepl-dict-get meta "clojure.tools.trace/traced")
(nrepl-dict-get meta "cider.inlined-deps.clojure.tools.trace/traced"))
(push sym traced))
@@ -383,8 +387,12 @@ The value can also be t, which means to font-lock as much as possible."
(while symbols-plist
(let ((sym (pop symbols-plist))
(meta (pop symbols-plist)))
- (when (nrepl-dict-get meta "cider.nrepl.middleware.util.instrument/breakfunction")
- (push sym instrumented))
+ (pcase (nrepl-dict-get meta "cider.nrepl.middleware.util.instrument/breakfunction")
+ (`nil nil)
+ (`"#'cider.nrepl.middleware.debug/breakpoint-if-interesting"
+ (push sym instrumented))
+ (`"#'cider.nrepl.middleware.enlighten/light-form"
+ (push sym enlightened)))
(when (or (nrepl-dict-get meta "clojure.tools.trace/traced")
(nrepl-dict-get meta "cider.inlined-deps.clojure.tools.trace/traced"))
(push sym traced))
@@ -414,6 +422,9 @@ The value can also be t, which means to font-lock as much as possible."
,@(when deprecated
`((,(regexp-opt deprecated 'symbols) 0
(cider--unless-local-match cider-deprecated-properties) append)))
+ ,@(when enlightened
+ `((,(regexp-opt enlightened 'symbols) 0
+ (cider--unless-local-match 'cider-enlightened) append)))
,@(when instrumented
`((,(regexp-opt instrumented 'symbols) 0
(cider--unless-local-match 'cider-instrumented-face) append)))
@@ -423,7 +434,7 @@ The value can also be t, which means to font-lock as much as possible."
(defconst cider--static-font-lock-keywords
(eval-when-compile
- `((,(regexp-opt '("#break" "#dbg") 'symbols) 0 font-lock-warning-face)))
+ `((,(regexp-opt '("#break" "#dbg" "#light") 'symbols) 0 font-lock-warning-face)))
"Default expressions to highlight in CIDER mode.")
(defvar-local cider--dynamic-font-lock-keywords nil)
diff --git a/doc/images/enlighten-off.png b/doc/images/enlighten-off.png
new file mode 100644
index 000000000..5033e7da2
Binary files /dev/null and b/doc/images/enlighten-off.png differ
diff --git a/doc/images/enlighten-on.png b/doc/images/enlighten-on.png
new file mode 100644
index 000000000..82995a4f2
Binary files /dev/null and b/doc/images/enlighten-on.png differ
diff --git a/nrepl-client.el b/nrepl-client.el
index 26e64b52e..abb1afada 100644
--- a/nrepl-client.el
+++ b/nrepl-client.el
@@ -999,6 +999,9 @@ Register CALLBACK as the response handler."
callback
connection))
+(define-minor-mode cider-enlighten-mode nil nil (cider-mode " light")
+ :global t)
+
(defun nrepl--eval-request (input session &optional ns line column)
"Prepare :eval request message for INPUT.
SESSION and NS provide context for the request.
@@ -1008,6 +1011,8 @@ If LINE and COLUMN are non-nil and current buffer is a file buffer, \"line\",
(list "op" "eval"
"session" session
"code" input)
+ (when cider-enlighten-mode
+ (list "enlighten" "true"))
(let ((file (or (buffer-file-name) (buffer-name))))
(when (and line column file)
(list "file" file