Coder Social home page Coder Social logo

Comments (10)

kkinnear avatar kkinnear commented on July 18, 2024 1

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.

NoahTheDuke avatar NoahTheDuke commented on July 18, 2024 1

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.

kkinnear avatar kkinnear commented on July 18, 2024 1

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.

kkinnear avatar kkinnear commented on July 18, 2024

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.

NoahTheDuke avatar NoahTheDuke commented on July 18, 2024

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.

kkinnear avatar kkinnear commented on July 18, 2024

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.

NoahTheDuke avatar NoahTheDuke commented on July 18, 2024

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.

riotrah avatar riotrah commented on July 18, 2024

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.

kkinnear avatar kkinnear commented on July 18, 2024

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.

kkinnear avatar kkinnear commented on July 18, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.