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

Can we indent with tabs rather than spaces? #421

Open
singularitti opened this issue Jun 1, 2021 · 10 comments
Open

Can we indent with tabs rather than spaces? #421

singularitti opened this issue Jun 1, 2021 · 10 comments
Labels
enhancement New feature or request

Comments

@singularitti
Copy link

Some people asked me whether they can indent with tabs instead of spaces. Can JuliaFormatter.jl do that?

@domluna
Copy link
Owner

domluna commented Jun 1, 2021

Would that mean using '\t' instead of ' '?

@liurui39660
Copy link

To be exact, use one '\t' instead of four ' '.

@domluna
Copy link
Owner

domluna commented Jun 1, 2021

what if the number of spaces is different than 4?

@liurui39660
Copy link

I don't think it's a problem, the options can be whether to indent with X spaces or 1 tab.

@domluna domluna added the enhancement New feature or request label Jun 1, 2021
@singularitti
Copy link
Author

singularitti commented Jun 1, 2021

Maybe instead of indent::Int = 4, we can set indent::Union{Char,String} = ' '^4 by default.

@rben01
Copy link

rben01 commented Jun 14, 2021

In general, the right way to indent with tabs is to use them for the "semantic" indent while continuing to use spaces for the "physical" indent. For instance, when indenting with four spaces, JuliaFormatter produces the following code:

@testset "Contrived example" begin
    @test (@test_logs very_very_very_very_very_very_very_very_very_very_long_expression()) ==
          another_very_very_very_very_very_very_very_very_very_very_long_expression() ==
          if contrived_example
              println("42")
              return 1
          else
              return 0
          end
end

The whole @test statement is indented because it lives inside the nested scope of the @testset. In addition, you can see that another_, if, else, and end are all lined up with (@test_logs; the a, i, and two es are directly under the (. They are each indented a total of ten spaces, four to account for @test's indent and an additional six to line up with (@test_logs (since @test␣ is six characters long). The statements inside the if-else-end, being inside an additional nested scope, are indented four additional spaces as expected.

If using tabs to indent, then @test should be indented with a tab, and -- crucially (every formatter, across every language, gets this wrong!) -- everything that is set to line up vertically should be indented with one tab and six spaces (not two tabs!), as using tabs alone for indentation will break the alignment of code. That way, regardless of how wide tabs are displayed on the user's computer, everything is still lined up. Then, inside the if-else-end, the additional indentation should be created with tabs because of the nested scope. Basically, wherever the indentation represents a semantic indent -- an indent that's representing nested scope -- you use tabs. And where indentation is purely physical -- used to line up multiple statements across different lines -- you use spaces. Some examples below, where [] with spaces in between the brackets represents a tab displayed at different user-specified widths.

# tab width = 2
@testset "Contrived example" begin
[]@test (@test_logs very_very_very_very_very_very_very_very_very_very_long_expression()) ==
[]      another_very_very_very_very_very_very_very_very_very_very_long_expression() ==
[]      if contrived_example
[]      []println("42")
[]      []return 1
[]      else
[]      []return 0
[]      end
end

# tab width = 4
@testset "Contrived example" begin
[  ]@test (@test_logs very_very_very_very_very_very_very_very_very_very_long_expression()) ==
[  ]      another_very_very_very_very_very_very_very_very_very_very_long_expression() ==
[  ]      if contrived_example
[  ]      [  ]println("42")
[  ]      [  ]return 1
[  ]      else
[  ]      [  ]return 0
[  ]      end
end

# tab width = 16!?
@testset "Contrived example" begin
[              ]@test (@test_logs very_very_very_very_very_very_very_very_very_very_long_expression()) ==
[              ]      another_very_very_very_very_very_very_very_very_very_very_long_expression() ==
[              ]      if contrived_example
[              ]      [              ]println("42")
[              ]      [              ]return 1
[              ]      else
[              ]      [              ]return 0
[              ]      end
end

Everything stays aligned regardless of the tab size, and you still get the right semantic indent.

@liurui39660
Copy link

@rben01 I think you are mixing the concept of continuation indent and code alignment. I don't know your preference, but for me, I usually turn off all possible code alignment.

My settings for most IDEs are like no code alignment, tab size = 4, indent = 1 tab, continuation indent = 1 tab. So in your example, a in another_... is at the same column of the 2nd t in @test. The if-else-end statement is also indented to the 2nd t.

For the tab size, I think many IDEs have such an option to choose its width.

My idea is: don't decide for users, give them options.

@rben01
Copy link

rben01 commented Jun 14, 2021

@liurui39660 Sure, the option is nice. But I don't think that JuliaFormatter currently has that option; it always aligns when there's a continuation (try replacing @test_logs with @test_logs_foo_bar; it'll push the stuff underneath it over). Given that, then, I was just describing the right way to use tabs in this paradigm. Continuation indent is a separate story.

@ProvocaTeach
Copy link

Any progress on this issue? It’s the one thing preventing me from using this package 😅

@montyvesselinov
Copy link

Can we set the formatter to indent with tabs instead of spaces?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants