kkinnear / zprint Goto Github PK
View Code? Open in Web Editor NEWExecutables, uberjar, and library to beautifully format Clojure and Clojurescript source code and s-expressions.
License: MIT License
Executables, uberjar, and library to beautifully format Clojure and Clojurescript source code and s-expressions.
License: MIT License
The appcds
script attempts to check to ensure that the version of Java being used has appcds implemented. But the way it does the version check doesn't work on Java 11, nor probably on other versions past 8. This needs to be fixed or removed.
The default interpose value for {:parse-string-all? true {:interpose true}} should give you one blank line between expressions, and :interpose "\n"
should give you none, but it doesn't work out that way. Ultimately the goal is to:
Can't do that today. Need to fix it so you can.
I've run into case where zprint is adding extra brackets resulting in incorrect code:
It seems to occur when the body of a fn
is moved to a new line:
input:
(zprint-str '(fn [contact] (= (contact :company) "Some Long String Here")) 50)
output:
(fn [contact]
((= (contact :company) ; <--- note extra set of brackets around the fn body
"Some Long String Here")))
When the contents of the fn
can fit on one line, it's ok:
input:
(zprint-str '(fn [contact] (= (contact :company) "Short")) 50)
output:
(fn [contact] (= (contact :company) "Short"))
When a very deeply nested function has an :arg2
function (e.g. catch
) which simply won't fit at all (or at least won't fit in a hang), it doesn't properly catch that and throws an exception because a value that is supposed to be a number is nil.
If a comment is inside of a vector (for which :wrap? true
is set, which it is by default), then if it ends up near the right margin when the comment wraps it can end up in a strange place.
Great project! I've built boot-fmt, similar to lein-zprint
. It can be used with lein or boot equally.
In dogfooding the auto-formatting feature in my core.clj, I noticed that zprint formats requires to go in a single line:
https://github.com/pesterhazy/boot-fmt/blob/master/src/boot_fmt/core.clj#L4
IMO (:requires)
should always be separated by newlines, even if they are short. What do you think?
I ran into a case where having a large set in a map prevents zprint from justifying it. Also the set is always flow regardless of :hang-expanded
. Smells like a performance optimization but can't see any way to turn it off.
(zp/zprint {:hello :not-indented
:genes #{"ABCB7" "ABCD1" "ABHD12" "ACAT1" "ACOX1" "ACTB" "ACVR1" "ADAR" "ADCY5"
"ADD3" "ADGRG1" "AFG3L2" "AHI1" "ALAS2" "ALDH5A1" "ALG6" "ALS2" "AMACR"
"AMPD2" "ANG" "ANO10" "ANO3" "ANO5" "AP1S2" "AP4B1" "AP4E1" "AP4M1"
"AP4S1" "AP5Z1" "APTX" "ARHGEF28" "ARL13B" "ARL6" "ARL6IP1" "ARSA" "ARSI"
"ARX" "ASAH1" "ATCAY" "ATL1" "ATM" "ATP13A2" "ATP1A2" "ATP1A3" "ATP6AP2"
"ATP7A" "ATP7B" "ATP8A2" "AUH" "B4GALNT1" "BAG3" "BBS1" "BBS10" "BBS12"
"BBS2" "BBS4" "BBS5" "BBS7" "BBS9" "BCAP31" "BEAN1" "BICD2" "BIN1" "BSCL2"
"BTD" "C12orf65" "C19orf12" "C5orf42" "C9orf72" "CA8" "CACNA1A" "CACNB4"
"CAMTA1" "CASQ1" "CAV3" "CC2D2A" "CCDC28B" "CCDC78" "CCDC88C" "CCT5"
"CEP290" "CEP41" "CFL2" "CHCHD10" "CHMP2B" "CIZ1" "CLCN2" "CLN3" "CLN5"
"CLPP" "CNTN1" "COL12A1" "COL6A1" "COL6A2" "COL6A3" "COMT" "COQ8A" "COX20"
"CP" "CRAT" "CRYAB" "CSF1R" "CSTB" "CTC1" "CTSD" "CWF19L1" "CYP27A1"
"CYP2U1" "CYP7B1" "DARS2" "DCAF17" "DCTN1" "DDB2" "DDC" "DDHD1" "DDHD2"
"DES" "DLAT" "DNA2" "DNAJC13" "DNAJC19" "DNAJC3" "DNAJC5" "DNAJC6" "DNM2"
"DNMT1" "DRD2" "DRD5" "DYSF" "EARS2" "EEF2" "EIF2B1" "EIF2B2" "EIF2B3"
"EIF2B4" "EIF2B5" "EIF4G1" "ELOVL4" "ELOVL5" "ENTPD1" "EPM2A" "ERCC2"
"ERCC3" "ERCC4" "ERCC5" "ERCC6" "ERLIN2" "FA2H" "FASTKD2" "FBXL4" "FBXO7"
"FGF14" "FHL1" "FKBP14" "FLNC" "FLRT1" "FLVCR1" "FOXG1" "FOXRED1" "FTL"
"FUS" "FXN" "GAD1" "GALC" "GAMT" "GAN" "GARS" "GBA" "GBA2" "GBE1" "GCDH"
"GCH1" "GCLC" "GFAP" "GIGYF2" "GJA1" "GJB1" "GJC2" "GLB1" "GNAL" "GNE"
"GOSR2" "GRID2" "GRM1" "HACD1" "HARS" "HEPACAM" "HEXA" "HEXB" "HNRNPA1"
"HNRNPA2B1" "HPRT1" "HSPB1" "HSPB3" "HSPB8" "HSPD1" "HTRA2" "IGHMBP2"
"ISCU" "ITM2B" "ITPR1" "KANK1" "KBTBD13" "KCNA1" "KCNC3" "KCND3" "KCNJ10"
"KCNMA1" "KCNQ2" "KDM5C" "KIF1A" "KIF1C" "KIF5C" "KIF7" "KLHL40" "KLHL41"
"KLHL9" "L2HGDH" "LAMP2" "LARS2" "LDB3" "LMNB1" "LMOD3" "LRRK2" "LYST"
"MAG" "MAPT" "MARS" "MARS2" "MAT1A" "MATR3" "MCOLN1" "MECP2" "MEGF10"
"MKKS" "MKS1" "MLC1" "MMADHC" "MPV17" "MR1" "MRE11" "MSTN" "MTHFR" "MTM1"
"MTMR14" "MTPAP" "MYF6" "MYH14" "MYH2" "MYH7" "MYOT" "NDUFV1" "NEB"
"NEDD4" "NEFH" "NEU1" "NHLRC1" "NIPA1" "NKX2-1" "NOL3" "NOP56" "NPC1"
"NPC2" "NPHP1" "NT5C2" "OFD1" "OPA1" "OPA3" "OPTN" "PABPN1" "PANK2"
"PARK7" "PAX6" "PDGFB" "PDGFRB" "PDHX" "PDSS1" "PDSS2" "PEX10" "PEX2"
"PEX7" "PFN1" "PGAP1" "PHYH" "PIK3R5" "PINK1" "PLA2G6" "PLEC" "PLEKHG4"
"PLEKHG5" "PLP1" "PMM2" "PMPCA" "PNKD" "PNKP" "PNPLA6" "PNPT1" "POLG"
"POLG2" "POLH" "PPP2R2B" "PQBP1" "PRICKLE1" "PRKCG" "PRKN" "PRKRA" "PRNP"
"PRPH" "PRRT2" "PSEN1" "PTEN" "PTS" "QDPR" "RAB29" "RAB39B" "RAB3GAP1"
"RAB3GAP2" "RARS2" "REEP1" "REEP2" "RELN" "RNASEH2A" "RNASEH2B" "RNASEH2C"
"RNF170" "RNF216" "RPGRIP1L" "RRM2B" "RTN2" "RUBCN" "RYR1" "SACS" "SAMD9L"
"SAMHD1" "SCN8A" "SCO2" "SCP2" "SDHAF1" "SERAC1" "SETX" "SGCE" "SIGMAR1"
"SIL1" "SLC16A2" "SLC17A5" "SLC19A3" "SLC1A3" "SLC20A2" "SLC25A15"
"SLC2A1" "SLC30A10" "SLC33A1" "SLC46A1" "SLC52A2" "SLC52A3" "SLC5A2"
"SLC6A3" "SMPD1" "SNCA" "SNX14" "SOD1" "SPART" "SPAST" "SPEG" "SPG11"
"SPG21" "SPG7" "SPR" "SPTBN2" "STAC3" "STIM1" "STUB1" "STXBP1" "SUCLA2"
"SUOX" "SYNE1" "SYNJ1" "SYT14" "TAF1" "TARDBP" "TBP" "TCTN1" "TCTN2"
"TCTN3" "TDP1" "TECPR2" "TFG" "TGM6" "TH" "THAP1" "TIA1" "TIMM8A" "TK2"
"TMEM138" "TMEM216" "TMEM230" "TMEM231" "TMEM237" "TMEM240" "TMEM67"
"TNNT1" "TOR1A" "TPK1" "TPM2" "TPM3" "TPP1" "TREM2" "TREX1" "TRIM32"
"TRPV4" "TSEN2" "TSEN34" "TSEN54" "TTBK2" "TTC8" "TTN" "TTPA" "TTR"
"TUBB4A" "TWNK" "UBA1" "UBQLN2" "UCHL1" "USP8" "VAMP1" "VAPB" "VCP"
"VEGFA" "VLDLR" "VMA21" "VPS13A" "VPS13C" "VPS35" "VPS37A" "VPS54" "VRK1"
"WASHC5" "WDPCP" "WDR45" "WDR48" "WDR81" "WFS1" "WWOX" "XPA" "XPC" "YARS2"
"ZFR" "ZFYVE26" "ZFYVE27" "ZNF423" "ZNF592"}}
{:map {:justify? true
:hang-expand 1000000}})
{:genes
#{"ABCB7" "ABCD1" "ABHD12" "ACAT1" "ACOX1" "ACTB" "ACVR1" "ADAR" "ADCY5"
"ADD3" "ADGRG1" "AFG3L2" "AHI1" "ALAS2" "ALDH5A1" "ALG6" "ALS2" "AMACR"
"AMPD2" "ANG" "ANO10" "ANO3" "ANO5" "AP1S2" "AP4B1" "AP4E1" "AP4M1" "AP4S1"
"AP5Z1" "APTX" "ARHGEF28" "ARL13B" "ARL6" "ARL6IP1" "ARSA" "ARSI" "ARX"
"ASAH1" "ATCAY" "ATL1" "ATM" "ATP13A2" "ATP1A2" "ATP1A3" "ATP6AP2" "ATP7A"
"ATP7B" "ATP8A2" "AUH" "B4GALNT1" "BAG3" "BBS1" "BBS10" "BBS12" "BBS2"
"BBS4" "BBS5" "BBS7" "BBS9" "BCAP31" "BEAN1" "BICD2" "BIN1" "BSCL2" "BTD"
"C12orf65" "C19orf12" "C5orf42" "C9orf72" "CA8" "CACNA1A" "CACNB4" "CAMTA1"
"CASQ1" "CAV3" "CC2D2A" "CCDC28B" "CCDC78" "CCDC88C" "CCT5" "CEP290"
"CEP41" "CFL2" "CHCHD10" "CHMP2B" "CIZ1" "CLCN2" "CLN3" "CLN5" "CLPP"
"CNTN1" "COL12A1" "COL6A1" "COL6A2" "COL6A3" "COMT" "COQ8A" "COX20" "CP"
"CRAT" "CRYAB" "CSF1R" "CSTB" "CTC1" "CTSD" "CWF19L1" "CYP27A1" "CYP2U1"
"CYP7B1" "DARS2" "DCAF17" "DCTN1" "DDB2" "DDC" "DDHD1" "DDHD2" "DES" "DLAT"
"DNA2" "DNAJC13" "DNAJC19" "DNAJC3" "DNAJC5" "DNAJC6" "DNM2" "DNMT1" "DRD2"
"DRD5" "DYSF" "EARS2" "EEF2" "EIF2B1" "EIF2B2" "EIF2B3" "EIF2B4" "EIF2B5"
"EIF4G1" "ELOVL4" "ELOVL5" "ENTPD1" "EPM2A" "ERCC2" "ERCC3" "ERCC4" "ERCC5"
"ERCC6" "ERLIN2" "FA2H" "FASTKD2" "FBXL4" "FBXO7" "FGF14" "FHL1" "FKBP14"
"FLNC" "FLRT1" "FLVCR1" "FOXG1" "FOXRED1" "FTL" "FUS" "FXN" "GAD1" "GALC"
"GAMT" "GAN" "GARS" "GBA" "GBA2" "GBE1" "GCDH" "GCH1" "GCLC" "GFAP"
"GIGYF2" "GJA1" "GJB1" "GJC2" "GLB1" "GNAL" "GNE" "GOSR2" "GRID2" "GRM1"
"HACD1" "HARS" "HEPACAM" "HEXA" "HEXB" "HNRNPA1" "HNRNPA2B1" "HPRT1"
"HSPB1" "HSPB3" "HSPB8" "HSPD1" "HTRA2" "IGHMBP2" "ISCU" "ITM2B" "ITPR1"
"KANK1" "KBTBD13" "KCNA1" "KCNC3" "KCND3" "KCNJ10" "KCNMA1" "KCNQ2" "KDM5C"
"KIF1A" "KIF1C" "KIF5C" "KIF7" "KLHL40" "KLHL41" "KLHL9" "L2HGDH" "LAMP2"
"LARS2" "LDB3" "LMNB1" "LMOD3" "LRRK2" "LYST" "MAG" "MAPT" "MARS" "MARS2"
"MAT1A" "MATR3" "MCOLN1" "MECP2" "MEGF10" "MKKS" "MKS1" "MLC1" "MMADHC"
"MPV17" "MR1" "MRE11" "MSTN" "MTHFR" "MTM1" "MTMR14" "MTPAP" "MYF6" "MYH14"
"MYH2" "MYH7" "MYOT" "NDUFV1" "NEB" "NEDD4" "NEFH" "NEU1" "NHLRC1" "NIPA1"
"NKX2-1" "NOL3" "NOP56" "NPC1" "NPC2" "NPHP1" "NT5C2" "OFD1" "OPA1" "OPA3"
"OPTN" "PABPN1" "PANK2" "PARK7" "PAX6" "PDGFB" "PDGFRB" "PDHX" "PDSS1"
"PDSS2" "PEX10" "PEX2" "PEX7" "PFN1" "PGAP1" "PHYH" "PIK3R5" "PINK1"
"PLA2G6" "PLEC" "PLEKHG4" "PLEKHG5" "PLP1" "PMM2" "PMPCA" "PNKD" "PNKP"
"PNPLA6" "PNPT1" "POLG" "POLG2" "POLH" "PPP2R2B" "PQBP1" "PRICKLE1" "PRKCG"
"PRKN" "PRKRA" "PRNP" "PRPH" "PRRT2" "PSEN1" "PTEN" "PTS" "QDPR" "RAB29"
"RAB39B" "RAB3GAP1" "RAB3GAP2" "RARS2" "REEP1" "REEP2" "RELN" "RNASEH2A"
"RNASEH2B" "RNASEH2C" "RNF170" "RNF216" "RPGRIP1L" "RRM2B" "RTN2" "RUBCN"
"RYR1" "SACS" "SAMD9L" "SAMHD1" "SCN8A" "SCO2" "SCP2" "SDHAF1" "SERAC1"
"SETX" "SGCE" "SIGMAR1" "SIL1" "SLC16A2" "SLC17A5" "SLC19A3" "SLC1A3"
"SLC20A2" "SLC25A15" "SLC2A1" "SLC30A10" "SLC33A1" "SLC46A1" "SLC52A2"
"SLC52A3" "SLC5A2" "SLC6A3" "SMPD1" "SNCA" "SNX14" "SOD1" "SPART" "SPAST"
"SPEG" "SPG11" "SPG21" "SPG7" "SPR" "SPTBN2" "STAC3" "STIM1" "STUB1"
"STXBP1" "SUCLA2" "SUOX" "SYNE1" "SYNJ1" "SYT14" "TAF1" "TARDBP" "TBP"
"TCTN1" "TCTN2" "TCTN3" "TDP1" "TECPR2" "TFG" "TGM6" "TH" "THAP1" "TIA1"
"TIMM8A" "TK2" "TMEM138" "TMEM216" "TMEM230" "TMEM231" "TMEM237" "TMEM240"
"TMEM67" "TNNT1" "TOR1A" "TPK1" "TPM2" "TPM3" "TPP1" "TREM2" "TREX1"
"TRIM32" "TRPV4" "TSEN2" "TSEN34" "TSEN54" "TTBK2" "TTC8" "TTN" "TTPA"
"TTR" "TUBB4A" "TWNK" "UBA1" "UBQLN2" "UCHL1" "USP8" "VAMP1" "VAPB" "VCP"
"VEGFA" "VLDLR" "VMA21" "VPS13A" "VPS13C" "VPS35" "VPS37A" "VPS54" "VRK1"
"WASHC5" "WDPCP" "WDR45" "WDR48" "WDR81" "WFS1" "WWOX" "XPA" "XPC" "YARS2"
"ZFR" "ZFYVE26" "ZFYVE27" "ZNF423" "ZNF592"},
:hello :not-indented}
The challenge of writing a macro that generates different code for Clojurescript and Clojure, and the same code for self-hosted Clojurescript as it does for browser-based (i.e., JVM compiled) Clojurescript managed to get me. There was supposed to be a macro that didn't use future
when it was in Clojurescript, but it didn't work except in self-hosted Clojurescript.
This code (generating hiccup data):
(defn main [{:keys [current-person] :as view-data} & hs]
(page/html5
(head view-data)
[:body
(if (some? current-person)
(navbar-logged-in view-data)
(navbar-logged-out view-data))
(flashes view-data)
hs
(bugsnag view-data)
(scripts view-data)
(start-app-script (:server.system/profile view-data))]))
is formatted to this (default and community styles):
(defn main
[{:keys [current-person], :as view-data} & hs]
(page/html5 (head view-data)
[:body
(if (some? current-person)
(navbar-logged-in view-data)
(navbar-logged-out view-data)) (flashes view-data) hs
(bugsnag view-data) (scripts view-data)
(start-app-script (:server.system/profile view-data))]))
This is very unreadable, especially because of the (flashes view-data) hs
wrapped into the same line as the else
branch of the if
.
Setting {:vector {:wrap-coll? nil}
fixes this, but I was wondering if the default formatting is intended as shown above, since I find this unreadable.
See conversation at issue #33, where we discuss alignment ideas for inline comments. At present, there is no attempt to align them.
If the path to an expression to highlight with "focus" includes a comment line which will be wrapped because it extends beyond the width, the path will either fail or lead to different expression.
As far as I can tell, inline comments always get moved to a new line.
{:a 1 ; Inline comment about :a 1
:b 2}
becomes
{:a 1
; Inline comment about :a 1
:b 2}
Which was quite surprising to me. I am nowhere near the 80 char wrap limit. I tried setting {:comment {:wrap? false}}
to avoid the comment being moved but the behavior for inline comments is unchanged.
I am using zprint-filter-0.4.3
which is where I observe this behavior.
Hello there,
I'm in the process of building a zprint configuration using a little live-reloading Clojurescript application and have gotten stuck trying to format Rum's macros nicely.
In Rum the following expressions exist:
(rum/defc my-other-widget
[]
[:h1 "This doesn't have a mixin"])
(rum/defc my-amazing-widget < rum/reactive
[]
[:h1 "Hello world!"])
(rum/defcs my-stateful-widget < (rum/state 0 ::key)
[state]
[:h1 (str "Count is " (::key @state))])
You can even write an inline map to build a mixin like so:
(rum/defcs some-other-component < {:will-mount (fn [state] ...)}
[state]
...)
With :flow
I get this:
(rum/defc
foobar
[]
[:h1 "hi there"])
(rum/defc
hello-world
<
rum/reactive
[]
[:div [:h1 (:text @app-state)] [:h3 "Not in real time of course!"]])
With :arg2-fn
I get this:
(rum/defc foobar [] [:h1 "hi there"])
(rum/defc hello-world <
rum/reactive
[]
[:div [:h1 (:text @app-state)] [:h3 "Not in real time of course!"]])
Oh, and you can list mixins after the <
so there could be several maps of function calls. Admittedly Rum is kinda strange. It looks like it's copying inheritance/mixin syntax from Ruby, and that's maybe not the easiest thing to format. Perhaps I should just stop using the macro instead…
If you do know of a way to format these forms please let me know, and if you're interested in the little playground I've setup I'll be open sourcing it shortly.
I wanted to ask what the policy is for adding fns to the default :fn-map
?
For example, I would suggest to add match
with :arg1-pair-body
, as I'd guess it's at least somewhat commonly used, but at the same time recognize this would be a never ending story.
Hi, I'm not sure which project this issue should belong to so I've filed it in both.
I'd like to use zprint as a dev-dependency, but when I try to do so I run into the following Exception when trying to start a REPL via CIDER:
(when using it as a regular project dependency everything seems to work alright)
Exception in thread "main" java.lang.RuntimeException: Unable to resolve var: cider.nrepl.middleware.macroexpand/wrap-macroexpand in this context, compiling:(C:\Users\Olli\AppData\Local\Temp\form-init755829693141095127.clj:1:9531)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6926)
at clojure.lang.Compiler.analyze(Compiler.java:6701)
at clojure.lang.Compiler.analyze(Compiler.java:6657)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3835)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6921)
at clojure.lang.Compiler.analyze(Compiler.java:6701)
at clojure.lang.Compiler.analyze(Compiler.java:6657)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3835)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6921)
at clojure.lang.Compiler.analyze(Compiler.java:6701)
at clojure.lang.Compiler.access$300(Compiler.java:38)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6298)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6919)
at clojure.lang.Compiler.analyze(Compiler.java:6701)
at clojure.lang.Compiler.analyze(Compiler.java:6657)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6030)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5407)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3973)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6917)
at clojure.lang.Compiler.analyze(Compiler.java:6701)
at clojure.lang.Compiler.eval(Compiler.java:6975)
at clojure.lang.Compiler.eval(Compiler.java:6968)
at clojure.lang.Compiler.load(Compiler.java:7430)
at clojure.lang.Compiler.loadFile(Compiler.java:7368)
at clojure.main$load_script.invokeStatic(main.clj:277)
at clojure.main$init_opt.invokeStatic(main.clj:279)
at clojure.main$init_opt.invoke(main.clj:279)
at clojure.main$initialize.invokeStatic(main.clj:310)
at clojure.main$null_opt.invokeStatic(main.clj:344)
at clojure.main$null_opt.invoke(main.clj:341)
at clojure.main$main.invokeStatic(main.clj:423)
at clojure.main$main.doInvoke(main.clj:386)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Unable to resolve var: cider.nrepl.middleware.macroexpand/wrap-macroexpand in this context
at clojure.lang.Util.runtimeException(Util.java:221)
at clojure.lang.Compiler$TheVarExpr$Parser.parse(Compiler.java:710)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6919)
... 34 more
Subprocess failed
Since {:pair {:nl-separator? true}}
is supposed to affect constant pairs, the code that does this got a bit overenthusiastic, and affects things that are not pairs:
(czprint-fn pair-tst 30 {:pair {:nl-separator? true}})
(defn pair-tst
[]
(println
(list :ajfkdkfdj
:bjlfkdsfjsdl)
(list :cjslkfsdjl
:dklsdfjsdsjsldf)
[:ejlkfjdsfdfklfjsljfsd
:fjflksdfjlskfdjlk]
:const1 "stuff"
:const2 "bother"))
There should be no completely blank lines in pair-tst!
Found a very serious bug. If there is whitespace after a left parenthesis and before the
first element in the list and the list does not fit on one line, the output repeats either the first or second element. This will cause code to break.
For example (this repeats the second element):
(czprint "(def x :thisisaverylongkeyword)" 15 {:parse-string? true})
(def x
:thisisaverylongkeyword)
(czprint "( def x :thisisaverylongkeyword)" 15 {:parse-string? true})
(def x
x
:thisisaverylongkeyword)
There is no workaround for this problem, other than to fix the input code to not have the whitespace.
When formatting clojure.spec.test, I get the following diff
(ns clojure.spec.test
- (:refer-clojure :exclude [test])
- (:require
- [clojure.pprint :as pp]
- [clojure.spec :as s]
- [clojure.spec.gen :as gen]
- [clojure.string :as str]))
+ (:refer-clojure :exclude [test])
+ (:require [clojure.pprint :as pp]
+ [clojure.spec :as s]
+ [clojure.spec.gen :as gen]
+ [clojure.string :as str]))
This looks strange because the second line is indented by one space. (By the way, I'm not talking about the fact that [clojure.pprint :as pp]
is moved to the first line, which is a change I like.)
Without specifying community style I get the correct
(ns clojure.spec.test
(:refer-clojure :exclude [test])
- (:require
- [clojure.pprint :as pp]
- [clojure.spec :as s]
- [clojure.spec.gen :as gen]
- [clojure.string :as str]))
+ (:require [clojure.pprint :as pp]
+ [clojure.spec :as s]
+ [clojure.spec.gen :as gen]
+ [clojure.string :as str]))
I think that the first argument of ns
should be indented by two, not one spaces, even when choosing community style.
ns
is an implicit exception to this rule.Is there a way to specify ns
as an exception and to include this exception in :style :community
?
For integration with JS-based editors it would be nice if there was an NPM package exposing a standard JS API (CommonJS?). I understand if this is out of scope for this project but wanted to leave a note here just in case :) Thank you!
Edit: An NPM package could also expose a binary similar to lumo
which could help with overall startup time.
Edit Jan 15th '18: Here's a twitter conversation that may provide additional context and (I think) stimulated recent activity around this issue.
As a config option
spec.cljc
pulls in [clojure.spec :as s]
rather than [clojure.spec.alpha :as s]
meaning it's no longer compatible with latest Clojure 1.9 and Spec libs.
So we could use a config map like
{:fn-map {"def*" :arg1-body}}
or
{:fn-map {#"def*" :arg1-body}}
and it would apply for def
, defn
, defproject
and so on. Ideally the regex would only be used if no direct matches were found so if we add a entry for defmethod
it would be used instead of #"def*"
.
It would simplify the config for common cases like def*
, with-*
, *->>
.
Is there an option to produce multiline strings in the formatted output?
For example, both of these are equivalent strings:
"foo\nbar"
"foo
bar"
But zprinting either of them results in:
"\"foo\\nbar\""
Is there a way to have it actually put a newline in the formatted result instead of the escaped \n?
If not, could that be added?
Thanks,
Matt
The support for turning :argn
functions into :argn-1
functions when they appear inside of a ->
thread first macro is currently being applied to the first expression in the ->
macro, which is a mistake since it is just an expression.
For example, the if
below is incorrect:
(defn parse-string-all-options
"Handle options for :parse-string-all?, by removing
:parse-string-all? and changing the default for
:parse {:interpose } to be true instead of nil."
[options]
(-> (if (nil? (:interpose (:parse options)))
(assoc-in options [:parse :interpose] true)
options)
(dissoc :parse-string-all?)
(assoc :trim-comments? true)))
Pull the insides of zprint-file
out and make it a separate function, zprint-whole
, for boot-fmt
or anyone else to use. Also, document at least one of them as part of the formal API.
boot.user=> (->> (zprint.core/zprint-str "(doseq [x xs]\n (foo x)\n (bar x))" {:parse-string-all? true, :parse {:interpose "\n\n"}}) println)
(doseq [x xs] (foo x) (bar x))
Based on clojure code I've read, I would expect each form in the body to be separated by a newline for do
and do
-likes (doseq
, dotimes
, dosync
).
I think the same is true for a lot of other macros as well, e.g. with-open
, future
It would be interesting to have this feature and the effort is not very high
The :fn-type
of a function is noted, and :fn-type
s with -body
on them have the -body
stripped off before matching the :fn-force-nl
set. This is confusing and also limits what can be configured. It should only match the exact :fn-type
s in the set.
I'm using shadow-cljs to compile my Clojurescript and it complains (loudly) about the ns form of main.cljc
. I believe it's because gen-class
isn't implemented in Clojurescript. Wrapping the (:gen-class)
expression in a :clj
reader conditional fixes it for me. Happy to put together a PR.
Unless you have a time machine and your personal timeline is now situated a year in the past (in which case I have some bets I'd like you to place), I believe the changelog has incorrect dates starting with version 0.2.11.
In the default styles, cond->
is formatted with :arg1-pair-body
Line 295 in ccfc04f
:community
styles :none-body
Line 526 in ccfc04f
According to the style-guide (https://github.com/bbatsov/clojure-style-guide#body-indentation), I think :arg1-pair-body
would be more appropriate for the :community
styles as well.
Not a big deal, since we can just revert it back to the default setting, but wanted to ask for the intention here.
I read this interesting comment describing how gofmt works and though it might be worth bringing up for discussion. I think gofmt is a very useful model to look at because it has won the hearts of the golang community.
Basically a code re-formatter could take one of two approaches:
Normalization: transform the input into an AST and reformat from scratch, disregarding all original whitespace.
Permissiveness: preserve some of the original whitespace. As explained in the comment I linked to, sometimes an unusual newline is introduced on purpose.
A (not very good, admittedly) example might be:
(defn square
[a]
(* a a))
Where the normalizer would reformat this
(defn square [a]
(* a a))
the permissive reformatter would take the newling as a hint and keep the linebreak (but would perhaps coalesce two subsequent linebreaks).
The normalization approach seems more "clean" from an implementation perspective (modulo comments?), but the second one could make more people happy with the results. Any thoughts on this distinction?
(defui AnimalsList
static om/IQueryParams
(params [this]
{:start 0 :end 10})
static om/IQuery
(query [this]
'[:app/title (:animals/list {:start ?start :end ?end})])
Object
(render [this]
(let [{:keys [app/title animals/list]} (om/props this)]
(dom/div nil
(dom/h2 nil title)
(apply dom/ul nil
(map
(fn [[i name]]
(dom/li nil (str i ". " name)))
list))))))
Do you have any idea how to format such a macro?
Because vectors are by default wrapped, the comment elements are wrapped with them. Because of this, a single line comment will frequently end up on the end of the previous line, even though originally it was on a line by itself.
For example:
[:a :b
; comment one
:c :d
; comment two
]
becomes:
[:a :b ; comment one
:c :d ; comment two
]
which just seems wrong. If a comment was already on the same line as some other element, having it wrap into the line that element is on would be good, but only if it was already an inline comment.
In particular, you can't do this: (set-options! {:fn-force-nl #{:binding}})
, and have it add to the existing set that is the value for :fn-force-nl
. At present it replaces the set that is there, and it should not. It should operate just like the maps to. This isn't just for set-options!
, it is true of any options map -- the command line, lein-zprint, etc.
In the 0.3.0
version some performance optimizations were added that caused the justified output to be completely missing when some lines in a map that is being justified don't fit inside of the width. The most obvious case is where a string is just too long to "fit", and that causes the map and possibly all of the output to be missing. For instance, the Clojure 1.8 definition of defn
has a string in the map of metadata that is too big for pretty much any width, and so if you do:
(czprint-fn defn {:map {:justify? true}})
you will not get any output. The same thing happens when you say {:style :justified}
.
The workaround is to not justify something, and this problem will not occur.
Given the following example and settings, I'm getting an unexpected result. The first map comes out as expected, but the second one is not justified. Do you know what would cause this?
(apologies for the confusing example - I tried for a simpler repro case, but obfuscating the data was easiest)
Input
(zp/zprint-str
'[{:abcd :abcd
:abcdef {:abcdefg [:abcdefgh :abcdefghijkl :abcdefgh :850fda697252 variable]
:abcdefgh [:s3 :abcdefgh-ijklmn :abcdefghijkl :abcdefgh :850fda697252 variable]}
:abcdefghijkl []
:abce {:abcd :abcd
:abcdef {:abcd "foo"}}}
{:abcd :abcd
:abcdef {:abcdefg [:abcdefgh :abcdefghijkl :850fda697252 variable]
:abcdefgh [:ab :abcdefgh-ijklmn :abcdefghijkl :850fda697252 variable]}
:abcdefghijkl [{:abcd "bar"
:abcdefg [:abcdefgh :abcdefghijkl :abcdefgh :850fda697252 variable]}]
:abce {:abcd :abcd
:abcdef {:abcd "foo"}}}]
100 {:vector {:wrap? false}
:map {:comma? false
:force-nl? true
:justify? true}})
Result:
[{:abcd :abcd
:abcdef {:abcdefg [:abcdefgh :abcdefghijkl :abcdefgh :850fda697252 variable]
:abcdefgh [:s3 :abcdefgh-ijklmn :abcdefghijkl :abcdefgh :850fda697252 variable]}
:abcdefghijkl []
:abce {:abcd :abcd
:abcdef {:abcd "foo"}}}
{:abcd :abcd
:abcdef {:abcdefg [:abcdefgh :abcdefghijkl :850fda697252 variable]
:abcdefgh [:ab :abcdefgh-ijklmn :abcdefghijkl :850fda697252 variable]}
:abcdefghijkl
[{:abcd "bar"
:abcdefg
[:abcdefgh :abcdefghijkl :abcdefgh :850fda697252 variable]}]
:abce {:abcd :abcd
:abcdef {:abcd "foo"}}}]
Using the docstring detection, would it be possible to perform formatting to match https://github.com/bbatsov/clojure-style-guide#align-docstring-lines ?
I'd like to use this style:
(cond x
y
a
b
:else
c)
As I understand it, :nl-separator?
only kicks in for flow instead of hang. Are you opposed to enabling it for hangs?
Thank you for zprint! As a new Clojure dev, I find zprint super helpful.
I'm curious if there are any known ways to setup zprint to work automatically at the repl. Or if there are any ways to hook it into existing tools, like Cider etc.
For example, currently, I can issue this command to see a zprinted function spec (one of my favorite uses).
(zprint (clojure.spec/describe (clojure.spec/get-spec `function-name)))
I'm curious what all would be involved in getting zprint to handle all output at the repl, or if that is a very bad idea for reasons I'm unaware of (performance comes to mind, but doesn't seem too critical at the repl).
i.e., being able to just issue the normal function call:
(clojure.spec/describe (clojure.spec/get-spec `function-name))
and have the result look nice.
I can ask the Cider folks about the editor issues, of course, but any thoughts or concerns you have about library, framework and editor integrations, in general, would be appreciated.
If you specify a set in an options map:
(set-options! {:fn-force-nl #{:arg1}})
it will add the element in the set to the existing elements. But the (czprint nil :explain)
output will be incorrect, and it will look like it replaced the existing set with the new set, instead of merging the new set with the existing set. The :explain
output shows:
:fn-force-nl {:set-by "repl or api call 3", :value #{:arg1}},
In fact, the options map now contains:
:fn-force-nl #{:force-nl :flow :noarg1 :noarg1-body :force-nl-body
:arg1-force-nl :flow-body :arg1},
The comments here are hard to find:
Lines 638 to 674 in 139e3ab
Is this a supported API and can they be moved to the readme?
With the default settings, I've found a fn which should be formatted like this
(fn [arg1 arg2 arg3] [:first-keyword-in-vector
:some-very-long-keyword-that-makes-this-wrap
:next-keyword])
turns into this after running zprint on it
(fn [arg1 arg2 arg3] [:first-keyword-in-vector
:some-very-long-keyword-that-makes-this-wrap
:next-keyword])
(Notice the extra space on wrapped vector items)
Using zprint 0.4.2:
(zp/zprint
'(def foo
{:a (abcdef-in12345678912)
:abcdef-abcdefgh-abc-abcdefghi-abcdefgh-abcdef-abcdefgh false})
80
{:map {:justify? true
:comma? false}})
(def foo
{:a (abcdef-in12345678912)
:abcdef-abcdefgh-abc-abcdefghi-abcdefgh-abcdef-abcdefgh false})
=> nil
When it should be:
(def foo
{:a (abcdef-in12345678912)
:abcdef-abcdefgh-abc-abcdefghi-abcdefgh-abcdef-abcdefgh false})
Unfortunately, there is special case code for (zprint nil), but it returns "" instead of nil.
lumo.core/*command-line-args*
has been removed in favour of cljs.core/*command-line-args*
zprint-file-str
only takes the string to reformat and the specifier.
This seems inconsistent to me, especially because in the readme it is stated:
;; All zprint- functions also allow the following arguments:
(zprint x <options>)
I use set-options!
now, which works. But I was wondering if this is intentional or not.
So that
{:a-big-key :a-really-long-value...
:c :d}
becomes
{:a-big-key
:a-really-long-value...
:c :d}
Let people configure this:
(:require
[boot-fmt.impl :as impl]
[boot.core :as bc]
[boot.util :as bu])
I prefer to format my namespaces as described in Stuart Sierra's How to ns. Here's an example:
(ns com.example.my-application.server
"Example application HTTP server and routing."
(:refer-clojure :exclude [send])
(:require
[clojure.core.async :as async :refer [<! <!! >! >!!]]
[com.example.my-application.base]
[com.example.my-application.server.sse :as server.sse]
[io.pedestal.http :as http]
[io.pedestal.http.sse :as http.sse]
[ring.util.response :as response])
(:import
(java.nio.file Files LinkOption)
(org.apache.commons.io FileUtils)))
Note the (:require ,,,)
and (:import ,,,)
s-exps are treated as lists rather than functions, with each item in the list aligned. I've experimented, but I haven't figured out a way to coax, persuade, or cajole zprint to help me out here and still permit me to format functions with indents at 2.
(ns com.grzm.ex.zprint
(:require
[clojure.string :as str]
[zprint.core :as z :refer [zprint zprint-str]]))
(def opts {:style :community
:list {:indent 2
:indent-arg 2}
:fn-map {":import" :flow
":require" :flow}})
(def forms ['(ns com.grzm.ex.zprint
(:require
[clojure.set :as set]
[clojure.spec.alpha :as s]
[clojure.string :as str]
[clojure.test :refer [deftest is]]
[zprint.core :as z :refer [zprint]])
(:import
(clojure.lang ExceptionInfo)
(java.io Closeable File)))
'(defn foo [x]
(println "some fun")
(println "some more fun")
(println "just making things long long long "))])
(println (->> forms
(map #(z/zprint-str % opts))
(interpose "\n")
(str/join "\n")))
output
(ns com.grzm.ex.zprint
(:require
[clojure.set :as set]
[clojure.spec.alpha :as s]
[clojure.string :as str]
[clojure.test :refer [deftest is]]
[zprint.core :as z :refer [zprint]])
(:import
(clojure.lang ExceptionInfo)
(java.io Closeable File)))
(defn foo
[x]
(println "some fun")
(println "some more fun")
(println "just making things long long long "))
If I understand the issue correctly, it's that the same indent value controls both the :flow
specified for :require
and :import
as for the other list. Is there a way to do what I'm hoping to do?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.