fredrikekre/Runic.jl

Automatic line breaking

Opened this issue · 6 comments

Note that currently there is no line-length limit employed so expressions that only take up a single line, even if they are long, are not formatted like the above. Thus, only expressions where the original author have "committed" to mulitples lines are affected by this rule.

Is this planned soon? For me, one reason to use an automatic formatter is that auto-formatted code immediately matched my expectations. Having to manually reformat lines that are too long defeats this purpose a bit.

Also, without automatic line breaks, we would end up with PR comments like "please split this long line", which were the main reason why we introduced automatic formatting in the first place. A strict line length limit in the CI check wouldn't work, as some lines (like comments containing long URLs) might not be possible to break.

A really cool feature would be what JuliaFormatter does in the SciML style:

julia> str2 = """
       some_function(some_argument, another_argument, foo, bar, more_foo, more_bar, even_more, more, more, more)
       """;

julia> println(format_text(str2, SciMLStyle()))
some_function(some_argument, another_argument, foo, bar,
    more_foo, more_bar, even_more, more, more, more)

It's not a greedy line break at the point where it's exceeding the limit, but there is some balancing logic going on to avoid this:

some_function(some_argument, another_argument, foo, bar, more_foo, more_bar, even_more, more, more,
    more)

Is this planned soon?

There is no plan, much less a timeline 🙂

For me, one reason to use an automatic formatter is that auto-formatted code immediately matched my expectations. Having to manually reformat lines that are too long defeats this purpose a bit.

Yea, this is a fair point. Personally I naturally line break when lines become too long based on editor guidelines so I never really end up with long lines to begin with. gofmt doesn't impose a line limit, and I kind of like that it gives the power to the author where to put line breaks, but I am also pretty strict with not overflowing 92 myself, so it is probably a good idea to let the formatter enforce it... Another reason I haven't even tried implementing this yet is that I think it would probably be the most difficult part of the formatter. Perhaps limiting the scope of what to break automatically would be a path forward.

I have thought about having a line length limit based on something like max(X - indent_level * 4, Y) (with X = 92 and Y = 50 or something like that) so that there is always at least Y columns to work with when nesting becomes too deep. Such deep nesting is very rare anyways, so in practice this would make the limit 92.

If this is implemented I would also only break lines where there already are natural breakpoints, for example, I don't think automatically splitting strings (or comments) should be done. In practice I think line overflows is mostly happening in long function calls or function signatures, so that shouldn't be too difficult to implement as a starting point.

A really cool feature would be what JuliaFormatter does in the SciML style:

Okay, I don't know if such balancing is better in general, perhaps you have something like

functioncall(foo1, foo2, foo3, bar1, bar2, bar3, baz1, baz2)

and if such a line is balanced it would become e.g.

functioncall(
    foo1, foo2, foo3, bar1,
    bar2, bar3, baz1, baz2
)

If the formatter does this you realize the line was too long, but you rather want to keep the bar arguments connected, so you reformat manually into

functioncall(
    foo1, foo2, foo3, bar1, bar2, bar3,
    baz1, baz2
)

(would JuliaFormatter keep this as is or is balancing always enforced also on lines that don't overflow?).
In this situation I would be perfectly happy with having the formatter do

functioncall(
    foo1, foo2, foo3, bar1, bar2, bar3, baz1,
    baz2
)

and then manually format into

functioncall(
    foo1, foo2, foo3, bar1, bar2, bar3,
    baz1, baz2
)

Perhaps this isn't such a common case though, but I kind of like the simplicity of not trying to guess or do balancing.

(would JuliaFormatter keep this as is or is balancing always enforced also on lines that don't overflow?).

It will keep manually broken lines, only balancing while automatically breaking a line.

As an alternative first step, perhaps the --check mode (or a new --check --strict mode) could error on overlong lines. This would cause CI to fail and there would be no review-argumentation about it at least. Perhaps this could be useful even if lines in some contexts are split automaticall as discussed above. For example, I am not sure it is feasible to automatically split things like (doc)strings in a good way.

Our current JuliaFormatter check passes when overlong lines are not split by JuliaFormatter, i.e. when the overlong lines are comments, docstrings or some weird constructs that cannot be split properly to fit into the limit.
That's why a hard check by an external tool without considering the context would not be feasible.

But what I mean is that e.g. a string can be split (by a human) so if CI fails it would be something you would have to fix, but Runic wouldn't do it for you.

Yes, I just wanted to say that this will require some complex logic as well (could this line be split?).