Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Formatting options to enable "vertical formatting" and "grid formatting" #8197

Closed
NeilGirdhar opened this issue Oct 25, 2023 · 1 comment
Labels
formatter Related to the formatter wish Not on the current roadmap; maybe in the future

Comments

@NeilGirdhar
Copy link

NeilGirdhar commented Oct 25, 2023

I realize that this may not be a popular feature request, but it's the only thing stopping me from using Black, and I love the idea of Black, so I feel compelled to propose it. Feel free to close this as "will not implement".

Fundamentally, Black has chosen to wrap lines in one of three ways:

  • single line:
    def super_softplus(x: JaxRealArray) -> JaxRealArray:
  • hanging single line:
      def geometry_energy(
          self, intermediate_explanation: FisherMessage, observation: FisherMessage, case: int
      ) -> RivalMessageEnergy:
  • and hanging multi-line:
      def infer_explanation_variationally(
          self,
          observation: FisherMessage,
          weights: Weights,
          *,
          key: None | KeyArray = None,
          use_variational_signal_noise: bool,
      ) -> RivalMessagePrediction:

This hanging formatting like mode 3 of isort. While mode 3 is very versatile, some people consider it harder to read than isort's mode 1: "vertical" (see e.g., numpy). My proposal is to try vertical formatting to see if all lines fit without wrapping, and if so prefer that to either of the hanging outputs. Thus, for the above examples, we have:

    def geometry_energy(self,
                        intermediate_explanation: FisherMessage,
                        observation: FisherMessage,
                        case: int
                        ) -> RivalMessageEnergy:

and

    def infer_explanation_variationally(self,
                                        observation: FisherMessage,
                                        weights: Weights,
                                        *,
                                        key: None | KeyArray = None,
                                        use_variational_signal_noise: bool,
                                        ) -> RivalMessagePrediction:

Of course legibility is in the eye of the beholder, but the two points in favour of vertical layout are that:

  • The arguments sit to the right of the function call, which makes the function call more visually obvious.
  • In the case of hanging multi-line, the vertical version uses fewer lines of vertical space. Minimizing vertical space means that more code is visible on the screen, which makes reasoning about large functions a lot easier since you don't need to scroll and memorize code.
  • In the case of hanging single line, the vertical layout puts each argument on its own line, which makes them easier to distinguish without looking for commas.

I concede that when there is a line that doesn't fit within the line length, hanging is definitely superior. I'm not proposing eliminating that. I'm proposing using vertical in particular cases. In short, my proposal is to format as follows:

  • Prefer single line if possible (as before)
  • Try vertical to see if all lines can be rendered without wrapping (proposed)
  • Try hanging multi-line otherwise (as before)

This algorithm would need to applied recursively for nested structures.

I realize that Black's rules are simple, but if the goal is to write code the way humans read and write code, I think a little bit of extra complexity in the rules would go a long way to making code easier for people to read. The downside of this proposal is longer diffs, but diffs are read a lot less often than code is read as it's being worked on.

--

Edit: Similarly, it would be nice to support grid formatting as another option. This comes in handy for NumPy arrays and imports:

from ...structure import (InferenceResult, InferenceResults, ListLabeler, LoggingManager, Plot,
                          Plotter, RLInference, Solver, TrainingResult, TrainingResults,
                          TrainingSolution, chooser_field, smooth_data, ui_dataclass)

np.array([[1, ...
           2, 1],
          [1, 1, 0],
          [0, 1, 1]])
@NeilGirdhar NeilGirdhar changed the title Proposal: Formatting option for compact output Proposal: Formatting option to enable "vertical formatting" Oct 25, 2023
@MichaReiser
Copy link
Member

Thanks for this detailed issue. Supporting different "styles" (similar to docstring conventions) might be something that we want to explore in the future but is currently out of scope. There's still a lot to do on the current style: from preview style, fixing deviations, check integration, etc... and building this style took us 6 months.

But we do understand that we have different preferences and a single style doesn't satisfy the needs of everyone.

@MichaReiser MichaReiser added formatter Related to the formatter wish Not on the current roadmap; maybe in the future labels Oct 25, 2023
@MichaReiser MichaReiser closed this as not planned Won't fix, can't repro, duplicate, stale Oct 26, 2023
@NeilGirdhar NeilGirdhar changed the title Proposal: Formatting option to enable "vertical formatting" Proposal: Formatting options to enable "vertical formatting" and "grid formatting" Nov 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
formatter Related to the formatter wish Not on the current roadmap; maybe in the future
Projects
None yet
Development

No branches or pull requests

2 participants