rewrite-clj

https://github.com/clj-commons/rewrite-clj
2019-11-09T11:45:52.162800Z

suppose in ../clojure there is a checkout of clojure and rewrite-clj has been patched to include find-last-by-pos (https://github.com/lread/rewrite-cljs-playground/blob/master/src/rewrite_clj/zip/findz.cljc#L44_L57) (and may be some other things in rewrite-cljs-playground). consider the following:

(require '[rewrite-clj.zip :as rz])

(def set-str
  (slurp "../clojure/src/clj/clojure/set.clj"))

;; nil
(-> (rz/of-string set-str
          {:track-position? true})
      (rz/find-last-by-pos [1 1]))

;; nil
(-> (rz/of-string set-str
          {:track-position? true})
      (rz/find-last-by-pos [178 1]))
the first of the thread-first forms gives nil because the position is before all top-level forms, iiuc. correspondingly, the second of the thread-first forms gives nil because the position is after all top-level forms. to distinguish between these cases it appears that comparing the position (e.g. row 1 col 1 or row 178 col 1 in the code above) with the return value of:
(-> (rz/of-string set-str
          {:track-position? true})
      rz/position)
is one approach. anyone know of a better or alternative method?

lread 2019-11-09T15:00:52.164300Z

Hi @sogaiu, I’ll study this and respond sometime soon

2019-11-09T15:03:47.164500Z

@lee thanks!

2019-11-09T16:22:53.165100Z

for some context, i'm doing this sort of thing:

(require '[rewrite-clj.zip :as rz])

  (defn rcb? ; rich comment block
    [zloc]
    (and (rz/list? zloc)
      (= "comment"
        (-> zloc
           rz/down
           rz/string))))

  (defn before?
    [[r1 c1] [r2 c2]]
    (cond (< r1 r2) true
          ;;
          (> r1 r2) false
          ;;
          :else (cond (< c1 c2)
                      true
                      ;;
                      :else
                      false)))

  ;; before
  (before? [1 1] [2 1])

  ;; not before, after
  (before? [5 5] [1 2])
  
  ;; not before, the same
  (before? [10 20] [10 20])

  (defn expr-str-at
    [src-str row col] ; XXX: consider [row col] as single parameter?
    (let [zloc-0 (rz/of-string src-str
                   {:track-position? true})
          _ (assert zloc-0 ; XXX: just return nil instead?
              "of-string returned nil")
          zloc (if-let [zloc (rz/find-last-by-pos zloc-0 [row col])]
                 zloc
                 ;; before or after all top-level forms
                 (let [pos-0 (rz/position zloc-0)]
                   (when (before? pos-0 [row col])
                     (rz/rightmost zloc-0))))]
      (when zloc
        (loop [zloc zloc]
          (if (or (contains? #{:comma :comment :newline :whitespace}
                    (rz/tag zloc))
                (rcb? zloc))
            (recur (rz/left zloc))
            (rz/string zloc))))))

2019-11-09T16:25:46.167Z

it's supposed to find the first non-comment-whitespace-etc expr string "at" row col (where "at" can look left if row col happens to refer to whitespace, newline, comment, comma nodes or (comment ...))

lread 2019-11-15T23:15:52.237800Z

I moved this to git issue so I don't forget to answer sometime https://github.com/lread/rewrite-cljs-playground/issues/3

lread 2019-11-15T23:16:32.238100Z

I'm not sure if I capture your entire question please feel free to add to it.

2019-11-15T23:44:35.238300Z

thanks -- added a comment

lread 2019-11-15T23:45:26.238500Z

awesome, thanks!

2019-11-09T17:35:41.170Z

although there's comment?, list?, and others, i don't see a forms? -- is there a good way to check whether one has "gone up" all the way to the top apart from looking at the tag value? edn seems to check the tag value directly. is it a problem to have a predicate for this? or alternatively, are there reasons to not have such a predicate?

borkdude 2019-11-09T17:45:53.170400Z

I'm not so familiar anymore with the zipper part of rewrite-clj so can't really help, sorry

2019-11-09T18:31:15.171300Z

np -- this is partly :duckie: ing 🙂 here's a use case for checking whether one is aleady at the top of the zipper:

(defn in-rcb?
    [src-str row col]
    (let [zloc-0 (rz/of-string src-str
                   {:track-position? true})
          _ (assert zloc-0 ; XXX: just return nil instead?
              "of-string returned nil")
          zloc (rz/find-last-by-pos zloc-0 [row col])]
      ;; zloc nil means before or after all top-levels, so not in rcb
      (when zloc
        (loop [zloc zloc]
          (cond (rcb? zloc)
                zloc
                ;;
                (= (rz/tag zloc) :forms)
                nil?
                ;;
                :else
                (recur (-> zloc
                         rz/leftmost
                         rz/up)))))))