Comments (10)
An interesting question, thanks! I can get zprint to do what you want in some cases, but when space is tight it might not end up being what you want. An example:
(czprint i261 {:parse-string? true :fn-map {"get-by-org-id-and-items" [:guided {:guide [:element :newline :element-best-*]}]}})
(let [example (data.example/get-by-org-id-and-items
db-conn true [org-id] {:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
That's pretty much what you want, I think. But when space is tight, this is what you will get:
[I've narrowed the :width
to simulate this expression being closer to the right margin, not because I expect you would ever use a :width
that narrow.]
; :width 60
(czprint i261 {:parse-string? true :fn-map {"get-by-org-id-and-items" [:guided {:guide [:element :newline :element-best-*]}]} :width 60})
(let [example (data.example/get-by-org-id-and-items
db-conn true [org-id] {:very-long-arg-here
true})]
(some-body expressions)
(more-body expressions))
; :width 55
(czprint i261 {:parse-string? true :fn-map {"get-by-org-id-and-items" [:guided {:guide [:element :newline :element-best-*]}]} :width 55})
(let [example (data.example/get-by-org-id-and-items
db-conn true [org-id]
{:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
I'm guessing that is not what you want. I'm thinking that you want the second line to format indented under the first line (as in the first example) if the second line fits within the width, but if it doesn't fit, I'm guessing that you want just a flow:
(czprint i261 {:parse-string? true :width 55})
(let [example (data.example/get-by-org-id-and-items
db-conn
true
[org-id]
{:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
I can think of several ways to implement what I think you want. I could extend the guide
capability to allow it, I could imagine a new fn-type
which would just do it explicitly.
It sounds like you have enough big functions, that having some way to configure this sort of formatting based on function size would be useful -- so that you don't have to put each big function in the :fn-map
.
I'll look into how to do both of those things. Seems like a lot more fun than rewriting one of the complex release tests, which I'm in the middle of just now.
Your last point was, I think, if there is any way to get zprint to prefer hangs less than it does now. There are a lot of heuristics that drives the formatting to be something that looks good -- to me, at least. These are all changeable.
That said, the interactions between them are complex. Some of the more simple examples:
(czprint i261 {:parse-string? true :tuning {:hang-if-equal-flow? false} :list {:hang-size 4}})
(let [example (data.example/get-by-org-id-and-items
db-conn
true
[org-id]
{:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
The one above says that if the number of things in the hang is > 4, don't hang it.
(czprint i261 {:parse-string? true :tuning {:hang-if-equal-flow? false :hang-flow 0.7}})
(let [example
(data.example/get-by-org-id-and-items
db-conn
true
[org-id]
{:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
This one just turns down the intent to hang things. You might notice that it also didn't hang the binding for example
, so that may not be what you want.
I've demonstrated these two tunings by changing the configuration for everything. You could just change the tunings inside of specific functions to get those functions behave differently if you wanted. But it sounded like you kind of want just fewer hangs than flows. You can turn them off for all lists (which are function calls, but not binding pairs) like this:
(czprint i261 {:parse-string? true :list {:hang? false}})
(let [example (data.example/get-by-org-id-and-items
db-conn
true
[org-id]
{:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
This will affect function calls for functions that are not already in the :fn-map
. If the function is in the fn-map, then this shouldn't affect it. That might be what you want, but I kind of doubt it.
You might want to try the three things above (or with slightly different numbers) on your code base to see if it generates things that you like better. If so, great. If not, I'd be happy to work with you to find other tunings (of which there are probably 7 or 8 more), each of which interacts with some of the others, to find something that is more to your liking.
I'll work in any case on handling the long function name situation at the top of this issue.
from zprint.
Wow, what a helpful and detailed response. Love asking you questions.
It sounds like you have enough big functions, that having some way to configure this sort of formatting based on function size would be useful -- so that you don't have to put each big function in the :fn-map.
If by "big" you mean "many characters", then exactly right. We currently have roughly 4k defns in our codebase and can't possibly list all of them.
:guided
is cool. I don't see it in the reference, is it detailed somewhere else? You're right it's not exactly what I want but it's close and something built off of it would be great.
I suspect for my hang preference, I'm just looking to tweak the numbers a little to make it less aggressive, as you suggested. I'll play around with it and see what I can do!
Thank you for all the help.
from zprint.
Great! Just to be clear, the above examples require new code in the "guide" capability that will only be available when 1.2.5
is released. Which should not be that long, I'm thinking in a couple of weeks or so.
from zprint.
The whole "guide" capability is something that I built originally intending to document for general use, but it is so complex that it would take a many pages (and more than many days) to fully document it. Now, that wouldn't be terrible, since my current working notes aren't all that clear. Since I did it several years ago, I'm sometimes wondering what this or that construct does. That said, the guide I put in the above example would work in general to give you what I demonstrated there. There isn't a way to use the current guide capability to get closer to what you want, as you can't say "if this whole thing fits on a line do this, or otherwise do that", either in a guide or in an :option-fn
which would generate a specific guide for just a single situation.
I'm still thinking about where would be best to actually implement what you want. It will be at least a week before I even start on it, as I'm tied up right now, so I'm mulling it over.
from zprint.
There is truly no rush here, our code won't be hurt if it keeps looking how it's looked for the past 5 years. Thanks for all the hard work you do.
from zprint.
I've think I've got something workable here for you. It won't ever hang it, and tries to put the remainder of the function expression on the next line, but if it doesn't fit, it flows it. Some examples:
; 80 columns
(czprint i261 {:parse-string? true :fn-map {"get-by-org-id-and-items" [:guided {:guide [:element :newline :element-wrap-flow-*]}]} :width 80})
(let [example (data.example/get-by-org-id-and-items
db-conn true [org-id] {:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
; 60 columns
(czprint i261 {:parse-string? true :fn-map {"get-by-org-id-and-items" [:guided {:guide [:element :newline :element-wrap-flow-*]}]} :width 60})
(let [example
(data.example/get-by-org-id-and-items
db-conn true [org-id] {:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
; 55 columns
(czprint i261 {:parse-string? true :fn-map {"get-by-org-id-and-items" [:guided {:guide [:element :newline :element-wrap-flow-*]}]} :width 55})
(let [example (data.example/get-by-org-id-and-items
db-conn
true
[org-id]
{:very-long-arg-here true})]
(some-body expressions)
(more-body expressions))
Three different widths, with different results. How does it look to you?
I haven't started on the "configure it this way if the size of the function name is > some specified number". This is just what would happen if the function name was longer than the specified number.
from zprint.
These look good! I think it's a nice option and if I can say "use this format if symbol is longer than 20 characters", I'll put it to work immediately.
from zprint.
Gosh I wish you drove all the OSS projects I used, @kkinnear. Always learn something and feel very oddly attended-to when you I read these FRs.
(Not just here to say the above, I also would really love a max-symbol-length-hang configuration)
from zprint.
Thanks! I appreciate the good words, it makes a difference.
I'm working on the underlying capabilities for the max-symbol-length detection. It is taking longer than expected, unfortunately, as I had to re-architect the implementation of the basic :option-fn
implementation. But I'm still hoping to release it soon-ish.
from zprint.
Your third thing -- handling long function names differently, is now implemented in 1.2.5
. You have to configure a built-in :option-fn
to get what you want, but there is an example which does exactly what you asked for.
Here is the explanation from the CHANGELOG.md:
* A couple of new capabilities. Several people have wanted regular
expression capabilities in the `:fn-map`. A couple of people have also
wanted a way to format functions where the function name was over
some length differently than they are usually formatted. Both capabilities
are now available by using a built-in `:option-fn`. See `:rule-example`
(and `:regex-example`) in the `:style-map` for some worked examples. The
`:option-fn` `rulesfn` accepts a vector of pairs of elements as its
first argument. If the left-hand-side of a pair is a function, it will
call that function with the string format of the function name. If the
function returns non-nil, then the right-hand-side of the pair is returned
as the option map. If the left-hand-side of the pair is not a function,
it is assumed to be a regular expression, and it is matched against the
string format of the function name. If it matches, then the right-hand-side
of the pair is returned as the option map. The pairs in the vector are
processed in order until one of them has the right-hand-side returned
as an option map or they are all completed, in which case the `:option-fn`
returns nil.
from zprint.
Related Issues (20)
- `;!zprint {:format :skip}` removes arglist when there's zero arg HOT 1
- 1.2.5 format changes: `dissoc` HOT 3
- Slowness when pairing smaller width with long strings HOT 4
- Search for .zprintrc in XDG_CONFIG_HOME HOT 1
- Request or help if exists already - `#js` reader syntax in cljs interop HOT 9
- how do I to check or write all files recurisvely in a folder? HOT 1
- Custom Syntax Formatting: Hiccup HOT 10
- "Smart" comment changes feedback HOT 15
- Parinfer compatability HOT 2
- Vertical alignment HOT 6
- Adding Better Clojure Formatting from Tonsky HOT 8
- Keep unchanged kondo directives HOT 3
- Consider segregating justification domains between blank lines
- Reflection and auto-box warnings - wrt GraalVM HOT 4
- Enforce a space between comment character and comment HOT 1
- Allow finer configuration of how certain Objects get printed HOT 3
- Sorting :require dependencies alphabetically. HOT 24
- Errors encountered when applying multiple styles may not be reported HOT 1
- Meta formatting HOT 4
- Making exceptions for `{:force-nl? true}` in maps when destructuring HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from zprint.