Format attribute `# fmt: wrap-list=16` to specify format of large arrays
Is your feature request related to a problem? Please describe.
This has a design goal to solve the problem addressed in #1281, #2026, #3182: formatting of very large arrays, but in a different way than proposed.
Describe the solution you'd like
Those two issues were closed because black does not want to introduce an external argument to determine array formatting. That makes complete sense, as adding an argument would lead to fragmenting style.
Instead, I would like to suggest a format attribute where you could specify wrapping on a case-by-case basis. For example:
mylist = [ # fmt: wrap-list=16
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
]
Would be the correct output from black under this proposal. If the attribute is removed, it would do its standard formatting (13 lines). This:
- Eliminates the need to hand format arrays
- Provides a reasonable way to render things like matrices where width is important (as opposed to just wrapping at the end of a line)
- Does not require
blackto guess how to format individual blocks (https://github.com/psf/black/issues/3182#issuecomment-1215776619) - Does not introduce a new configuration option (https://github.com/psf/black/issues/1281#issuecomment-1024946991) or reformat anything that already exists
- Would likely be a net positive for commonized formatting: a) providing an alternative to hand formatting arrays means they would all be formatted consistently, and b) not being a global option means users can't turn it on for their entire project
All in all, I feel like this makes it a pretty reasonable solution.
Describe alternatives you've considered
The exact output syntax is debatable, e.g. whether to align the commas and keep equal spacing (I believe they should)
A global flag is not an option, as discussed in the linked issues.
Formatting of large arrays is a common pain point for Black users and I'm sympathetic to the issue. Thanks for coming up with an innovative solution.
However, I see some problems:
- The reason we dislike formatting options is that we want Black to be the tool that takes care of formatting for you, so that users don't have to think or argue about what formatting to use. That reasoning applies in the same way to this proposed feature: people will be able to argue about whether to use
wrap-list=16orwrap-list=15. - You don't fully specify how this would work, but it appears that
wrap-list=16would mean to put 16 items on a line with the commas aligned. How does that work if the line gets too long for the line length limit? What if there are internal line breaks within the list items?
The reason we dislike formatting options is that we want Black to be the tool that takes care of formatting for you, so that users don't have to think or argue about what formatting to use. That reasoning applies in the same way to this proposed feature: people will be able to argue about whether to use wrap-list=16 or wrap-list=15.
Yeah, I know it's not perfect in that regard. My main thought with being able to specify the count is that in many cases, there's a pretty obvious answer - like matrices or cyclic patterns. For cases where it's not obvious, I don't think there's much to do, since that would be a really bikesheddy thing for teams to fight over. Not that it couldn't happen, but I don't see it being nearly as much of an issue as with global wrap items flag.
Maybe to help this a bit, black could have the internal guideline for making examples always only use 2^n or 10 * n values, or something along those lines.
You don't fully specify how this would work, but it appears that wrap-list=16 would mean to put 16 items on a line with the commas aligned. How does that work if the line gets too long for the line length limit? What if there are internal line breaks within the list items?
For the line length, my thought was just to leave that to the user. If there's a reason for a strict limit, their linter should probably enforce it but if they just pick a bad wrap length, that's no different than doing the same thing manually within #fmt:on/off
Internal breaks and comments - I don't know, and this would likely be the source of the first few issues, if this were ever implemented. I think that in general, decisions could be made that more or less follow the current guidelines. Examples of current behavior:
# input
lst = [
"apple", # comment
"banana" # other comment
]
# output
lst = ["apple", "banana"] # comment # other comment
# input
lst = [
"apple", # comment
"banana", "cantaloupe", # some comment
]
# output
lst = [
"apple", # comment
"banana",
"cantaloupe", # some comment
]
Based on that it seems like the rule is "concat comments if combining lines, comments stay with last item if splitting lines". I think this could still be followed
# input
lst = [ # fmt:wrap-list=3
1, # 1 cmt
2, # 2 cmt
3, 4, 5, # other comment
6
]
# possible output
lst = [ # fmt:wrap-list=3
1, 2, 3, # 1 cmt # 2 cmt
4, 5, 6, # other comment
]
And long comments could get moved to the line above. I don't know about breaks, but I feel like this is kind of a niche case. Adding something like # fmt: wrap-break could do the trick, but I think that might be just a pinch beyond the minimal viable solution.
Anyway, not a thoroughly fleshed out idea, but something that would at least solve quite a few of the complaints.
Perhaps just something like a # fmt: pack that would apply to the remainder of the open comma separated sequence would be nice for this kind of case.
The presence of any other line end comments within a packed sequence should be interpreted as "leave that line alone within the sequence aside from indentation". Related: A comment on a line by itself preceding a line could be treated similarly to a trailing comment after a sequence item on a line. Preserve the comment as is other than indentation and skip reflowing that line.
I believe the point a user is trying to communicate by using such a directive is that they value vertical screen real estate over readability and line based diff-ability of changes specifically within this one sequence.
I'm intentionally side stepping ideas like "is this a sequence of values that'd look well fixed width justified" or concepts of explicitly supplying =number of items to try to fit on a line or figuring out how to reflow anything with a comment potentially mentally "attached" by just suggesting this mode look the other way and avoid modifying those.
# input
lst = [ # fmt:pack
1,
# this one is special because I said so.
2,
2.5, 2.6,
e,
3, 4, 5, # other comment
6
]
# my idea of such output
lst = [ # fmt:pack
1,
# this one is special because I said so.
2,
2.5, 2.6, e,
3, 4, 5, # other comment
6
]
The original poster's grid of numbers wouldn't look "pretty" but would be vertically compact. If automatic fixed width field spacing is desired that feels like a separate directive feature to me. I don't have a bikeshed paint color name to offer for that.
Perhaps just something like a
# fmt: packthat would apply to the remainder of the open comma separated sequence would be nice for this kind of case.在这种情况下,或许只需使用# fmt: pack这样的字样,就能适用于逗号分隔序列的剩余部分。The presence of any other line end comments within a packed sequence should be interpreted as "leave that line alone within the sequence aside from indentation". Related: A comment on a line by itself preceding a line could be treated similarly to a trailing comment after a sequence item on a line. Preserve the comment as is other than indentation and skip reflowing that line.如果在打包序列中出现任何其他行尾注释,则应解释为 "除缩进外,该行在序列中不存在"。相关:在一行之前的一行上的注释,其处理方法与在一行上的序列项之后的尾注类似。除缩进外,保留注释的原样,并跳过该行的回流。
I believe the point a user is trying to communicate by using such a directive is that they value vertical screen real estate over readability and line based diff-ability of changes specifically within this one sequence.我认为,用户使用这样的指令所要表达的意思是,他们看重的是垂直屏幕空间,而不是可读性和基于行的可变性,特别是在这个序列中的可变性。
I'm intentionally side stepping ideas like "is this a sequence of values that'd look well fixed width justified" or concepts of explicitly supplying =number of items to try to fit on a line or figuring out how to reflow anything with a comment potentially mentally "attached" by just suggesting this mode look the other way and avoid modifying those.我有意避开了 "这是否是一连串的数值,看起来很适合固定宽度对齐 "这样的想法,或明确提供 = 项目数的概念,以尝试在一行中容纳更多的项目,或找出如何回流任何可能在心理上 "附加 "注释的内容,而只是建议这种模式另辟蹊径,避免修改这些内容。
# input lst = [ # fmt:pack 1, # this one is special because I said so. 2, 2.5, 2.6, e, 3, 4, 5, # other comment 6 ] # my idea of such output lst = [ # fmt:pack 1, # this one is special because I said so. 2, 2.5, 2.6, e, 3, 4, 5, # other comment 6 ]The original poster's grid of numbers wouldn't look "pretty" but would be vertically compact. If automatic fixed width field spacing is desired that feels like a separate directive feature to me. I don't have a bikeshed paint color name to offer for that.原作者的数字网格看起来并不 "漂亮",但在垂直方向上却很紧凑。如果需要自动固定宽度的字段间距,我觉得这是一个单独的指令功能。我没有自行车棚油漆颜色的名称可以提供。
emm, I hope the style of long arrays is configurable. It's frustrating to be forced to have only one element per line.