Default style
JuliaFormatter has a default style. This page is intended to give a rough overview of how the output of a formatted file looks like when using the default style. Additional examples can be found in JuliaFormatter's codebase itself.
All examples assume indentation of 4 spaces.
Nesting decisions
Where possible JuliaFormatter's default style attempts to keep code on a single line.
With no arguments
Functions, macros, and structs with no arguments are placed on a single line. This also applies to abstract and primitive types:
function foo
end
abstract type
AbstractFoo
endis formatted to
function foo end
abstract type AbstractFoo endWith arguments
Functions calls foo(args...), tuples (args...), arrays [args...], braces {args...}, and type parameter definitions Foo{args...} are placed on a single line. This applies to any code which has opening and closing punctuation: (...), {...}, [...].
Whitespace is inserted after commas, but not for type definitions:
f(
a,b
,c )
Foo{
a,b
,c }is formatted to
f(a, b, c)
Foo{a,b,c}Blocks
Blocks and their bodies are spread across multiple lines and properly indented.
Example 1:
begin
a
b; c
end
struct Foo{A, B}
a::A
b::B
endis formatted to
begin
a
b
c
end
struct Foo{A,B}
a::A
b::B
endBinary operators (without nesting)
Binary calls are placed on a single line where possible. Their operands are separated by whitespace, except for : operators (i.e. ranges), and for operators which are inside indexing brackets.
Example 1:
a+b
a : a : c
list[a + b]a + b
a:b:c
list[a+b]Ternary expressions are placed on a single line and separated by whitespace:
cond1 ?
expr1 : expr2is formatted to
cond1 ? expr1 : expr2Comments are aligned with surrounding code blocks.
# comment
if a
# comment
else
# comment
end
# commentis formatted to
# comment
if a
# comment
else
# comment
end
# commentBinary operators (with nesting)
If a binary operation exceeds the margin, they are nested back-to-front:
arg1 + arg2becomes (with a small margin)
arg1 +
arg2For the ternary operator, as the margin decreases, the : is first moved to the next line, and then the ?:
cond ? e1 : e2becomes (with a small margin)
cond ? e1 :
e2and with an even smaller margin
cond ?
e1 : e2and with a yet smaller margin
cond ?
e1 :
e2If nesting is required for an assignment (i.e., a binary operation with = as the operator), the RHS is placed on the following line and indented.
foo() = bodyis formatted to
foo() =
bodyAll arguments of a function call (applies to any opening/closing punctuation type) are nested if the expression exceeds the margin. The arguments are indented one level.
function longfunctionname_that_is_long(lots, of, args, even, more, args)
body
endbecomes
function longfunctionname_that_is_long(
lots,
of,
args,
even,
more,
args,
)
body
endWith where operations (A where B), A is nested prior to B.
function f(arg1::A, key1 = val1; key2 = val2) where {A,B,C}
body
endbecomes
function f(
arg1::A,
key1 = val1;
key2 = val2,
) where {A,B,C}
body
endand if the margin is shrunk even more,
function f(
arg1::A,
key1 = val1;
key2 = val2,
) where {
A,
B,
C,
}
body
endIf a comment is detected inside of an expression, that expression is automatically nested:
var = foo(
a, b, # comment
c,
)becomes
var = foo(
a,
b, # comment
c,
)Unnesting
In certain cases it is desirable to unnest parts of a FST to avoid excessive whitespace. For example, the following
var =
funccall(
arg1,
arg2,
arg3,
)will be un-nested to
var = funccall(arg1, arg2, arg3)or
var = funccall(
arg1,
arg2,
arg3,
)Syntax transformations
for in vs. for =
By default if the RHS is a range, e.g. 1:10, then for ... in ... is converted to for ... = .... Otherwise for ... = ... is converted to for ... in .... See this issue for the rationale and further explanation.
This behaviour can be controlled using the always_for_in option. Setting always_for_in=true will always convert = to in even if the RHS is a range. always_for_in=nothing will leave the choice of in vs = up to the user.
Trailing Commas
If the node is iterable, for example a function call or list and is nested, a trailing comma is added to the last argument. The trailing comma is removed if unnested:
func(a, b, c)becomes
func(
a,
b,
c,
)See this issue for more details.
Trailing Semicolons
If a matrix node is nested, the semicolons are removed.
A = [1 0; 0 1]
->
A = [
1 0
0 1
]See this issue for more details.
Leading and trailing 0s for float literals
If a float literal is missing a trailing or leading 0, it is added:
a = 1.
b = .1becomes
a = 1.0
b = 0.1For Float32 literals, if there is no decimal point, .0 is added:
a = 1f0
->
a = 1.0f0See this issue for more details.
Surround where arguments with curly brackets
If the arguments of a where call are not surrounded by curly brackets, they are added:
foo(x::T) where T = ...becomes
foo(x::T) where {T} = ...This can be controlled with the surround_whereop_typeparameters option.
See this issue for more details.
Annotate unannotated type fields with Any
In structs, if a field is unannotated, it is annotated with Any:
struct Foo
field
endbecomes
struct Foo
field::Any
endThis can be controlled with the annotate_untyped_fields_with_any option.
Move @ in macro calls to the final identifier
@Module.macrobecomes
Module.@macro