This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-18
Channels
- # announcements (4)
- # babashka (2)
- # beginners (72)
- # calva (2)
- # cider (18)
- # clj-kondo (30)
- # cljs-dev (2)
- # clojure (106)
- # clojure-austin (2)
- # clojure-europe (17)
- # clojure-italy (6)
- # clojure-nl (4)
- # clojure-uk (109)
- # clojurescript (31)
- # cursive (6)
- # data-science (2)
- # datomic (30)
- # events (1)
- # fulcro (20)
- # graphql (4)
- # jobs (2)
- # joker (8)
- # kaocha (2)
- # meander (31)
- # off-topic (1)
- # pathom (53)
- # re-frame (22)
- # reitit (1)
- # shadow-cljs (26)
- # specter (2)
- # sql (20)
- # testing (2)
- # tools-deps (2)
- # tree-sitter (1)
- # xtdb (20)
- # yada (6)
I recently decided to reduce my mental block of refactoring things into let
bindings and losing the ability to eval subexpressions - the following command looks backwards within the current defun for any let-bindings and wraps them around the sexp at point to evaluate:
(defun cider--guess-evaluation-context ()
"Returns list of let-binding strings from the inside out, without closing parens
\"(let [...]\""
(save-excursion
(let ((res ()))
(condition-case er
(while t
(backward-up-list)
(when (looking-at (rx "(" (or "when-let" "if-let" "let") (opt "*")
symbol-end (* space)
(group "["))) ;; binding vector
(let ((beg (match-beginning 0))
(end (save-excursion
(goto-char (match-beginning 1))
(forward-sexp 1)
(point))))
(push (buffer-substring-no-properties beg end) res))))
(scan-error res)))))
(defun cider-eval-dwim ()
(interactive)
(let ((ctx (cider--guess-evaluation-context))
(bounds (cider-sexp-at-point 'bounds)))
(cider-interactive-eval (concat (apply #'concat ctx)
(buffer-substring-no-properties (car bounds) (cadr bounds))
(make-string (length ctx) ?\)))
nil bounds
(cider--nrepl-pr-request-map))))
I guess you can enhance the existing eval in context with your logic to guess the let-bindings there.
Btw, the approach with the context I took was much simpler - I just balance the unbalanced sexp at point and make it evaluatable. This way you don’t have to guess the evaluation context, as you’re using it directly.
(let [a 1]
[:lots
(of unnecessary
:things)
(assert false)
(let [b (inc a)]
(+ a b))
etc
etc])
eg. I want to place my cursor at the (+ a b)
form and eval, and get only the result => 3
cider-eval-in-context
was too much friction because it didn't pick up on existing let bindings and requires you to enter a context into the minibuffer
> eg. I want to place my cursor at the (+ a b) form and eval, and get only the result => 3
Well, that’s exactly what eval-upto-point does. I think I’m not understanding something.
In the example above eval-upto-point
would throw an assertion error or return all the unnecessary things
in particular I found this useful as a way to debug an expression which was throwing errors by inspecting sub-expressions independently of others