Can we indent with tabs rather than spaces?
Some people asked me whether they can indent with tabs instead of spaces. Can JuliaFormatter.jl do that?
Would that mean using '\t' instead of ' '?
To be exact, use one '\t' instead of four ' '.
what if the number of spaces is different than 4?
I don't think it's a problem, the options can be whether to indent with X spaces or 1 tab.
Maybe instead of indent::Int = 4, we can set indent::Union{Char,String} = ' '^4 by default.
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.
@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.
@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.
Any progress on this issue? It’s the one thing preventing me from using this package 😅
Can we set the formatter to indent with tabs instead of spaces?