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

Newline for each item in JSON array #2716

Open
Robinfr opened this issue Aug 31, 2017 · 63 comments
Open

Newline for each item in JSON array #2716

Robinfr opened this issue Aug 31, 2017 · 63 comments
Labels
status:needs discussion Issues needing discussion and a decision to be made before action can be taken

Comments

@Robinfr
Copy link

Robinfr commented Aug 31, 2017

Is there an option to place each item in a JSON array on a new line regardless of the line of the length? I have quite a lot of the following:

[
    ["thing1"],
    ["thing2"]
]

And would like keep them this way instead of the whole thing becoming one line. I also think in general placing each item in an array on a new line is preferable.

@azz
Copy link
Member

azz commented Aug 31, 2017

I also think in general placing each item in an array on a new line is preferable.

That's a little bit tricky.

[
    ["thing1", "thing2"],
    ["thing3"]
]

would have to be formatted as

[
    [
        "thing1",
        "thing2"
    ],
    ["thing3"]
]

@Robinfr
Copy link
Author

Robinfr commented Aug 31, 2017

Yes I see what you mean. Personally I would always go for the second one, but I understand why someone would want the first one.

Is there any way this can be configurable?

@nickiaconis
Copy link

+1 to the second format @azz posted, for JS too. When paired (in JS) with trailing commas, that format leads to clean version control diffs.

I would recommend a similar format for JS object literals as well (which is why I'm looking through Prettier issues in the first place).

@lydell
Copy link
Member

lydell commented Sep 2, 2017

An idea worth discussing: What if we took the “3-or-more” rule from chained method calls and applied it to arrays (both in JS and in JSON)? One or two items would always be single-line (if it fits), while three or more items would always be multiline (even if it fits in a single line).

let a = [];
let b = [1];
let c = [1, 2];
let d = [
  1,
  2,
  3,
];

@Robinfr
Copy link
Author

Robinfr commented Sep 2, 2017

Wouldn't it be better if there was an option to choose after how many items the split happens?

@maraisr
Copy link

maraisr commented Sep 4, 2017

What about if its based on column count - ie > 80 then new line them in some sort of snake? Just thinking like, single char arrays would take up way too many lines.. Or is it more about what makes the diff prettier (no pun intended 😎)?

- [1, 2, 3, 4, 5, 6]
+ [1, 2, 3
+ , 4, 5]

🐍 version.

@azz azz added the status:needs discussion Issues needing discussion and a decision to be made before action can be taken label Sep 4, 2017
@Robinfr
Copy link
Author

Robinfr commented Sep 8, 2017

@maraisr that's also fine in my opinion. Except it should be:

[
    1, 2, 3,
    4, 5
]

@Robinfr
Copy link
Author

Robinfr commented Sep 26, 2017

I'm not sure more discussion is possible here @azz ..

@bennycode
Copy link
Contributor

Regarding new lines for array items...

I do prefer:

queryCategories() {
  return Category.query().select([
    'id',
    'color',
    'name',
  ]);
}

Over:

queryCategories() {
  return Category.query().select(['id', 'color', 'name']);
}

Reasons:

  1. Although the first example is longer, it makes it easier for me to add new array items, because they are listed one per each line which makes it easy to insert (or remove) an item by cutting (Ctrl + X) or copy & pasting (Ctrl + C & Ctrl + V) lines.
  2. There are line sorting plugins (like Lines Sorter & Sort line tools) which work by selecting the lines, that you want to have sorted, with your mouse. When taking the Prettier approach (all items within one line), you cannot select multiple lines because there is just one.
  3. Another reason why I favor the first option is because Prettier would also go that way (if the statement with the array exceed printWidth). Having sometimes array items one per each line (statement length > printWidth) and sometimes not (statement length < printWidth) doesn't look very consistent to me and leads to bigger Git diffs.

Let me give you another example...

Example A: Without Prettier

exports.down = (knex, Promise) => {
  return Promise.all([
    knex.schema.alterTable('categories', (table) => table.dropColumns('created_at', 'updated_at')),
  ]);
};

Example B: With Prettier

exports.down = (knex, Promise) => {
  return Promise.all([knex.schema.alterTable('categories', table => table.dropColumns('created_at', 'updated_at'))]);
};

It's easier to add another knex.schema.alterTable statement to Example A, don't you think so?

@suchipi
Copy link
Member

suchipi commented Oct 12, 2017

What settings are you using prettier with that output example B? Default settings output:

exports.down = (knex, Promise) => {
  return Promise.all([
    knex.schema.alterTable("categories", table =>
      table.dropColumns("created_at", "updated_at")
    )
  ]);
};

But also, for what it's worth, I would flag a Promise.all with 1 item in it in a code review anyway; I would write something like this until there were two items:

exports.down = (knex, Promise) =>
  knex.schema.alterTable("categories", table =>
    table.dropColumns("created_at", "updated_at")
  );

That's arguably a matter of preference, though (optimizing for diff vs. optimizing for now).

@bennycode
Copy link
Contributor

@suchipi: These are my Prettier settings:

{
  "bracketSpacing": false,
  "jsxBracketSameLine": false,
  "printWidth": 120,
  "requirePragma": false,
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "useTabs": false
}

I guess my example looks different than yours because I use a printWidth of 120 (instead of the recommended 80).

Regarding the Promise.all... There I like to quote Lea Verou who once wrote: "Always strive to make code that can be modified with the least number of edits".

@jeznag
Copy link

jeznag commented Nov 29, 2017

I have the opposite desire. I'd like to maximise the number of array items on one line. I have test data that looks like this. I'd much prefer to have the values array over 1-2 lines instead of 48. Any way to achieve that?

const timeIntervalData = [
  {
    timePeriod: '日',
    values: [
      1,
      1,
      1,
      1,
      1,
      2,
      2,
      2,
      2,
      2,
      2,
      2,
      2,
      2,
      2,
      2,
      2,
      0,
      0,
      0,
      0,
      2,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
    ],
    dayIndex: '0',
  },

@JounQin
Copy link
Member

JounQin commented Nov 29, 2017

A configurable option would be great. Prettier output .json is really not pretty like other json formatter tools.

@suchipi
Copy link
Member

suchipi commented Nov 29, 2017

It's unfortunate that prettier-ignore comments usually can't be used in JSON, or I'd recommend that for @jeznag's situation...

@duailibe
Copy link
Member

I don't think @jeznag's example is JSON though... he can use // prettier-ignore there.

@suchipi
Copy link
Member

suchipi commented Nov 29, 2017

Ah, you're totally right

@mmermerkaya
Copy link

Clang-Format handles this beautifully by using single-line formatting if you don't add a trailing comma, and multi-line formatting if you do.

let x = {a, b, c};
let x = {
  a,
  b,
  c,
};

Unfortunately Prettier enforces a single rule for trailing commas which makes this impossible.

@nikolaycviv
Copy link

Any further work on this? I would like to have different options available. Like @jeznag suggested, I have such array in .js file...

@j-f1
Copy link
Member

j-f1 commented Mar 18, 2018

@nikolaycviv Right now, your only option is to put a // prettier-ignore comment before the array.

@psy901
Copy link

psy901 commented Mar 23, 2018

@j-f1 Thanks for the tip!
I was having hard time watching my array being formatted like

values: [
      1,
      1,
      1,
      1,
      1,
      2,
      2,
      2,
      2,
      2,
      2,
      2,
];

now it looks better with // prettier-ignore

@dvlsg
Copy link

dvlsg commented May 14, 2018

Just to chime in with another use case, the array format rules often make Map harder to read in the code I've been writing.

For example, the following:

const map = new Map([
  [Constants.A, functionA],
  [Constants.B, functionB],
  [Constants.C, functionC],
]);

Gets turned into this (assuming the line max length is large enough):

const map = new Map([[Constants.A, functionA], [Constants.B, functionB], [Constants.C, functionC]]);

Using prettier-ignore works fine, of course, but I do find myself tossing prettier-ignore around pretty frequently when instantiating maps.

@j-f1
Copy link
Member

j-f1 commented May 14, 2018

@dvlsg That’s why we recommend using a printWidth of 80 🙂

@dvlsg
Copy link

dvlsg commented May 15, 2018

Haha, that's fair. I use 80 on any new projects I start. and I definitely prefer it. Unfortunately, the one I'm currently working on (with a team) is using 120.

Just ran across this issue while checking to see if there was a way I could hint to prettier to keep array values on separate lines without losing the rest of prettier's formatting capabilities for that chunk of code -- similar to what clang-format does with trailing commas -- and figured I'd toss my use case on the pile.

@wmakley
Copy link

wmakley commented Aug 4, 2020

Just came here due to trying to adopt prettier, being fine with most of the formatting until I hit a wall with arrays. Why are arrays not treated the same as objects? This rule is actually reducing the readability and increasing the git diffs in my code, two things that are contrary to the prettier goals.

Otherwise I am fine with almost everything prettier did to my code, and a lot of it was a readability improvement over what I was doing and I'm quite happy with it!

@guilhermetod
Copy link

That's really the only thing keeping me from using prettier. I would use it through my entire project if it wasn't for this rule, but because of it I can only see myself using it on html files.

At least let us disable it and use ESLint rules.

@ghost
Copy link

ghost commented Aug 12, 2020

In Jest the function "toMatchInlineSnapshot" uses prettier to format inline snapshots which are json-strings. My test files become unreadable because of the many newlines inserted for objects and arrays. It would be really great to be able to modify this behaviour!

@lydell
Copy link
Member

lydell commented Aug 12, 2020

@Baehn You might also be interested in #5807

@varthc
Copy link

varthc commented Oct 1, 2020

Any news/update on this? We were starting to implement Prettier in all the Angular projects we have, but this is definitely a huge problem and we had to put it on hold.
All the alternatives to solve this are hacks and the issue and workarounds impact in the readability of the code.
How hard is to be consistent and have the same rule(s) that Prettier has for multi-line objects? Serious question.

@SimonFarrugia
Copy link

I desperately need this. I have code that represents DOM structure, and need it to be readable (HTML like).

@fisker
Copy link
Member

fisker commented Nov 26, 2020

Is "json-stringfy" parser you are looking for?

@SimonFarrugia
Copy link

@fisker No I don't think so. What I have is something similar to react-hyperscript.

@rb-mwindh
Copy link

It's the same for me. I'm just trying to integrate prettier into our workflow when it turned my angular imports into oneliners. Since this messes up my git diffs, for now prettier is a no-go for me. That' s a shame.

@AndreasA
Copy link

AndreasA commented Jun 9, 2021

To be honest if it is just readability I would not care but if I have arrays with fix values that are edited by multiple persons,
it is extremely tricky to resolve a merge conflict if everything is in one line.
Whereas if it is multiple lines, most IDEs provide an easy way to resolve such conflicts and there might not even be conflicts but the single line version will nearly always have such issues.

Probably not necessary if the array has just one value though. and maybe some other scenarios too but in general the multi line approach seems safer regarding git merges.

@IT-CASADO
Copy link

For me this is also the most (if not the only) annoying issue with prettier.

And the reason to reduce merge conflicts should be enough to change this formatting rule.

Either by hard coded rule or by configuration.

@hypeJunction
Copy link

This formatting is driving me crazy. You have to be able to use git blame to see who changed what array values.

@OJFord
Copy link

OJFord commented Jul 24, 2021

I found this issue wanting the same for objects, e.g.:

import {
  One,
  Two,
} from "whatever";

becomes:

import { One, Two } from "whatever";

(with default config).

Perhaps one solution is to take after black (python formatter) and consider the manual trailing comma as a signal to keep one-per-line?

Also, another workaround - I found that adding an inline comment (any comment, doesn't have to be an ignore) inside the array/object stops it:

import {
  //
  One,
  Two,
} from "whatever";

let a = [
  //
];

@shiomax
Copy link

shiomax commented Jul 26, 2021

Also ran into this. Im working on a project that can read DPM Data Matrix Codes. So, I have test data that´s for instance a 14x14 2d array of booleans. It makes a ton more sence to arrange this as a grid instead of newlines between every element, so you can actually read it more or less. Im probably never gonna change the test data Ill just add more. But now my 14x14 arrays take up 225 lines instead of 16 and it´s virtually impossible to read as a human.

@Char2sGu
Copy link

Char2sGu commented Jul 31, 2021

Agree. It makes me really uncomfortable to see my arrays like imports in Angular be formatted into a single line!!

@NgModule({
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
  ],
})
export class AppModule {}
@NgModule({
  imports: [BrowserModule, AppRoutingModule, BrowserAnimationsModule],
})
export class AppModule {}

Why not treat multi-line arrays as multi-line objects?

@armchairdeity
Copy link

@suchipi: These are my Prettier settings:
...
Regarding the Promise.all... There I like to quote Lea Verou who once wrote: "Always strive to make code that can be modified with the least number of edits".

Not to distract too much from the actual purpose of the thread, as this is only secondarily related, but:

@suchipi - A word in agreement: I have had this exact argument, so many times, with so many other developers... about why I "over-engineered" a solution. What you said is exactly why I did so. I made it simple enough to be manageable, yet flexible enough to be moderately future-proof. There's a huge difference between something being "over-engineered" and something "flexible and powerful". I wish more software authors understood that!

So +1 to your argument that Prettier should support formatting the contents of JSON and JS arrays...

@shiomax
Copy link

shiomax commented Oct 18, 2021

A word in agreement: I have had this exact argument, so many times, with so many other developers... about why I "over-engineered" a solution. What you said is exactly why I did so. I made it simple enough to be manageable, yet flexible enough to be moderately future-proof. There's a huge difference between something being "over-engineered" and something "flexible and powerful". I wish more software authors understood that!

You´ll always have arguments about code, can´t change that. Even lookin just at myself in isolation simple enough to be manageable is a moving target. As I get more sufficient with the tools I am using at the time, more conceptionally complex things appear simple, Justifying them with the payoff they promise. There isn´t a golden formular to do things the right way. It depends. And it´s fundermentally very oppinionated in my oppinion. Therefore argue you will.

@taletski
Copy link

taletski commented Nov 7, 2021

+1 to configuring multi-line

Looks like a lot of folks are frustrated by of the absence of this feature: prettier/prettier-vscode#352

@Gregorein
Copy link

being able to configure for arrays in general would be nice, but I don't think we'll ever get that: https://prettier.io/docs/en/option-philosophy.html

@IT-CASADO
Copy link

In general I'm a big fan of the "no option philosophy".

But the current implementation of this array rule is difficult to read/resolve code in merge conflicts.

If an additional option is not an option, then prettier should think about to change the current implementation (in the next major/minor release).

@julix-unity
Copy link

What @IT-CASADO said. It's fine that it's opinionated, but this opinion is wrong based on Prettier's goals (i.e. less merge conflicts, etc.)

@electrovir
Copy link

I just published a plugin that achieves this: prettier-plugin-multiline-arrays. It works on TypeScript, JavaScript, and JSON.

@Robinfr by setting the multilineArrayWrapThreshold option in your prettierrc file to 1, you can achieve your exact desired formatting from your original message.

@lydell you can achieve wrapping at more than 2 elements ("3 or more") by setting the multilineArrayWrapThreshold option in your prettierrc file to 2.

You can explicitly control the number of elements per line as well with a // prettier-elements-per-line: 1 2 3 comment or multilineArrayElementsPerLine config value. (I find this particularly helpful when working with a static 2d array of numbers.) See the readme for details and exact syntax.

@baerrach
Copy link

baerrach commented Feb 9, 2022

@electrovir

I had no idea that plugins was a thing in prettier.

This is a decent compromise if this feature won't get put into core.
Thanks for putting it together.

@varthc
Copy link

varthc commented Feb 9, 2022

@electrovir thanks very much for the plugin! I'll try it when I come back from vacations.
We forked prettier to solve this issue, but I think your plugin if it works in our projects, it's the right way to go. Thanks again!

@lppedd
Copy link

lppedd commented Oct 16, 2023

The mentioned plugin seems stuck trying to adapt to Prettier v3.
Since Prettier maintainers do not seem to like it in the main repo, it would be nice if we could get it (again) as a plugin, so I think it would be useful for the plugin author to get some "official" help.

@electrovir
Copy link

electrovir commented Oct 26, 2023

FYI (@lppedd) prettier-plugin-multiline-arrays now supports Prettier v3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:needs discussion Issues needing discussion and a decision to be made before action can be taken
Projects
None yet
Development

No branches or pull requests