= Misc Functionality

== Pretty Printing

NOTE: Pretty printing support was added in nREPL 0.6 and the API is still
considered experimental.

The namespace `nrepl.middleware.print` contains some dynamic vars you can `set!`
at the REPL to alter how evaluation results will be printed. Note that if your
nREPL client supports passing these options in requests, then it may override
some or all of these options.

* `\*print-fn*`: the function to use for printing. Defaults to the equivalent of
  `clojure.core/pr`. The function must take two arguments:

** `value`: the value to print.
** `writer`: the `java.io.Writer` to print on.

* `\*stream?*`: if logical true, the result of printing each value will be
  streamed to the client over one or more messages. Defaults to false.

** This lets you see results being printed incrementally, and optionally
   interrupt the evaluation while it is printing.

** Your nREPL client may not fully support this mode of operation.

* `\*buffer-size*`: size of the buffer to use when streaming results. Defaults
  to 1024.

* `\*quota*`: a hard limit on the number of bytes printed for each value.
  Defaults to nil (no limit).

** Your nREPL client may not indicate if truncation has occurred.

For example, to prevent printing infinite lazy sequences from causing the REPL
to hang:

[source,clojure]
----
user=> (set! nrepl.middleware.print/*quota* 32)
32
user=> (range)
(0 1 2 3 4 5 6 7 8 9 10 11 12 13
user=>
----

Or to use `clojure.pprint` to print evaluation results:

[source,clojure]
----
user=> (set! nrepl.middleware.print/*print-fn* clojure.pprint/pprint)
#object[clojure.pprint$pprint 0x2bc11aa0 "clojure.pprint$pprint@2bc11aa0"]

user=> (meta #'int)
{:added "1.0",
 :ns #object[clojure.lang.Namespace 0xea12515 "clojure.core"],
 :name int,
 :file "clojure/core.clj",
 :column 1,
 :line 882,
 :arglists ([x]),
 :doc "Coerce to int",
 :inline
 #object[clojure.core$int__inliner__5509 0x3c79d89 "clojure.core$int__inliner__5509@3c79d89"]}

user=>
----

However, note well that `clojure.pprint/pprint` rebinds `\*out*` internally, and
so if anything else prints to `\*out*` while evaluating, that output will end up
intermingled in the result. See the
<<../design/middleware#_pretty_printing,print middleware documentation>> for a
more detailed explanation.

== Evaluation Errors

The dynamic var `nrepl.middleware.caught/\*caught-fn*` can be `set!` at the REPL
to alter how evaluation errors will be handled. Like the `:caught` option to
`clojure.main/repl`, this is a function that takes a `java.lang.Throwable`
(default `clojure.main/repl-caught`) and is called when either read, eval, or
print throws an exception or error.

For example, to automatically print the stacktrace of each error:

[source,clojure]
----
user> (set! nrepl.middleware.caught/*caught-fn* clojure.repl/pst)
#function[clojure.repl/pst]
user> (first 1)
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long
	clojure.lang.RT.seqFrom (RT.java:542)
	clojure.lang.RT.seq (RT.java:523)
	clojure.lang.RT.first (RT.java:668)
	clojure.core/first--4339 (core.clj:55)
	clojure.core/first--4339 (core.clj:55)
	user/eval11339 (form-init6612168545889071220.clj:12)
	user/eval11339 (form-init6612168545889071220.clj:12)
	clojure.lang.Compiler.eval (Compiler.java:6927)
	clojure.lang.Compiler.eval (Compiler.java:6890)
	clojure.core/eval (core.clj:3105)
	clojure.core/eval (core.clj:3101)
	clojure.main/repl/read-eval-print--7408/fn--7411 (main.clj:240)

user=>
----

Or to use the link:https://github.com/AvisoNovate/pretty[pretty] stacktrace
printing library to print stacktraces:

[source,clojure]
----
user=> (set! nrepl.middleware.caught/*caught-fn* io.aviso.repl/pretty-pst)
#function[io.aviso.repl/pretty-pst]
user=> (first 1)
 clojure.core/eval   core.clj: 3214
               ...
     user/eval5945  REPL Input
clojure.core/first   core.clj:   55
               ...
java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long

user=>
----

== Hot-loading dependencies

From time to time you'd want to experiment with some library without
adding it as a dependency of your project.  You can easily achieve
this with `tools.deps` or `pomegranate`. Let's start with a `tools.deps` example:

[source,shell]
----
$ clj -Sdeps '{:deps {nrepl {:mvn/version "0.6.0"}
                      org.clojure/tools.deps.alpha {:git/url "https://github.com/clojure/tools.deps.alpha.git"
                                                    :sha "d492e97259c013ba401c5238842cd3445839d020"}}}' -m nrepl.cmdline --interactive
network-repl
Clojure 1.9.0
user=> (require '[clojure.tools.deps.alpha.repl :refer [add-lib]])
nil
user=> (add-lib 'org.clojure/core.memoize {:mvn/version "0.7.1"})
true
user=> (require 'clojure.core.memoize)
nil
user=>

----

Alternatively with `pomegranate` you can do the following:

[source,shell]
----
$ clj -Sdeps '{:deps {nrepl {:mvn/version "0.6.0"} com.cemerick/pomegranate {:mvn/version "1.0.0"}}}' -m nrepl.cmdline --interactive
network-repl
Clojure 1.9.0
user=> (require '[cemerick.pomegranate :refer [add-dependencies]])
nil
user=> (add-dependencies :coordinates '[[org.clojure/core.memoize "0.7.1"]]
                         :repositories (merge cemerick.pomegranate.aether/maven-central
                                             {"clojars" "https://clojars.org/repo"}))
{[org.clojure/core.memoize "0.7.1"] #{[org.clojure/core.cache "0.7.1"] [org.clojure/clojure "1.6.0"]}, [org.clojure/core.cache "0.7.1"] #{[org.clojure/data.priority-map "0.0.7"]}, [org.clojure/data.priority-map "0.0.7"] nil, [org.clojure/clojure "1.6.0"] nil}
user=> (require 'clojure.core.memoize)
nil
----
