kkinnear / zprint

Executables, uberjar, and library to beautifully format Clojure and Clojurescript source code and s-expressions.
MIT License
559 stars 49 forks source link

Garbled formatting on deps.edn generated by seancorfield/clj-new #208

Closed redbeardymcgee closed 3 years ago

redbeardymcgee commented 3 years ago

I'm using Emacs 27.2 + CIDER 1.2.0snapshot, with the zprint-mode (0.3) package.

My ~/.zprintrc only contains {:style :community, :width 70}

clj -X:project/new :template app :name org/my-app results in this deps.edn file.

{:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.10.3"}}
 :aliases
 {:run-m {:main-opts ["-m" "foo.bar-baz"]}
  :run-x {:ns-default foo.bar-baz
          :exec-fn greet
          :exec-args {:name "Clojure"}}
  :test {:extra-paths ["test"]
         :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"}
                      io.github.cognitect-labs/test-runner
                      {:git/url "https://github.com/cognitect-labs/test-runner"
                       :sha "62ef1de18e076903374306060ac0e8a752e57c86"}}
         :exec-fn cognitect.test-runner.api/test}
  :uberjar {:replace-deps {com.github.seancorfield/depstar {:mvn/version "2.1.278"}}
            :exec-fn hf.depstar/uberjar
            :exec-args {:aot true
                        :jar "bar-baz.jar"
                        :main-class "foo.bar-baz"
                        :sync-pom true}}}}

M-x zprint results in this new formatting.

{:aliases
 {:run-m {:main-opts ["-m" "foo.bar-baz"]},
  :run-x {:exec-args {:name "Clojure"},
          :exec-fn greet,
          :ns-default foo.bar-baz},
  :test {:exec-fn cognitect.test-runner.api/test,
         :extra-deps
         {io.github.cognitect-labs/test-runner
          {:git/url "https://github.com/cognitect-labs/test-runner",
           :sha "62ef1de18e076903374306060ac0e8a752e57c86"},
          org.clojure/test.check #:mvn{:version "1.1.0"}},
         :extra-paths ["test"]},
  :uberjar {:exec-args {:aot true,
                        :jar "bar-baz.jar",
                        :main-class "foo.bar-baz",
                        :sync-pom true},
            :exec-fn hf.depstar/uberjar,
            :replace-deps
            #:com.github.seancorfield{depstar #:mvn{:version
                                                    "2.1.278"}}}},
 :deps #:org.clojure{clojure #:mvn{:version "1.10.3"}},
 :paths ["src" "resources"]}

I couldn't even tell you what's valid anymore from the zprint version.

kkinnear commented 3 years ago

Thanks for bringing this up. The "garbled" version is semantically identical to the input, as it happens. Thus:

zprint.core=> (print i208)
; The original input
{:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.10.3"}}
 :aliases
 {:run-m {:main-opts ["-m" "foo.bar-baz"]}
  :run-x {:ns-default foo.bar-baz
          :exec-fn greet
          :exec-args {:name "Clojure"}}
  :test {:extra-paths ["test"]
         :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"}
                      io.github.cognitect-labs/test-runner
                      {:git/url "https://github.com/cognitect-labs/test-runner"
                       :sha "62ef1de18e076903374306060ac0e8a752e57c86"}}
         :exec-fn cognitect.test-runner.api/test}
  :uberjar {:replace-deps {com.github.seancorfield/depstar {:mvn/version "2.1.278"}}
            :exec-fn hf.depstar/uberjar
            :exec-args {:aot true
                        :jar "bar-baz.jar"
                        :main-class "foo.bar-baz"
                        :sync-pom true}}}}
nil
zprint.core=> (print i208a)
; The "garbled" output
{:aliases
 {:run-m {:main-opts ["-m" "foo.bar-baz"]},
  :run-x {:exec-args {:name "Clojure"},
          :exec-fn greet,
          :ns-default foo.bar-baz},
  :test {:exec-fn cognitect.test-runner.api/test,
         :extra-deps
         {io.github.cognitect-labs/test-runner
          {:git/url "https://github.com/cognitect-labs/test-runner",
           :sha "62ef1de18e076903374306060ac0e8a752e57c86"},
          org.clojure/test.check #:mvn{:version "1.1.0"}},
         :extra-paths ["test"]},
  :uberjar {:exec-args {:aot true,
                        :jar "bar-baz.jar",
                        :main-class "foo.bar-baz",
                        :sync-pom true},
            :exec-fn hf.depstar/uberjar,
            :replace-deps
            #:com.github.seancorfield{depstar #:mvn{:version
                                                    "2.1.278"}}}},
 :deps #:org.clojure{clojure #:mvn{:version "1.10.3"}},
 :paths ["src" "resources"]}
nil
zprint.core=> (= (read-string i208) (read-string i208a))
true
zprint.core=>

What happened is that the map had "namespaced keys", and these keys were "lifted" out of the map to make it a namespaced map. The zprint configuration for this is here.

I happen to agree with you that the result is not visually pleasing, despite its semantic equivalence, and so just over a year ago the default for zprint changed to what you see in the above documentation. The last zprint version to default to lifting out namespaces from keys was 1.0.0, and zprint version 1.0.1 changed to output it in the more "normal" way. For example:

; This is the "old" way it worked:

√ projects/zprint % ./zprintm-1.0.0 <cljfiles/i208.clj
{:aliases
   {:run-m {:main-opts ["-m" "foo.bar-baz"]},
    :run-x
      {:exec-args {:name "Clojure"}, :exec-fn greet, :ns-default foo.bar-baz},
    :test {:exec-fn cognitect.test-runner.api/test,
           :extra-deps {io.github.cognitect-labs/test-runner
                          {:git/url
                             "https://github.com/cognitect-labs/test-runner",
                           :sha "62ef1de18e076903374306060ac0e8a752e57c86"},
                        org.clojure/test.check #:mvn{:version "1.1.0"}},
           :extra-paths ["test"]},
    :uberjar {:exec-args {:aot true,
                          :jar "bar-baz.jar",
                          :main-class "foo.bar-baz",
                          :sync-pom true},
              :exec-fn hf.depstar/uberjar,
              :replace-deps
                #:com.github.seancorfield{depstar #:mvn{:version "2.1.278"}}}},
 :deps #:org.clojure{clojure #:mvn{:version "1.10.3"}},
 :paths ["src" "resources"]}

; This is the way zprint now works (as of 9/22/20)

√ projects/zprint % ./zprintm-1.0.1 <cljfiles/i208.clj
{:aliases
   {:run-m {:main-opts ["-m" "foo.bar-baz"]},
    :run-x
      {:exec-args {:name "Clojure"}, :exec-fn greet, :ns-default foo.bar-baz},
    :test {:exec-fn cognitect.test-runner.api/test,
           :extra-deps {io.github.cognitect-labs/test-runner
                          {:git/url
                             "https://github.com/cognitect-labs/test-runner",
                           :sha "62ef1de18e076903374306060ac0e8a752e57c86"},
                        org.clojure/test.check {:mvn/version "1.1.0"}},
           :extra-paths ["test"]},
    :uberjar {:exec-args {:aot true,
                          :jar "bar-baz.jar",
                          :main-class "foo.bar-baz",
                          :sync-pom true},
              :exec-fn hf.depstar/uberjar,
              :replace-deps {com.github.seancorfield/depstar {:mvn/version
                                                                "2.1.278"}}}},
 :deps {org.clojure/clojure {:mvn/version "1.10.3"}},
 :paths ["src" "resources"]}
√ projects/zprint %

There is an outstanding pull request for zprint-mode which will update it to use zprint 1.1.2, the latest version that has been released. If that pull request were to be accepted, that would solve the problem.

Until that happens, I think that you could also solve this problem by adding this to your ~/.zprintrc configuration file:

{:map {:lift-ns? false}}

as you can see from this example using your data and zprint 1.0.0:

√ projects/zprint % ./zprintm-1.0.0 '{:map {:lift-ns? false}}' <cljfiles/i208.clj
{:aliases
   {:run-m {:main-opts ["-m" "foo.bar-baz"]},
    :run-x
      {:exec-args {:name "Clojure"}, :exec-fn greet, :ns-default foo.bar-baz},
    :test {:exec-fn cognitect.test-runner.api/test,
           :extra-deps {io.github.cognitect-labs/test-runner
                          {:git/url
                             "https://github.com/cognitect-labs/test-runner",
                           :sha "62ef1de18e076903374306060ac0e8a752e57c86"},
                        org.clojure/test.check {:mvn/version "1.1.0"}},
           :extra-paths ["test"]},
    :uberjar {:exec-args {:aot true,
                          :jar "bar-baz.jar",
                          :main-class "foo.bar-baz",
                          :sync-pom true},
              :exec-fn hf.depstar/uberjar,
              :replace-deps {com.github.seancorfield/depstar {:mvn/version
                                                                "2.1.278"}}}},
 :deps {org.clojure/clojure {:mvn/version "1.10.3"}},
 :paths ["src" "resources"]}
√ projects/zprint %

I hope that this helps!

redbeardymcgee commented 3 years ago

Your reply was much more thorough than the effort I put into this issue. It's very much appreciated. I did find this namespaced keys syntax in EDN but could not understand why zprint was meddling with the data this way.

Thanks for your response. I'll look deeper at the zprint config this weekend.