rust-lang / rustfmt

Format Rust code
https://rust-lang.github.io/rustfmt/
Apache License 2.0
6.04k stars 888 forks source link

Discussion: `hard_tab = true` by default for accessibility #4067

Closed louy2 closed 4 years ago

louy2 commented 4 years ago

Accessibility means accepting that code should look differently according to different needs.

I have changed my stance completely on tab vs space after reading this reddit post describing accessibility problems with space indentation. I believe it is worthwhile to change the default to using hard_tab = true for the accessibility benefit. As a reference, go fmt by default uses tab to indent as well.

I know this is not without dispute, and even if we all agree on this, we need a plan and it will be a time and labor consuming transition. So I want to start a discussion and see what we all think about this. What problems do you have with either option? What problems do you have now? What problems do you think you would have during the transition?

I believe the accessibility benefit would outweigh the cost. Parsing Rust is whitespace agnostic, unlike Haskell or Python, so I do not think it would break code, which helps. On the other hand, it may make some bugs more prominent, e.g. #3148 is a bug with hard_tabs we have not fixed.

Using terms @nrc developed in #1081, this is only related to block indent, not visual indent (alignment).

calebcartwright commented 4 years ago

There was extensive discussion on this topic in https://github.com/rust-dev-tools/fmt-rfcs/issues/1 that resulted in the decision for hard_tabs to be false, also re-affirmed in https://github.com/rust-dev-tools/fmt-rfcs/issues/106, so I personally doubt this will be changed (just my two cents)

louy2 commented 4 years ago

Thank you so much for the pointers!

louy2 commented 4 years ago

Thank you very much for the pointers!

From what I have read, @nrc started rust-dev-tools/fmt-rfcs#1 to determine a default indentation width in the first place, and due to the consistency preference @nrc already favored space.

In the entire thread, "accessibility" is never mentioned; "visually impaired" is only mentioned once by @Alex-PK, carelessly dismissed by @ssokolow with "Can we get a genuine visually-impaired person to comment on this?", and forgotten since. With the reddit post, we have a second-hand account of visually impaired people's comment on tab vs space. People with different visual difficulties need very different tab widths. I believe it is time for us to invite more people from the visually impaired community into the discussion and reassess the influence of the current default on their participation.

I share your doubt that it will be difficult to change this. But the accessibility community is no stranger to such challenges, from accessible public transit to accessible workplaces. I have confidence that the indentation challenge is not larger than those. In the meantime, I will participate in the support of tabs as @nrc called for.

ssokolow commented 4 years ago

I never intended it to be casual dismissal. I honestly want input from someone who actually needs this, rather than second-hand input or even possibly just guesses by people with a personal preference for tabs.

That aside, isn't the purpose of something like rustfmt to be powerful enough that a person with a visual impairment could plumb things together so that it could automatically reformat to hard tabs on checkout, then reformat to whatever the project calls for on checkin? Wouldn't that be a more optimal solution, given that many projects are likely to override any hard_tab = true default? (Sort of like how Git has built-in support for doing LF↔CRLF conversion when a Windows user checks out a repo.)

louy2 commented 4 years ago

I am sorry I characterized your question a bit too harshly. But I know if I want feedback from people with any disabilities I almost always have to actively look for them in addition to asking. People with visual difficulties already have more trouble learning to program, accessing code and contributing to projects. Asking them to compose some plumbing on top of that only serves to dissuade more of them, and partly why we could not even find one of them for comments.

The purpose of rustfmt is first of all an enforceable standard style. Therefore, I want first of all a more inclusive standard style. For the same reason, the power of rustfmt should be first of all enforcing a change to the standard. The power to deviate from the standard should be second to that.

Something like LF↔CRLF conversion definitely helps during the transition, or if the more inclusive style is not agreed upon as the standard.

ssokolow commented 4 years ago

I am sorry I characterized your question a bit too harshly. But I know if I want feedback from people with any disabilities I almost always have to actively look for them in addition to asking. People with visual difficulties already have more trouble learning to program, accessing code and contributing to projects.

Fair enough. In hindsight, I was also feeling irritable and let myself be more blunt than I should have been.

At minimum, I should have phrased it more like this:

It seems questionable that someone using a monospace font would be able to distinguish between individual letters like a and e, yet would simultaneously have difficulty with indents that default to four times that width. I'd think, before indentation becomes a problem, they would increase their font size, which would also remedy any problems with the indent. (Including increasing the line height.) Do we have any citations or participants with visual disabilities who can elaborate on this?


Asking them to compose some plumbing on top of that only serves to dissuade more of them, and partly why we could not even find one of them for comments.

But that makes an assumption about how willing people will be to stick to the rustfmt defaults, which could leave everyone more inconvenienced and people with visual disabilities still having to cut together a solution to translate between project defaults and their needs.

People switched away from tabs for good reason: Because the ecosystem had multiple decades to come up with a solution and it's still an unreliable mess to get rendering of tabs in agreement across all sorts of different things.

Not to mention that most applications don't obey things like .editorconfig, Vim modelines, and emacs file variables, so you wind up with the default, very unappealing 8-space definition of tabs.

That's why you wound up with things like set ts=8 sts=4 sw=4 in Vim, which renders tabs as 8 characters wide (so alignment doesn't fall to pieces when exchanging documents between editors) and then uses 4-space indent... and, if expandtab isn't set, then it mixes tabs and spaces to achieve that... which will, again, blow up if anyone sets a tab width other than 8 because Vim isn't smart enough to switch from tabs to spaces where semantic indentation gives way to alignment indentation.

It'd be much better to just cook up and clearly document an official accessibility solution which works everywhere, comparable to how Firefox's "Language and Appearance" preferences have an "Allow pages to choose their own fonts, instead of your selections above" checkbox you can uncheck and an "Override the colours specified by the page with your selections above" dropdown which defaults to "Only with High Contrast themes" and can be switched to "Always".

The purpose of rustfmt is first of all an enforceable standard style. Therefore, I want first of all a more inclusive standard style. For the same reason, the power of rustfmt should be first of all enforcing a change to the standard. The power to deviate from the standard should be second to that.

Note this line from my original concern:

Sort of like how, when JSLint got too opinionated, JSHint got forked and JSLint waned

Using tabs produces real problems for the majority with normal vision and, if you try to force them without a proper solution, you run the risk of seeing either a ton of rustfmt.toml use, rustfmt forks, or people being reluctant to use rustfmt, depending on how difficult it is to circumvent.

louy2 commented 4 years ago

People switched away from tabs for good reason: Because the ecosystem had multiple decades to come up with a solution and it's still an unreliable mess to get rendering of tabs in agreement across all sorts of different things.

That's the common narrative, and I'd like to question it. Why is "get rendering of tabs in agreement across all sorts of different things" the goal in the first place? Personally I only want my indentations to be consistent. I just have not realized until now that consistency is unrelated to the width. I am fine with 8-space tabs.

My theory is that a vocal minority who align variables beautifully, who regard their code as "art" and insist on seeing it the same everywhere, cared about their code deeply enough to have made the first wave of automatic code formatters to enforce their styles across their projects. They valued consistency first, so they chose space. Then projects pick up those tools appreciating the consistency, but not caring much about the indentation width. Unfortunately, they then leave the silent minority who need to customize indentation width behind.

It'd be much better to just cook up and clearly document an official accessibility solution which works everywhere

Yes! I totally agree. But let's look at your example:

"Allow pages to choose their own fonts, instead of your selections above" checkbox you can uncheck

We can choose our tabstops. The checkbox exists, in the form of whether I enable EditorConfig or not. But it doesn't work. Using space is like using 𝔉𝔒𝔑𝔗 ("font" in Mathematical Fraktur Capital unicode). You cannot customize what is not specified in metadata.

Using tabs produces real problems for the majority with normal vision

The Golang community is a glaring counterexample to this assertion. go fmt is the only formatter using tab by default to my knowledge, and to this day no alternative has gained popularity.

https://github.com/golang/go/issues/19618

In 2012 Fireside chat the Go team mentioned explicitly that they chose tab because tabstop can be personalized.

Robert Griesemer: [...] But then when it comes to indentation, I thought, everybody has a different style, and ideally, it would be great if everybody could just look at the code the way they want to look at it in their editor. [...] Rob Pike: I know Ken uses eight-space tabs and I use four-space tabs. -- https://www.quora.com/Why-does-Go-go-fmt-uses-tabs-instead-of-whitespaces/answer/Josh-Hoak

when JSLint got too opinionated, JSHint got forked and JSLint waned

You are correct in the case of linters. But rustfmt is a formatter, not a linter. JSLint is analogous to clippy and go lint. Instead of "fire and forget", the user has to additionally fix the reported errors, and pick out false positives or disable common false positives in an audit beforehand. The additional work drives people to configure a linter much more than a formatter. While go fmt doesn't have notable alternatives, go lint has revive as an alternative.

I agree that rustfmt should not be too opinionated, lest people make alternatives. But from what people are complaining, indentation is not where the contention is at:

rustfmt blindly makes big formatting changes, like forced line wrapping and unwrapping, which changes the layout of the code, and destroys visual grouping. -- kronel

I see you were in that thread too. So you know rustfmt is already opinionated enough for them to plan an alternative.

Therefore the relation table is:

Tool Default Status
Prettier space popular with competitors
rustfmt space ubiquitous with alternative planned
gofmt tab ubiquitous without notable alternatives

I should caution that no causation can be derived from the table, but at least it shows no correlation between using tab as default and having alternatives.

ssokolow commented 4 years ago

I am fine with 8-space tabs.

Evidence seems to suggest that you are in a small minority, as 4-spaces seems to be the "old standard" for anything still in major use that's newer than C or Bourne shell script, with languages that settled on standard styles later (either as younger languages or as languages new to automatic reformatting) typically opting to develop conventions built around 2-space indent steps instead.

My theory is that a vocal minority who align variables beautifully, who regard their code as "art" and insist on seeing it the same everywhere, cared about their code deeply enough to have made the first wave of automatic code formatters to enforce their styles across their projects. They valued consistency first, so they chose space. Then projects pick up those tools appreciating the consistency, but not caring much about the indentation width. Unfortunately, they then leave the silent minority who need to customize indentation width behind.

Here is a sampling of all the code formatters I'm aware of, young and old, across a wide range of languages. I think the patterns which show up in it across such a wide range of languages, which were developed and/or came to automatic styling at widely varying times, should call your hypothesis into question:

  1. The Artistic Style code formatter for C, C++, C++/CLI, Objective‑C, C#, and Java not only defaults to 4-space indent, it specifically claims to have been written to deal with real-world unreadability caused by exchanging tab-using source code between differently-configured editors.
  2. The Prettier code formatter for JavaScript (Plain, JSX, Flow), TypeScript, JSON, HTML (Plain, Vue, Angular), CSS, Less, SCSS, GraphQL, Markdown, YAML, and various third-party plugins for languages like Apex, Java, PHP, Ruby, and XML defaults to 2-space indent.
  3. The Uncrustify code formatter for C, C++, C#, ObjectiveC, D, Java, Pawn, and VALA appears to have no default style, but the example configuration file provided seems to request that all tabs be interpreted as 8-spaces wide, then squashed down to 3-space indent steps.
  4. clang-format, like Uncrustify, appears to have no default style.
  5. cmake_format defaults to 2-space indent and the docs show no configuration option to switch from spaces to tabs for indenting.
  6. The dartfmt/dart_style formatter follows the Dart style guide, but has authoritative indentation policy delegated back to it. It is adamant that you should use spaces and appears to default to 2-space indentation.
  7. dfmt for the D language defaults to 4-space indent.
  8. Elm's elm-format follows the official Elm Style Guide with no options to reconfigure it. The result is 4-space indent with 2-space in certain special cases.
  9. fprettify for Fortran 90 defaults to 3-space indent. (And the Fortran company's style guide says "Indent blocks a consistent number of spaces (such as 2, 3, or 4).")
  10. Haskell's hindent defaults to 2-space indentation. . The HTB HTML/XML/XSL Beautifier defaults to 3-space indent.
  11. HTML Tidy defaults to 2-space indent.
  12. The JEDI code formatter for Delphi Object Pascal uses 2-space indents, as specified by the style guide that Embarcadero inherited from Borland. The style guide used for the Free Pascal standard library agrees, and, for Lazarus, it actually points people at the Borland Delphi one. The GNU Pascal style guide is adamant about using spaces, not tabs, but doesn't try to dictate how many.
  13. The perlstyle style guide (also installed as a manpage) calls for "4-column indent" and the perltidy code formatter defaults to following that.
  14. The PEP8 style guide for the Python standard library, which the Python ecosystem has chosen to use as equivalent to rustfmt's defaults, calls for 4-space indentation. The autopep8 code formatter defaults to this. The Black code formatter prides itself on being "uncompromising", meaning that you can't enable tab-based indenting. (There's also pycodestyle, which is a style linter but not a reformatter, which used to be called pep8.)
  15. The qmlfmt formatter for QML has only two options dealing with indenting... one which controls how many spaces to use for an indent level, and one controls how many spaces to replace each Tab with. (Both default to 4)
  16. Hadley Wickham's R Style Guide calls for 2-space indent and that's what the lintr style linter follows. The tidyverse R style guide also calls for 2-space indent and that's what the styler reformatter follows.
  17. The Ruby Style Guide says "Use only spaces for indentation. No hard tabs." and calls for 2-space indents. This is what RuboCop defaults to following. I haven't been able to get a solid answer on what cookstyle for Chef manifests formats to without installing it, but it's built on RuboCop, so it's likely to be the same.
  18. scalafmt for Scala defaults to 2-space indentation at the call site and 4-space indentation at the definition site, with no option to switch to tabs.
  19. pgFormatter for PostgreSQL-dialect SQL defaults to 4-space indent any the only option I could find is to change the number of spaces.
  20. refmt for Reason doesn't seem to have readily available docs, but documents like this one appear to indicate that it will produce 2-space indentation if enabled.
  21. sqlfmt uses 2-space indentation and appears to have no configuration options.
  22. sqlparse.format() defaults to 2-space indent.
  23. Google and raywenderlich both call for spaces over tabs in their Swift style guides, and Google's guide claims to be based on the style Apple uses within Swift's standard library. None of the code formatters document their defaults well, but Apple's swift-format appears to specify 2-space indentation, while SwiftFormat looks to be specifying 4-space indentation.

...and I went through the popular ALE plugin for Vim to make sure I wasn't missing anything popular. Those are all the tools ALE supports which I was able to identify as caring about code style and which have an opinion on tabs vs. spaces, plus a few more it doesn't. (Some, like clang-format, appear to have no default style and require you to read through a configuration guide before you can use them.)

The recurring theme is "indent with 2, 3, or 4 spaces".

The exceptions which, by their rarity, seem to support my point, are gofmt, shfmt, and https://beautifier.io/

shfmt makes sense in context with the modern C beautifiers generally refusing to choose a default, given that Bourne shell and C are ancient enough to come from the era when tab-based indentation was king. As for beautifier.io, it appears to default to tabs merely because the browser's drop-down widget defaults to the first entry when no preference for a selected entry is specified and the entries are sorted by their values, the number of bytes per indent step, in ascending order.

We can choose our tabstops. The checkbox exists, in the form of whether I enable EditorConfig or not. But it doesn't work. Using space is like using 𝔉𝔒𝔑𝔗 ("font" in Mathematical Fraktur Capital unicode). You cannot customize what is not specified in metadata.

My point is that you're always going to see projects either overriding the rustfmt defaults or refusing to use rustfmt if that's not possible. It makes more sense to make a solid, easy-to-use way for those with accessibility needs to use rustfmt as some kind of load/save or checkout/checkin filter.

That is the equivalent to Firefox's accessibility settings when considered based on reliability.

The Golang community is a glaring counterexample to this assertion. go fmt is the only formatter using tab by default to my knowledge, and to this day no alternative has gained popularity.

One case isn't exactly a powerful argument... especially when the design goals of the language, and resulting decisions such as the lack of generics and the late arrival of proper package management, may be inducing a bias such that its community preferentially selects itself for people willing to adapt themselves to the language. (Never underestimate the lasting power of the seed users to shape the user base demographics going forward. Google found that out the hard way with Google+.)

In 2012 Fireside chat the Go team mentioned explicitly that they chose tab because tabstop can be personalized.

Except that you're generalizing from the example of a language ecosystem built around a non-configurable formatter and aggressive code conformity. That's not likely to be representative of the rest of things.

(It causes enough trouble when incoming C and C++ programmers don't understand how important memory-safety and avoiding undefined behaviour are to existing Rust community members. I strongly suspect there's some self-selection going on which is pre-emptively avoiding the friction which would produce a gofmt fork.)

I agree that rustfmt should not be too opinionated, lest people make alternatives. But from what people are complaining, indentation is not where the contention is at:

I wouldn't expect it to be. The hard_tab and tab_spaces options for rustfmt.toml exist.

calebcartwright commented 4 years ago

I share your doubt that it will be difficult to change this. But the accessibility community is no stranger to such challenges, from accessible public transit to accessible workplaces. I have confidence that the indentation challenge is not larger than those

@louy2 - To clarify my comment.. IMHO rustfmt is highly unlikely to change the default to tabs because the decision on tabs vs. spaces default has been a closed matter for nearly 3 years. As summarized at the end of https://github.com/rust-dev-tools/fmt-rfcs/issues/1#issuecomment-288847963:

With regards to tabs vs spaces, the matter is settled - there is pretty strong (though obviously not unanimous) consensus in the Rust community in favour of spaces, and we've discussed here the objective benefits of the two approaches, as best we can. I firmly believe that at this point there is no possibility of changing this decision, so it's not really worth discussing further.

To summarise:

the style guide will recommend using spaces and not tabs, Rustfmt will use spaces by default, Rustfmt will continue to support tabs as an option, so if you are a tabs supporter you will still be able to use Rustfmt, just with some minimal configuration.

If you'd like to attempt to change that decision, I'd suggest opening a new issue in https://github.com/rust-dev-tools/fmt-rfcs/ because it's a highly contentious topic and making such a change would have a widespread impact.

louy2 commented 4 years ago

@ssokolow Thank you so much for showing me all the resources! This is what I like about the Rust community. We share what we learn.

That said, I feel like I am not fully understood, and we are talking past each other a bit. Let me try to clarify myself a bit more. I am not disputing that the majority of the code formatters are using space. In the very quote you quoted I said:

[...] who regard their code as "art" [...] the first wave of automatic code formatters to enforce their styles across their projects. They valued consistency first, so they chose space. [emphasis added]

I totally agree with your finding, and thank you again for looking into it for me. Indeed, we have authors who outright name the formatter "Artistic", and most of the style guides and formatters choose space for a consistent look.

The majority of the programming community has bought into these tools because they prefer consistency to mixed tab and space.

To solve mixed space and tab, the formatters need to indent either consistently with space or consistently with tab. For the implementers of the formatters, if they care much about alignment as well as indentation, because alignment uses space inevitably, it is much easier to implement with only space. #1081 shows an example of how the hard_tab option can complicate implementation. That's another reason for the implementers to prefer space to tab.

I take this for granted: Everyone prefers consistency to mixed tab and space.

From the observation: The implementers of formatters prefer space to tab. I'd like to note that the implementers are only a minority of the programming community. That's the whole point of distributing such a tool, after all.

Not observed: The majority of the programming community prefers space to tab. I simply hypothesize that most people do not hold a strong preference over this matter for them to change the default setting. Which also answers your doubt:

My point is that you're always going to see projects either overriding the rustfmt defaults or refusing to use rustfmt if that's not possible.

I'd like to note that you are also "[making] an assumption about how willing people will be to stick to the rustfmt defaults." I assume most people follow the default from the anchor effect of behavioral economics, while you assume the opposite, from a similar principle ("Never underestimate the lasting power of the seed users to shape the user base demographics going forward."). I take it that you think the seed users of Rust like to configure the formatter to their liking.

One way to resolve this difference is to scan the crates repository, pick only those which uses rustfmt, and check what portion of them has set non-default values in rustfmt.toml. (This can also be used to check what portion of code would changing hard_tab = true to default would "break".)

It makes more sense to make a solid, easy-to-use way for those with accessibility needs to use rustfmt as some kind of load/save or checkout/checkin filter.

I agree that such a tool would be very helpful. I can already imagine using rustfmt --config-path along with git post-checkout and pre-commit hook to do so. But advocating for a change of culture and in turn a change of default makes as much sense. Allow me to stretch this analogy a bit: building wheelchairs for the movement impaired is very helpful, but convincing people to equip each building with ramps and elevators makes as much sense.

[The tool] is the equivalent to Firefox's accessibility settings when considered based on reliability. [emphasis added]

The EditorConfig tabstop setting cannot change space. Firefox's accessibility font setting cannot change 𝔉𝔒𝔑𝔗. They are as unreliable as each other. The tool aims to be reliable beyond that.

a non-configurable formatter and aggressive code conformity

From the thread you were in:

I'm do not contribute to projects that enforce rustfmt formatting. I can't stand rustfmt.

BTW, I love gofmt. It doesn't actually do what everyone assumes it does. gofmt preserves single-line expressions as single-line, and preserves multi-line expressions as multi-line. It just makes existing indentation neater, preserving original style and layout of the code. Rustfmt OTOH is a bulldozer that destroys everything. -- kornel

If anything, gofmt is more configurable and less aggressive than rustfmt. It is more configurable not by having a configuration file and many options, but by preserving much of the style already present in the code. That we put up with rustfmt, heck, that we put up with the steep learning curve of Rust, is the actual story of "adapting ourselves to the language". Go, being simple and easy to pick up, is selecting for people who do not want to adapt much.

ssokolow commented 4 years ago

we have authors who outright name the formatter "Artistic"

Bear in mind that it's a formatter primarily for C and C++. When I did my little survey, I found it puzzling how clearly and significantly disjoint the design philosophy for C and C++ formatters was from all other formatters... even the much younger clang-format. (possibly because C and C++ seem to be the only pre-1990s languages of note with such longevity and market share and that's affected the culture that produces said formatters.)

1081 shows an example of how the hard_tab option can complicate implementation.

Good catch. Even with spaces, the examples in #1081 embody the main type of rustfmt decision (which is independent of spaces or tabs) which prompts me to only use it infrequently... wasting vertical space on a non-portrait monitor. However, requiring hard tabs would make it impossible to go for the design I use unless it was smart enough to use tabs within a line to align arguments.

Also, one thing I haven't seen you touch on is formatters rewrapping ines to fit line length limits. I don't know about others, but I find that I often trim down local variable names to preserve the wrapping points necessary to keep good scannability in long method chains or banks of test asserts or what have you.

The readability of my code when the indent size or line length constraints have been altered is "WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED".

Not observed: The majority of the programming community prefers space to tab. I simply hypothesize that most people do not hold a strong preference over this matter for them to change the default setting.

It'd certainly be an interesting thing to see if nothing else. How many people who root around to learn how to change their tabs from 8-spaces, and how many editors would be revealed to have poor/no support for setting it on a per-language basis?

One way to resolve this difference is to scan the crates repository, pick only those which uses rustfmt, and check what portion of them has set non-default values in rustfmt.toml. (This can also be used to check what portion of code would changing hard_tab = true to default would "break".)

I see two difficulties ensuring that meaningful conclusions can be drawn from that data. Specifically, you'll need to find ways to measure or estimate the portions of the population who...

  1. ...were influenced on whether or not to use rustfmt based on its defaults.
  2. ...would have a rustfmt.toml but the default style is close enough that it's not worth the effort... especially when, last I checked, you had to already want it enough to work around how downplayed its existence and how to use it are in the first place.

I take this for granted: Everyone prefers consistency to mixed tab and space.

From the observation: The implementers of formatters prefer space to tab. I'd like to note that the implementers are only a minority of the programming community. That's the whole point of distributing such a tool, after all.

Part of what I was trying to convey was that, because the implementers of formatters almost universally prefer spaces, any language which uses tabs in its formatting will represent a lack of consistency between languages. That also needs to be considered when judging how to approach things.

In my experience, people prefer deviations between languages to be justified by associated advantages. Tabs vs. spaces is the utlimate bikesheddable disagreement.

My point is that you're always going to see projects either overriding the rustfmt defaults or refusing to use rustfmt if that's not possible.

I'd like to note that you are also "[making] an assumption about how willing people will be to stick to the rustfmt defaults." I assume most people follow the default from the anchor effect of behavioral economics, while you assume the opposite, from a similar principle ("Never underestimate the lasting power of the seed users to shape the user base demographics going forward."). I take it that you think the seed users of Rust like to configure the formatter to their liking.

Actually, the intent behind the statement you quoted was more in the vein of "A proper solution is going to need to deal with projects that defy the push for tabs anyway, so why push to inconvenience the majority of users before we've seen how far a universally applicable solution can take us?"

But advocating for a change of culture and in turn a change of default makes as much sense. Allow me to stretch this analogy a bit: building wheelchairs for the movement impaired is very helpful, but convincing people to equip each building with ramps and elevators makes as much sense.

The problem is that the "wheelchair" I propose works equally well whether or not "the building has ramps and elevators", we're not in a position to legislate that every "building" has this, and, whether or not they had a specific problem with the outcome, it would inconvenience and annoy a great many people to arbitrarily change things which were working just fine for them before.

(Not to mention potentially trash git diffs for anyone who wasn't warned to check in all their pending changes before upgrading rustfmt, then run rustfmt before making new changes.)

The EditorConfig tabstop setting cannot change space. Firefox's accessibility font setting cannot change 𝔉𝔒𝔑𝔗. They are as unreliable as each other. The tool aims to be reliable beyond that.

I don't see how those are comparable. The approach I propose would be built on top of rustfmt... something specifically designed to reformat the code with understanding of its structure sufficient to rework the whitespace as is needed.

If anything, EditorConfig's tabstop setting is a better analogy for what you propose, because rustfmt defaults can be overridden and rustfmt is optional.

If anything, gofmt is more configurable and less aggressive than rustfmt. It is more configurable not by having a configuration file and many options, but by preserving much of the style already present in the code. That we put up with rustfmt, heck, that we put up with the steep learning curve of Rust, is the actual story of "adapting ourselves to the language". Go, being simple and easy to pick up, is selecting for people who do not want to adapt much.

I'll certainly agree that rustfmt is a bulldozer that needs to be improved but, to some extent, it also depends on what you consider to be a hindrance and what you consider to be a help.

For example, there's a Python lint that I'd normally want... ensure that all imports are at the top of the file... and then you run into things like PyGObject, where from gi.repository import Gtk will yell at you to first import gi and call gi.require_version('Gtk', '3.0') ...which, last I checked, failed the "all imports at the top" check because it's "import, function call, import".

I haven't used gofmt, so I can't judge it, but I feel skeptical of its ability to be that much better than rustfmt at telling the difference between "style" and "stylistic typo".

I think they just chose different balance points between the two concerns. (Plus, they're also, to some extent, expressions of the different cultures that produced them. The Rust compiler catches a lot more at compile time than the Go compiler.)

Jordandev678 commented 4 years ago

I never intended it to be casual dismissal. I honestly want input from someone who actually needs this, rather than second-hand input or even possibly just guesses by people with a personal preference for tabs.

That aside, isn't the purpose of something like rustfmt to be powerful enough that a person with a visual impairment could plumb things together so that it could automatically reformat to hard tabs on checkout, then reformat to whatever the project calls for on checkin? Wouldn't that be a more optimal solution, given that many projects are likely to override any hard_tab = true default? (Sort of like how Git has built-in support for doing LF↔CRLF conversion when a Windows user checks out a repo.)

Bit of a bump on an old-ish bug so hopefully people will forgive me but as someone who is affected by this for similar but different reasons than the case OP mentions let me throw in my real first-hand experience. One that I've literally just had today with Rust that lead to me finding this thread. It might be useful in the future for others to point at if they can jump on the language before the tab vs spaces decision is made. But I suspect I've missed that boat at this point for Rust.

I'm dyslexic and as a result I can struggle with alignment of things when it comes to code. My standard is the 8 spaces size tab. 4 makes my life difficult in that I won't be able to skim the code anymore; I'll have to go slow and really read it. I'll need to take a really good look at each line, sometimes multiple times, to make sure I've properly picked up on the indentation level. 2 space indents literally are not there most of the time.

Terminal related editors are actually pretty good with this, defaulting to 8 spaces (Nano, Vim). If I need to edit a file, lets say a config file, quickly in a terminal I can pull those up and if it's indented with tabs I'm good to go immediately. If it's not I'll end up doing sed "s/ /\t/" to make it tabs so I can properly read it, then roll it back later. But you'll note that depending on the context and syntax of the file that's not always safe. In my experience in programming languages it's virtually never safe in anything other than small projects. One case being log lines and other things in strings where it's important the spaces are spaces and the tabs are tabs so I stopped doing that long ago on code.

That means I need an editor that doesn't just do "spaces to tabs" but that understands the syntax of the file and what's safe to expand and what isn't. Was that space in a multi-line string? is but one question you can't answer with a per-line regular expression. But the moral of the story is if I end up in that situation, I'm pretty much excluded from working on it in a timely manner without a full on syntax aware IDE setup and customized to back up my efforts.

Mostly to cope with quick one-offs I've learned to use the { ... } to mentally note "this is an indented block" without actually having to recognize/see the indent. On a related note, Pythons an inaccessible hell hole not just lacking the braces for me to follow but also making the spaces that I can't reliably see syntactically important. Never mind the bike-shed someone get me a pipe wrench.

Anyway, onto the Rust encounter. After posting https://github.com/mozilla-mobile/fenix/issues/14582 I started digging into why it was broken to see if I can fix it. I believe I've tracked down the library with the issue, never used rust before so spin up a quick blank VM, install rust, download the library, cargo test to ensure it works, and quickly crack it open in Vim. I think I know the fix, one line change + accompanying unit test. Right, it's 4 spaces... The files 400+ lines and as the library handles encryption I'm going to need to make damn sure I understand what's going on all around the class even though I only want to change one line. An hour later I'm looking through Rust documentation (again having never used Rust) to find out rustfmt exists but didn't come down with the rust package in apt; figure out how to get it; and then make it reflow the document with tabs.

I finished work at 5pm and tried to quickly knock a Firefox bug out I already think I tracked down by clicking around Github. One line change and a unit test. It's now 8pm and I'm still setting this up with rustfmt to make it easily editable and haven't stopped yet to go make dinner. If this was indented with tabs Vim would have picked up my tab setting and I'd be done by now and have a pull request sitting upstream assuming the change worked. I haven't even gotten to the point of finding out yet!

I've seen this more than once in Rustfmt, Python, etc. refereed to as a "bike shed argument". My understanding of the term is that it's a "lengthy, unproductive discussion over a minor issue". I'd like to call out at this point for me and others this affects it's not a minor issue - it's the difference between people affected by this like me being able to read it reliably or not and we end up working around this before we can do anything productive. What should have been a quick introduction to the language and knocking out a bug in an open source project has turned into a multi-hour saga of learning the formatting tool and building that plumbing of the formatter around the editor that was referred to in earlier posts. I'm having to learn the formatter before even learning the compiler. I once had to waste more than half a day debugging Vim because someone upstream decided to include a "force space indent of width 4" into Vim for python files in such a way as it overrode my own settings in .vimrc and if I wanted them back I had to override their override in a specific file for that filetype. But I had to figure that out before I could read and write the code properly again.

Perhaps it's a bit oversensitive - but IMO if this was any other accessibility issue like color blindness it'd be a hunt to find the right thing with a UI review required before release to ensure it was acceptable. Blindness? Look at aria appearing in HTML much more and frameworks like bootstrap including it in their examples. But in my time coding spaces are becoming more common not less, communities are adopting common style guidelines (good) pushing people to default to spaces (bad) and coding is becoming less accessible to me not more. There's a real accessibility issue here and the community across many languages is calling it a bikeshed issue and going the wrong way. If it's a tab Vim or any editor these days picks up everybody's favorite setting, mine, yours, theirs. If it's a space it is only yours - and I end up where I'm sitting now debating if fixing a bug in Firefox for nothing is really worth the hassle this is currently puting me though.

P.S. It's been mentioned in the previous threads that the majority of the community is clearly on side or indifferent. I'm sure that's absolutely true. Most people are indifferent to wheelchair ramps too. Your criteria for accessibility can't be majority support. Accessibility often relies on people making these decisions to side against the majority and towards accessibility. Yes, people could always do the opposite and manually set it to spaces but the fact is the agreed guidelines and the defaults do carry weight and do make a difference.

</rant>

ssokolow commented 4 years ago

@Jordandev678

Thank you. :)

calebcartwright commented 4 years ago

I appreciate the opinions and perspectives shared here, but I'm locking this conversation as resolved because ths issue (and this repo) is not the right place for the discussion.

rustfmt's defaults are explicitly and strictly governed by the Rust Style Guide, and that Style Guide explicitly requires the default value for hard_tabs to be false. Unless and until the Style Guide is changed, we cannot and will not change the default option in rustfmt.