Skip to content

Update to nREPL 0.6.0 / cider-nrepl 0.21.0 #2579

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 17 commits into from
Feb 12, 2019
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: 0 additions & 1 deletion .dir-locals.el
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
(cider--jack-in . 1)
(cider--make-result-overlay . 1)
;; need better solution for indenting cl-flet bindings
(multiline-comment-handler . defun) ;; cl-flet
(insert-label . defun) ;; cl-flet
(insert-align-label . defun) ;; cl-flet
(insert-rect . defun) ;; cl-flet
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,29 @@

### New features

* The `cider-test-run-*` and `cider-ns-refresh-*` commands are now interruptible by the `cider-interrupt` command.
* Many commands now stream printed results back to the client incrementally – meaning it's now possible to, for example, interrupt evaluations while their result is being rendered.
* New option: `cider-repl-init-code`. This is a list of strings containing Clojure code to evaluate when the REPL starts (with bindings for any `set!`-able vars in place). Replaces `cider-print-length` and `cider-print-level`, which are now obsolete.
* New option: `cider-print-quota`. This is a hard limit on the number of bytes that will be returned by any printing operation. This defaults to one megabyte and can be set to `nil` if no limit is desired.

### Changes

* **(Breaking)** Upgrade to nREPL 0.6.0. This is now the minimum required version.
* **(Breaking)** Upgrade to piggieback 0.4.0. This is now the minimum required version.
* **(Breaking)** Remove `cider.nrepl.middleware.pprint`. All functionality has been replaced by the built-in printing support in nREPL 0.6.
* Option `cider-repl-scroll-on-output` is now obsolete, and the default REPL behaviour has changed to _not_ recenter the window. The built-in variable `scroll-conservatively` can be set to 101 (either globally or locally in the REPL buffer) to restore the old behaviour. This change has a dramatic positive effect on REPL performance.
* `cider-pprint-fn` and `cider-pprint-options` are now obsolete, replaced by `cider-print-fn` and `cider-print-options`.
* `cider-debug-print-options`, `cider-stacktrace-print-options`, and `cider-repl-pretty-print-width` are now all obsolete, replaced by `cider-print-options`.
* [#2546](https://github.com/clojure-emacs/cider/pull/2546): New defcustom `cider-ns-save-files-on-refresh-modes` to control for which buffers `cider-ns-refresh` should save before refreshing.

### Bug fixes

* Fix values for `cider-preferred-build-tool` variable.
* Fix value and safe property for `cider-allow-jack-in-without-project` variable.
* `cider-ns-save-files-on-refresh` will now save any modified buffers visiting files on the classpath, rather than just in the current project.
* `cider-expected-ns` no longer requires an absolute path as its argument, and now internally handles paths canonically and consistently.
* Fixed a bug causing REPL output to be inserted after the prompt.
* Fixed a bug causing `cider-pprint-eval-last-sexp-to-comment` and `cider-pprint-eval-defun-to-comment` to not insert anything.

## 0.20.0 (2019-01-14)

Expand Down
159 changes: 94 additions & 65 deletions cider-client.el
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@

;;; Code:

(require 'map)
(require 'seq)
(require 'subr-x)

(require 'clojure-mode)
(require 'spinner)
(require 'nrepl-client)

(require 'cider-compat)
(require 'cider-connection)
(require 'cider-common)
(require 'cider-util)
(require 'clojure-mode)

(require 'subr-x)
(require 'cider-compat)
(require 'seq)
(require 'nrepl-client)


;;; Eval spinner
Expand Down Expand Up @@ -195,64 +197,71 @@ buffer, defaults to (cider-current-repl)."
If NS is non-nil, include it in the eval request."
(nrepl-sync-request:eval input (or connection (cider-current-repl)) ns))

(defcustom cider-pprint-fn 'pprint
"Sets the function to use when pretty-printing evaluation results.
(defcustom cider-print-fn 'pprint
"Sets the function to use for printing.

nil – to defer to nREPL to choose the printing function. This will use
the bound value of \\=`nrepl.middleware.print/*print-fn*\\=`, which
defaults to the equivalent of \\=`clojure.core/pr\\=`.

The value must be one of the following symbols:
`pr' – to use the equivalent of \\=`clojure.core/pr\\=`.

`pprint' - to use \\=`clojure.pprint/pprint\\=`
`pprint' to use \\=`clojure.pprint/pprint\\=` (this is the default).

`fipp' - to use the Fast Idiomatic Pretty Printer, approximately 5-10x
faster than \\=`clojure.core/pprint\\=` (this is the default)
`fipp' to use the Fast Idiomatic Pretty Printer, approximately 5-10x
faster than \\=`clojure.core/pprint\\=`.

`puget' - to use Puget, which provides canonical serialization of data on
top of fipp, but at a slight performance cost
`puget' to use Puget, which provides canonical serialization of data on
top of fipp, but at a slight performance cost.

`zprint' - to use zprint, a fast and flexible alternative to the libraries
`zprint' to use zprint, a fast and flexible alternative to the libraries
mentioned above.

Alternatively, can be the namespace-qualified name of a Clojure function of
two arguments - an object to print and an options map. The options map will
have string keys. If the function
cannot be resolved, an exception will be thrown.

The function should ideally have a two-arity variant that accepts the
object to print and a map of configuration options for the printer. See
`cider-pprint-options' for details.

The function is also assumed to respect the contract of
\\=`clojure.pprint/pprint\\=` with respect to the bound values of
\\=`*print-length*\\=`, \\=`*print-level*\\=`, \\=`*print-meta*\\=`, and
\\=`clojure.pprint/*print-right-margin*\\=`. Those would normally serve as
fallback values when a map of print options is not supplied explicitly."
:type '(choice (const pprint)
Alternatively can be the namespace-qualified name of a Clojure var whose
function takes three arguments: the object to print, the
\\=`java.io.PrintWriter\\=` to print on, and a (possibly nil) map of
options. If the function cannot be resolved, will behave as if set to
nil."
:type '(choice (const nil)
(const pr)
(const pprint)
(const fipp)
(const puget)
(const zprint)
string)
:group 'cider
:package-version '(cider . "0.11.0"))
:package-version '(cider . "0.21.0"))

(defcustom cider-pprint-options nil
"A list of options for the pretty-printer that will be converted to a map.
Note that map can only have string keys, so the printer functions should be
able to handle those. Here's an example for `pprint':
(defcustom cider-print-options nil
"A map of options that will be passed to `cider-print-fn'.
Here's an example for `pprint':

'(dict \"length\" 50 \"right-margin\" 70)"
'((\"length\" 50) (\"right-margin\" 70))"
:type 'list
:group 'cider
:package-version '(cider . "0.20.0"))
:package-version '(cider . "0.21.0"))

(make-obsolete-variable 'cider-pprint-fn 'cider-print-fn "0.21")
(make-obsolete-variable 'cider-pprint-options 'cider-print-options "0.21")

(defcustom cider-print-quota (* 1024 1024)
"A hard limit on the number of bytes to return from any printing operation.
Set to nil for no limit."
:type 'integer
:group 'cider
:package-version '(cider . "0.21.0"))

(defun cider--pprint-fn ()
"Return the value to send in the pprint-fn slot of messages."
(pcase cider-pprint-fn
(defun cider--print-fn ()
"Return the value to send in the nrepl.middleware.print/print slot."
(pcase cider-print-fn
(`pr "cider.nrepl.pprint/pr")
(`pprint "cider.nrepl.pprint/pprint")
(`fipp "cider.nrepl.pprint/fipp-pprint")
(`puget "cider.nrepl.pprint/puget-pprint")
(`fipp "cider.nrepl.pprint/fipp-pprint")
(`puget "cider.nrepl.pprint/puget-pprint")
(`zprint "zprint.core/zprint-str")
(_ cider-pprint-fn)))
(_ cider-print-fn)))

(defvar cider--pprint-options-mapping
(defvar cider--print-options-mapping
'((right-margin
((fipp . width) (puget . width) (zprint . width)))
(length
Expand All @@ -261,32 +270,49 @@ able to handle those. Here's an example for `pprint':
((fipp . print-level) (puget . print-level) (zprint . max-depth))))
"A mapping of print option for the various supported print engines.")

(defun cider--pprint-option (name printer)
"Covert the generic NAME to its PRINTER specific variant.
(defun cider--print-option (name printer)
"Convert the generic NAME to its PRINTER specific variant.
E.g. pprint's right-margin would become width for fipp.
The function is useful when you want to generate dynamically
print options.

NAME can be a string or a symbol. PRINTER has to be a symbol.
The result will be a string."
(let* ((name (cider-maybe-intern name))
(result (cdr (assoc printer (cadr (assoc name cider--pprint-options-mapping))))))
(result (cdr (assoc printer (cadr (assoc name cider--print-options-mapping))))))
(symbol-name (or result name))))

(defun cider--nrepl-pprint-request-plist (right-margin &optional pprint-fn)
"Plist to be appended to an eval request to make it use pprint.
PPRINT-FN is the name of the Clojure function to use.
RIGHT-MARGIN specifies the maximum column-width of the pretty-printed
result, and is included in the request if non-nil."
(let* ((print-options (or cider-pprint-options (nrepl-dict))))
(when right-margin
(setq print-options (nrepl-dict-put print-options (cider--pprint-option "right-margin" cider-pprint-fn) right-margin)))
(nconc `("printer" ,(or pprint-fn (cider--pprint-fn)))
(and (not (nrepl-dict-empty-p print-options)) `("print-options" ,print-options)))))

(defun cider--nrepl-content-type-plist ()
"Plist to be appended to an eval request to make it use content-types."
'("content-type" "true"))
(defun cider--nrepl-print-request-map (&optional right-margin)
"Map to merge into requests that require pretty-printing.
RIGHT-MARGIN specifies the maximum column-width of the printed result, and
is included in the request if non-nil."
(let* ((width-option (cider--print-option "right-margin" cider-print-fn))
(print-options (thread-last
(map-merge 'hash-table
`((,width-option ,right-margin))
cider-print-options)
(map-pairs)
(seq-mapcat #'identity)
(apply #'nrepl-dict))))
(map-merge 'list
`(("nrepl.middleware.print/print" ,(cider--print-fn))
("nrepl.middleware.print/stream?" "1"))
(when cider-print-quota
`(("nrepl.middleware.print/quota" ,cider-print-quota)))
(unless (nrepl-dict-empty-p print-options)
`(("nrepl.middleware.print/options" ,print-options))))))

(defun cider--nrepl-pr-request-map ()
"Map to merge into requests that do not require pretty printing."
(map-merge 'list
`(("nrepl.middleware.print/print" "cider.nrepl.pprint/pr"
"nrepl.middleware.print/stream?" nil))
(when cider-print-quota
`(("nrepl.middleware.print/quota" ,cider-print-quota)))))

(defun cider--nrepl-content-type-map ()
"Map to be merged into an eval request to make it use content-types."
'(("content-type" "true")))

(defun cider-tooling-eval (input callback &optional ns connection)
"Send the request INPUT to CONNECTION and register the CALLBACK.
Expand Down Expand Up @@ -585,10 +611,13 @@ The result entries are relative to the classpath."

(defun cider-sync-request:format-edn (edn right-margin)
"Perform \"format-edn\" op with EDN and RIGHT-MARGIN."
(let* ((response (thread-first `("op" "format-edn"
"edn" ,edn)
(append (cider--nrepl-pprint-request-plist right-margin))
(cider-nrepl-send-sync-request)))
(let* ((request (thread-last
(map-merge 'list
`(("op" "format-edn")
("edn" ,edn))
(cider--nrepl-print-request-map right-margin))
(seq-mapcat #'identity)))
(response (cider-nrepl-send-sync-request request))
(err (nrepl-dict-get response "err")))
(when err
;; err will be a stacktrace with a first line that looks like:
Expand Down
35 changes: 17 additions & 18 deletions cider-debug.el
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,21 @@

;;; Code:

(require 'nrepl-dict)
(require 'nrepl-client) ; `nrepl--mark-id-completed'
(require 'cider-eval)
(require 'map)
(require 'seq)
(require 'subr-x)

(require 'spinner)

(require 'cider-browse-ns)
(require 'cider-client)
(require 'cider-util)
(require 'cider-eval)
(require 'cider-inspector)
(require 'cider-browse-ns)
(require 'cider-util)
(require 'cider-common)
(require 'subr-x)
(require 'cider-compat)
(require 'seq)
(require 'spinner)
(require 'nrepl-client) ; `nrepl--mark-id-completed'
(require 'nrepl-dict)


;;; Customization
Expand Down Expand Up @@ -103,13 +106,7 @@ configure `cider-debug-prompt' instead."

(make-obsolete 'cider-debug-print-length 'cider-debug-print-options "0.20")
(make-obsolete 'cider-debug-print-level 'cider-debug-print-options "0.20")

(defcustom cider-debug-print-options '(dict "length" 10 "level" 10)
"The print options for values displayed by the debugger.
This variable must be set before starting the repl connection."
:type 'listp
:group 'cider-stacktrace
:package-version '(cider . "0.20.0"))
(make-obsolete-variable 'cider-debug-print-options 'cider-print-options "0.21")


;;; Implementation
Expand Down Expand Up @@ -156,9 +153,11 @@ This variable must be set before starting the repl connection."
(defun cider--debug-init-connection ()
"Initialize a connection with the cider.debug middleware."
(cider-nrepl-send-request
(nconc '("op" "init-debugger")
(when cider-debug-print-options
`("print-options" ,cider-debug-print-options)))
(thread-last
(map-merge 'list
'(("op" "init-debugger"))
(cider--nrepl-print-request-map fill-column))
(seq-mapcat #'identity))
#'cider--debug-response-handler))


Expand Down
Loading