Format if condition multiline

Is there a way to format an if statement that the or and keyword go to the beginning of the line instead of the end?
So instead of

if (something_long or
    something_other_long or
    next_long)

do this:

if (something_long
    or something_other_long
    or next_long)

The autoformatter always chooses the first but I really like the second.

4 Likes

I don’t believe so, at least not without altering the formatter code yourself which is probably not what you had in mind with this question.

If I have learned one thing with programming languages, it simply causes friction to not embrace the conventional style, regardless of personal opinions. I have definitely adopted the “do as the Romans do” mentality when it comes to language conventions and formatters.

(I prefer the second style too)

7 Likes

I agree that accepting the ways of the formatter is probably best, but there’s always the possibility to temporarily disable zig fmt from inside your code:

switch (cond) {
// zig fmt: off
    .one_thing               => foo(),
    .another_thing           => bar(),
    .something_else_entirely => baz(),
// zig fmt: on
}
1 Like

FWIW I also started to prefer putting the boolean operators at the front of the line, it is more readable than the ‘traditional’ way (IMHO). I wouldn’t mind this becoming the standard formatting in zig fmt.

10 Likes

I don’t mind putting the “or” an the end… I did not know this behaviour and I was wondering why it was putting all the condition on the same line.
My opinion is one should not have to adjust the code according to the desired formatting. The formatter should format the code according to the expression tree.

Welcome to Ziggit @houdelou!

The issue can be forced by sticking a comment at the end:

if (someThing() //
   or someThingElse() //
   or yetAnotherThing()) {
    // ...
   }

But this is ugly. Personally I also favor ‘conjunction first’ logical statements over the trailing kind, I also wouldn’t mind seeing that become the standard.

But it seems to be one of those things where people tend to see one, or the other, as ‘obviously correct’, so I doubt we can please everyone in this matter.

Normalizing the statement to whichever pattern is seen first (so if (a or \n b) is trailing and if (a \n or b) is leading) is at least possible, but I could see that surprising users, at least at first.

5 Likes

Thanks ! The expected behavior of the formatter would be to always format the same way. Currently, depending on how you write the statement, it can change the result. You could end up having different formats on the same project based on how the developer wrote the code.

1 Like

A good description of the issue.

One of the better things about zig fmt is how trailing commas are used to dictate single-line vs. multi-line formatting. Unfortunately, there’s no visible character which could be used to control trailing conjunction vs. leading conjunction.

I agree that it’s better if a codebase uses only one of those conventions, rather than mixing them up (unlike single vs. multi line). Which would be the result if the formatter were to pick a style based on the existing whitespace.

I prefer leading conjunction because I find that it makes complex logic easier to understand. However, I must assume that those who favor trailing conjunction feel the same way about their preference. The important part of having a built-in formatter is that it makes code consistent; the details of how it does so are less important, IMHO.

2 Likes

I think this is a case where I would like editors to have a feature of “projectional editing”, basically allowing the user to view it either way (and have that be part of their persistent editor state) while still saving it in the canonical/normalized way.

4 Likes

This could be extended to the entire formatting… have one canonical style which is enforced by the Zig compiler, and then format to a personal style on loading into the editor, and convert to canonical style on save. Especially useful for highly controversial topics like brace-style or tabs-vs-spaces :wink:

…of course not as simple as it sounds, since the editor also needs to be able to map line numbers in error messages between the canonical and personal style, and across all tools (e.g. also debugging, diffing, etc…).

4 Likes

How would you deal with git, then. Especially if you use editors that show changes in the gutter, they would compare the buffer to the saved file. I was kind of planning to edit zig fmt at least for my personal use, I don’t see anything wrong in having your own formatting style.

Complex conditionals involving logical operators are often hard to understand. Breaking such statements into iterative steps make them easier to follow:

    const condition = blk: {
        if (something_long) break :blk true;
        if (something_other_long) break :blk true;
        if (next_long) break :blk true;
        break :blk false;
    };
    if (condition) {
        // ...
    }
1 Like

Yeah that’s the problem. Git itself would need to work on the canonical style of course, but diff-visualizations need to be mapped back to the personal style (maybe similar to how you can select between white-space-changes being visible or invisible in diff-visualizations)

I don’t see anything wrong in having your own formatting style.

It’s not a big deal of course, but adds friction for people who prefer a different formatting style. E.g. if a seemless support for a ‘personal vs canonical’ style can’t be implemented, I would prefer the canonical style everywhere… as long as it uses the 1-true-brace-style of course, because any other brace style is completely unacceptable for any civilized human being :wink:

1 Like

Yuck! :smiley: At least get rid of that ugly block, I also find the if-sequence harder to parse than a boolean expression tbh…

    const any_true = something_long
        or something_other_long
        or next_long;
    if (any_true) {
         // ...
    }

…and if the boolean expression gets too complicated I would rather split that up into multiple booleans with descriptive names:

    const is_apple = ...;
    const is_orange = ...;
    if (is_apple or is_orange) {
        // ....
    }

No no no. I like space and symmetry.
Braces on a new line for example is perfectly readable for everyone.
Some people like larger indent or more empty lines etc. etc.
I prefer personal style above “the style the whole world should use”.
More individual, more recognizable. I would even say that could have benefits in a company, as long as we stay rational of course.

All my files start with
zig fmt: off

2 Likes

Heathen! :smiley:

PS: My ‘entirely objective’ reasoning for preferring 1tbs is that vertical space is more valuable than horizontal space on common landscape-oriented displays :wink: FWIW until the 2010s I also used to place curly braces on their own lines, but then slowly transitioned to 1tbs (in my hobby projects, while at work still being stuck with the ‘Allman style’ until around 2020)

3 Likes

A lot of times the logic needs to be short-circuited so we can’t just break it down into multiple booleans.

Personally, I’m absolutely not a fan of the current block syntax. A construct used so frequently ought to have a proper keyword (“do” being a good candidate). Using a non-functional label as a pseudo-keyword is just plain silly.

Imho it wouldn’t be a big issue, for example if zig fmt allowed switches for formatting options, the same formatting style would be enforced on a single repo by the owners. It would allow higher degree of consistence than having people totally ignoring zig fmt just because they don’t like something about it.

Then, I don’t think we’re talking about clang-format level of options, since clang-format works for different languages and their conventions. Personally I would only care about braces style and maybe maximum width (assuming that the OP issue would be handled by default because I consider it objectively better).

2 Likes

I am strongly in favor of a language enforcing a standardized style in its formatter (or even community conventions), even if it goes against my own preferences. It seems easier to get accustomed to different styles for different languages than it is to have a crap-shoot of different styles for the same language. Different languages each have their own look and feel to the code, but is far more jarring to my simple mind to see [insert language name] with a format that goes against what I would expect from it.

For example, I am a strong advocate for the One True Brace Style™, but if I am writing or reading C#, I both use and expect Allman style braces on separate lines, and would even say that my preferred style seems out of place and “wrong” in that language.

That said, I think we can all agree that Go is objectively wrong in its decision to have no whitespace around mathematical operators.

3 Likes

Certain enforced styles are bad for me. For example compare

if (true) {
    // code
} else if {
    // code
} else {
    // code
}

with

if (true) {
    // code
}
else if {
    // code
}
else {
    // code
}

In C the first form makes more sense, but only with indentation of 8

if (true) {
        // code
} else if {
        // code
} else {
        // code
}

There you can see clearly the else branch even with the brace before, but not in Zig or with an indentation of 4.

I’ll always prefer a style where I feel comfortable.