zprint
zprint copied to clipboard
Change default behavior of .zprintrc/:search-config?
Hey there!
I feel like the current workflow for using a given project's .zprintrc
doesn't work well when dealing with multiple open source projects and contributors.
I'm trying to use zprint in a community project and finding it hard to get everyone on board with setting up $HOME/.zprintrc
(that says {:search-config? true}
). I know a solution is to move the options into a (z/set-options! ...)
call, but that then requires either always requiring that namespace everywhere zprint is used or creating some wrapper around zprint and then only using our wrapper (which then loads the options) or setting the options at the top of every file where zprint is used (and then keeping all of those in sync somehow). Another solution I just thought of is to move the file into resources/
and then read it with (clojure.edn/read-string (slurp (io/resource ".zprintrc")))
and then use that in my set-options!
call, but that likewise feels like quite the complex set of steps for something intended to be "simple".
The solution folks at my job found (before I joined) is to copy the entirety of our .zprintrc
to the user's home directory in our Dockerfile lol: COPY .zprint.edn /home/$USER/.zprint.edn
.
Given all of that, I would like it if zprint used :search-config?
for the opposite purpose: if :search-config?
is false, only use $HOME/.zprintrc
; otherwise, use the project's .zprintrc
. This would more closely align zprint with other similar formatting tools, such as prettier/black/rustfmt/etc. It would also allow for contributors to open source projects to correctly format the project's code without having to touch files outside of the project directory.
Thanks for asking, I appreciate the opportunity to try to figure out a solution for you.
I believe I understand what you would like to have changed, but I don't entirely understand the way that you are using zprint. Most people use zprint either from the pre-built binaries, the uberjar, or lein-zprint
. But you mentioned (set-options! ...)
, which doesn't fit that usage model. It would help me a lot if I had some additional overall context for how you are using zprint in your environment. In other words, I'd like to understand your workflow in more detail.
That said, I have two things to offer regarding your current proposal:
-
The
{:search-config? true}
capability came as an addition some years after zprint was first released. Since it didn't exist initially, I wasn't willing to make a behavior change that would affect people already using zprint in a way that they might not expect. That remains true today, though I have no idea how many people would actually be affected by such a change. I agree that it would have been better if zprint had first been released with{:search-config? true}
as the default behavior. -
If you are using the uberjar, or the pre-built binaries (or
lein-zprint
, though the approach would be different) for your formatting, you can get the `{:search-config? true}' behavior by specifying it on the command line:
./zprintm-1.2.4 '{:search-config? true}' <helloworld.clj
This is equivalent to having {:search-config? true}
in your ~/.zprintrc
.
That may or may not help you, but I can imagine an alias or shell script that could hide the {:search-config? true}
from people and still let them have their own options maps on the command line.
As I recall, I fixed this to work in late 2019 or early 2021, so if you are using some zprint from before 1.0.0
, this certainly won't work. I think I've fixed some minor problems with it since then as well, so you really want to be using a current version of zprint.
All that said, I would be very interested in learning more about your particular workflow so that I can perhaps offer some solution to the problem you are encountering which helps and which doesn't change the current default behavior.
Thanks for bringing this up!
I kind of mushed together multiple scenarios, so let me rephrase.
At my job we use zprint as a cli tool "as intended", so this issue doesn't come up a lot. We include in the "New Hire" docs instructions to add the "search-config" stub to the dev's HOME directory, and do some docker magic to make sure the same file is available for CI. This is very slightly annoying but overall doesn't affect anything.
In an open source project I maintain, we occasionally process csvs into individual edn files. We have roughly 2500 edn files of varying size. We use zprint as a library to correctly format the edn files at the time of creation using zprint-str
. For a couple years I was the only person who contributed so I never noticed that if someone else contributed and they don't have the "search-config" stub in their HOME directory, when they run the "consumer csv" command, it outputs edn that doesn't conform to the zprintrc file in the root of the repo. This is more annoying lol, as it requires modifying a contributor's HOME directory for a project they might only contribute once to.
So, for your open source project, I have two thoughts:
- If there is a single entry point (or maybe one or two), you can call
(set-options! ...)
with whatever configuration you want zprint to have early on in the code, and then every subsequent call to zprint will have that configuration. Then you might not need the.zprintrc
in the project directory. Even more interesting in this application (I would think), if your first call to zprint is this:(set-options! {:configured? true})
, then zprint will not look at any external files. Then if your second call to(set-options! ...)
has the configuration you want, nobody else's personal zprint configuration will affect what your use of the zprint library will see as configuration, and all of the calls tozprint-str
will use that configuration. (Actually, I think that you might be able to put:configured? true
in with your options in the first call, and it will still work, but I don't remember for sure and I don't have time to test it just now. I know that two back-to-back calls will work!) - If there isn't a single code path at entry where you can call
(set-options! ...)
, then you could define a map with the configuration you want zprint to have. Then in all of your calls to zprint, you just put the name of that(def ...)
as the third parameter of the call to zprint. Again, you don't have to have a project.zprintrc
if you do this.
It seems like one of these approaches would solve your problem, and the first one (if you can do it), would also isolate the zprint format from anyone's personal zprint configuration, which would seem like a good thing in general.
I hope that this helps!
Thanks for the reply and ideas.
The first one doesn't work quite as well because there are multiple entry points. Sometimes we generate the edn files from a single csv, sometimes we use another namespace that can process some json files, sometimes we use the existing edn to build new edn, lol. It's a mess honestly, but so far it works well.
What this means is that I can't trust that a given namespace will call set-options!
unless, like you suggest in your second idea, I dedicate a namespace to zprint config and pull that in in every namespace where zprint is used.
And to follow up on that, if I use such a namespace, I cut myself off from being able to seamlessly use the same configuration at the command line as well as in the code. I like to sanity check the edn files by running zprint from the command line sometimes (after manually editing the files or pulling in someone else's changes), as we don't have CI set up yet. If we did set it up, we'd deal with this same issue.
All that sounds doom and gloom but it's overall pretty small annoyance lol. Would just be nice to have this change (or something similar) to unify everything.
Thanks so much for the in-depth back and forth.
One more thought. If you use leiningen
, you can put :search-config? true
is the :zprint
key in your project.clj
. Then if you were to somehow create commands that were invoked with or through lein ...
, then I think you might get what you want. Maybe.