I'm considering adding optional https://github.com/clojure-lsp/clojure-lsp/issues/1315 for format feature, especially because of cljfmt performance + missing vertical alignment configs, anyone had experience with zprint and knows if is possible to matches all cljfmt configs?
I found https://clojureverse.org/t/i-need-some-zprint-config-examples/3121/15 but seems a little bit old, any thoughts @pez?
my team uses zprint for formatting all our codebases. I think you'd be able to recreate pretty much any formatting style you want with it. It is incredibly configurable.
One gotcha, at least for however we have our formatters setup, is that we occasionally need to run it twice to get to a stable format.
> occasionally need to run it twice to get to a stable format. that's odd, do you know if it's a zprint bug or maybe some nested cleans and format of yours that can result in that need?
unsure. I think it might be neither a bug or something about our formatting choices but I'm struggling to find the documentation about it. I have a vague memory of there being some heuristics for getting code looking "good" that can result in the starting state affecting the output.
the maintainer is pretty active on github (at least, back when I was setting this up).
there are occasional bugs with zprint with consistency but kim responds fast if you find issues
i used to be the maintainer of our zprint config at my last job, we ran it over 120k lines of clojure
lol i can answer many questions about zprint if you have them
thanks! for now, I'll start implement the support in clojure-lsp with a flag to use it, but then I will start doing tests especially related with configs to have similar behavior of cljfmt
Are you planning to also have https://github.com/oakmac/standard-clojure-style-js integrated in some form?
The maintainer of zprint and I have discussed things also among the issues on zprint, @ericdallo. Heβs very responsive and generous with his time. Itβs only because his and my attention span for it has never quite overlapped for long periods enough that we havenβt been able to get zprint implemented in Calva as a formatter. Calva uses zprint for formatting things still, just not for the formatting provider.
the biggest pains from cljfmt ATM mentioned in the original issue: performance + missing vertical aligment configs
I wonder if performance is much better with zprint than with cljfmt, though. I have always thought it was the other way around (but never measured).
got it, one thing I'd love to see someday is calva delegate all format stuff to clojure-lsp like other editors
native zprint is pretty dang fast, clojure zprint is not very fast
at Nubank we are having big problems with cljfmt performance, there are files that take 10mins to format... zprint i wanna test those things
oh my god lol
zprint was never that bad
yeah, clojure-lsp is native, so we need to use zprint compiled with graal
also we can't have control over vertical alignment, or ensure any standard because cljfmt doesn't support it, and I've been following this cljfmt issue for years, saw multiple PRs that never got merged
I think vertical alignment is pretty close to be added to cljfmt. It has been like that for very long, though, so I could be wrong. @weavejester is also very responsive so checking with him could shed some light on this particular issue. Calva is currently bundling an old fork of cljfmt to support targeted vertical alignment.
What is this vertical alignment you speak up? Is it a Go-style "make my diffs bigger please" setting? π
why would zprint be faster than cljfmt?
> there are files that take 10mins to format huh...
@stig328 we can't ensure code to follow or not this
{:something 1
:foo 2}
I personally dislike format like that, the point is that we can't ensure use or not that, so there are codebase with multiple standards related to that> why would zprint be faster than cljfmt? I don't know if it's, it's something to be tested yet
I guess you could test before going through the hoops of building it into clojure-lsp first?
yes, that's what I'm researching right now, how to have a similar config to cljfmt to then compare
Vertical alignment is difficult due to the many edge conditions. I made some progress on it, and there's a branch on the repository, but other work interrupted my progress. It's one of those problems that takes a while to get back into due to its complexity.
I was getting close to finishing a vertical alignment effort for cljfmt, but completely lost my mojo when I got some "why don't you just" feedback (rare in the clojure community, but I actually accidentally asked for it, so kind of my bad!). Never got back to the effort. I was thinking some inline tagging might be interesting because you might not want to vertically align everything.
When working with kkinnear on zprint rewrite-clj-isms/issues, I've always found him very nice to work with. But I also would say the same of weavejester on cljfmt!
The zprint config is turing-complete due to SCI. Not sure if that's good or bad though!
There are many many knobs to turn in zprint. The docs can be overwhelming.
It's a difficult problem. I can understand getting demotivated!
@ericdallo when you get some numbers, I'd be interested to see the results of your zprint vs cljfmt perf tests. They both use rewrite-clj zippers under the hood, so I always assumed they would have similar performance.
I'm not too surprised that cljfmt ends up being less performant. There are a number of parts of the code that could be made to be more efficient.
interesting @lee, will do!
The design of cljfmt emphasizes clarity over efficiency, as it's easier to start from a clear base and optimize out bottlenecks, than it is to try to begin with something performant but complex. cljfmt is hard enough for me to hold in my head as it is!
yeah, makes total sense @weavejester, thanks for sharing
I will do some tests later with big codebases to understand the tradeoffs, thanks all for the input
I do think it wouldn't be hard to improve cljfmt's performance. We could probably do quite well via just memoizing some key functions.
The design of cljfmt emphasizes clarity over efficiency,probably the reason why cljfmt works in bb as well π babashka
bb -Sdeps '{:deps {dev.weavejester/cljfmt {:mvn/version "0.13.0"}}}' -m cljfmt.main fix ~/dev/clojure/src/clj/clojure/core.cljIβm curious about the files that take 10m to format. π
one of them is a single edn file, with a single set`#{}` of uuids, like #{#uuid "1234.."} , but with 100k uuids, I know it's a lot, but >10m to format a single set looks weird
well, i spit 100k uuids into a single set in an edn file and zprint crashed after 12 minutes when trying to format it so it's hard to know if it's better than cljfmt in this case
however, it did format a 5Mb file of varying shapes and sizes from a single line to a formatted 94k lines in 6 minutes
yeah, of course we excluded this file from formatting after we found out, but there are other cases where the problem is not a single file, but a medium/big size project, so harder to find the performance issues there
comparatively, fipp formats a set of 100k uuids in 1.3 seconds lol
why even format that large file, it's not like someone wants to open that in emacs :P
it's part of the classpath, so clojure-lsp considers it when linting/formatting, it took some time to find that file was the culprit
If anyone is interested I recently rebased my PRs for adding vertical alignment (re-implemented by weavejester, so I mostly wrote the tests IIRC): https://github.com/weavejester/cljfmt/pull/299