This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-03
Channels
- # announcements (35)
- # aws (20)
- # babashka (4)
- # beginners (88)
- # cider (9)
- # clara (1)
- # clj-kondo (6)
- # cljsrn (3)
- # clojure (107)
- # clojure-dev (7)
- # clojure-europe (99)
- # clojure-nl (3)
- # clojure-spec (9)
- # clojure-uk (2)
- # clojurescript (28)
- # core-async (53)
- # cursive (11)
- # datascript (1)
- # datomic (2)
- # emacs (20)
- # fulcro (3)
- # graalvm (4)
- # holy-lambda (18)
- # jobs (1)
- # kaocha (7)
- # leiningen (2)
- # lsp (25)
- # luminus (1)
- # membrane-term (52)
- # missionary (8)
- # nextjournal (19)
- # off-topic (16)
- # other-languages (3)
- # podcasts-discuss (2)
- # polylith (23)
- # re-frame (4)
- # reclojure (6)
- # remote-jobs (1)
- # rewrite-clj (36)
- # ring (1)
- # sci (10)
- # shadow-cljs (7)
- # spacemacs (5)
- # sql (20)
- # uncomplicate (1)
- # vscode (3)
- # xtdb (27)
here’s a question that i’m struggling to answer: i am iterating over the above changed files, hoping to remove all of the deftest
blocks that are empty. when I call z/remove
when the zloc is at the <list: (deftest blahtest)>
node, it changes the zloc to the deepest token immediately above/before, meaning I have to traverse all the way back to the level of the deftest
s every time I call it. if I go too far, then i’m doing a lot of extra work as I then have to iterate over all of the forms above the zloc again.
that means I have to special case my find-root-deftest
to also look for ns
forms because sometimes the empty deftest
is the first test in the file and when I remove it, i am placed at <token: :all>
which is in <vector: [clojure.test :refer :all]>
which is in <list: (:require … [clojure.test :refer :all])>
which is in <list: (ns game.cards.example (:require … ))>
which is of course not a deftest
lol
i would expect that the zloc doesn’t “change” when removing something, that it would be like I called z/right
(or maybe z/left
like we’re stepping back to reassess). given that I can’t just call z/right
when at the deepest node behind the removed zloc makes me do a lot of extra work to get back to where I was, with as far as I can tell, no visible benefit
@nbtheduke, yeah z/remove
can be a bit tricky. The behavior matches that of clojure.zip/remove
.
The location does kinda have to change tho, right? The location you z/remove
d is now gone.
I think maybe (?) you are talking about this kind of case:
(-> "([1 [2 [3]]] 8 9)"
z/of-string
z/down
z/right
z/remove
((juxt z/string z/root-string)))
;; => ["3" "([1 [2 [3]]] 9)"]
After deleting 8
you are now at located at a nested 3
.right, good example. that’s the issue i’m running into. i’d love for a z/remove
that ends up either pointing to [1 [2 [3]]
or 9
(-> "[8]" z/of-string z/down z/remove ((juxt z/string z/root-string))) ;; => ["[]", "[]"]
, right?
if it has no siblings, it goes up one level
or maybe it stays at an “empty” space within the vector/list
When removing things I will sometimes resort to using a sub zipper. I dig down and remove what I want but don’t lose my spot.
Other times a walk can be handy
(-> "([1 [2 [3]]] 8 9 3 10)"
z/of-string
z/up
(z/prewalk #(= "3" (z/string %)) z/remove)
z/root-string)
;; => "([1 [2 []]] 8 9 10)"
huh interesting
There are also some kill
function in the paredit
API that I have not experimented with much yet. I don’t think they fit your use case though.
yeah, i looked at those but they were a fundamental shift in how to think about it so i didn’t pursue
that does indeed! excellent, thank you
(defn find-root-deftest [zloc]
(if (or (-> zloc z/down deftest?)
(-> zloc z/down z/string (= "ns")))
zloc
(recur (z/up zloc))))
(defn clean-deftest [zloc]
(if (and (deftest? (z/down zloc))
(-> zloc z/down z/right z/right z/end?))
(-> zloc z/remove find-root-deftest)
zloc))
(defn clean-file [zloc]
(let [zloc (clean-deftest zloc)]
(if (z/end? (z/right zloc))
zloc
(recur (z/right zloc)))))
to
(defn clean-file [zloc]
(z/prewalk
(z/up zloc)
(fn [zloc]
(and (-> zloc z/down deftest?)
(-> zloc z/down z/right z/right z/end?)))
z/remove))
:chefs_kiss:
given (deftest example)
, i want to see if it’s empty after the name (“example”)
down to enter the list, right right to move one past “example”
if there’s a better way to check that the list is only 2 non-whitespace, non-comment elements long, i’m all for it
in a macro, i’d say (and (= 'deftest (first l)) (= 2 (count l)))
@nbtheduke would something like this work?
(-> "(deftest empty)
(deftest empty2
)
(deftest has-stuff-so-keep 1)
(deftest with-comment
;; don't delete me, I have a comment!
)
(;; don't delete me either!
deftest with-comment2
)
(deftest ;; comment
with-comment3
)
"
z/of-string
z/up
(z/prewalk (fn [zloc]
(and
(z/list? zloc)
(= "deftest" (-> zloc z/down z/string))
;; no sibs?
(not (-> zloc z/down z/right z/right))
;; no comments? (we use * here because comments are otherwise skipped)
(not (-> zloc z/down*
(z/find z/right* #(n/comment? (z/node %)))))))
z/remove)
z/print-root)
Ouputs:
(deftest has-stuff-so-keep 1)
(deftest with-comment
;; don't delete me, I have a comment!
)
(;; don't delete me either!
deftest with-comment2
)
(deftest ;; comment
with-comment3
)
I intend to delete empty deftests even with comments. Otherwise looks right to me!
Ah! Ok, simpler then:
(-> "(deftest empty)
(deftest empty2
)
(deftest has-stuff-so-keep 1)
(deftest with-comment
;; don't delete me, I have a comment!
)
(;; don't delete me either!
deftest with-comment2
)
(deftest ;; comment
with-comment3
)
"
z/of-string
z/up
(z/prewalk (fn [zloc]
(and
(z/list? zloc)
(= "deftest" (-> zloc z/down z/string))
;; no sibs?
(not (-> zloc z/down z/right z/right))))
z/remove)
z/print-root)
Outputs:
(deftest has-stuff-so-keep 1)
So z/end?
just happened to work for you because (z/end? nil)
returns true! So basically your original was just fine. Just omit the z/end?
!
Oh and negate that test. So (-> zloc z/down z/right z/right z/end?)
becomes (not (-> zloc z/down z/right z/right))
interesting, okay, cool
thank you very much, i appreciate all of the help