diff --git a/CHANGELOG.md b/CHANGELOG.md index 67b4a3f..a6a4883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Change Log All notable changes to this project will be documented in this file. +## 1.2.5 - 2022-08-03 + +### Added + +### Changed + +### Fixed + ## 1.2.4 - 2022-08-02 ### Added diff --git a/appcds b/appcds index fc1cc05..baef24b 100755 --- a/appcds +++ b/appcds @@ -43,7 +43,7 @@ helptext="Usage: ./appcds zprint-filter output-command-name" if [[ -z "$1" ]] then - echo "Missing first required argument: zprint-filter-file (e.g. zprint-filter-1.2.4)" + echo "Missing first required argument: zprint-filter-file (e.g. zprint-filter-1.2.5)" echo "$helptext" exit 1 fi diff --git a/bb.edn b/bb.edn index 7a0f3e7..db9bede 100644 --- a/bb.edn +++ b/bb.edn @@ -1,25 +1,49 @@ -{:paths ["src"] - :deps {org.babashka/spec.alpha {:git/url "https://github.com/babashka/spec.alpha" - :git/sha "1a841c4cc1d4f6dab7505a98ed2d532dd9d56b78"}} - :tasks {test:bb {:extra-paths ["test"] - :extra-deps {com.github.seancorfield/expectations - {:mvn/version "2.0.143"} - io.github.cognitect-labs/test-runner - {:git/tag "v0.5.0" :git/sha "b3fd0d2"} - org.clojure/tools.namespace {:git/url "https://github.com/babashka/tools.namespace" - :git/sha "3625153ee66dfcec2ba600851b5b2cbdab8fae6c"} - cljc.java-time {:mvn/version "0.1.11"}} - :requires ([cognitect.test-runner :as tr]) - :task (apply tr/-main - "-d" "test" - "-n" "zprint.core-test" - "-n" "zprint.config-test" - "-n" "zprint.zprint-test" - "-n" "zprint.finish-test" - "-n" "zprint.guide-test" - "-n" "zprint.main-test" - "-n" "zprint.range-test" - "-n" "zprint.rewrite-test" - "-n" "zprint.spec-test" - "-n" "zprint.zutil-test" - *command-line-args*)}}} +{:deps {org.babashka/spec.alpha + {:git/sha "1a841c4cc1d4f6dab7505a98ed2d532dd9d56b78", + :git/url "https://github.com/babashka/spec.alpha"}}, + :paths ["src"], + :tasks + {test:bb {:extra-deps + {cljc.java-time/cljc.java-time {:mvn/version "0.1.11"}, + com.github.seancorfield/expectations {:mvn/version "2.0.143"}, + io.github.cognitect-labs/test-runner {:git/sha "b3fd0d2", + :git/tag "v0.5.0"}, + org.clojure/tools.namespace + {:git/sha "3625153ee66dfcec2ba600851b5b2cbdab8fae6c", + :git/url "https://github.com/babashka/tools.namespace"}}, + :extra-paths ["test"], + :requires ([cognitect.test-runner :as tr]), + :task (apply tr/-main + "-d" + "test" "-n" + "zprint.core-test" "-n" + "zprint.config-test" "-n" + "zprint.zprint-test" "-n" + "zprint.finish-test" "-n" + "zprint.guide-test" "-n" + "zprint.main-test" "-n" + "zprint.range-test" "-n" + "zprint.rewrite-test" "-n" + "zprint.spec-test" "-n" + "zprint.zutil-test" *command-line-args*)}, + testconfig:bb + {:extra-deps {cljc.java-time/cljc.java-time {:mvn/version "0.1.11"}, + com.github.seancorfield/expectations {:mvn/version + "2.0.143"}, + io.github.cognitect-labs/test-runner {:git/sha "b3fd0d2", + :git/tag "v0.5.0"}, + + ; pjstadig/humane-test-output {:mvn/version "0.11.0" + ; :exclusions [org.clojure/tools.namespace]}}, + + + lambdaisland/ansi {:mvn/version "0.2.37"} + org.clojure/tools.namespace + {:git/sha "3625153ee66dfcec2ba600851b5b2cbdab8fae6c", + :git/url "https://github.com/babashka/tools.namespace"}}, + :extra-paths ["test"], + :requires ([cognitect.test-runner :as tr]), + :task + (tr/-main "-d" "test" "-n" "zprint.test-config")}}} + + diff --git a/deps.edn b/deps.edn index 53d0bb1..d835962 100644 --- a/deps.edn +++ b/deps.edn @@ -7,22 +7,31 @@ :extra-paths ["src" "test" "cljs-test-runner-out/gen"], :main-opts ["-m" "cljs-test-runner.main" "--doo-opts" "dooopts.edn" "-x" "planck"]}, - :cljtest {:extra-deps {com.github.seancorfield/expectations - {:mvn/version "2.0.143"}}, + :cljtest {:extra-deps {com.github.seancorfield/expectations {:mvn/version + "2.0.143"}}, :extra-paths ["test"]}, :humane {:extra-deps {pjstadig/humane-test-output {:mvn/version "0.10.0"}}}, - :runner {:extra-deps {com.cognitect/test-runner - {:git/url - "https://github.com/cognitect-labs/test-runner", - :sha "b6b3193fcc42659d7e46ecd1884a228993441182"}}, - :main-opts ["-m" "cognitect.test-runner" "-d" "test"]}, + ;:runner {:extra-deps {com.cognitect/test-runner + ; {:git/url + ; "https://github.com/cognitect-labs/test-runner", + ; :sha "b6b3193fcc42659d7e46ecd1884a228993441182"}}, + ; :main-opts ["-m" "cognitect.test-runner" "-d" "test"]}, + :test {:exec-fn cognitect.test-runner.api/test, + :extra-deps {com.github.seancorfield/expectations {:mvn/version + "2.0.143"}, + io.github.cognitect-labs/test-runner + {:sha "dfb30dd", #_"a85b3b0", :git/tag "v0.5.1"}, + pjstadig/humane-test-output {:mvn/version "0.10.0"}}, + :extra-paths ["test"], + :main-opts ["-m" "cognitect.test-runner"]}, :zprint {:main-opts ["-m" "zprint.main"]}}, :deps {#_#_org.clojure/clojure {:mvn/version "1.9.0"}, #_#_org.clojure/clojurescript {:mvn/version "1.9.946"}, #_#_org.clojure/clojure {:mvn/version "1.10.3"}, org.babashka/sci {:mvn/version "0.3.4"}, ;; To use zprint with babashka, include the following dependency: - ;; org.babashka/spec.alpha {:git/url "https://github.com/babashka/spec.alpha" - ;; :sha "0dec1f88cbde74a0470b454396f09a03adb4ae39"} + ;; org.babashka/spec.alpha {:git/url + ;; "https://github.com/babashka/spec.alpha" + ;; :sha "0dec1f88cbde74a0470b454396f09a03adb4ae39"} rewrite-clj/rewrite-clj {:mvn/version "1.1.45"}}, :paths ["src" "test" "cljs-test-runner-out/gen"]} diff --git a/doc/getting/appcds.md b/doc/getting/appcds.md index b415aea..f95b1c4 100644 --- a/doc/getting/appcds.md +++ b/doc/getting/appcds.md @@ -44,7 +44,7 @@ zprint-filter in about a second. ## 5. Try it with `-v` ``` % zprint -v -zprint-1.2.4 +zprint-1.2.5 ``` This will also demonstrate the time it takes to start up the uberjar with appcds. diff --git a/doc/getting/linux.md b/doc/getting/linux.md index 5e5e892..a8a381d 100644 --- a/doc/getting/linux.md +++ b/doc/getting/linux.md @@ -13,14 +13,14 @@ You may wish to name it something different so that any scripts that you have will use the new version without requiring a change. We will assume that you have renamed it `zprint`. ``` -mv zprintl-1.2.4 zprint +mv zprintl-1.2.5 zprint ``` Note that you can always find the version of zprintl (no matter what you called it), by giving it the -v switch: ``` ./zprint -v -zprint-1.2.4 +zprint-1.2.5 ``` ## 3. Put zprint into a directory in your path diff --git a/doc/getting/macos.md b/doc/getting/macos.md index 3812808..f6e8341 100644 --- a/doc/getting/macos.md +++ b/doc/getting/macos.md @@ -16,7 +16,7 @@ you have will use the new version without requiring a change. We will assume that you have renamed it `zprint`. ``` -mv zprintm-1.2.4 zprint +mv zprintm-1.2.5 zprint ``` Note that you might *not* want to name it `zprint`, since there is also diff --git a/doc/getting/uberjar.md b/doc/getting/uberjar.md index adbc3f5..ef2073f 100644 --- a/doc/getting/uberjar.md +++ b/doc/getting/uberjar.md @@ -13,14 +13,14 @@ You may wish to name it something different so that any scripts that you have will use the new version without requiring a change. We will assume that you have renamed it `zprint-filter`. ``` -mv zprint-filter-1.2.4 zprint-filter +mv zprint-filter-1.2.5 zprint-filter ``` Note that you can always find the version of zprint-filter (no matter what you called it), by giving it the -v switch: ``` java -jar zprint-filter -v -zprint-1.2.4 +zprint-1.2.5 ``` ## 3. Test it with `-e` diff --git a/doc/reference.md b/doc/reference.md index 0a18dff..4f66f22 100644 --- a/doc/reference.md +++ b/doc/reference.md @@ -1274,9 +1274,15 @@ are formatted by default. Note that the `:indent` for lists is not changed by this function type. You may find it useful to set the `:indent` for `:list` to 1 when using this function type. -```clojure {:fn-map {"my-fn" [:wrap {:list {:indent 1}}]}} +```clojure +{:fn-map {"my-fn" [:wrap {:list {:indent 1}}]}} ``` +When using this function type, you may find it useful to use +`{:list {:no-wrap-after #{"stuff"}}}` where `stuff` is some element you +don't want to ever be the last element on a line. See `:list :no-wrap-after` +for more details. + #### :gt2-force-nl and :gt3-force-nl These two function styles exist to be assigned to functions that should @@ -3787,6 +3793,37 @@ formatting in some special cases where a `fn-type` is in use`. It isn't meant to be a generally useful capabiity to, say, format all lists with extra lines between them. +`:list` supports some of the same keys as does vector: + +##### :no-wrap-after _nil_ +##### :wrap? _true_ +##### :wrap-coll? _true_ +##### :wrap-after-multi? _true_ + +See the section on :vector for information on these keys. A simple example: + +``` +(czprint i252d {:parse-string? true}) +(stuff example + vvvvvveeeeeeeerrrrrrryyyyy + looooooooooooonnnnggggg + paraaaaaaams + & + body) + +(czprint i252d {:parse-string? true :list {:wrap? true}}) +(stuff example vvvvvveeeeeeeerrrrrrryyyyy looooooooooooonnnnggggg paraaaaaaams & + body) + +(czprint i252d {:parse-string? true :list {:wrap? true :no-wrap-after #{"&"}}}) +(stuff example vvvvvveeeeeeeerrrrrrryyyyy looooooooooooonnnnggggg paraaaaaaams + & body) +``` + +Generally, `&` isn't something with special meaning in a list, but there +may be something else that you wish to not dangle as the last element on +a line when a list is being wrapped. + _____ ## :map @@ -4950,6 +4987,7 @@ _____ `:set` supports the same keys as does vector and a few more. ##### :indent _1_ +##### :no-wrap-after _nil_ ##### :wrap? _true_ ##### :wrap-coll? _true_ ##### :wrap-after-multi? _true_ @@ -6194,6 +6232,42 @@ printed? "key" "value"} 10 11 12 13 14 15 16 17 18 19 ``` + +#### :no-wrap-after _nil_ + +There are times when you might like two elements that appear in a +vector that is wrapping to not be separated by the line break. For +instance, this is not great: + +``` +(czprint i252a {:parse-string? true :width 79}) +(defn example + [vvvvvveeeeeeeerrrrrrryyyyy looooooooooooooooooonnnnggggg paraaaaaaams & + body] + (+ 1 2 3)) +``` + +You can prevent vectors from wrapping between `&` and whatever comes +immediately after by configuring `:no-wrap-after`, which is a set +that contains strings. For instance: + +``` +(czprint i252a {:parse-string? true :width 79 :vector {:no-wrap-after #{"&"}}}) +(defn example + [vvvvvveeeeeeeerrrrrrryyyyy looooooooooooooooooonnnnggggg paraaaaaaams + & body] + (+ 1 2 3)) +``` + +will solve this particular problem. + +It would make sense to simply configure `{:vector {:no-wrap-after #{"&"}}}` +globally, since it probably wouldn't affect anything but +the argument vectors of functions, and in the event that `&` appeared +by itself in a vector, the worst that would happen is that the `&` +would end up on the next line if it was right at the end of the +previous line, which you might not even notice. + _____ ## :vector-fn diff --git a/doc/using/files.md b/doc/using/files.md index 836a8a0..ef32062 100644 --- a/doc/using/files.md +++ b/doc/using/files.md @@ -83,7 +83,7 @@ The exit status is unchanged by any of these additional switches: For example: ``` -% ./zprintm-1.2.4 -lfsc src/zprint/*.cljc +% ./zprintm-1.2.5 -lfsc src/zprint/*.cljc Processing file src/zprint/ansi.cljc Processing file src/zprint/config.cljc Formatting required in file src/zprint/config.cljc @@ -113,7 +113,7 @@ Here is another example, using the same files, where the formatting width is changed to 90: ``` - % ./zprintm-1.2.4 '{:width 90}' -lfsc src/zprint/*.cljc + % ./zprintm-1.2.5 '{:width 90}' -lfsc src/zprint/*.cljc Processing file src/zprint/ansi.cljc Processing file src/zprint/config.cljc Formatting required in file src/zprint/config.cljc @@ -162,8 +162,8 @@ zprint -h is your friend! ``` - % ./zprintm-1.2.4 -h -zprint-1.2.4 + % ./zprintm-1.2.5 -h +zprint-1.2.5 zprint output-file zprint output-file @@ -173,9 +173,9 @@ zprint-1.2.4 Where zprint is any of: - zprintm-1.2.4 - zprintl-1.2.4 - java -jar zprint-filter-1.2.4 + zprintm-1.2.5 + zprintl-1.2.5 + java -jar zprint-filter-1.2.5 is a Clojure map containing zprint options. Must be first. Note that since it contains spaces, it must be @@ -279,10 +279,10 @@ $ cat > deps.edn <<< $' {org.clojure/clojure {:mvn/version "1.9.0"}, zprint {:mvn/version - "1.2.4"}}, + "1.2.5"}}, :main-opts ["-m" "zprint.main"]}}, :deps {org.clojure/clojure {:mvn/version "1.9.0"}, - zprint {:mvn/version "1.2.4"}}}' + zprint {:mvn/version "1.2.5"}}}' $ clj -A:zprint < deps.edn $ clj -m zprint.main " :arg1-pair-body, + "cond->>" :arg1-pair-body, "condp" :arg2-pair, "def" :arg1-body, "defc" :arg1-mixin, @@ -362,6 +366,7 @@ "defmulti" :arg1-body, "defn" :arg1-body, "defn-" :arg1-body, + "defonce" :arg1-body "defproject" [:arg2-pair {:vector {:wrap? false}}], "defprotocol" [:guided-body {:style :defprotocolguide, @@ -373,7 +378,7 @@ "do" :none-body, "doseq" :binding, "dotimes" :binding, - "doto" :arg1, + "doto" :arg1-body, "extend" :arg1-extend, "extend-protocol" :arg1-extend, "extend-type" :arg1-extend, @@ -383,6 +388,7 @@ "fn" :fn, "fn*" :fn, "for" :binding, + "go-loop" :binding "if" :arg1-body, "if-let" :binding, "if-not" :arg1-body, @@ -392,6 +398,7 @@ "letfn" [:guided-body {:guide [:element :options {:next-inner {:fn-style :fn}} :element-best :options-reset :newline :element-best-*]}], + "locking" :arg1-body "loop" :binding, "map" :arg1, "mapcat" :arg1, @@ -413,14 +420,16 @@ "some->" :force-nl-body, "some->>" :force-nl-body, "swap!" :arg2, + "testing" :arg1-body "try" :none-body, "when" :arg1-body, "when-first" :binding, "when-let" :binding, "when-not" :arg1-body, "when-some" :binding, - "with-bindings" :arg1, - "with-bindings*" :arg1, + "while" :arg1-body + "with-bindings" :arg1-body, + "with-bindings*" :arg1-body, "with-local-vars" :binding, "with-meta" :arg1-body, "with-open" :binding, @@ -506,6 +515,7 @@ :hang? true, :indent 2, :modifiers #{"static"}, + :nl-count nil :nl-separator? false}, :file? false, :fn-force-nl #{:noarg1-body :noarg1 :force-nl-body :force-nl :flow @@ -545,6 +555,7 @@ :indent-only? false, :indent-only-style :input-hang, :nl-count nil, + :no-wrap-after nil :option-fn nil, :pair-hang? true, :respect-bl? false, @@ -656,6 +667,7 @@ :sort-in-code? nil, :sort? nil}, :record {:hang? true, :record-type? true, :to-string? false}, + ; All of the sets need to be here, so elements can be removed from them :remove {:fn-force-nl nil, :fn-gt2-force-nl nil, :fn-gt3-force-nl nil, @@ -664,12 +676,14 @@ :binding {:justify {:no-justify nil, :ignore-for-variance nil}}, :map {:key-no-sort nil, :justify {:no-justify nil, :ignore-for-variance nil}}, - :parse {:ignore-if-parse-fails nil}}, + :parse {:ignore-if-parse-fails nil} + :vector {:no-wrap-after nil}}, :return-cvec? false, :script {:more-options nil}, :search-config? false, :set {:indent 2, :indent-only? false, + :no-wrap-after nil :respect-bl? false, :respect-nl? false, :sort? true, @@ -1012,6 +1026,7 @@ :fn-format nil, :force-nl? false, :hang? nil, + :no-wrap-after nil :respect-bl? false, :respect-nl? false, :wrap-after-multi? true, @@ -1036,6 +1051,7 @@ :indent-arg nil, :indent-only? false, :indent-only-style :input-hang, + :no-wrap-after nil :pair-hang? true, :respect-bl? false, :respect-nl? false, @@ -1701,6 +1717,8 @@ (def opts {:namespaces {'clojure.core {'jrequireguide zprint.guide/jrequireguide, 'defprotocolguide zprint.guide/defprotocolguide, + 'defprotocolguide-s + zprint.guide/defprotocolguide-s, 'signatureguide1 zprint.guide/signatureguide1, 'guideguide zprint.guide/guideguide, 'rodguide zprint.guide/rodguide, diff --git a/src/zprint/guide.cljc b/src/zprint/guide.cljc index 526d780..bdd9db9 100644 --- a/src/zprint/guide.cljc +++ b/src/zprint/guide.cljc @@ -588,3 +588,99 @@ :newline :element-*)] {:guide guide}))) +(defn defprotocolguide-s + "Handle defprotocol with options, uses extend." + ([] "defprotocolguide") + ([options len sexpr] + (when (= (first sexpr) 'defprotocol) + (let [remaining (nnext sexpr) + [docstring remaining] (if (string? (first remaining)) + [(first remaining) (next remaining)] + [nil remaining]) + pair-count (some identity + (map-indexed (fn [idx item] (when (list? item) idx)) + remaining)) + pair-count (if (= pair-count 0) nil pair-count) + guide (cond-> [:element :element-best :newline] + docstring (conj :element :newline) + pair-count (conj :group-begin) + pair-count (into (repeat pair-count :element)) + pair-count (conj :group-end :element-pair-group :newline) + :else (conj :element-newline-extend-*))] + {:guide guide, :next-inner {:list {:option-fn nil}}})))) + +;; +;; Temporary place to stash semantic3 to make collaboration easier +;; +;; -alt +;; + +(def semantic3 + ; version 0.1.6 + ; Requires zprint 1.2.5 + {:style-map + {:s1.0 {:doc "Set up community indentation", + :binding {:indent 0}, + :list {:indent-arg 1}, + :map {:indent 0}, + :pair {:indent 0}}, + :s1.1 {:doc "defn and fn", + :fn-map {"defn" [:force-nl-body {:style :rod-base}], + "defn-" "defn", + "fn" "defn"}}, + :s1.2 + {:doc "defprotocol, defrecord, deftype, extend-type, extend-protocol", + :fn-map {"defprotocol" [:arg1-extend-body + {:extend {:nl-count 2, :nl-separator? true}, + :list {:option-fn defprotocolguide-s}, + :fn-type-map {:fn :flow-body}}], + "defrecord" [:arg2-extend-body {:style :s1.2-base}], + "deftype" "defrecord", + "extend-type" [:arg1-extend-body {:style :s1.2-base}], + "extend-protocol" "extend-type"}}, + :s1.2-base {:doc "Common code for extend things", + :extend {:nl-count 2, :nl-separator? true, :indent 0}, + :fn-force-nl #{:fn}, + :fn-type-map {:fn [:force-nl-body {:style :rod-base}]}, + :next-inner {:next-inner {:fn-type-map {:fn nil}}}}, + :s1.3 {:doc "defmethod", + :fn-map {"defmethod" [:guided-body + {:guide [:element :element-best + :element-best-first + :element-best-first :newline + :element-newline-best-*]}]}}, + :s1.4 {:doc "if, if-not, handled now in s1.5"}, + :s1.5 + {:doc + "Don't format on single line: case cond-> cond->> when + while when-not when-first locking let binding loop for doseq + dotimes when-let if-let when-some if-some testing go-loop", + :binding {:force-nl? true}, + :fn-force-nl #{:arg1-pair-body}, + :fn-map {"when" :arg1-force-nl-body, + "when-not" "when", + "while" "when", + "locking" "when", + "testing" "when"}}, + :s1.6 {:doc "=, not=, or, and, <, >, <=, >=", + :fn-force-nl #{:hang}, + :fn-map {"<" "=", ">" "=", "<=" "=", ">=" "="}}, + :s1.7 {:doc "->, ->>", :remove {:fn-force-nl #{:noarg1-body}}}, + :s1.8 {:doc "try, catch, finally", + :fn-map {"try" :flow-body, + "catch" :arg2-force-nl-body, + "finally" :flow-body}}, + :s1.9 {:doc "other stuff", :fn-map {"is" :force-nl-body}}, + :s1.10 {:doc "cond do delay future comment alt! alt!! go thread", + :pair-fn {:hang? false}, + :fn-map {"do" :flow-body, + "delay" "do", + "future" "do", + "comment" "do", + "go" "do", + "thread" "do"}}, + :sall {:doc "version 0.1.4", + :style [:s1.0 :s1.1 :s1.2 :s1.3 :s1.4 :s1.5 :s1.6 :s1.7 :s1.8 :s1.9 + :s1.10]}}}) + + diff --git a/src/zprint/spec.cljc b/src/zprint/spec.cljc index 2242869..02c12d5 100644 --- a/src/zprint/spec.cljc +++ b/src/zprint/spec.cljc @@ -95,7 +95,7 @@ :gt2-force-nl :gt3-force-nl :flow :flow-body :force-nl-body :force-nl :pair-fn :arg1-mixin :arg2-mixin :indent :replace-w-string :guided :arg1-force-nl-body :arg2-extend-body :wrap :guided-body :arg2-force-nl-body - :arg2-force-nl}) + :arg2-force-nl :arg1-extend-body}) (s/def ::fn-type-w-map (s/or :general-options (s/tuple ::fn-type ::options) :string-w-structure-options (s/tuple ::fn-type ::options ::options))) @@ -266,7 +266,10 @@ (s/def ::option-fn-first (s/nilable fn?)) (s/def ::option-fn (s/nilable fn?)) (s/def ::fn-format (s/nilable ::fn-type)) -(s/def ::fn-style (s/nilable ::fn-type)) +(s/def ::fn-style (s/nilable (s/or :fn-type ::fn-type + :string string?))) + + (s/def ::fn-str (s/nilable string?)) (s/def ::real-le? ::boolean) (s/def ::real-le-length number?) @@ -361,7 +364,7 @@ ::option-fn ::pair-hang? ::return-altered-zipper ::respect-bl? ::respect-nl? ::indent-only? ::indent-only-style ::replacement-string ::wrap-coll? ::wrap-after-multi? ::wrap-multi? - ::force-nl? ::wrap? ::nl-count])) + ::force-nl? ::wrap? ::nl-count ::no-wrap-after])) ; vector-fn needs to accept exactly the same things as list (s/def ::vector-fn ::list) (s/def ::map @@ -383,6 +386,7 @@ (s/def ::max-length ::number-or-vector-of-numbers) (s/def ::meta (only-keys :opt-un [::split?])) (s/def ::no-justify (s/nilable (s/coll-of string? :kind set?))) +(s/def ::no-wrap-after (s/nilable (s/coll-of string? :kind set?))) (s/def ::object (only-keys :opt-un [::indent ::wrap-coll? ::wrap-after-multi?])) (s/def ::old? ::boolean) (s/def ::guide ::guide-seq) @@ -413,7 +417,7 @@ (s/def ::record (only-keys :opt-un [::hang? ::record-type? ::to-string?])) (s/def ::remove (only-keys :opt-un [::fn-force-nl ::fn-gt2-force-nl ::fn-gt3-force-nl - :alt/extend ::binding ::pair ::map ::parse])) + :alt/extend ::binding ::pair ::map ::parse ::vector])) (s/def ::next-inner (s/nilable ::options)) @@ -432,7 +436,7 @@ (s/def ::set (only-keys :opt-un [::indent ::indent-only? ::respect-bl? ::respect-nl? ::sort? ::sort-in-code? ::wrap-after-multi? ::wrap-coll? - ::wrap?])) + ::wrap? ::no-wrap-after])) (s/def ::spaces? ::boolean) (s/def ::spec (only-keys :opt-un [::docstring? ::value])) (s/def ::split? ::boolean) @@ -451,7 +455,8 @@ (only-keys :opt-un [::indent ::binding? ::respect-bl? ::respect-nl? ::option-fn-first ::option-fn ::fn-format ::wrap-after-multi? ::wrap-multi? ::wrap-coll? ::wrap? - ::indent-only? ::hang? ::force-nl?])) + ::indent-only? ::hang? ::force-nl? + ::no-wrap-after])) (s/def ::version string?) (s/def ::width number?) (s/def ::url (only-keys :opt-un [::cache-dir ::cache-path ::cache-secs])) diff --git a/src/zprint/zprint.cljc b/src/zprint/zprint.cljc index abf1c34..437e005 100644 --- a/src/zprint/zprint.cljc +++ b/src/zprint/zprint.cljc @@ -3722,13 +3722,19 @@ (def body-set #{:binding :arg1-> :arg2 :arg2-fn :arg2-pair :pair-fn :fn :arg1-body :arg1-pair-body :none-body :noarg1-body :flow-body :arg2-extend-body - :arg1-force-nl-body :arg2-force-nl-body :guided-body}) + :arg1-force-nl-body :arg2-force-nl-body :guided-body :arg1-extend-body + :force-nl-body}) + +;; +;; Note Well -- every key in body-map should also appear in body-set! +;; (def body-map {:arg1-body :arg1, :arg1-pair-body :arg1-pair, :arg1-force-nl-body :arg1-force-nl, :arg2-extend-body :arg2-extend, + :arg1-extend-body :arg1-extend :none-body :none, :flow-body :flow, :noarg1-body :noarg1, @@ -3765,6 +3771,7 @@ :extend :extend, :binding :binding, :arg1-extend :extend, + :arg1-extend-body :extend :arg2-extend :extend, :arg2-extend-body :extend, :pair-fn :pair}) @@ -3920,6 +3927,42 @@ [options fn-style])) ([options fn-style] (handle-fn-style options fn-style #{}))) +(defn handle-new-fn-style + "If we have new-options, we might also have a new fn-style. It might + be a traditional keyword, in which case we just return it as the new + fn-style. But it might be a string, in which case we need to look it + up in the :fn-map, and deal with handling the results (or failure) of + that lookup. In any case, return [options fn-style]" + [caller options fn-style new-options fn-map user-fn-map option-fn] + (if new-options + (let [new-fn-style (:fn-style new-options)] + (if new-fn-style + (if (string? new-fn-style) + (let [found-fn-style (or (lookup-fn-str fn-map new-fn-style) + (lookup-fn-str user-fn-map new-fn-style))] + (if found-fn-style + ; Found something, use that. + (handle-fn-style options found-fn-style) + ; Didn't find it. + (throw (#?(:clj Exception. + :cljs js/Error.) + (str " When " + caller + " called an option-fn " + (option-fn-name option-fn) + " it returned a fn-style which" + " was a string '" + new-fn-style + "' which was not found in the :fn-map!"))))) + ; It wasn't a string, but it might be a full-on + ; complex vector style + (handle-fn-style options new-fn-style)) + ; Didn't get a new fn-style in new-options, + ; use the ones we already have + [options fn-style])) + ; Didn't get new-options at all + [options fn-style])) + (declare fzprint-noformat) (defn fzprint-list* @@ -4086,10 +4129,22 @@ "\nfn-style local:" fn-style "\nguide:" (:guide options) "\ncall-stack:" (:call-stack options)) + + ; Handle a new fn-style in the options map return from the + ; options-fn, as well as a string value, which means we need to + ; do it "like that" function. + [options fn-style] (handle-new-fn-style caller + options + fn-style + new-options + fn-map + user-fn-map + option-fn) + ; If we calculated a new fn-style in the option-fn, ; this will pick it up, else we will use the one that we figured ; out above. - fn-style (or (:fn-style new-options) fn-style) + #_#_fn-style (or (:fn-style new-options) fn-style) guide (or (:guide options) (guide-debug caller options)) ; Remove :guide and any forced :fn-style from options so they only ; happen once! @@ -4852,7 +4907,7 @@ and ind is where we should be after a newline." [caller {:keys [width rightcnt], - {:keys [wrap-after-multi? respect-nl?]} caller, + {:keys [wrap-after-multi? respect-nl? no-wrap-after]} caller, :as options} cur-ind ind coll-print] #_(prn "wrap-zmap:" coll-print) (let [last-index (dec (count coll-print)) @@ -4875,6 +4930,24 @@ last-width (last lines) len (- last-width ind) len (max 0 len) + ; Do we have a no-wrap element? + no-wrap-element? (when no-wrap-after + (no-wrap-after (first (first this-seq)))) + ; If we do, then add its length to the length of the + ; existing element + next-len (when (and no-wrap-element? (second cur-seq)) + (let [[linecnt max-width lines] + (style-lines options ind (second cur-seq)) + last-width (last lines)] + (max 0 (- last-width ind)))) + ; If we have a no-wrap element, make the index the index + ; of the next element, so we handle rightcnt correctly + original-len len + [len index] + (if next-len + ; Add the lengths together, and also one for the space + [(+ len next-len 1) (inc index)] + [len index]) newline? (= (nth (first this-seq) 2) :newline) comment? (if respect-nl? nil (= (nth (first this-seq) 2) :comment)) @@ -4889,6 +4962,15 @@ (or (zero? index) (and (if multi? (= linecnt 1) true) (<= (+ cur-ind len) width)))) + _ (when no-wrap-element? + (dbg-pr options + "wrap-zmap: no-wrap-element:" (first (first + this-seq)) + "original-len:" original-len + "next-len:" next-len + "index:" index + "rightcnt:" rightcnt + "fit?" fit?)) new-ind (cond ; Comments cause an overflow of the size (or comment? comment-inline?) (inc width) @@ -4909,7 +4991,10 @@ "\nlinecnt:" linecnt "\nmax-width:" max-width "\nlast-width:" last-width + "\nno-wrap-element?" no-wrap-element? + "\nnext-len:" next-len "\nlen:" len + "\nindex:" index "\ncur-ind:" cur-ind "\nnew-ind:" new-ind "\nwidth:" width @@ -5105,11 +5190,29 @@ (= next-guide :element-best-first) (= next-guide :element-best-*)) [true [zloc]]) + [do-extend? extend-seq] + (cond (or (= next-guide :element-newline-extend-group) + (= next-guide :element-newline-extend-*)) + [true group-seq] + (or (= next-guide :element-extend) + (= next-guide :element-extend-first) + (= next-guide :element-extend-*)) + [true [zloc]]) + [do-wrap-flow? wrap-flow-seq] + (cond (or (= next-guide :element-wrap-flow-group) + (= next-guide :element-wrap-flow-*)) + [true group-seq]) try-this? (and (or zloc do-pairs? group-seq) - (not previous-newline?) - (if (= next-guide :element-best-first) all-fit? true) + (or (not previous-newline?) + do-wrap-flow?) + (if (or (= next-guide :element-best-first) + (= next-guide :element-extend-first)) + all-fit? + true) (not guided-newline?) (or do-hang-remaining? + do-extend? + do-wrap-flow? (and (< cur-ind width) (< this-ind width)))) this-result (when try-this? @@ -5127,6 +5230,19 @@ #_group-seq nil ;fn-type ) + + do-wrap-flow? + (fzprint-one-line options this-ind wrap-flow-seq) + + do-extend? + + (prepend-nl options + (+ indent ind) + (fzprint-extend options + ; Might be this-ind? + this-ind + extend-seq)) + ; We don't need to use fzprint-hang-unless-fail, because ; that is pretty much what we are doing with everything. (= next-guide :element-binding-vec) @@ -5137,11 +5253,12 @@ :else (fzprint* (in-hang options) this-ind zloc))) ; If we did fzprint-hang-remaining and it has a single space at the ; beginning, then drop that space. - this-result (if (and do-hang-remaining? + this-result (if (and (or do-hang-remaining? do-extend?) (= (nth (first this-result) 2) :whitespace) (= (ffirst this-result) " ")) (next this-result) this-result) + #_ (println "this-result:" this-result) this-lines (style-lines options this-ind this-result) ; Force wrap-multi? true for this guide if we are doing binding, ; regardless of its value in the options map. @@ -5242,6 +5359,28 @@ #_group-seq nil ;fn-type ) + + do-wrap-flow? (fzprint-hang-remaining + caller + options + #_(assoc options :dbg? true) + ; flow it if we are doing it here + next-ind + next-ind + wrap-flow-seq + #_group-seq + nil ;fn-type + ) + + do-extend? + (prepend-nl options + (+ indent ind) + (fzprint-extend options + ; Might be this-ind? + next-ind + extend-seq)) + + (= next-guide :element-binding-vec) (fzprint-binding-vec options next-ind zloc) (or (= next-guide :element-binding-group) @@ -5252,8 +5391,10 @@ ; If we did fzprint-hang-remaining and it has a newline at the ; beginning, then we should drop that because we are going to ; do it ourselves since this is the "next" processing. - #_(prn "***********" next-result) + #_ (prn "next-result" next-result) next-result (if (and (or do-hang-remaining? + do-extend? + do-wrap-flow? (= next-guide :element-binding-*) (= next-guide :element-binding-group)) (= (nth (first next-result) 2) :indent) @@ -5429,6 +5570,8 @@ "\n this-fit?" this-fit? "\n fail-fit?" fail-fit? "\n do-hang-remaining?" do-hang-remaining? + "\n do-extend?" do-extend? + "\n do-wrap-flow?" do-wrap-flow? "\n regular-space:" regular-space "\n additional-spaces:" additional-spaces "\n beyond-cur-ind:" beyond-cur-ind @@ -6198,6 +6341,8 @@ ; :element-newline-best-* also has to come after ; newline handling (or (= first-guide-seq :element-newline-best-*) + (= first-guide-seq :element-newline-extend-*) + (= first-guide-seq :element-wrap-flow-*) (= first-guide-seq :element-binding-*) (= first-guide-seq :element-pair-*)) ; Consider everything else for a -* command. @@ -6336,8 +6481,11 @@ (or (= first-guide-seq :element) (= first-guide-seq :element-guide) (= first-guide-seq :element-best) + (= first-guide-seq :element-extend) (= first-guide-seq :element-best-first) + (= first-guide-seq :element-extend-first) (= first-guide-seq :element-best-*) + (= first-guide-seq :element-extend-*) (= first-guide-seq :element-*) (= first-guide-seq :element-binding-vec)) ; Do basic guided output, moving both cur-seq and guide-seq @@ -6347,7 +6495,8 @@ first-guide-seq) :bright-red)) _ (when (and (or (= first-guide-seq :element-*) - (= first-guide-seq :element-best-*)) + (= first-guide-seq :element-best-*) + (= first-guide-seq :element-extend-*)) (not (empty? (next guide-seq)))) (throw (#?(:clj Exception. @@ -6375,7 +6524,8 @@ ; Make sure to consume the guide too (nnext guide-seq) (or (= first-guide-seq :element-*) - (= first-guide-seq :element-best-*)) + (= first-guide-seq :element-best-*) + (= first-guide-seq :element-extend-*)) ; We just stay "stuck" on last command ; in guide-seq for :element-* and ; :element-best-* @@ -6390,6 +6540,8 @@ options new-out)) (or (= first-guide-seq :element-newline-best-group) + (= first-guide-seq :element-newline-extend-group) + (= first-guide-seq :element-wrap-flow-group) (= first-guide-seq :element-pair-group) (= first-guide-seq :element-binding-group)) ; Operate on previously grouped elements @@ -7671,13 +7823,20 @@ [l-str r-str options zloc] (let [l-str-vec [[l-str (zcolor-map options l-str) :left]] r-str-vec (rstr-vec options 0 zloc r-str) + len (zcount zloc) + _ (dbg-s-pr options + :noformat + "fzprint-noformat zloc" (zstring zloc) + "len:" len) fzprint*-seq (zmap-all-nl-comment (partial fzprint* options 0) zloc) _ (dbg-s-pr options :noformat "fzprint-noformat fzprint*-seq:" fzprint*-seq) concat-vec - (concat-no-nil l-str-vec (apply concat fzprint*-seq) r-str-vec) + (if (zero? len) + (concat-no-nil l-str-vec r-str-vec) + (concat-no-nil l-str-vec (apply concat fzprint*-seq) r-str-vec)) _ (dbg-s-pr options :noformat "fzprint-noformat concat-vec:" concat-vec) remove-spaces-vec (remove-spaces-pre-nl concat-vec) _ (dbg-s-pr options diff --git a/test/zprint/core_test.cljc b/test/zprint/core_test.cljc index 69346eb..1ec285c 100644 --- a/test/zprint/core_test.cljc +++ b/test/zprint/core_test.cljc @@ -1035,11 +1035,11 @@ insert-missing-whitespace) (reindent (:indents opts {})))))") (expect - "(defn reformat-form\n[form & [{:as opts}]]\n; This is a comment\n(-> form\n#_(cond-> (:remove-surrounding-whitespace? opts true)\nremove-surrounding-whitespace)\n(cond-> (:insert-missing-whitespace? opts true)\ninsert-missing-whitespace)\n(cond-> (:indentation? opts true)\n(reindent (:indents opts )))))" + "(defn reformat-form\n[form & [{:as opts}]]\n; This is a comment\n(-> form\n#_(cond-> (:remove-surrounding-whitespace? opts true)\nremove-surrounding-whitespace)\n(cond-> (:insert-missing-whitespace? opts true)\ninsert-missing-whitespace)\n(cond-> (:indentation? opts true)\n(reindent (:indents opts {})))))" (zprint-str rffb {:parse-string? true, :format :off})) (expect - 709 + 720 (count (zprint-str rffb {:parse-string? true, :format :off, :color? true}))) (def rffc @@ -1060,7 +1060,7 @@ insert-missing-whitespace) (zprint-str rffc {:parse-string? true})) (expect - "(defn reformat-form\n[form & [{:as opts}]]\n; This is a comment\n(-> form\n#_(cond-> (:remove-surrounding-whitespace? opts true)\nremove-surrounding-whitespace) ; This is an inline comment\n(cond-> (:insert-missing-whitespace? opts true) ; an aligned inline comment\n; This is a comment that is really much too long and will need to wrap, somewhere around after the r in somewhere.\ninsert-missing-whitespace)\n(cond-> (:indentation? opts true)\n(reindent (:indents opts )))))" + "(defn reformat-form\n[form & [{:as opts}]]\n; This is a comment\n(-> form\n#_(cond-> (:remove-surrounding-whitespace? opts true)\nremove-surrounding-whitespace) ; This is an inline comment\n(cond-> (:insert-missing-whitespace? opts true) ; an aligned inline comment\n; This is a comment that is really much too long and will need to wrap, somewhere around after the r in somewhere.\ninsert-missing-whitespace)\n(cond-> (:indentation? opts true)\n(reindent (:indents opts {})))))" (zprint-str rffc {:parse-string? true, :format :off})) ;; @@ -1304,7 +1304,6 @@ insert-missing-whitespace) (catch :default e (str e))))) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; End of defexpect diff --git a/test/zprint/zprint_test.cljc b/test/zprint/zprint_test.cljc index d02f44f..f2aec63 100644 --- a/test/zprint/zprint_test.cljc +++ b/test/zprint/zprint_test.cljc @@ -951,17 +951,30 @@ :clj (expect "#" (clojure.string/replace (zprint-str ag) #"\@[0-9a-f]*" ""))) - #?(:bb nil - :clj (def agf (agent [:c :d]))) - - #?(:bb nil - :clj (expect - "#" - (do (send agf + 5) - ; Wait a bit for the send to get to the agent and for the - ; agent to fail - (Thread/sleep 100) - (clojure.string/replace (zprint-str agf) #"\@[0-9a-f]*" "")))) +; +; This test causes cognitect test-runner to hang instead of exiting cleanly. +; I have been unable to figure out what to do to prevent that, and since this +; is clearly marginal functionality, I've left it out for now (and probably +; forever). +; +; #?(:bb nil +; :clj (def agf (agent [:c :d]))) +; +; #?(:bb nil +; :clj (expect +; "#" +; (let [agf (agent [:c :d])] +; (send agf + 5) +; ; Wait a bit for the send to get to the agent and for the +; ; agent to fail +; (Thread/sleep 100) +; (let [result +; (clojure.string/replace (zprint-str agf) #"\@[0-9a-f]*" "")] +; ; If we don't restart the agent, the tests will hang +; ; forever with , even though there is a shutdown-agents call +; (agent-error agf) +; (restart-agent agf [:c :d] :clear-actions true) +; result)))) ;; ;; # Sorting maps in code @@ -7342,6 +7355,90 @@ ser/collect-vars-acc %1 %2) )))" " (def ^:const ^:private ^:test ^:lots ^:of ^:meta ^:stuff port-file-name \".nrepl-port\")\n" {:parse-string? true, :meta {:split? true}})) +;; +;; Add no-wrap-after to :vector, Issue #252 +;; + +(expect + "(defn example\n [vvvvvveeeeeeeerrrrrrryyyyy looooooooooooooooooonnnnggggg paraaaaaaams &\n body]\n (+ 1 2 3))" + (zprint-str + "(defn example\n [vvvvvveeeeeeeerrrrrrryyyyy looooooooooooooooooonnnnggggg paraaaaaaams & body]\n (+ 1 2 3))\n" + {:parse-string? true, :width 79})) + + +(expect + "(defn example\n [vvvvvveeeeeeeerrrrrrryyyyy looooooooooooooooooonnnnggggg paraaaaaaams\n & body]\n (+ 1 2 3))" + (zprint-str + "(defn example\n [vvvvvveeeeeeeerrrrrrryyyyy looooooooooooooooooonnnnggggg paraaaaaaams & body]\n (+ 1 2 3))\n" + {:parse-string? true, :width 79, :vector {:no-wrap-after #{"&"}}})) + +;; Does it work for :wrap in lists as well? + +(expect + "(stuff example vvvvvveeeeeeeerrrrrrryyyyy looooooooooooonnnnggggg paraaaaaaams &\n body)" + (zprint-str + "(stuff example vvvvvveeeeeeeerrrrrrryyyyy looooooooooooonnnnggggg paraaaaaaams & body)\n" + {:parse-string? true, :fn-map {"stuff" :wrap}})) + +(expect + "(stuff example vvvvvveeeeeeeerrrrrrryyyyy looooooooooooonnnnggggg paraaaaaaams\n & body)" + (zprint-str + "(stuff example vvvvvveeeeeeeerrrrrrryyyyy looooooooooooonnnnggggg paraaaaaaams & body)\n" + {:parse-string? true, + :fn-map {"stuff" :wrap}, + :list {:no-wrap-after #{"&"}}})) + +;; +;; Add :element-wrap-flow-* to guide +;; + +(expect + "(let [example (data.example/get-by-org-id-and-items\n db-conn true [org-id] {:very-long-arg-here true})]\n (some-body expressions)\n (more-body expressions))" + (zprint-str + " (let [example (data.example/get-by-org-id-and-items\n db-conn true [org-id] {:very-long-arg-here true})]\n (some-body expressions)\n (more-body expressions))\n" + {:parse-string? true, + :fn-map {"get-by-org-id-and-items" + [:guided {:guide [:element :newline :element-wrap-flow-*]}]}, + :width 80})) + + +(expect + "(let [example\n (data.example/get-by-org-id-and-items\n db-conn true [org-id] {:very-long-arg-here true})]\n (some-body expressions)\n (more-body expressions))" + (zprint-str + " (let [example (data.example/get-by-org-id-and-items\n db-conn true [org-id] {:very-long-arg-here true})]\n (some-body expressions)\n (more-body expressions))\n" + {:parse-string? true, + :fn-map {"get-by-org-id-and-items" + [:guided {:guide [:element :newline :element-wrap-flow-*]}]}, + :width 60})) + +(expect + "(let [example (data.example/get-by-org-id-and-items\n db-conn\n true\n [org-id]\n {:very-long-arg-here true})]\n (some-body expressions)\n (more-body expressions))" + (zprint-str + " (let [example (data.example/get-by-org-id-and-items\n db-conn true [org-id] {:very-long-arg-here true})]\n (some-body expressions)\n (more-body expressions))\n" + {:parse-string? true, + :fn-map {"get-by-org-id-and-items" + [:guided {:guide [:element :newline :element-wrap-flow-*]}]}, + :width 55})) + + +;; +;; The :fn-type return from an :option-fn can now be a string, and this +;; will be an alias. +;; + +(expect + "(defn regexa\n \"This should format like when.\"\n [this is a test]\n (list this is a test)\n (let [some stuff\n more stuff\n lots (when-tst stuff\n this\n needs\n to\n be\n longer\n than\n one\n lineeven\n more\n things)]\n (stuff bother)))" + (zprint-str + "(defn regexa\n \"This should format like when.\"\n [this is a test]\n (list this is a test)\n (let [some stuff\n more stuff\n lots (when-tst stuff this needs to be longer than one lineeven more things)]\n (stuff bother)))\n" + {:parse-string? true, + :fn-map {:default-not-none + [:none + {:list {:option-fn (fn ([] "rulesfn") + ([options len sexpr] + (let [fn-str (str (first sexpr))] + (cond (re-find #"^when" fn-str) + {:fn-style "when"} + :else nil))))}}]}})) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/test/zprint/zutil_test.cljc b/test/zprint/zutil_test.cljc index a8c5cb4..3e53b12 100644 --- a/test/zprint/zutil_test.cljc +++ b/test/zprint/zutil_test.cljc @@ -15,6 +15,7 @@ ; Keep tests from configuring from any $HOME/.zprintrc or local .zprintrc ; + (set-options! {:configured? true}) ;; @@ -44,3 +45,4 @@ (expect nil (z/string (zprint.zutil/znthnext za 5))) ) + diff --git a/test_config b/test_config index bbc2a39..c55dfee 100755 --- a/test_config +++ b/test_config @@ -595,7 +595,7 @@ output_length=`$command --explain-all 2>&1 >/dev/null | wc -l` output_length=`echo "${output_length}" | sed -e 's/^[[:space:]]*//'` #echo "length is $output_length" -expected_length=877 +expected_length=890 if [[ $output_length != $expected_length ]] then diff --git a/test_uberjar b/test_uberjar index eca9220..040d5a0 100755 --- a/test_uberjar +++ b/test_uberjar @@ -1,3 +1,3 @@ -java -jar target/zprint-filter-1.2.4 z.cljc +java -jar target/zprint-filter-1.2.5 z.cljc diff z.cljc src/zprint/zprint.cljc rm z.cljc diff --git a/test_zprintm b/test_zprintm index 279cf77..2f4bf1a 100755 --- a/test_zprintm +++ b/test_zprintm @@ -1,9 +1,9 @@ -./zprintm-1.2.4 z.cljc +./zprintm-1.2.5 z.cljc diff z.cljc src/zprint/zprint.cljc rm z.cljc -java -jar target/zprint-filter-1.2.4 -e 2>uj.edn +java -jar target/zprint-filter-1.2.5 -e 2>uj.edn grep -v "\ujx.edn -./zprintm-1.2.4 -e 2>gv.edn +./zprintm-1.2.5 -e 2>gv.edn grep -v "\gvx.edn diff ujx.edn gvx.edn rm uj.edn ujx.edn gv.edn gvx.edn