Skip to content

Add inspect-print-current-value op #933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## master (unreleased)

* [#933](https://github.com/clojure-emacs/cider-nrepl/pull/933): Add the `cider-inspector-print-current-value` command to print the current value of the inspector.
* Bump `orchard` to [0.34.1](https://github.com/clojure-emacs/orchard/blob/master/CHANGELOG.md#0341-2025-04-23).
* [#935](https://github.com/clojure-emacs/cider-nrepl/pull/935): Unify injected print-method implementations with orchard.print.

Expand Down
24 changes: 24 additions & 0 deletions doc/modules/ROOT/pages/nrepl-api/ops.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,30 @@ Returns::



=== `inspect-print-current-value`

Print the current value of the inspector.

Required parameters::
* `:session` The current session


Optional parameters::
* `:nrepl.middleware.print/buffer-size` The size of the buffer to use when streaming results. Defaults to 1024.
* `:nrepl.middleware.print/keys` A seq of the keys in the response whose values should be printed.
* `:nrepl.middleware.print/options` A map of options to pass to the printing function. Defaults to ``nil``.
* `:nrepl.middleware.print/print` A fully-qualified symbol naming a var whose function to use for printing. Must point to a function with signature [value writer options].
* `:nrepl.middleware.print/quota` A hard limit on the number of bytes printed for each value.
* `:nrepl.middleware.print/stream?` If logical true, the result of printing each value will be streamed to the client over one or more messages.


Returns::
* `:path` Printed representation of current inspector path.
* `:status` "done"
* `:value` The inspector result. Contains a specially-formatted string that can be ``read`` and then rendered client-side.



=== `inspect-push`

Inspects the inside value specified by index.
Expand Down
7 changes: 6 additions & 1 deletion src/cider/nrepl.clj
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,12 @@ Note: Documentation may be incomplete; not all return keys are described."
inspector's state in the `:value` slot."
:requires #{"clone" #'wrap-caught #'wrap-print}
:expects #{"eval"}
:handles {"inspect-pop"
:handles {"inspect-print-current-value"
{:doc "Print the current value of the inspector."
:requires {"session" "The current session"}
:optional wrap-print-optional-arguments
:returns inspector-returns}
"inspect-pop"
{:doc "Moves one level up in the inspector stack."
:requires {"session" "The current session"}
:returns inspector-returns}
Expand Down
22 changes: 21 additions & 1 deletion src/cider/nrepl/middleware/inspect.clj
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
(ns cider.nrepl.middleware.inspect
(:require
[cider.nrepl.middleware.util :refer [respond-to]]
[cider.nrepl.middleware.util.cljs :as cljs]
[cider.nrepl.middleware.util.error-handling
:refer [eval-interceptor-transport with-safe-transport]]
[cider.nrepl.pprint :as pprint]
[nrepl.middleware.print :as print]
[nrepl.misc :refer [response-for]]
[nrepl.transport :as transport]
[orchard.inspect :as inspect]))
Expand Down Expand Up @@ -107,16 +110,33 @@
(defn def-current-value [msg]
(inspector-response msg (swap-inspector! msg inspect/def-current-value (symbol (:ns msg)) (:var-name msg))))

(defn print-current-value-reply [{:keys [::print/print-fn session] :as msg}]
(let [inspector (-> session meta ::inspector)]
(with-open [writer (print/replying-PrintWriter :value msg msg)]
(binding [*print-length* (or *print-length* 100)
*print-level* (or *print-level* 20)]
((or print-fn pprint/pprint) (:value inspector) writer)
(.flush writer)))
(respond-to msg :status :done)))

(defn tap-current-value [msg]
(inspector-response msg (swap-inspector! msg inspect/tap-current-value)))

(defn tap-indexed [msg]
(inspector-response msg (swap-inspector! msg inspect/tap-indexed (:idx msg))))

(defn handle-inspect [handler {:keys [op inspect] :as msg}]
(if (and (= op "eval") inspect)
(cond
(and (= op "eval") inspect)
(handle-eval-inspect handler msg)

;; This is outside of `with-safe-transport` because it streams the pretty
;; printed result to the client in multiple messages. It does NOT return any
;; value, which is expected by `with-safe-transport`.
(= op "inspect-print-current-value")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexander-yakushev Should we prefix this with cider/ from the beginning or leave this to for another day? (e.g. when we add aliases for the all the existing ops)

Copy link
Member

@alexander-yakushev alexander-yakushev Apr 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind; might as well add the prefix now indeed. Would you do it, @r0man?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep it consistent and do it once we decide to rename all. But I can also do this now (we are talking about this op only right?) if you prefer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, let's do this later.

(print-current-value-reply msg)

:else
(with-safe-transport handler msg
"inspect-pop" pop-reply
"inspect-push" push-reply
Expand Down
51 changes: 51 additions & 0 deletions test/clj/cider/nrepl/middleware/inspect_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,57 @@
:inspect "true"
:code "(range 100)"}))))))))

(deftest inspect-print-current-value-test
(testing "inspect-print-current-value returns the currently inspected value as a printed string"
(is (= [(str/join "\n" ["{:a -1,"
" :bb \"111\","
" :ccc (1),"
" :d"
" ({:a 0, :bb \"000\", :ccc ()}"
" {:a -1, :bb \"111\", :ccc (1)}"
" {:a -2, :bb \"222\", :ccc (2 1)}"
" {:a -3, :bb \"333\", :ccc (3 2 1)}"
" {:a -4, :bb \"444\", :ccc (4 3 2 1)})}"])]
(:value (do
(session/message {:op "eval"
:code "(def test-val
(for [i (range 2)]
{:a (- i)
:bb (str i i i)
:ccc (range i 0 -1)
:d (for [i (range 5)]
{:a (- i)
:bb (str i i i)
:ccc (range i 0 -1)})}))"})
(session/message {:op "eval"
:inspect "true"
:code "test-val"})
(session/message {:op "inspect-push"
:idx 2})
(session/message {:op "inspect-print-current-value"
:nrepl.middleware.print/print "cider.nrepl.pprint/pprint"})))))))

(deftest inspect-print-current-value-no-value-test
(testing "inspect-print-current-value returns nil if nothing has been inspected yet"
(is (= ["nil"] (:value (session/message
{:op "inspect-print-current-value"
:nrepl.middleware.print/print "cider.nrepl.pprint/pprint"}))))))

(deftest inspect-print-current-value-default-print-fn-test
(testing "inspect-print-current-value uses a default print fn when none is provided"
(is (= ["nil"] (:value (session/message {:op "inspect-print-current-value"}))))))

(deftest inspect-print-current-value-infinite-seq-test
(testing "inspect-print-current-value works with infinite-seqs"
(is (str/starts-with? (first (:value (do (session/message {:op "eval"
:code "(def test-val (repeat :x))"})
(session/message {:op "eval"
:inspect "true"
:code "test-val"})
(session/message {:op "inspect-print-current-value"
:nrepl.middleware.print/print "cider.nrepl.pprint/pprint"}))))
"(:x"))))

(deftest inspect-def-current-value-test
(testing "inspect-def-current-value defines a var with the current inspector value"
(is (= "{3 4}"
Expand Down