Js-beautify: Support comma first style of variable declaration

Created on 23 Apr 2013  ·  27Comments  ·  Source: beautify-web/js-beautify

Allow code to be formatted like this:

var a = 1
  , b = "somethign else"
  , isAwesome = true;

And apparently, we have a somewhat ready patch available. Would be great if this can get included in here!

enhancement

All 27 comments

Considering we support both JS and Python, the patch (which is severely out of date) is incomplete, at best.

We're open to pull requests, but I personally consider "comma-first" an anti-pattern. At its core, js-beautifier is opinionated about how JS should look, with reasonable options that largely conform to widely-accepted "idiomatic" JS. Comma-first is, in my opinion, not beautiful, nor is it widely-accepted. What's more, it will severely complicate the beautifier code (which is already incredibly complicated) for very little gain.

With indent=4 set, which indentation is appropriate? From a consistency standpoint, I would argue this:

var a = 1
    , b = "foo"
    , c = false;

Which is clearly not the expected output. And how would it look with tab indents?

Where does the semi-colon live? At the end? Nowhere? (I've seen both, and more)

This gist is just as out-of-date, but makes for easier understanding of the desired change: https://gist.github.com/nemtsov/2864266/revisions

This is similar to #80, so I thought the reasons for it might be the same - easier diffing and reordering.

But in this scenario, unlike #80, there is a viable workaround that meets those requirements:

var a = 1;
var b = "foo";
var c = false;

It is slightlly more verbose, but not horrendous.

Of course, if someone implements #80, the simplest change would probably cover this scenario as well.
As @evocateur said, pull requests welcome.

@evocateur: You're entitled to your opinion and I respect that. Personally I've always disliked comma first style but throughout years, I've come to appreciate the ease of moving, taking out (commenting, deleting etc.) and as @bitwiseman says - diffing. So I'm willing to leave this as an option and let the user do whatever he prefers. Sometimes, its not in his hands and he has to go by already set standards. Yeah, fugly but reality!

@bitwiseman: At any level of indent (2 or 4), I guess this is how it should look:

var a = 1
  , b = "foo"
  , c = false;

I think this is also consistent with how some of SQL editors (where comma first is more prevalent) do it.

And while I'm not advocating promoting bad layouts, I guess there is always a fine line between being idiomatic and dogmatic (think Crockford here). Comma first may not be prevalent because many of the formatters don't support it, whatever may be their reason.

You're more familiar with the state of affairs code-wise so I perfectly agree your ROI argument. Nevertheless, I thought of asking so that we can get these things out in the open, have a quorum to discuss things and if there is demand from community, maybe you guys can rethink about it.

P.S. I spent a couple of hours trying to see if I can quickly spin off something and wasn't very successful. Maybe I'll give it a shot some other time.

@mrchief My apologies for being brusque yesterday, I was taking a break from a frustrating debugging session. You make good points, and I want to be clear that I respect your choice as well. I myself attempt to maintain the style of a given project if I'm contributing a patch (comma-first, no-semicolons, other wackiness), and I do agree that options like these can at the very least help enforce a little bit of consistency in the projects that choose to employ them.

+1. I use the comma-first pattern for it's advantages when diffing and merging.

As for the position of the semi-colon: I put it in a newline, in line with the var keyword, like this:

var a
  , b
  , c
;

I've seen several projects that use the same pattern.

Also, IMHO, i think it would be nice to be able to keep each variable in a separate line, even-though a value is not given next to the declaration. In the example above, the beautifier would group everything in one line var a, b, c; which also breaks the whole purpose of using comma fist style.

+1 for comma-first support.

At 2-space indentation, it's the tidiest way of arranging variables:

var foo = true
  , bar = 'hello'
  , something;

What about 4 spaces per tab? Actual tabs?

On Fri, Nov 8, 2013 at 9:36 AM, Luke Martin [email protected]
wrote:

+1 for comma-first support.
At 2-space indentation, it's the tidiest way of arranging variables
var foo = true
, bar = 'hello'

, something;

Reply to this email directly or view it on GitHub:
https://github.com/einars/js-beautify/issues/245#issuecomment-28081629

I guess the crux of the comma-first issue actually comes down to tab preference.

I use 2-space tabs, and comma-before is the only way to arrange variables without adding unnecessary whitespace (~ represent extra spaces added to make things line up):

// eww
var foo = true,
  ~~bar = 'hello',
  ~~something;

// yum
var foo = true
  , bar = 'hello'
  , something;

Conversely, if you use 4-space tabs, comma-before is going to look bad, and you naturally won't care about support for it.

// also eww
var foo = true
    , bar = 'hello'
    , something;

So there's discussion about comma-before being easier to comment and debug and blah blah blah. But to me, it just comes down to aesthetics. I use 2-space tabs, so I need to use comma-before. Currently I can't use beautify because I have a preference for 2-space tabs.

Now I know I'm probably in a minority, and I'm absolutely not demanding support for my little preference. I was just adding my +1 to the conversation. I might even look at adding support myself if I get the time.

Cheers :)

I would like to see this for json objects.

var a = ({
     a: 1
    ,b: 2
});

@lukemartin That is an interesting perspective! :+1:

Another +1 for comma first support, for variable declaration as well as array and objects - https://gist.github.com/isaacs/357981

I've been working on a patch to support this feature "on demand" (the user can enable or disable the option of using comma first with a setting I've created).

I've achieved the following formatting for variable declaration (using 2 spaces):

var firstVar = 1
  , secondVar = 2
  , thirdVar = 3
;

But I have some doubts.

How should we treat arrays, objects and arguments declarations? Lately I've been using the following format:

myArray = [
  item1
, item2
, item3
];

myObject = {
  prop1: 1
, prop2: 2
, prop3: 3
}

Which, as you can see, is not exactly the same as the variable declaration formatting: this last one includes a +1 indentation level for the second variable (notice the two spaces before the comma that are not present before the comma for "item2" nor for the one for "prop2"). Var declarations use this extra indentation in order to align in the same column the start of each variable name as stated by @lukemartin.

The reasons for using the formatting shown on the above code are:

1.- To avoid the linting errors that would be thrown by jshint (indentation errors). For example:

myArray = [
    item1
  , item2
];

Throws "Expected ] to have an indentation at 3, instead at 1". If we follow the suggestion, we get a very ugly result.

2.- To maintain the advantage of aligning the start of each property name, array item, etc. For example:

myArray = [
  item1
  , item2
];

Also doesn't produce a linting error, but doesn't look as nice as the examples above.

With a more clear idea of how I should treat those cases I could finish the implementation of this feature and issue a Pull Request.

Is it possible to support all the above? Everything you listed is technically "comma first".

I believe it could be possible, but it would be necessary to implement more settings that would allow the user to achieve the desired result. For example, it would be necessary to tell the formatter if you want to use 2 indentation levels for arrays, objects and arguments or just one.

I think it would be better to achieve the basic functionality first, and then extend it with more settings. I believe i would have no problem implementing those in a second patch.

As you say, basic functionality is fine. It is a _non-goal_ of this project to support _all_ formatting options. :smile:

// 2-space indents
var itemA = 1
  , itemB: 2
  , itemC: 3;

myObj = {
  itemA: 1
  , itemB: 2
}

myArray = [
  item1
  , item2
];

// 4-space indents
var itemA = 1
    , itemB: 2
    , itemC: 3;

myObj = {
    itemA: 1
    , itemB: 2
}

myArray = [
    item1
    , item2
];

These should keep your code simple, the formatting consistent no matter what indents are used, and lets us close this issue, and open a new issue for "Columnize comma-first identifiers" (or whatever) that can be spec'd and implemented separately.

I look forward to seeing your pull request!

@tgirardi Great work. Can't wait to try this out.

All Feedback welcomed :-) !!!

My idea is to adjust the code until it is considered as the correct solution and then proceed with the following TODO list:

1.- Create tests for this new feature
2.- Apply feature on the Python version (If anyone volunters for this, even better! ... I don't have much experience with python).
3.- Discuss other possible variations of comma-first styles

4-spaces indent

var x = a
    , y = b
;
obj = {
    attr1: "value1"
    , attr2: "value2"
    , attr3: "value3"
};

The variable names and attribute names need not to be lined up. This doesn't affect readability at all. In my opinion, the main reason for using column-first is to make commenting, removing and inserting lines easier. It just happens to line up when using 2-spaces indent.

The semi-column should be on its own line after the declaration of multiple variables to make it easier to append a new variable after 'y'. In this case in VIM, 'o' + ', z = c' instead of '$a,' + 'z = c'

@lewisdiamond I agree with your semi-colon comment. Having it in it's own line ensures that the last variable can also be easily edited (remove, replace, insert line after/before, etc).

But it's also been noted that:

1.- Its not the goal of the project to support all kinds of formatting.
2.- Adding too much complexity at once is a bad idea. So it could be better to keep this feature as simple as possible first and start improving it after it has reached a release state and been tested for some time

+1 for comma first support, and I agree with lewisdiamond's sentiment that ensuring tabs line up properly should not be the end goal as there are pragmatic reasons for the comma-first style. I would love support for json as well. Currently I have a hack in the global js-beautify code to do a lot of punctuation-first alternatives (for ternary operators was a must).

To everyone who +1'd this: please take a look at branch https://github.com/beautify-web/js-beautify/tree/feature/comma-first .

Tell me if this is a sufficient first step towards what you want that I should add it to the next release.

@olsonpm, @lewisdiamond, @lukemartin, @mrchief - could you guys take a look at branch https://github.com/beautify-web/js-beautify/tree/feature/comma-first .

I will spend 30 minutes on it tonight and respond with thoughts. Thanks for following up.

Got around to it this morning. It all looks good to me due to your tests. I have a personal branch with a lot of operator first functionality - I put my comma-first tests through your branch and they all passed no problem which is great news.

When I created my personal branch, I decided the comma-first operator would be passive, meaning the following:

var a,
    b;

would not be changed. You clearly stated this is not the case in the commit message, I just feel it's worth discussing with others what behavior they'd expect if they chose to use opt.comma_first.

Another thing, <Output>.previous_line and flags.previous_text are the same thing I believe, which was confusing to me at first but made sense in how you used it.

Other than that, the main difference between our implementations is that you opted to modify the previous line. I was trying not to "go back and edit things" because I thought it was more confusing to develop. Now your way is more concise than mine - it is easily read and you commented everything. The existing code also edits previous tokens so your code is perfectly in line - honestly I'm just bringing it up because I'd like to know what your thoughts are. In short, my opinion is that this program would be much easier to debug if tokens were only in charge of the white space ahead of them based on next tokens.

Thanks for addressing this!

Edit: My mistake - <Output>.previous_line and flags.previous_text are completely different.

Forward-only is preferable. I looked at the hairball of how and where we decide what to do with/about commas, there are already places that we trim the output back to get them in the right place. I decided to do something a little simplistic, get some tests in that verify the simplistic behavior and then see about tuning and refactor it later.

The example you mention:

var a,
    b;

Would be an example of tuning that could be discussed later.

Sounds good. I appreciate the feedback.

And thank you very much for looking it over. If you have any tests you want to add that would be a great help.

Was this page helpful?
0 / 5 - 0 ratings