Repository: domluna/JuliaFormatter.jl
Pull request #171 (2020-01-14 05:17:39)

Styles
Implements styles.

The same as #164 except functions are not overloaded as much. It looks like overloading functions as we do in #164 causes noticeable compilation times at no performance benefit.


Patch:
diff --git a/docs/src/custom_styles.md b/docs/src/custom_styles.md
new file mode 100644
index 00000000..e714c7b4
--- /dev/null
+++ b/docs/src/custom_styles.md
@@ -0,0 +1,66 @@
+# Custom Styles
+
+The default style surrounds keyword arguments with whitespace. Suppose
+we wanted to have no spaces, how could we do this? Using custom styles this turns
+out to be easy.
+
+First we'll define the style:
+
+```julia
+using JuliaFormatter, CSTParser
+using JuliaFormatter: AbstractStyle, FST, State, add_node!
+import JuliaFormatter: pretty, p_kw
+
+struct CustomStyle <: AbstractStyle end
+
+# this must be defined
+getstyle(s::CustomStyle) = s
+```
+
+Next we'll create a function for the `p_kw` to dispatch on `CustomStyle`.
+
+```julia
+function p_kw(style::CustomStyle, cst::CSTParser.EXPR, s::State)
+    t = FST(cst, 0)
+    for a in cst
+        add_node!(t, pretty(style, a, s), s, join_lines = true)
+    end
+    t
+end
+```
+
+For comparison here's the default definition:
+
+```julia
+function p_kw(style::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(style)
+    t = FST(cst, nspaces(s))
+    for a in cst
+        if a.kind === Tokens.EQ
+            add_node!(t, Whitespace(1), s)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
+            add_node!(t, Whitespace(1), s)
+        else
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
+        end
+    end
+    t
+end
+```
+
+And that's it! All other functions will fallback to use `DefaultStyle`.
+
+Finally, let's check the output:
+
+```julia
+julia> s = "foo(a,b, key1=val1, key3=val4)"
+"foo(a,b, key1=val1, key3=val4)"
+
+julia> format_text(s) |> print
+foo(a, b, key1 = val1, key3 = val4)
+
+julia> format_text(s, style=CustomStyle()) |> print
+foo(a, b, key1=val1, key3=val4)
+```
+
+Nice! Looks like it's working.
diff --git a/src/JuliaFormatter.jl b/src/JuliaFormatter.jl
index cba983d2..6641acd0 100644
--- a/src/JuliaFormatter.jl
+++ b/src/JuliaFormatter.jl
@@ -188,9 +188,19 @@ State(doc, indent_size, margin, opts) = State(doc, indent_size, 0, 1, 0, margin,
 end
 @inline cursor_loc(s::State) = cursor_loc(s, s.offset)
 
+abstract type AbstractStyle end
+
+struct DefaultStyle <: AbstractStyle
+    innerstyle::Union{Nothing,AbstractStyle}
+end
+DefaultStyle() = DefaultStyle(nothing)
+
+@inline getstyle(s::DefaultStyle) = s.innerstyle === nothing ? s : s.innerstyle
+
 include("pretty.jl")
 include("nest.jl")
 include("print.jl")
+include("styles/yas.jl")
 
 """
     format_text(
@@ -200,6 +210,7 @@ include("print.jl")
         always_for_in::Bool = false,
         whitespace_typedefs::Bool = false,
         whitespace_ops_in_indices::Bool = false,
+        style::AbstractStyle = DefaultStyle(),
     )::String
 
 Formats a Julia source passed in as a string, returning the formatted
@@ -231,6 +242,7 @@ function format_text(
     always_for_in::Bool = false,
     whitespace_typedefs::Bool = false,
     whitespace_ops_in_indices::Bool = false,
+    style::AbstractStyle = DefaultStyle(),
 )
     isempty(text) && return text
 
@@ -246,9 +258,9 @@ function format_text(
         whitespace_ops_in_indices = whitespace_ops_in_indices,
     )
     s = State(Document(text), indent, margin, opts)
-    t = pretty(x, s)
+    t = pretty(style, x, s)
     hascomment(s.doc, t.endline) && (add_node!(t, InlineComment(t.endline), s))
-    nest!(t, s)
+    nest!(style, t, s)
 
     s.line_offset = 0
     io = IOBuffer()
diff --git a/src/nest.jl b/src/nest.jl
index 6de1f973..17d4c568 100644
--- a/src/nest.jl
+++ b/src/nest.jl
@@ -93,7 +93,14 @@ function dedent!(fst::FST, s::State)
     unnest!(fst, nl_inds)
 end
 
-function nest!(nodes::Vector{FST}, s::State, indent::Int; extra_margin = 0)
+function nest!(
+    ds::DefaultStyle,
+    nodes::Vector{FST},
+    s::State,
+    indent::Int;
+    extra_margin = 0,
+)
+    style = getstyle(ds)
     for (i, n) in enumerate(nodes)
         if n.typ === NEWLINE && nodes[i+1].typ === CSTParser.Block
             s.line_offset = nodes[i+1].indent
@@ -103,83 +110,98 @@ function nest!(nodes::Vector{FST}, s::State, indent::Int; extra_margin = 0)
             s.line_offset = indent
         else
             n.extra_margin = extra_margin
-            nest!(n, s)
+            nest!(style, n, s)
         end
     end
 end
-
-function nest!(fst::FST, s::State)
+nest!(
+    style::S,
+    nodes::Vector{FST},
+    s::State,
+    indent::Int;
+    extra_margin = 0,
+) where {S<:AbstractStyle} =
+    nest!(DefaultStyle(style), nodes, s, indent, extra_margin = extra_margin)
+
+function nest!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     if is_leaf(fst)
         s.line_offset += length(fst)
         return
     end
 
     if fst.typ === CSTParser.Import
-        n_import!(fst, s)
+        n_import!(style, fst, s)
     elseif fst.typ === CSTParser.Export
-        n_export!(fst, s)
+        n_export!(style, fst, s)
     elseif fst.typ === CSTParser.Using
-        n_using!(fst, s)
+        n_using!(style, fst, s)
     elseif fst.typ === CSTParser.WhereOpCall
-        n_whereopcall!(fst, s)
+        n_whereopcall!(style, fst, s)
     elseif fst.typ === CSTParser.ConditionalOpCall
-        n_conditionalopcall!(fst, s)
+        n_conditionalopcall!(style, fst, s)
     elseif fst.typ === CSTParser.BinaryOpCall
-        n_binaryopcall!(fst, s)
+        n_binaryopcall!(style, fst, s)
     elseif fst.typ === CSTParser.Curly
-        n_curly!(fst, s)
+        n_curly!(style, fst, s)
     elseif fst.typ === CSTParser.Call
-        n_call!(fst, s)
+        n_call!(style, fst, s)
     elseif fst.typ === CSTParser.MacroCall
-        n_macrocall!(fst, s)
+        n_macrocall!(style, fst, s)
     elseif fst.typ === CSTParser.Ref
-        n_ref!(fst, s)
+        n_ref!(style, fst, s)
     elseif fst.typ === CSTParser.TypedVcat
-        n_typedvcat!(fst, s)
+        n_typedvcat!(style, fst, s)
     elseif fst.typ === CSTParser.TupleH
-        n_tupleh!(fst, s)
+        n_tupleh!(style, fst, s)
     elseif fst.typ === CSTParser.Vect
-        n_vect!(fst, s)
+        n_vect!(style, fst, s)
     elseif fst.typ === CSTParser.Vcat
-        n_vcat!(fst, s)
+        n_vcat!(style, fst, s)
     elseif fst.typ === CSTParser.Parameters
-        n_parameters!(fst, s)
+        n_parameters!(style, fst, s)
     elseif fst.typ === CSTParser.Braces
-        n_braces!(fst, s)
+        n_braces!(style, fst, s)
     elseif fst.typ === CSTParser.InvisBrackets
-        n_invisbrackets!(fst, s)
+        n_invisbrackets!(style, fst, s)
     elseif fst.typ === CSTParser.Comprehension
-        n_comphrehension!(fst, s)
+        n_comprehension!(style, fst, s)
     elseif fst.typ === CSTParser.Do
-        n_do!(fst, s)
+        n_do!(style, fst, s)
     elseif fst.typ === CSTParser.Generator
-        n_generator!(fst, s)
+        n_generator!(style, fst, s)
     elseif fst.typ === CSTParser.Filter
-        n_filter!(fst, s)
+        n_filter!(style, fst, s)
     elseif fst.typ === CSTParser.Block
-        n_block!(fst, s)
+        n_block!(style, fst, s)
     elseif fst.typ === CSTParser.ChainOpCall
-        n_chainopcall!(fst, s)
+        n_chainopcall!(style, fst, s)
     elseif fst.typ === CSTParser.Comparison
-        n_comparison!(fst, s)
+        n_comparison!(style, fst, s)
     elseif fst.typ === CSTParser.For
-        n_for!(fst, s)
+        n_for!(style, fst, s)
     elseif fst.typ === CSTParser.Let
-        n_let!(fst, s)
+        n_let!(style, fst, s)
     elseif fst.typ === CSTParser.UnaryOpCall && fst[2].typ === CSTParser.OPERATOR
-        n_unaryopcall!(fst, s)
+        n_unaryopcall!(style, fst, s)
     else
-        nest!(fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
     end
 end
+nest!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    nest!(DefaultStyle(style), fst, s)
 
-function n_unaryopcall!(fst::FST, s::State)
+function n_unaryopcall!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     fst[1].extra_margin = fst.extra_margin + length(fst[2])
-    nest!(fst[1], s)
-    nest!(fst[2], s)
+    nest!(style, fst[1], s)
+    nest!(style, fst[2], s)
 end
+n_unaryopcall!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_unaryopcall!(DefaultStyle(style), fst, s)
 
-function n_do!(fst::FST, s::State)
+function n_do!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     extra_margin = sum(length.(fst[2:3]))
     # make sure there are nodes after "do"
     if fst[4].typ === WHITESPACE
@@ -187,13 +209,16 @@ function n_do!(fst::FST, s::State)
         extra_margin += length(fst[5])
     end
     fst[1].extra_margin = fst.extra_margin + extra_margin
-    nest!(fst[1], s)
-    nest!(fst[2:end], s, fst.indent, extra_margin = fst.extra_margin)
+    nest!(style, fst[1], s)
+    nest!(style, fst[2:end], s, fst.indent, extra_margin = fst.extra_margin)
 end
+n_do!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_do!(DefaultStyle(style), fst, s)
 
 
 # Import,Using,Export
-function n_import!(fst::FST, s::State)
+function n_import!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     line_margin = s.line_offset + length(fst) + fst.extra_margin
     idx = findfirst(n -> n.typ === PLACEHOLDER, fst.nodes)
     if idx !== nothing && (line_margin > s.margin || fst.force_nest)
@@ -214,18 +239,26 @@ function n_import!(fst::FST, s::State)
                 fst[i] = Newline(length = n.len)
                 s.line_offset = fst.indent
             else
-                nest!(n, s)
+                nest!(style, n, s)
             end
         end
     else
-        nest!(fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
     end
 end
-n_export!(fst::FST, s::State) = n_import!(fst, s)
-n_using!(fst::FST, s::State) = n_import!(fst, s)
-n_importall!(fst::FST, s::State) = n_import!(fst, s)
+n_import!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_import!(DefaultStyle(style), fst, s)
+
+@inline n_export!(ds::DefaultStyle, fst::FST, s::State) = n_import!(ds, fst, s)
+n_export!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_export!(DefaultStyle(style), fst, s)
 
-function n_tupleh!(fst::FST, s::State)
+@inline n_using!(ds::DefaultStyle, fst::FST, s::State) = n_import!(ds, fst, s)
+n_using!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_using!(DefaultStyle(style), fst, s)
+
+function n_tupleh!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     line_margin = s.line_offset + length(fst) + fst.extra_margin
     idx = findlast(n -> n.typ === PLACEHOLDER, fst.nodes)
     # @info "ENTERING" idx fst.typ s.line_offset length(fst) fst.extra_margin
@@ -249,18 +282,18 @@ function n_tupleh!(fst::FST, s::State)
             elseif n.typ === TRAILINGCOMMA
                 n.val = ","
                 n.len = 1
-                nest!(n, s)
+                nest!(style, n, s)
             elseif n.typ === TRAILINGSEMICOLON
                 n.val = ""
                 n.len = 0
-                nest!(n, s)
+                nest!(style, n, s)
             elseif opener && (i == 1 || i == length(fst.nodes))
-                nest!(n, s)
+                nest!(style, n, s)
             else
                 diff = fst.indent - fst[i].indent
                 add_indent!(n, s, diff)
                 n.extra_margin = 1
-                nest!(n, s)
+                nest!(style, n, s)
             end
         end
 
@@ -271,18 +304,39 @@ function n_tupleh!(fst::FST, s::State)
     else
         extra_margin = fst.extra_margin
         opener && (extra_margin += 1)
-        nest!(fst.nodes, s, fst.indent, extra_margin = extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = extra_margin)
     end
 end
-n_vect!(fst::FST, s::State) = n_tupleh!(fst, s)
-n_vcat!(fst::FST, s::State) = n_tupleh!(fst, s)
-n_braces!(fst::FST, s::State) = n_tupleh!(fst, s)
-n_parameters!(fst::FST, s::State) = n_tupleh!(fst, s)
-n_invisbrackets!(fst::FST, s::State) = n_tupleh!(fst, s)
-n_comphrehension!(fst::FST, s::State) = n_tupleh!(fst, s)
+n_tupleh!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_tupleh!(DefaultStyle(style), fst, s)
+
+@inline n_vect!(ds::DefaultStyle, fst::FST, s::State) = n_tupleh!(ds, fst, s)
+n_vect!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_vect!(DefaultStyle(style), fst, s)
+
+@inline n_vcat!(ds::DefaultStyle, fst::FST, s::State) = n_tupleh!(ds, fst, s)
+n_vcat!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_vcat!(DefaultStyle(style), fst, s)
+
+@inline n_braces!(ds::DefaultStyle, fst::FST, s::State) = n_tupleh!(ds, fst, s)
+n_braces!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_braces!(DefaultStyle(style), fst, s)
+
+@inline n_parameters!(ds::DefaultStyle, fst::FST, s::State) = n_tupleh!(ds, fst, s)
+n_parameters!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_parameters!(DefaultStyle(style), fst, s)
+
+@inline n_invisbrackets!(ds::DefaultStyle, fst::FST, s::State) = n_tupleh!(ds, fst, s)
+n_invisbrackets!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_invisbrackets!(DefaultStyle(style), fst, s)
 
+@inline n_comprehension!(ds::DefaultStyle, fst::FST, s::State) = n_tupleh!(ds, fst, s)
+n_comprehension!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_comprehension!(DefaultStyle(style), fst, s)
 
-function n_call!(fst::FST, s::State)
+
+function n_call!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     line_margin = s.line_offset + length(fst) + fst.extra_margin
     idx = findlast(n -> n.typ === PLACEHOLDER, fst.nodes)
     # @info "ENTERING" fst.typ s.line_offset length(fst) fst.extra_margin s.margin fst[1].val
@@ -301,21 +355,21 @@ function n_call!(fst::FST, s::State)
             elseif n.typ === TRAILINGCOMMA
                 n.val = ","
                 n.len = 1
-                nest!(n, s)
+                nest!(style, n, s)
             elseif n.typ === TRAILINGSEMICOLON
                 n.val = ""
                 n.len = 0
-                nest!(n, s)
+                nest!(style, n, s)
             elseif i == 1 || i == length(fst.nodes)
                 n.typ === CSTParser.Parameters && (n.force_nest = true)
                 n.extra_margin = 1
-                nest!(n, s)
+                nest!(style, n, s)
             else
                 diff = fst.indent - fst[i].indent
                 add_indent!(n, s, diff)
                 n.typ === CSTParser.Parameters && (n.force_nest = true)
                 n.extra_margin = 1
-                nest!(n, s)
+                nest!(style, n, s)
             end
         end
 
@@ -323,15 +377,30 @@ function n_call!(fst::FST, s::State)
     else
         extra_margin = fst.extra_margin
         is_closer(fst[end]) && (extra_margin += 1)
-        nest!(fst.nodes, s, fst.indent, extra_margin = extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = extra_margin)
     end
 end
-n_curly!(fst::FST, s::State) = n_call!(fst, s)
-n_macrocall!(fst::FST, s::State) = n_call!(fst, s)
-n_ref!(fst::FST, s::State) = n_call!(fst, s)
-n_typedvcat!(fst::FST, s::State) = n_call!(fst, s)
+n_call!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_call!(DefaultStyle(style), fst, s)
+
+@inline n_curly!(ds::DefaultStyle, fst::FST, s::State) = n_call!(ds, fst, s)
+n_curly!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_curly!(DefaultStyle(style), fst, s)
+
+@inline n_macrocall!(ds::DefaultStyle, fst::FST, s::State) = n_call!(ds, fst, s)
+n_macrocall!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_macrocall!(DefaultStyle(style), fst, s)
+
+@inline n_ref!(ds::DefaultStyle, fst::FST, s::State) = n_call!(ds, fst, s)
+n_ref!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_ref!(DefaultStyle(style), fst, s)
 
-function n_whereopcall!(fst::FST, s::State)
+@inline n_typedvcat!(ds::DefaultStyle, fst::FST, s::State) = n_call!(ds, fst, s)
+n_typedvcat!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_typedvcat!(DefaultStyle(style), fst, s)
+
+function n_whereopcall!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     line_margin = s.line_offset + length(fst) + fst.extra_margin
     # @info "" s.line_offset fst.typ line_margin fst.extra_margin length(fst) fst.force_nest line_margin > s.margin
     if line_margin > s.margin || fst.force_nest
@@ -342,10 +411,10 @@ function n_whereopcall!(fst::FST, s::State)
 
         # A, +7 is the length of " where "
         fst[1].extra_margin = Blen + 7 + fst.extra_margin
-        nest!(fst[1], s)
+        nest!(style, fst[1], s)
 
         for (i, n) in enumerate(fst[2:idx-1])
-            nest!(n, s)
+            nest!(style, n, s)
         end
 
         # "B"
@@ -366,31 +435,34 @@ function n_whereopcall!(fst::FST, s::State)
                     fst.indent = s.line_offset + 1
                     fst[end].indent = s.line_offset
                 end
-                nest!(n, s)
+                nest!(style, n, s)
             elseif n.typ === PLACEHOLDER && over
                 fst[i+idx] = Newline(length = n.len)
                 s.line_offset = fst.indent
             elseif n.typ === TRAILINGCOMMA && over
                 n.val = ","
                 n.len = 1
-                nest!(n, s)
+                nest!(style, n, s)
             elseif has_braces
                 n.extra_margin = 1 + fst.extra_margin
-                nest!(n, s)
+                nest!(style, n, s)
             else
                 n.extra_margin = fst.extra_margin
-                nest!(n, s)
+                nest!(style, n, s)
             end
         end
 
         s.line_offset = line_offset
         walk(reset_line_offset!, fst, s)
     else
-        nest!(fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
     end
 end
+n_whereopcall!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_whereopcall!(DefaultStyle(style), fst, s)
 
-function n_conditionalopcall!(fst::FST, s::State)
+function n_conditionalopcall!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     line_margin = s.line_offset + length(fst) + fst.extra_margin
     # @info "ENTERING" fst.typ s.line_offset line_margin fst.force_nest
     if line_margin > s.margin || fst.force_nest
@@ -414,14 +486,14 @@ function n_conditionalopcall!(fst::FST, s::State)
         for (i, n) in enumerate(fst.nodes)
             if i == length(fst.nodes)
                 n.extra_margin = fst.extra_margin
-                nest!(n, s)
+                nest!(style, n, s)
             elseif fst[i+1].typ === WHITESPACE
                 n.extra_margin = length(fst[i+1]) + length(fst[i+2])
-                nest!(n, s)
+                nest!(style, n, s)
             elseif n.typ === NEWLINE
                 s.line_offset = fst.indent
             else
-                nest!(n, s)
+                nest!(style, n, s)
             end
         end
 
@@ -448,10 +520,11 @@ function n_conditionalopcall!(fst::FST, s::State)
         s.line_offset = line_offset
         walk(reset_line_offset!, fst, s)
     else
-        nest!(fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
     end
 end
-
+n_conditionalopcall!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_conditionalopcall!(DefaultStyle(style), fst, s)
 
 no_unnest(fst::FST) = fst.typ === CSTParser.BinaryOpCall && contains_comment(fst)
 
@@ -461,7 +534,8 @@ no_unnest(fst::FST) = fst.typ === CSTParser.BinaryOpCall && contains_comment(fst
 #
 # lhs op
 # lhs
-function n_binaryopcall!(fst::FST, s::State)
+function n_binaryopcall!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     # If there's no placeholder the binary call is not nestable
     idxs = findall(n -> n.typ === PLACEHOLDER, fst.nodes)
     line_margin = s.line_offset + length(fst) + fst.extra_margin
@@ -489,16 +563,16 @@ function n_binaryopcall!(fst::FST, s::State)
 
         # rhs
         fst[end].extra_margin = fst.extra_margin
-        nest!(fst[end], s)
+        nest!(style, fst[end], s)
 
         # "lhs op" rhs
         s.line_offset = line_offset
 
         # extra margin for " op"
         fst[1].extra_margin = length(fst[2]) + length(fst[3])
-        nest!(fst[1], s)
+        nest!(style, fst[1], s)
         for n in fst[2:i1]
-            nest!(n, s)
+            nest!(style, n, s)
         end
 
         # Undo nest if possible
@@ -581,26 +655,29 @@ function n_binaryopcall!(fst::FST, s::State)
                 s.line_offset = fst.indent
             elseif i == 1
                 n.extra_margin = return_width + fst.extra_margin
-                nest!(n, s)
+                nest!(style, n, s)
             elseif i == idx
                 n.extra_margin = fst.extra_margin
-                nest!(n, s)
+                nest!(style, n, s)
             else
                 n.extra_margin = fst.extra_margin
-                nest!(n, s)
+                nest!(style, n, s)
             end
         end
     end
 end
+n_binaryopcall!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_binaryopcall!(DefaultStyle(style), fst, s)
 
-function n_for!(fst::FST, s::State)
+function n_for!(ds::DefaultStyle, fst::FST, s::State)
+    style = getstyle(ds)
     block_idx = findfirst(n -> !is_leaf(n), fst.nodes)
     if block_idx === nothing
-        nest!(fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
         return
     end
     ph_idx = findfirst(n -> n.typ === PLACEHOLDER, fst[block_idx].nodes)
-    nest!(fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+    nest!(style, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
 
     # return if the argument block was nested
     ph_idx !== nothing && fst[3][ph_idx].typ === NEWLINE && return
@@ -612,9 +689,15 @@ function n_for!(fst::FST, s::State)
         res == (0, "") && deleteat!(fst.nodes, idx - 1)
     end
 end
-n_let!(fst::FST, s::State) = n_for!(fst, s)
+n_for!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_for!(DefaultStyle(style), fst, s)
+
+@inline n_let!(ds::DefaultStyle, fst::FST, s::State) = n_for!(ds, fst, s)
+n_let!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_let!(DefaultStyle(style), fst, s)
 
-function n_block!(fst::FST, s::State; custom_indent = 0)
+function n_block!(ds::DefaultStyle, fst::FST, s::State; custom_indent = 0)
+    style = getstyle(ds)
     line_margin = s.line_offset + length(fst) + fst.extra_margin
     idx = findfirst(n -> n.typ === PLACEHOLDER, fst.nodes)
     # @info "ENTERING" idx fst.typ s.line_offset length(fst) fst.extra_margin
@@ -633,25 +716,41 @@ function n_block!(fst::FST, s::State; custom_indent = 0)
             elseif n.typ === TRAILINGCOMMA
                 n.val = ","
                 n.len = 1
-                nest!(n, s)
+                nest!(style, n, s)
             elseif n.typ === TRAILINGSEMICOLON
                 n.val = ""
                 n.len = 0
-                nest!(n, s)
+                nest!(style, n, s)
             else
                 diff = fst.indent - fst[i].indent
                 add_indent!(n, s, diff)
                 n.extra_margin = 1
-                nest!(n, s)
+                nest!(style, n, s)
             end
         end
 
         # @info "EXITING" fst.typ s.line_offset fst.indent fst[end].indent
     else
-        nest!(fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+        nest!(style, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
     end
 end
-n_generator!(fst::FST, s::State) = n_block!(fst, s, custom_indent = fst.indent)
-n_filter!(fst::FST, s::State) = n_block!(fst, s, custom_indent = fst.indent)
-n_comparison!(fst::FST, s::State) = n_block!(fst, s)
-n_chainopcall!(fst::FST, s::State) = n_block!(fst, s)
+n_block!(style::S, fst::FST, s::State; custom_indent = 0) where {S<:AbstractStyle} =
+    n_block!(DefaultStyle(style), fst, s, custom_indent = custom_indent)
+
+@inline n_generator!(ds::DefaultStyle, fst::FST, s::State) =
+    n_block!(ds, fst, s, custom_indent = fst.indent)
+n_generator!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_generator!(DefaultStyle(style), fst, s)
+
+@inline n_filter!(ds::DefaultStyle, fst::FST, s::State) =
+    n_block!(ds, fst, s, custom_indent = fst.indent)
+n_filter!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_filter!(DefaultStyle(style), fst, s)
+
+@inline n_comparison!(ds::DefaultStyle, fst::FST, s::State) = n_block!(ds, fst, s)
+n_comparison!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_comparison!(DefaultStyle(style), fst, s)
+
+@inline n_chainopcall!(ds::DefaultStyle, fst::FST, s::State) = n_block!(ds, fst, s)
+n_chainopcall!(style::S, fst::FST, s::State) where {S<:AbstractStyle} =
+    n_chainopcall!(DefaultStyle(style), fst, s)
diff --git a/src/pretty.jl b/src/pretty.jl
index eca0d14f..31bc8999 100644
--- a/src/pretty.jl
+++ b/src/pretty.jl
@@ -37,42 +37,43 @@ function FST(cst::CSTParser.Head, startline::Integer, endline::Integer, val::Abs
     FST(cst, startline, endline, 0, length(val), val, nothing, nothing, false, 0)
 end
 
-Base.setindex!(fst::FST, node::FST, ind::Int) = fst.nodes[ind] = node
-Base.getindex(fst::FST, inds...) = fst.nodes[inds...]
-Base.lastindex(fst::FST) = length(fst.nodes)
+@inline Base.setindex!(fst::FST, node::FST, ind::Int) = fst.nodes[ind] = node
+@inline Base.getindex(fst::FST, inds...) = fst.nodes[inds...]
+@inline Base.lastindex(fst::FST) = length(fst.nodes)
 
 
-Newline(; length = 0, force_nest = false) =
+@inline Newline(; length = 0, force_nest = false) =
     FST(NEWLINE, -1, -1, 0, length, "\n", nothing, nothing, force_nest, 0)
-Semicolon() = FST(SEMICOLON, -1, -1, 0, 1, ";", nothing, nothing, false, 0)
-TrailingComma() = FST(TRAILINGCOMMA, -1, -1, 0, 0, "", nothing, nothing, false, 0)
-TrailingSemicolon() = FST(TRAILINGSEMICOLON, -1, -1, 0, 1, ";", nothing, nothing, false, 0)
-Whitespace(n) = FST(WHITESPACE, -1, -1, 0, n, " "^n, nothing, nothing, false, 0)
-Placeholder(n) = FST(PLACEHOLDER, -1, -1, 0, n, " "^n, nothing, nothing, false, 0)
-Notcode(startline, endline) =
+@inline Semicolon() = FST(SEMICOLON, -1, -1, 0, 1, ";", nothing, nothing, false, 0)
+@inline TrailingComma() = FST(TRAILINGCOMMA, -1, -1, 0, 0, "", nothing, nothing, false, 0)
+@inline TrailingSemicolon() =
+    FST(TRAILINGSEMICOLON, -1, -1, 0, 1, ";", nothing, nothing, false, 0)
+@inline Whitespace(n) = FST(WHITESPACE, -1, -1, 0, n, " "^n, nothing, nothing, false, 0)
+@inline Placeholder(n) = FST(PLACEHOLDER, -1, -1, 0, n, " "^n, nothing, nothing, false, 0)
+@inline Notcode(startline, endline) =
     FST(NOTCODE, startline, endline, 0, 0, "", nothing, nothing, false, 0)
-InlineComment(line) = FST(INLINECOMMENT, line, line, 0, 0, "", nothing, nothing, false, 0)
+@inline InlineComment(line) =
+    FST(INLINECOMMENT, line, line, 0, 0, "", nothing, nothing, false, 0)
 
-Base.length(fst::FST) = fst.len
+@inline Base.length(fst::FST) = fst.len
 
-is_leaf(cst::CSTParser.EXPR) = cst.args === nothing
-is_leaf(fst::FST) = fst.nodes === nothing
-empty_start(fst::FST) = fst.startline == 1 && fst.endline == 1 && fst.val == ""
+@inline is_leaf(cst::CSTParser.EXPR) = cst.args === nothing
+@inline is_leaf(fst::FST) = fst.nodes === nothing
 
-is_punc(x) = CSTParser.ispunctuation(x)
-is_end(x) = x.typ === CSTParser.KEYWORD && x.val == "end"
-is_colon(x) = x.typ === CSTParser.OPERATOR && x.val == ":"
-is_comma(fst::FST) =
+@inline is_punc(cst::CSTParser.EXPR) = CSTParser.ispunctuation(cst)
+@inline is_end(x) = x.typ === CSTParser.KEYWORD && x.val == "end"
+@inline is_colon(x) = x.typ === CSTParser.OPERATOR && x.val == ":"
+@inline is_comma(fst::FST) =
     (fst.typ === CSTParser.PUNCTUATION && fst.val == ",") || fst.typ === TRAILINGCOMMA
-is_comment(fst::FST) = fst.typ === INLINECOMMENT || fst.typ === NOTCODE
+@inline is_comment(fst::FST) = fst.typ === INLINECOMMENT || fst.typ === NOTCODE
 
-is_colon_op(x) =
-    (x.typ === CSTParser.BinaryOpCall && x[2].kind === Tokens.COLON) ||
-    x.typ === CSTParser.ColonOpCall
+@inline is_colon_op(cst::CSTParser.EXPR) =
+    (cst.typ === CSTParser.BinaryOpCall && cst[2].kind === Tokens.COLON) ||
+    cst.typ === CSTParser.ColonOpCall
 
-is_lazy_op(x) =
-    x.typ === CSTParser.BinaryOpCall &&
-    (x[2].kind === Tokens.LAZY_OR || x[2].kind === Tokens.LAZY_AND)
+@inline is_lazy_op(cst::CSTParser.EXPR) =
+    cst.typ === CSTParser.BinaryOpCall &&
+    (cst[2].kind === Tokens.LAZY_OR || cst[2].kind === Tokens.LAZY_AND)
 
 function is_multiline(fst::FST)
     fst.typ === CSTParser.StringH && return true
@@ -289,7 +290,7 @@ function add_node!(t::FST, n::FST, s::State; join_lines = false, max_padding = -
     nothing
 end
 
-function is_prev_newline(fst::FST)
+@inline function is_prev_newline(fst::FST)
     if fst.typ === NEWLINE
         return true
     elseif is_leaf(fst) || length(fst.nodes) == 0
@@ -303,7 +304,7 @@ end
 
 Returns the length to any node type in `ntyps` based off the `start` index.
 """
-function length_to(fst::FST, ntyps::Vector; start::Int = 1)
+@inline function length_to(fst::FST, ntyps::Vector; start::Int = 1)
     fst.typ in ntyps && return 0, true
     is_leaf(fst) && return length(fst), false
     len = 0
@@ -315,168 +316,186 @@ function length_to(fst::FST, ntyps::Vector; start::Int = 1)
     return len, false
 end
 
-is_closer(fst::FST) =
+@inline is_closer(fst::FST) =
     fst.typ === CSTParser.PUNCTUATION &&
     (fst.val == "}" || fst.val == ")" || fst.val == "]")
-is_closer(cst::CSTParser.EXPR) =
+@inline is_closer(cst::CSTParser.EXPR) =
     cst.kind === Tokens.RBRACE || cst.kind === Tokens.RPAREN || cst.kind === Tokens.RSQUARE
 
-is_opener(fst::FST) =
+@inline is_opener(fst::FST) =
     fst.typ === CSTParser.PUNCTUATION &&
     (fst.val == "{" || fst.val == "(" || fst.val == "[")
-is_opener(cst::CSTParser.EXPR) =
+@inline is_opener(cst::CSTParser.EXPR) =
     cst.kind === Tokens.LBRACE || cst.kind === Tokens.LPAREN || cst.kind === Tokens.LSQUARE
 
-function pretty(cst::CSTParser.EXPR, s::State)
+function pretty(ds::DefaultStyle, cst::CSTParser.EXPR, s::State; kwargs...)
+    style = getstyle(ds)
     if cst.typ === CSTParser.IDENTIFIER
-        return p_identifier(cst, s)
+        return p_identifier(style, cst, s)
     elseif cst.typ === CSTParser.OPERATOR
-        return p_operator(cst, s)
+        return p_operator(style, cst, s)
     elseif cst.typ === CSTParser.PUNCTUATION
-        return p_punctuation(cst, s)
+        return p_punctuation(style, cst, s)
     elseif cst.typ === CSTParser.KEYWORD
-        return p_keyword(cst, s)
+        return p_keyword(style, cst, s)
     elseif cst.typ === CSTParser.LITERAL
-        return p_literal(cst, s)
+        return p_literal(style, cst, s)
     elseif cst.typ === CSTParser.StringH
-        return p_stringh(cst, s)
+        return p_stringh(style, cst, s)
     elseif cst.typ === CSTParser.Block
-        return p_block(cst, s)
+        return p_block(style, cst, s; kwargs...)
     elseif cst.typ === CSTParser.ModuleH
-        return p_module(cst, s)
+        return p_module(style, cst, s)
     elseif cst.typ === CSTParser.BareModule
-        return p_baremodule(cst, s)
+        return p_baremodule(style, cst, s)
     elseif cst.typ === CSTParser.FunctionDef
-        return p_functiondef(cst, s)
+        return p_functiondef(style, cst, s)
     elseif cst.typ === CSTParser.Macro
-        return p_macro(cst, s)
+        return p_macro(style, cst, s)
     elseif cst.typ === CSTParser.Primitive
-        return p_primitive(cst, s)
+        return p_primitive(style, cst, s)
     elseif cst.typ === CSTParser.Struct
-        return p_struct(cst, s)
+        return p_struct(style, cst, s)
     elseif cst.typ === CSTParser.Mutable
-        return p_mutable(cst, s)
+        return p_mutable(style, cst, s)
     elseif cst.typ === CSTParser.Abstract
-        return p_abstract(cst, s)
+        return p_abstract(style, cst, s)
     elseif cst.typ === CSTParser.Primitive
-        return p_primitive(cst, s)
+        return p_primitive(style, cst, s)
     elseif cst.typ === CSTParser.For
-        return p_for(cst, s)
+        return p_for(style, cst, s)
     elseif cst.typ === CSTParser.While
-        return p_while(cst, s)
+        return p_while(style, cst, s)
     elseif cst.typ === CSTParser.Do
-        return p_do(cst, s)
+        return p_do(style, cst, s)
     elseif cst.typ === CSTParser.If
-        return p_if(cst, s)
+        return p_if(style, cst, s)
     elseif cst.typ === CSTParser.Try
-        return p_try(cst, s)
+        return p_try(style, cst, s)
     elseif cst.typ === CSTParser.TopLevel
-        return p_toplevel(cst, s)
+        return p_toplevel(style, cst, s)
     elseif cst.typ === CSTParser.Begin
-        return p_begin(cst, s)
+        return p_begin(style, cst, s)
     elseif cst.typ === CSTParser.Quote
-        return p_quote(cst, s)
+        return p_quote(style, cst, s)
     elseif cst.typ === CSTParser.Let
-        return p_let(cst, s)
+        return p_let(style, cst, s)
     elseif cst.typ === CSTParser.Vect
-        return p_vect(cst, s)
+        return p_vect(style, cst, s)
     elseif cst.typ === CSTParser.Comprehension
-        return p_comprehension(cst, s)
+        return p_comprehension(style, cst, s)
     elseif cst.typ === CSTParser.Braces
-        return p_braces(cst, s)
+        return p_braces(style, cst, s)
     elseif cst.typ === CSTParser.TupleH
-        return p_tupleh(cst, s)
+        return p_tupleh(style, cst, s)
     elseif cst.typ === CSTParser.InvisBrackets
-        return p_invisbrackets(cst, s)
+        return p_invisbrackets(style, cst, s; kwargs...)
     elseif cst.typ === CSTParser.Curly
-        return p_curly(cst, s)
+        return p_curly(style, cst, s)
     elseif cst.typ === CSTParser.Call
-        return p_call(cst, s)
+        return p_call(style, cst, s)
     elseif cst.typ === CSTParser.MacroCall
-        return p_macrocall(cst, s)
+        return p_macrocall(style, cst, s)
     elseif cst.typ === CSTParser.WhereOpCall
-        return p_whereopcall(cst, s)
+        return p_whereopcall(style, cst, s)
     elseif cst.typ === CSTParser.ConditionalOpCall
-        return p_conditionalopcall(cst, s)
+        return p_conditionalopcall(style, cst, s)
     elseif cst.typ === CSTParser.BinaryOpCall
-        return p_binaryopcall(cst, s)
+        return p_binaryopcall(style, cst, s; kwargs...)
     elseif cst.typ === CSTParser.UnaryOpCall
-        return p_unaryopcall(cst, s)
+        return p_unaryopcall(style, cst, s; kwargs...)
     elseif cst.typ === CSTParser.ChainOpCall
-        return p_chainopcall(cst, s)
-    elseif cst.typ === CSTParser.ColonOpCall
-        return p_colonopcall(cst, s)
+        return p_chainopcall(style, cst, s; kwargs...)
     elseif cst.typ === CSTParser.Comparison
-        return p_comparison(cst, s)
+        return p_comparison(style, cst, s; kwargs...)
+    elseif cst.typ === CSTParser.ColonOpCall
+        return p_colonopcall(style, cst, s)
     elseif cst.typ === CSTParser.Kw
-        return p_kw(cst, s)
+        return p_kw(style, cst, s)
     elseif cst.typ === CSTParser.Parameters
-        return p_parameters(cst, s)
+        return p_parameters(style, cst, s)
     elseif cst.typ === CSTParser.Local
-        return p_local(cst, s)
+        return p_local(style, cst, s)
     elseif cst.typ === CSTParser.Global
-        return p_global(cst, s)
+        return p_global(style, cst, s)
     elseif cst.typ === CSTParser.Const
-        return p_const(cst, s)
+        return p_const(style, cst, s)
     elseif cst.typ === CSTParser.Return
-        return p_return(cst, s)
+        return p_return(style, cst, s)
     elseif cst.typ === CSTParser.Import
-        return p_import(cst, s)
+        return p_import(style, cst, s)
     elseif cst.typ === CSTParser.Export
-        return p_export(cst, s)
+        return p_export(style, cst, s)
     elseif cst.typ === CSTParser.Using
-        return p_using(cst, s)
+        return p_using(style, cst, s)
     elseif cst.typ === CSTParser.Row
-        return p_row(cst, s)
+        return p_row(style, cst, s)
     elseif cst.typ === CSTParser.Vcat
-        return p_vcat(cst, s)
+        return p_vcat(style, cst, s)
     elseif cst.typ === CSTParser.TypedVcat
-        return p_typedvcat(cst, s)
+        return p_typedvcat(style, cst, s)
     elseif cst.typ === CSTParser.Hcat
-        return p_hcat(cst, s)
+        return p_hcat(style, cst, s)
     elseif cst.typ === CSTParser.TypedHcat
-        return p_typedhcat(cst, s)
+        return p_typedhcat(style, cst, s)
     elseif cst.typ === CSTParser.Ref
-        return p_ref(cst, s)
+        return p_ref(style, cst, s)
     elseif cst.typ === CSTParser.Generator
-        return p_generator(cst, s)
+        return p_generator(style, cst, s)
     elseif cst.typ === CSTParser.Filter
-        return p_filter(cst, s)
+        return p_filter(style, cst, s)
+    elseif cst.typ === CSTParser.FileH
+        return p_fileh(style, cst, s)
     end
 
     t = FST(cst, nspaces(s))
-    is_fileh = cst.typ === CSTParser.FileH
     for a in cst
         if a.kind === Tokens.NOTHING
             s.offset += a.fullspan
             continue
         end
-        # @debug "" a a.typ
-        add_node!(
-            t,
-            pretty(a, s),
-            s,
-            join_lines = !is_fileh,
-            max_padding = is_fileh ? 0 : -1,
-        )
+        add_node!(t, pretty(style, a, s), s, join_lines = true)
+    end
+    t
+end
+pretty(style::S, cst::CSTParser.EXPR, s::State; kwargs...) where {S<:AbstractStyle} =
+    pretty(DefaultStyle(style), cst, s; kwargs...)
+
+function p_fileh(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    t = FST(cst, nspaces(s))
+    for a in cst
+        if a.kind === Tokens.NOTHING
+            s.offset += a.fullspan
+            continue
+        end
+        add_node!(t, pretty(ds, a, s), s, join_lines = false, max_padding = 0)
     end
     t
 end
+p_fileh(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_fileh(DefaultStyle(style), cst, s)
 
-function p_identifier(cst::CSTParser.EXPR, s::State)
+@inline function p_identifier(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     loc = cursor_loc(s)
     s.offset += cst.fullspan
     FST(cst, loc[1], loc[1], cst.val)
 end
+p_identifier(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_identifier(DefaultStyle(style), cst, s)
 
-function p_operator(cst::CSTParser.EXPR, s::State)
+@inline function p_operator(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     loc = cursor_loc(s)
     val = string(CSTParser.Expr(cst))
     s.offset += cst.fullspan
     FST(cst, loc[1], loc[1], val)
 end
+p_operator(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_operator(DefaultStyle(style), cst, s)
 
-function p_keyword(cst::CSTParser.EXPR, s::State)
+@inline function p_keyword(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     loc = cursor_loc(s)
     val = cst.kind === Tokens.ABSTRACT ? "abstract" :
         cst.kind === Tokens.BAREMODULE ? "baremodule" :
@@ -513,8 +532,11 @@ function p_keyword(cst::CSTParser.EXPR, s::State)
     s.offset += cst.fullspan
     FST(cst, loc[1], loc[1], val)
 end
+p_keyword(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_keyword(DefaultStyle(style), cst, s)
 
-function p_punctuation(cst::CSTParser.EXPR, s::State)
+@inline function p_punctuation(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     loc = cursor_loc(s)
     val = cst.kind === Tokens.LPAREN ? "(" :
         cst.kind === Tokens.LBRACE ? "{" :
@@ -528,8 +550,11 @@ function p_punctuation(cst::CSTParser.EXPR, s::State)
     s.offset += cst.fullspan
     FST(cst, loc[1], loc[1], val)
 end
+p_punctuation(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_punctuation(DefaultStyle(style), cst, s)
 
-function p_literal(cst::CSTParser.EXPR, s::State)
+@inline function p_literal(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     loc = cursor_loc(s)
     if !is_str_or_cmd(cst.kind)
         val = cst.val
@@ -599,9 +624,12 @@ function p_literal(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_literal(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_literal(DefaultStyle(style), cst, s)
 
 # StringH
-function p_stringh(cst::CSTParser.EXPR, s::State)
+function p_stringh(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     loc = cursor_loc(s)
     startline, endline, str = s.doc.lit_strings[s.offset-1]
 
@@ -645,26 +673,28 @@ function p_stringh(cst::CSTParser.EXPR, s::State)
     end
     t
 end
-
+p_stringh(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_stringh(DefaultStyle(style), cst, s)
 
 # MacroCall
-function p_macrocall(cst::CSTParser.EXPR, s::State)
+function p_macrocall(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     if cst[1].typ === CSTParser.GlobalRefDoc
         # cst[1] is empty and fullspan is 0 so we can skip it
         if cst[2].typ === CSTParser.LITERAL
-            add_node!(t, p_literal(cst[2], s), s, max_padding = 0)
+            add_node!(t, p_literal(style, cst[2], s), s, max_padding = 0)
         elseif cst[2].typ == CSTParser.StringH
-            add_node!(t, p_stringh(cst[2], s), s)
+            add_node!(t, p_stringh(style, cst[2], s), s)
         end
-        add_node!(t, pretty(cst[3], s), s, max_padding = 0)
+        add_node!(t, pretty(style, cst[3], s), s, max_padding = 0)
         return t
     elseif length(cst) == 3 &&
            cst[1].typ === CSTParser.MacroName && cst[1][2].val == "doc" && is_str(cst[2])
-        add_node!(t, pretty(cst[1], s), s)
+        add_node!(t, pretty(style, cst[1], s), s)
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[2], s), s, join_lines = true)
-        n = pretty(cst[3], s)
+        add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
+        n = pretty(style, cst[3], s)
         join_lines = t.endline == n.startline
         join_lines && add_node!(t, Whitespace(1), s)
         add_node!(t, n, s, join_lines = join_lines, max_padding = 0)
@@ -679,7 +709,7 @@ function p_macrocall(cst::CSTParser.EXPR, s::State)
 
     # same as CSTParser.Call but whitespace sensitive
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         if a.typ === CSTParser.MacroName
             if a.fullspan - a.span > 0 && length(cst) > 1
                 add_node!(t, n, s, join_lines = true)
@@ -717,23 +747,27 @@ function p_macrocall(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_macrocall(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_macrocall(DefaultStyle(style), cst, s)
 
 # Block
 # length Block is the length of the longest expr
 function p_block(
+    ds::DefaultStyle,
     cst::CSTParser.EXPR,
     s::State;
     ignore_single_line = false,
     from_quote = false,
     join_body = false,
 )
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     single_line = ignore_single_line ? false :
         cursor_loc(s)[1] == cursor_loc(s, s.offset + cst.span - 1)[1]
 
     # @info "" from_quote single_line ignore_single_line join_body
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         if from_quote && !single_line
             if i == 1 || CSTParser.is_comma(a)
                 add_node!(t, n, s, join_lines = true)
@@ -770,208 +804,256 @@ function p_block(
     end
     t
 end
+p_block(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_block(DefaultStyle(style), cst, s)
 
 # Abstract
-function p_abstract(cst::CSTParser.EXPR, s::State)
+function p_abstract(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[3], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[4], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[4], s), s, join_lines = true)
     t
 end
+p_abstract(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_abstract(DefaultStyle(style), cst, s)
 
 # Primitive
-function p_primitive(cst::CSTParser.EXPR, s::State)
+function p_primitive(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[3], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[4], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[4], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[5], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[5], s), s, join_lines = true)
     t
 end
+p_primitive(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_primitive(DefaultStyle(style), cst, s)
 
 # FunctionDef/Macro
-function p_functiondef(cst::CSTParser.EXPR, s::State)
+function p_functiondef(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     if length(cst) > 3
         if cst[3].fullspan == 0
             add_node!(t, Whitespace(1), s)
-            add_node!(t, pretty(cst[4], s), s, join_lines = true)
+            add_node!(t, pretty(style, cst[4], s), s, join_lines = true)
         else
             s.indent += s.indent_size
             add_node!(
                 t,
-                p_block(cst[3], s, ignore_single_line = true),
+                pretty(style, cst[3], s, ignore_single_line = true),
                 s,
                 max_padding = s.indent_size,
             )
             s.indent -= s.indent_size
-            add_node!(t, pretty(cst[4], s), s)
+            add_node!(t, pretty(style, cst[4], s), s)
         end
     else
         # function stub, i.e. "function foo end"
         # this should be on one line
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[3], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
     end
     t
 end
-p_macro(cst::CSTParser.EXPR, s::State) = p_functiondef(cst, s)
+p_functiondef(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_functiondef(DefaultStyle(style), cst, s)
+
+@inline p_macro(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_functiondef(ds, cst, s)
+p_macro(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_macro(DefaultStyle(style), cst, s)
 
 # Struct
-function p_struct(cst::CSTParser.EXPR, s::State)
+function p_struct(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     if cst[3].fullspan == 0
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[4], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[4], s), s, join_lines = true)
     else
         s.indent += s.indent_size
         add_node!(
             t,
-            p_block(cst[3], s, ignore_single_line = true),
+            pretty(style, cst[3], s, ignore_single_line = true),
             s,
             max_padding = s.indent_size,
         )
         s.indent -= s.indent_size
-        add_node!(t, pretty(cst[4], s), s)
+        add_node!(t, pretty(style, cst[4], s), s)
     end
     t
 end
+p_struct(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_struct(DefaultStyle(style), cst, s)
 
 # Mutable
-function p_mutable(cst::CSTParser.EXPR, s::State)
+function p_mutable(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[3], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
     if cst[4].fullspan == 0
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[5], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[5], s), s, join_lines = true)
     else
         s.indent += s.indent_size
         add_node!(
             t,
-            p_block(cst[4], s, ignore_single_line = true),
+            pretty(style, cst[4], s, ignore_single_line = true),
             s,
             max_padding = s.indent_size,
         )
         s.indent -= s.indent_size
-        add_node!(t, pretty(cst[5], s), s)
+        add_node!(t, pretty(style, cst[5], s), s)
     end
     t
 end
+p_mutable(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_mutable(DefaultStyle(style), cst, s)
 
 # ModuleH/BareModule
-function p_module(cst::CSTParser.EXPR, s::State)
+function p_module(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     if cst[3].fullspan == 0
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[4], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[4], s), s, join_lines = true)
     else
-        add_node!(t, pretty(cst[3], s), s, max_padding = 0)
-        add_node!(t, pretty(cst[4], s), s)
+        add_node!(t, pretty(style, cst[3], s), s, max_padding = 0)
+        add_node!(t, pretty(style, cst[4], s), s)
     end
     t
 end
-p_baremodule(cst::CSTParser.EXPR, s::State) = p_module(cst, s)
+p_module(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_module(DefaultStyle(style), cst, s)
+
+@inline p_baremodule(style::DefaultStyle, cst::CSTParser.EXPR, s::State) =
+    p_module(style, cst, s)
+p_baremodule(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_baremodule(DefaultStyle(style), cst, s)
 
 # Const/Local/Global/Return
-function p_const(cst::CSTParser.EXPR, s::State)
+function p_const(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     if cst[2].fullspan != 0
         for a in cst.args[2:end]
             add_node!(t, Whitespace(1), s)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
-p_local(cst::CSTParser.EXPR, s::State) = p_const(cst, s)
-p_global(cst::CSTParser.EXPR, s::State) = p_const(cst, s)
-p_return(cst::CSTParser.EXPR, s::State) = p_const(cst, s)
+p_const(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_const(DefaultStyle(style), cst, s)
+
+@inline p_local(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_const(ds, cst, s)
+p_local(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_local(DefaultStyle(style), cst, s)
+
+@inline p_global(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_const(ds, cst, s)
+p_global(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_global(DefaultStyle(style), cst, s)
+
+@inline p_return(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_const(ds, cst, s)
+p_return(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_return(DefaultStyle(style), cst, s)
 
 # TopLevel
-function p_toplevel(cst::CSTParser.EXPR, s::State)
+function p_toplevel(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     for a in cst.args
         if a.kind === Tokens.NOTHING
             s.offset += a.fullspan
             continue
         end
-        add_node!(t, pretty(a, s), s, max_padding = s.indent_size)
+        add_node!(t, pretty(style, a, s), s, max_padding = s.indent_size)
         add_node!(t, Semicolon(), s)
     end
     t
 end
+p_toplevel(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_toplevel(DefaultStyle(style), cst, s)
 
 # Begin
-function p_begin(cst::CSTParser.EXPR, s::State)
+function p_begin(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     if cst[2].fullspan == 0
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[3], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
     else
         s.indent += s.indent_size
         add_node!(
             t,
-            p_block(cst[2], s, ignore_single_line = true),
+            pretty(style, cst[2], s, ignore_single_line = true),
             s,
             max_padding = s.indent_size,
         )
         s.indent -= s.indent_size
-        add_node!(t, pretty(cst[3], s), s)
+        add_node!(t, pretty(style, cst[3], s), s)
     end
     t
 end
+p_begin(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_begin(DefaultStyle(style), cst, s)
 
 # Quote
-function p_quote(cst::CSTParser.EXPR, s::State)
+function p_quote(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     if cst[1].typ === CSTParser.KEYWORD && cst[1].kind === Tokens.QUOTE
-        add_node!(t, pretty(cst[1], s), s)
+        add_node!(t, pretty(style, cst[1], s), s)
         if cst[2].fullspan == 0
             add_node!(t, Whitespace(1), s)
-            add_node!(t, pretty(cst[3], s), s, join_lines = true)
+            add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
         else
             s.indent += s.indent_size
             add_node!(
                 t,
-                p_block(cst[2], s, ignore_single_line = true),
+                pretty(style, cst[2], s, ignore_single_line = true),
                 s,
                 max_padding = s.indent_size,
             )
             s.indent -= s.indent_size
-            add_node!(t, pretty(cst[3], s), s)
+            add_node!(t, pretty(style, cst[3], s), s)
         end
     else
         for a in cst.args
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
+p_quote(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_quote(DefaultStyle(style), cst, s)
 
 # Let
 #
@@ -984,16 +1066,17 @@ end
 # y, back = let
 #     body
 # end
-function p_let(cst::CSTParser.EXPR, s::State)
+function p_let(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     if length(cst.args) > 3
         add_node!(t, Whitespace(1), s)
         s.indent += s.indent_size
         if cst[2].typ === CSTParser.Block
-            add_node!(t, p_block(cst[2], s, join_body = true), s, join_lines = true)
+            add_node!(t, pretty(style, cst[2], s, join_body = true), s, join_lines = true)
         else
-            add_node!(t, pretty(cst[2], s), s, join_lines = true)
+            add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
         end
         s.indent -= s.indent_size
 
@@ -1001,7 +1084,7 @@ function p_let(cst::CSTParser.EXPR, s::State)
         s.indent += s.indent_size
         add_node!(
             t,
-            p_block(cst[3], s, ignore_single_line = true),
+            pretty(style, cst[3], s, ignore_single_line = true),
             s,
             max_padding = s.indent_size,
         )
@@ -1011,16 +1094,17 @@ function p_let(cst::CSTParser.EXPR, s::State)
         if cst[2].typ === CSTParser.Block && t.nodes[end-2].typ !== NOTCODE
             add_node!(t.nodes[idx], Placeholder(0), s)
         end
-        add_node!(t, pretty(cst.args[end], s), s)
+        add_node!(t, pretty(style, cst.args[end], s), s)
     else
         s.indent += s.indent_size
-        add_node!(t, p_block(cst[2], s, ignore_single_line = true), s)
+        add_node!(t, pretty(style, cst[2], s, ignore_single_line = true), s)
         s.indent -= s.indent_size
-        add_node!(t, pretty(cst.args[end], s), s)
+        add_node!(t, pretty(style, cst.args[end], s), s)
     end
     t
 end
-
+p_let(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_let(DefaultStyle(style), cst, s)
 
 
 # Transforms
@@ -1063,25 +1147,26 @@ function eq_to_in_normalization!(cst::CSTParser.EXPR, always_for_in::Bool)
 end
 
 # For/While
-function p_for(cst::CSTParser.EXPR, s::State)
+function p_for(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
     if cst[1].kind === Tokens.FOR
         eq_to_in_normalization!(cst[2], s.opts.always_for_in)
     end
     if cst[2].typ === CSTParser.Block
         s.indent += s.indent_size
-        add_node!(t, p_block(cst[2], s, join_body = true), s, join_lines = true)
+        add_node!(t, pretty(style, cst[2], s, join_body = true), s, join_lines = true)
         s.indent -= s.indent_size
     else
-        add_node!(t, pretty(cst[2], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     end
     idx = length(t.nodes)
     s.indent += s.indent_size
     add_node!(
         t,
-        p_block(cst[3], s, ignore_single_line = true),
+        pretty(style, cst[3], s, ignore_single_line = true),
         s,
         max_padding = s.indent_size,
     )
@@ -1092,47 +1177,56 @@ function p_for(cst::CSTParser.EXPR, s::State)
     if cst[2].typ === CSTParser.Block && t.nodes[end-2].typ !== NOTCODE
         add_node!(t.nodes[idx], Placeholder(0), s)
     end
-    add_node!(t, pretty(cst[4], s), s)
+    add_node!(t, pretty(style, cst[4], s), s)
     t
 end
-p_while(cst::CSTParser.EXPR, s::State) = p_for(cst, s)
+p_for(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_for(DefaultStyle(style), cst, s)
+
+@inline p_while(style::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_for(style, cst, s)
+p_while(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_while(DefaultStyle(style), cst, s)
 
 # Do
-function p_do(cst::CSTParser.EXPR, s::State)
+function p_do(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     if cst[3].fullspan != 0
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[3], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
     end
     if cst[4].typ === CSTParser.Block
         s.indent += s.indent_size
         add_node!(
             t,
-            p_block(cst[4], s, ignore_single_line = true),
+            pretty(style, cst[4], s, ignore_single_line = true),
             s,
             max_padding = s.indent_size,
         )
         s.indent -= s.indent_size
     end
-    add_node!(t, pretty(cst.args[end], s), s)
+    add_node!(t, pretty(style, cst.args[end], s), s)
     t
 end
+p_do(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_do(DefaultStyle(style), cst, s)
 
 # Try
-function p_try(cst::CSTParser.EXPR, s::State)
+function p_try(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     for a in cst.args
         if a.fullspan == 0 && a.typ !== CSTParser.Block
         elseif a.typ === CSTParser.KEYWORD
-            add_node!(t, pretty(a, s), s, max_padding = 0)
+            add_node!(t, pretty(style, a, s), s, max_padding = 0)
         elseif a.typ === CSTParser.Block
             s.indent += s.indent_size
             add_node!(
                 t,
-                p_block(a, s, ignore_single_line = true),
+                pretty(style, a, s, ignore_single_line = true),
                 s,
                 max_padding = s.indent_size,
             )
@@ -1140,7 +1234,7 @@ function p_try(cst::CSTParser.EXPR, s::State)
         else
             len = length(t)
             add_node!(t, Whitespace(1), s)
-            n = pretty(a, s)
+            n = pretty(style, a, s)
             # "catch n"
             t.len = max(len, 5 + 1 + length(n))
             add_node!(t, n, s, join_lines = true, max_padding = 0)
@@ -1148,18 +1242,21 @@ function p_try(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_try(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_try(DefaultStyle(style), cst, s)
 
 # If
-function p_if(cst::CSTParser.EXPR, s::State)
+function p_if(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     if cst[1].typ === CSTParser.KEYWORD && cst[1].kind === Tokens.IF
-        add_node!(t, pretty(cst[1], s), s)
+        add_node!(t, pretty(style, cst[1], s), s)
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(cst[2], s), s, join_lines = true)
+        add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
         s.indent += s.indent_size
         add_node!(
             t,
-            p_block(cst[3], s, ignore_single_line = true),
+            pretty(style, cst[3], s, ignore_single_line = true),
             s,
             max_padding = s.indent_size,
         )
@@ -1167,10 +1264,10 @@ function p_if(cst::CSTParser.EXPR, s::State)
 
         len = length(t)
         if length(cst.args) > 4
-            add_node!(t, pretty(cst[4], s), s, max_padding = 0)
+            add_node!(t, pretty(style, cst[4], s), s, max_padding = 0)
             if cst[4].kind === Tokens.ELSEIF
                 add_node!(t, Whitespace(1), s)
-                n = pretty(cst[5], s)
+                n = pretty(style, cst[5], s)
                 add_node!(t, n, s, join_lines = true)
                 # "elseif n"
                 t.len = max(len, length(n))
@@ -1179,7 +1276,7 @@ function p_if(cst::CSTParser.EXPR, s::State)
                 s.indent += s.indent_size
                 add_node!(
                     t,
-                    p_block(cst[5], s, ignore_single_line = true),
+                    pretty(style, cst[5], s, ignore_single_line = true),
                     s,
                     max_padding = s.indent_size,
                 )
@@ -1187,16 +1284,16 @@ function p_if(cst::CSTParser.EXPR, s::State)
             end
         end
         # END KEYWORD
-        add_node!(t, pretty(cst.args[end], s), s)
+        add_node!(t, pretty(style, cst.args[end], s), s)
     else
         # "cond" part of "elseif cond"
         t.len += 7
-        add_node!(t, pretty(cst[1], s), s)
+        add_node!(t, pretty(style, cst[1], s), s)
 
         s.indent += s.indent_size
         add_node!(
             t,
-            p_block(cst[2], s, ignore_single_line = true),
+            pretty(style, cst[2], s, ignore_single_line = true),
             s,
             max_padding = s.indent_size,
         )
@@ -1205,11 +1302,11 @@ function p_if(cst::CSTParser.EXPR, s::State)
         len = length(t)
         if length(cst.args) > 2
             # this either else or elseif keyword
-            add_node!(t, pretty(cst[3], s), s, max_padding = 0)
+            add_node!(t, pretty(style, cst[3], s), s, max_padding = 0)
 
             if cst[3].kind === Tokens.ELSEIF
                 add_node!(t, Whitespace(1), s)
-                n = pretty(cst[4], s)
+                n = pretty(style, cst[4], s)
                 add_node!(t, n, s, join_lines = true)
                 # "elseif n"
                 t.len = max(len, length(n))
@@ -1217,7 +1314,7 @@ function p_if(cst::CSTParser.EXPR, s::State)
                 s.indent += s.indent_size
                 add_node!(
                     t,
-                    p_block(cst[4], s, ignore_single_line = true),
+                    pretty(style, cst[4], s, ignore_single_line = true),
                     s,
                     max_padding = s.indent_size,
                 )
@@ -1227,13 +1324,22 @@ function p_if(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_if(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_if(DefaultStyle(style), cst, s)
 
 # ChainOpCall/Comparison
-function p_chainopcall(cst::CSTParser.EXPR, s::State; nonest = false, nospace = false)
+function p_chainopcall(
+    ds::DefaultStyle,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     nws = nospace ? 0 : 1
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         if a.typ === CSTParser.OPERATOR
             !nospace && add_node!(t, Whitespace(1), s)
             add_node!(t, n, s, join_lines = true)
@@ -1250,22 +1356,45 @@ function p_chainopcall(cst::CSTParser.EXPR, s::State; nonest = false, nospace =
     end
     t
 end
-p_comparison(cst::CSTParser.EXPR, s::State; nonest = false, nospace = false) =
-    p_chainopcall(cst, s, nonest = nonest, nospace = nospace)
+p_chainopcall(
+    style::S,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+) where {S<:AbstractStyle} =
+    p_chainopcall(DefaultStyle(style), cst, s, nonest = nonest, nospace = nospace)
+
+@inline p_comparison(
+    ds::DefaultStyle,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+) = p_chainopcall(ds, cst, s, nonest = nonest, nospace = nospace)
+p_comparison(
+    style::S,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+) where {S<:AbstractStyle} =
+    p_comparison(DefaultStyle(style), cst, s, nonest = nonest, nospace = nospace)
 
 # ColonOpCall
-function p_colonopcall(cst::CSTParser.EXPR, s::State)
+function p_colonopcall(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     nospace = !s.opts.whitespace_ops_in_indices
     for a in cst
         if a.typ === CSTParser.BinaryOpCall
-            n = p_binaryopcall(a, s, nonest = true, nospace = nospace)
+            n = pretty(style, a, s, nonest = true, nospace = nospace)
         elseif a.typ === CSTParser.InvisBrackets
-            n = p_invisbrackets(a, s, nonest = true, nospace = nospace)
+            n = pretty(style, a, s, nonest = true, nospace = nospace)
         elseif a.typ === CSTParser.ChainOpCall || a.typ === CSTParser.Comparison
-            n = p_chainopcall(a, s, nonest = true, nospace = nospace)
+            n = pretty(style, a, s, nonest = true, nospace = nospace)
         else
-            n = pretty(a, s)
+            n = pretty(style, a, s)
         end
 
         if s.opts.whitespace_ops_in_indices && !is_leaf(n) && !is_iterable(n)
@@ -1280,23 +1409,28 @@ function p_colonopcall(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_colonopcall(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_colonopcall(DefaultStyle(style), cst, s)
 
 # Kw
-function p_kw(cst::CSTParser.EXPR, s::State)
+function p_kw(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     for a in cst
         if a.kind === Tokens.EQ
             add_node!(t, Whitespace(1), s)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Whitespace(1), s)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
+p_kw(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_kw(DefaultStyle(style), cst, s)
 
-is_str(cst::CSTParser.EXPR) = is_str_or_cmd(cst.kind) || is_str_or_cmd(cst.typ)
+@inline is_str(cst::CSTParser.EXPR) = is_str_or_cmd(cst.kind) || is_str_or_cmd(cst.typ)
 
 is_iterable(x::Union{CSTParser.EXPR,FST}) =
     x.typ === CSTParser.TupleH || x.typ === CSTParser.Vect ||
@@ -1315,7 +1449,7 @@ unnestable_arg(cst::CSTParser.EXPR) =
     is_iterable(cst) || is_str(cst) || cst.typ === CSTParser.LITERAL ||
     (cst.typ === CSTParser.BinaryOpCall && cst[2].kind === Tokens.DOT)
 
-function nestable(cst::CSTParser.EXPR)
+function nestable(::S, cst::CSTParser.EXPR) where {S<:AbstractStyle}
     CSTParser.defines_function(cst) && cst[1].typ !== CSTParser.UnaryOpCall && return true
     nest_assignment(cst) && return !is_str(cst[3])
     true
@@ -1331,7 +1465,14 @@ function nest_rhs(cst::CSTParser.EXPR)::Bool
 end
 
 # BinaryOpCall
-function p_binaryopcall(cst::CSTParser.EXPR, s::State; nonest = false, nospace = false)
+function p_binaryopcall(
+    ds::DefaultStyle,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     op = cst[2]
     nonest = nonest || op.kind === Tokens.COLON
@@ -1344,13 +1485,13 @@ function p_binaryopcall(cst::CSTParser.EXPR, s::State; nonest = false, nospace =
     nospace_args = s.opts.whitespace_ops_in_indices ? false : nospace
 
     if cst[1].typ === CSTParser.BinaryOpCall
-        n = p_binaryopcall(cst[1], s, nonest = nonest, nospace = nospace_args)
+        n = pretty(style, cst[1], s, nonest = nonest, nospace = nospace_args)
     elseif cst[1].typ === CSTParser.InvisBrackets
-        n = p_invisbrackets(cst[1], s, nonest = nonest, nospace = nospace_args)
+        n = pretty(style, cst[1], s, nonest = nonest, nospace = nospace_args)
     elseif cst[1].typ === CSTParser.ChainOpCall || cst[1].typ === CSTParser.Comparison
-        n = p_chainopcall(cst[1], s, nonest = nonest, nospace = nospace_args)
+        n = pretty(style, cst[1], s, nonest = nonest, nospace = nospace_args)
     else
-        n = pretty(cst[1], s)
+        n = pretty(style, cst[1], s)
     end
 
     if op.kind === Tokens.COLON &&
@@ -1366,37 +1507,37 @@ function p_binaryopcall(cst::CSTParser.EXPR, s::State; nonest = false, nospace =
 
     nrhs = nest_rhs(cst)
     nrhs && (t.force_nest = true)
-    nest = (nestable(cst) && !nonest) || nrhs
+    nest = (nestable(style, cst) && !nonest) || nrhs
     # @info "" nestable(cst) !nonest nrhs nest cst[2]
 
     if op.fullspan == 0 && cst[3].typ === CSTParser.IDENTIFIER
         # do nothing
     elseif op.kind === Tokens.EX_OR
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(op, s), s, join_lines = true)
+        add_node!(t, pretty(style, op, s), s, join_lines = true)
     elseif op.kind === Tokens.CIRCUMFLEX_ACCENT && op.dot
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(op, s), s, join_lines = true)
+        add_node!(t, pretty(style, op, s), s, join_lines = true)
         nest ? add_node!(t, Placeholder(1), s) : add_node!(t, Whitespace(1), s)
     elseif (
         nospace ||
         (CSTParser.precedence(op) in (8, 13, 14, 16) && op.kind !== Tokens.ANON_FUNC)
     ) && op.kind !== Tokens.IN
-        add_node!(t, pretty(op, s), s, join_lines = true)
+        add_node!(t, pretty(style, op, s), s, join_lines = true)
     else
         add_node!(t, Whitespace(1), s)
-        add_node!(t, pretty(op, s), s, join_lines = true)
+        add_node!(t, pretty(style, op, s), s, join_lines = true)
         nest ? add_node!(t, Placeholder(1), s) : add_node!(t, Whitespace(1), s)
     end
 
     if cst[3].typ === CSTParser.BinaryOpCall
-        n = p_binaryopcall(cst[3], s, nonest = nonest, nospace = nospace_args)
+        n = pretty(style, cst[3], s, nonest = nonest, nospace = nospace_args)
     elseif cst[3].typ === CSTParser.InvisBrackets
-        n = p_invisbrackets(cst[3], s, nonest = nonest, nospace = nospace_args)
+        n = pretty(style, cst[3], s, nonest = nonest, nospace = nospace_args)
     elseif cst[3].typ === CSTParser.ChainOpCall || cst[3].typ === CSTParser.Comparison
-        n = p_chainopcall(cst[3], s, nonest = nonest, nospace = nospace_args)
+        n = pretty(style, cst[3], s, nonest = nonest, nospace = nospace_args)
     else
-        n = pretty(cst[3], s)
+        n = pretty(style, cst[3], s)
     end
 
     if op.kind === Tokens.COLON &&
@@ -1417,15 +1558,24 @@ function p_binaryopcall(cst::CSTParser.EXPR, s::State; nonest = false, nospace =
 
     t
 end
+p_binaryopcall(
+    style::S,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+) where {S<:AbstractStyle} =
+    p_binaryopcall(DefaultStyle(style), cst, s, nonest = nonest, nospace = nospace)
 
 # WhereOpCall
 # A where B
-function p_whereopcall(cst::CSTParser.EXPR, s::State)
+function p_whereopcall(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
 
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
 
     # Used to mark where `B` starts.
@@ -1450,26 +1600,26 @@ function p_whereopcall(cst::CSTParser.EXPR, s::State)
     # @debug "" nest in_braces cst[3].val == "{" cst.args[end].val
     for (i, a) in enumerate(cst.args[3:end])
         if is_opener(a) && nest
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(0), s)
             s.indent += s.indent_size
         elseif is_closer(a) && nest
             add_node!(t, TrailingComma(), s)
             add_node!(t, Placeholder(0), s)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             s.indent -= s.indent_size
         elseif CSTParser.is_comma(a) && !is_punc(cst[i+3])
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(nws), s)
         elseif a.typ === CSTParser.BinaryOpCall
             add_node!(
                 t,
-                p_binaryopcall(a, s, nospace = !s.opts.whitespace_typedefs),
+                pretty(style, a, s, nospace = !s.opts.whitespace_typedefs),
                 s,
                 join_lines = true,
             )
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     add_braces && add_node!(
@@ -1480,37 +1630,50 @@ function p_whereopcall(cst::CSTParser.EXPR, s::State)
     )
     t
 end
+p_whereopcall(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_whereopcall(DefaultStyle(style), cst, s)
 
 # Conditional
-function p_conditionalopcall(cst::CSTParser.EXPR, s::State)
+function p_conditionalopcall(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     add_node!(t, Placeholder(1), s)
 
-    add_node!(t, pretty(cst[3], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[3], s), s, join_lines = true)
     add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[4], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[4], s), s, join_lines = true)
     add_node!(t, Placeholder(1), s)
 
-    add_node!(t, pretty(cst[5], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[5], s), s, join_lines = true)
     t
 end
+p_conditionalopcall(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_conditionalopcall(DefaultStyle(style), cst, s)
 
 # UnaryOpCall
-function p_unaryopcall(cst::CSTParser.EXPR, s::State; nospace = true)
+function p_unaryopcall(ds::DefaultStyle, cst::CSTParser.EXPR, s::State; nospace = true)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     !nospace && add_node!(t, Whitespace(1), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
     t
 end
+p_unaryopcall(
+    style::S,
+    cst::CSTParser.EXPR,
+    s::State;
+    nospace = true,
+) where {S<:AbstractStyle} = p_unaryopcall(DefaultStyle(style), cst, s, nospace = nospace)
 
-function p_curly(cst::CSTParser.EXPR, s::State)
+function p_curly(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[1], s), s)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
 
     args = get_args(cst)
     nest = length(args) > 0 && !(length(args) == 1 && unnestable_arg(cst[1]))
@@ -1524,21 +1687,24 @@ function p_curly(cst::CSTParser.EXPR, s::State)
         if i + 2 == length(cst) && nest
             add_node!(t, TrailingComma(), s)
             add_node!(t, Placeholder(0), s)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         elseif CSTParser.is_comma(a) && i < length(cst) - 3 && !is_punc(cst[i+3])
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(nws), s)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
+p_curly(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_curly(DefaultStyle(style), cst, s)
 
-function p_call(cst::CSTParser.EXPR, s::State)
+function p_call(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
-    add_node!(t, pretty(cst[2], s), s, join_lines = true)
+    add_node!(t, pretty(style, cst[1], s), s)
+    add_node!(t, pretty(style, cst[2], s), s, join_lines = true)
 
     args = get_args(cst)
     nest = length(args) > 0 && !(length(args) == 1 && unnestable_arg(args[1]))
@@ -1551,64 +1717,82 @@ function p_call(cst::CSTParser.EXPR, s::State)
         if i + 2 == length(cst) && nest
             add_node!(t, TrailingComma(), s)
             add_node!(t, Placeholder(0), s)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         elseif CSTParser.is_comma(a) && i < length(cst) - 3 && !is_punc(cst[i+3])
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(1), s)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
+p_call(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_call(DefaultStyle(style), cst, s)
 
 # InvisBrackets
-function p_invisbrackets(cst::CSTParser.EXPR, s::State; nonest = false, nospace = false)
+function p_invisbrackets(
+    ds::DefaultStyle,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     nest = !is_iterable(cst[2]) && !nonest
     # @info "nest invis" nonest
 
     for (i, a) in enumerate(cst)
         if a.typ === CSTParser.Block
-            add_node!(t, p_block(a, s, from_quote = true), s, join_lines = true)
+            add_node!(t, pretty(style, a, s, from_quote = true), s, join_lines = true)
         elseif a.typ === CSTParser.BinaryOpCall
             add_node!(
                 t,
-                p_binaryopcall(a, s, nonest = nonest, nospace = nospace),
+                pretty(style, a, s, nonest = nonest, nospace = nospace),
                 s,
                 join_lines = true,
             )
         elseif a.typ === CSTParser.InvisBrackets
             add_node!(
                 t,
-                p_invisbrackets(a, s, nonest = nonest, nospace = nospace),
+                pretty(style, a, s, nonest = nonest, nospace = nospace),
                 s,
                 join_lines = true,
             )
         elseif is_opener(a) && nest
             # @info "opening"
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(0), s)
         elseif is_closer(a) && nest
             # @info "closing"
             add_node!(t, Placeholder(0), s)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
+p_invisbrackets(
+    style::S,
+    cst::CSTParser.EXPR,
+    s::State;
+    nonest = false,
+    nospace = false,
+) where {S<:AbstractStyle} =
+    p_invisbrackets(DefaultStyle(style), cst, s, nonest = nonest, nospace = nospace)
 
 # TupleH
-function p_tupleh(cst::CSTParser.EXPR, s::State)
+function p_tupleh(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
 
     args = get_args(cst)
     nest = length(args) > 0 && !(length(args) == 1 && unnestable_arg(args[1]))
 
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         if is_opener(n) && nest
             add_node!(t, n, s, join_lines = true)
             add_node!(t, Placeholder(0), s)
@@ -1625,14 +1809,17 @@ function p_tupleh(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_tupleh(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_tupleh(DefaultStyle(style), cst, s)
 
 # Braces
-function p_braces(cst::CSTParser.EXPR, s::State)
+function p_braces(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     nest = length(cst) > 2 && !(length(cst) == 3 && unnestable_arg(cst[2]))
 
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         if i == 1 && nest
             add_node!(t, n, s, join_lines = true)
             add_node!(t, Placeholder(0), s)
@@ -1649,14 +1836,17 @@ function p_braces(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_braces(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_braces(DefaultStyle(style), cst, s)
 
 # Vect
-function p_vect(cst::CSTParser.EXPR, s::State)
+function p_vect(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     nest = length(cst) > 2 && !(length(cst) == 3 && unnestable_arg(cst[2]))
 
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         if i == 1 && nest
             add_node!(t, n, s, join_lines = true)
             add_node!(t, Placeholder(0), s)
@@ -1673,14 +1863,20 @@ function p_vect(cst::CSTParser.EXPR, s::State)
     end
     t
 end
-p_comprehension(cst::CSTParser.EXPR, s::State) = p_vect(cst, s)
+p_vect(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_vect(DefaultStyle(style), cst, s)
 
+@inline p_comprehension(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) =
+    p_vect(ds, cst, s)
+p_comprehension(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_comprehension(DefaultStyle(style), cst, s)
 
 # Parameters
-function p_parameters(cst::CSTParser.EXPR, s::State)
+function p_parameters(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         if i == length(cst) && CSTParser.is_comma(a)
             # do nothing
         elseif CSTParser.is_comma(a) && i < length(cst) && !is_punc(cst[i+1])
@@ -1692,29 +1888,40 @@ function p_parameters(cst::CSTParser.EXPR, s::State)
     end
     t
 end
+p_parameters(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_parameters(DefaultStyle(style), cst, s)
 
-# Import, Export, Using, ImportAll
-function p_import(cst::CSTParser.EXPR, s::State)
+# Import, Export, Using
+function p_import(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
-    add_node!(t, pretty(cst[1], s), s)
+    add_node!(t, pretty(style, cst[1], s), s)
     add_node!(t, Whitespace(1), s)
 
     for (i, a) in enumerate(cst.args[2:end])
         if CSTParser.is_comma(a) || CSTParser.is_colon(a)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(1), s)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
-p_export(cst::CSTParser.EXPR, s::State) = p_import(cst, s)
-p_using(cst::CSTParser.EXPR, s::State) = p_import(cst, s)
-p_importall(cst::CSTParser.EXPR, s::State) = p_import(cst, s)
+p_import(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_import(DefaultStyle(style), cst, s)
+
+@inline p_export(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_import(ds, cst, s)
+p_export(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_export(DefaultStyle(style), cst, s)
+
+@inline p_using(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_import(ds, cst, s)
+p_using(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_using(DefaultStyle(style), cst, s)
 
 # Ref
-function p_ref(cst::CSTParser.EXPR, s::State)
+function p_ref(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     nest = length(cst) > 5 && !(length(cst) == 5 && unnestable_arg(cst[3]))
     nospace = !s.opts.whitespace_ops_in_indices
@@ -1722,36 +1929,39 @@ function p_ref(cst::CSTParser.EXPR, s::State)
         if is_closer(a) && nest
             add_node!(t, TrailingComma(), s)
             add_node!(t, Placeholder(0), s)
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         elseif is_opener(a) && nest
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(0), s)
         elseif CSTParser.is_comma(a) && i < length(cst) && !is_punc(cst[i+1])
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Placeholder(1), s)
         elseif a.typ === CSTParser.BinaryOpCall
             add_node!(
                 t,
-                p_binaryopcall(a, s, nonest = true, nospace = nospace),
+                pretty(style, a, s, nonest = true, nospace = nospace),
                 s,
                 join_lines = true,
             )
         elseif a.typ === CSTParser.InvisBrackets
             add_node!(
                 t,
-                p_invisbrackets(a, s, nonest = true, nospace = nospace),
+                pretty(style, a, s, nonest = true, nospace = nospace),
                 s,
                 join_lines = true,
             )
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
+p_ref(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_ref(DefaultStyle(style), cst, s)
 
 # Vcat/TypedVcat
-function p_vcat(cst::CSTParser.EXPR, s::State)
+function p_vcat(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     st = cst.typ === CSTParser.Vcat ? 1 : 2
     args = get_args(cst)
@@ -1759,7 +1969,7 @@ function p_vcat(cst::CSTParser.EXPR, s::State)
     # @info "" nest length(cst) st
 
     for (i, a) in enumerate(cst)
-        n = pretty(a, s)
+        n = pretty(style, a, s)
         diff_line = t.endline != t.startline
         if is_opener(a) && nest
             add_node!(t, n, s, join_lines = true)
@@ -1784,26 +1994,38 @@ function p_vcat(cst::CSTParser.EXPR, s::State)
     end
     t
 end
-p_typedvcat(cst::CSTParser.EXPR, s::State) = p_vcat(cst, s)
+p_vcat(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_vcat(DefaultStyle(style), cst, s)
+
+@inline p_typedvcat(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_vcat(ds, cst, s)
+p_typedvcat(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_typedvcat(DefaultStyle(style), cst, s)
 
 # Hcat/TypedHcat
-function p_hcat(cst::CSTParser.EXPR, s::State)
+function p_hcat(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     st = cst.typ === CSTParser.Hcat ? 1 : 2
     for (i, a) in enumerate(cst)
         if i > st && i < length(cst) - 1
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Whitespace(1), s)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
-p_typedhcat(cst::CSTParser.EXPR, s::State) = p_hcat(cst, s)
+p_hcat(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_hcat(DefaultStyle(style), cst, s)
+
+@inline p_typedhcat(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_hcat(ds, cst, s)
+p_typedhcat(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_typedhcat(DefaultStyle(style), cst, s)
 
 # Row
-function p_row(cst::CSTParser.EXPR, s::State)
+function p_row(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
 
     # Currently {A <:B} is parsed as a Row type with elements A and <:B
@@ -1815,21 +2037,24 @@ function p_row(cst::CSTParser.EXPR, s::State)
 
     for (i, a) in enumerate(cst)
         if in_braces && i < length(cst) && cst[i+1].typ === CSTParser.UnaryOpCall
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Whitespace(nospace ? 0 : 1), s)
         elseif in_braces && a.typ === CSTParser.UnaryOpCall
-            add_node!(t, p_unaryopcall(a, s, nospace = nospace), s, join_lines = true)
+            add_node!(t, pretty(style, a, s, nospace = nospace), s, join_lines = true)
             i < length(cst) && add_node!(t, Whitespace(1), s)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             i < length(cst) && add_node!(t, Whitespace(1), s)
         end
     end
     t
 end
+p_row(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_row(DefaultStyle(style), cst, s)
 
 # Generator/Filter
-function p_generator(cst::CSTParser.EXPR, s::State)
+function p_generator(ds::DefaultStyle, cst::CSTParser.EXPR, s::State)
+    style = getstyle(ds)
     t = FST(cst, nspaces(s))
     for (i, a) in enumerate(cst)
         if a.typ === CSTParser.KEYWORD
@@ -1848,7 +2073,7 @@ function p_generator(cst::CSTParser.EXPR, s::State)
                 add_node!(t, Whitespace(1), s)
             end
 
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Whitespace(1), s)
             if a.kind === Tokens.FOR
                 for j = i+1:length(cst)
@@ -1856,14 +2081,19 @@ function p_generator(cst::CSTParser.EXPR, s::State)
                 end
             end
         elseif a.typ === CSTParser.BinaryOpCall
-            add_node!(t, p_binaryopcall(a, s, nonest = true), s, join_lines = true)
+            add_node!(t, pretty(style, a, s, nonest = true), s, join_lines = true)
         elseif CSTParser.is_comma(a) && i < length(cst) && !is_punc(cst[i+1])
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
             add_node!(t, Whitespace(1), s)
         else
-            add_node!(t, pretty(a, s), s, join_lines = true)
+            add_node!(t, pretty(style, a, s), s, join_lines = true)
         end
     end
     t
 end
-p_filter(cst::CSTParser.EXPR, s::State) = p_generator(cst, s)
+p_generator(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_generator(DefaultStyle(style), cst, s)
+
+@inline p_filter(ds::DefaultStyle, cst::CSTParser.EXPR, s::State) = p_generator(ds, cst, s)
+p_filter(style::S, cst::CSTParser.EXPR, s::State) where {S<:AbstractStyle} =
+    p_filter(DefaultStyle(style), cst, s)
diff --git a/src/styles/yas.jl b/src/styles/yas.jl
new file mode 100644
index 00000000..02acdd2c
--- /dev/null
+++ b/src/styles/yas.jl
@@ -0,0 +1,222 @@
+# YAS style !!!
+# This is a WIP
+
+struct YASStyle <: AbstractStyle end
+@inline getstyle(s::YASStyle) = s
+
+yasformat(s::AbstractString; kwargs...) = format_text(
+    s;
+    kwargs...,
+    always_for_in = true,
+    whitespace_ops_in_indices = true,
+    whitespace_typedefs = false,
+    style = YASStyle(),
+)
+
+nestable(::YASStyle, cst::CSTParser.EXPR) = false
+
+function p_kw(ys::YASStyle, cst::CSTParser.EXPR, s::State)
+    t = FST(cst, nspaces(s))
+    for a in cst
+        add_node!(t, pretty(ys, a, s), s, join_lines = true)
+    end
+    t
+end
+
+function p_curly(ys::YASStyle, cst::CSTParser.EXPR, s::State)
+    t = FST(cst, nspaces(s))
+    for (i, a) in enumerate(cst)
+        n = pretty(ys, a, s)
+        if CSTParser.is_comma(a) && i < length(cst) && !is_punc(cst[i+1])
+            add_node!(t, n, s, join_lines = true)
+        elseif CSTParser.is_comma(a) && i == length(cst) - 1
+            # remove trailing comma
+        elseif is_closer(n) || is_opener(n)
+            add_node!(t, n, s, join_lines = true)
+        else
+            add_node!(t, n, s, join_lines = t.endline == n.startline)
+        end
+    end
+    t
+end
+@inline p_braces(ys::YASStyle, cst::CSTParser.EXPR, s::State) = p_curly(ys, cst, s)
+
+function p_call(ys::YASStyle, cst::CSTParser.EXPR, s::State)
+    t = FST(cst, nspaces(s))
+
+    for (i, a) in enumerate(cst)
+        n = pretty(ys, a, s)
+        if CSTParser.is_comma(a) && i < length(cst) && !is_punc(cst[i+1])
+            add_node!(t, n, s, join_lines = true)
+        elseif CSTParser.is_comma(a) && i == length(cst) - 1
+            # remove trailing comma
+        elseif is_closer(n) || is_opener(n)
+            add_node!(t, n, s, join_lines = true)
+        elseif n.typ === CSTParser.Parameters
+            join_lines = t.endline == n.startline
+            add_node!(t, n, s, join_lines = join_lines)
+        else
+            join_lines = t.endline == n.startline
+            if join_lines && !is_opener(t[end])
+                add_node!(t, Whitespace(1), s)
+            end
+            add_node!(t, n, s, join_lines = join_lines)
+        end
+    end
+    t
+end
+@inline p_ref(ys::YASStyle, cst::CSTParser.EXPR, s::State) = p_call(ys, cst, s)
+@inline p_vect(ys::YASStyle, cst::CSTParser.EXPR, s::State) = p_call(ys, cst, s)
+@inline p_tupleh(ys::YASStyle, cst::CSTParser.EXPR, s::State) = p_call(ys, cst, s)
+@inline p_parameters(ys::YASStyle, cst::CSTParser.EXPR, s::State) = p_call(ys, cst, s)
+@inline p_comprehension(ys::YASStyle, cst::CSTParser.EXPR, s::State) = p_call(ys, cst, s)
+
+function p_whereopcall(ys::YASStyle, cst::CSTParser.EXPR, s::State)
+    t = FST(cst, nspaces(s))
+    add_node!(t, pretty(ys, cst[1], s), s)
+    add_node!(t, Whitespace(1), s)
+    add_node!(t, pretty(ys, cst[2], s), s, join_lines = true)
+    add_node!(t, Whitespace(1), s)
+
+    add_braces =
+        !CSTParser.is_lbrace(cst[3]) && cst.parent.typ !== CSTParser.Curly &&
+        cst[3].typ !== CSTParser.Curly && cst[3].typ !== CSTParser.BracesCat
+
+    brace = FST(CSTParser.PUNCTUATION, t.endline, t.endline, "{")
+    add_braces && add_node!(t, brace, s, join_lines = true)
+
+    for (i, a) in enumerate(cst.args[3:end])
+        n = a.typ === CSTParser.BinaryOpCall ? pretty(ys, a, s, nospace = true) :
+            pretty(ys, a, s)
+        if is_closer(n) || is_opener(n)
+            add_node!(t, n, s, join_lines = true)
+        elseif CSTParser.is_comma(a) && !is_punc(cst[i+3])
+            add_node!(t, n, s, join_lines = true)
+        elseif a.typ === CSTParser.BinaryOpCall
+            add_node!(t, n, s, join_lines = t.endline == n.startline)
+        else
+            add_node!(t, n, s, join_lines = t.endline == n.startline)
+        end
+    end
+    brace = FST(CSTParser.PUNCTUATION, t.endline, t.endline, "}")
+    add_braces && add_node!(t, brace, s, join_lines = true)
+    t
+end
+
+function p_generator(ys::YASStyle, cst::CSTParser.EXPR, s::State)
+    t = FST(cst, nspaces(s))
+    for (i, a) in enumerate(cst)
+        n = a.typ === CSTParser.BinaryOpCall ? pretty(ys, a, s, nonest = true) :
+            pretty(ys, a, s)
+        if a.typ === CSTParser.KEYWORD
+            add_node!(t, Whitespace(1), s)
+            add_node!(t, n, s, join_lines = true)
+            # add_node!(t, Whitespace(1), s)
+            if a.kind === Tokens.FOR
+                for j = i+1:length(cst)
+                    eq_to_in_normalization!(cst[j], s.opts.always_for_in)
+                end
+            end
+        elseif CSTParser.is_comma(a) && i < length(cst) && !is_punc(cst[i+1])
+            add_node!(t, n, s, join_lines = true)
+        else
+            join_lines = t.endline == n.startline
+            join_lines && add_node!(t, Whitespace(1), s)
+            add_node!(t, n, s, join_lines = join_lines)
+        end
+    end
+    t
+end
+@inline p_filter(ys::YASStyle, cst::CSTParser.EXPR, s::State) = p_generator(ys, cst, s)
+
+#
+# Nesting
+#
+
+function nest_if_over_margin!(style, fst::FST, s::State, i::Int)
+    margin = s.line_offset
+    idx = findnext(n -> n.typ === PLACEHOLDER, fst.nodes, i + 1)
+    if idx === nothing
+        margin += sum(length.(fst[i+1:end])) + fst.extra_margin
+    else
+        margin += sum(length.(fst[i+1:idx]))
+    end
+    if margin > s.margin || is_comment(fst[i+1])
+        fst[i] = Newline(length = fst[i].len)
+        s.line_offset = fst.indent
+    else
+        nest!(style, fst[i], s)
+    end
+end
+
+function n_call!(ys::YASStyle, fst::FST, s::State)
+    line_offset = s.line_offset
+    fst.indent = line_offset + sum(length.(fst[1:2]))
+
+    for (i, n) in enumerate(fst.nodes)
+        if n.typ === NEWLINE
+            s.line_offset = fst.indent
+        elseif n.typ === TRAILINGSEMICOLON
+            n.val = ""
+            n.len = 0
+            nest!(ys, n, s)
+        elseif n.typ === CSTParser.Parameters || n.typ === CSTParser.Generator
+            n.indent = fst.indent
+            n.extra_margin = 1
+            nest!(ys, n, s)
+        else
+            n.extra_margin = 1
+            nest!(ys, n, s)
+        end
+    end
+end
+@inline n_curly!(ys::YASStyle, fst::FST, s::State) = n_call!(ys, fst, s)
+@inline n_ref!(ys::YASStyle, fst::FST, s::State) = n_call!(ys, fst, s)
+
+function n_tupleh!(ys::YASStyle, fst::FST, s::State)
+    line_offset = s.line_offset
+    fst.typ !== CSTParser.Parameters && (fst.indent = line_offset)
+    length(fst.nodes) > 0 && is_opener(fst[1]) && (fst.indent += 1)
+
+    for (i, n) in enumerate(fst.nodes)
+        if n.typ === NEWLINE
+            s.line_offset = fst.indent
+        elseif n.typ === TRAILINGSEMICOLON
+            n.val = ""
+            n.len = 0
+            nest!(ys, n, s)
+        elseif n.typ === CSTParser.Generator
+            n.indent = fst.indent
+            n.extra_margin = 1
+            nest!(ys, n, s)
+        else
+            n.extra_margin = 1
+            nest!(ys, n, s)
+        end
+    end
+end
+@inline n_braces!(ys::YASStyle, fst::FST, s::State) = n_tupleh!(ys, fst, s)
+@inline n_vect!(ys::YASStyle, fst::FST, s::State) = n_tupleh!(ys, fst, s)
+@inline n_parameters!(ys::YASStyle, fst::FST, s::State) = n_tupleh!(ys, fst, s)
+@inline n_invisbrackets!(ys::YASStyle, fst::FST, s::State) = n_tupleh!(ys, fst, s)
+@inline n_comprehension!(ys::YASStyle, fst::FST, s::State) = n_tupleh!(ys, fst, s)
+
+function n_import!(ys::YASStyle, fst::FST, s::State)
+    fst.indent = s.line_offset + sum(length.(fst[1:2]))
+    for (i, n) in enumerate(fst.nodes)
+        if n.typ === PLACEHOLDER
+            nest_if_over_margin!(ys, fst, s, i)
+        elseif n.typ === NEWLINE
+            s.line_offset = fst.indent
+        else
+            nest!(ys, n, s)
+        end
+    end
+end
+@inline n_export!(ys::YASStyle, fst::FST, s::State) = n_import!(ys, fst, s)
+@inline n_using!(ys::YASStyle, fst::FST, s::State) = n_import!(ys, fst, s)
+
+n_whereopcall!(ys::YASStyle, fst::FST, s::State) =
+    nest!(ys, fst.nodes, s, fst.indent, extra_margin = fst.extra_margin)
+n_chainopcall!(ys::YASStyle, fst::FST, s::State) =
+    n_block!(DefaultStyle(ys), fst, s, custom_indent = s.line_offset)


Test patch:
diff --git a/test/runtests.jl b/test/runtests.jl
index 4e81fb7d..2208eec6 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -1,4 +1,5 @@
 using JuliaFormatter
+using JuliaFormatter: DefaultStyle
 using CSTParser
 using Test
 
@@ -34,20 +35,20 @@ end
 fmt(s, i, m) = fmt(s; i = i, m = m)
 fmt1(s, i, m) = fmt1(s, i, m, false, false, false)
 
-function run_pretty(text::String, print_width::Int)
+function run_pretty(text::String, print_width::Int; style = DefaultStyle())
     d = JuliaFormatter.Document(text)
     s = JuliaFormatter.State(d, 4, print_width, JuliaFormatter.Options())
     x = CSTParser.parse(text, true)
-    t = JuliaFormatter.pretty(x, s)
+    t = JuliaFormatter.pretty(style, x, s)
     t
 end
 
-function run_nest(text::String, print_width::Int)
+function run_nest(text::String, print_width::Int; style = DefaultStyle())
     d = JuliaFormatter.Document(text)
     s = JuliaFormatter.State(d, 4, print_width, JuliaFormatter.Options())
     x = CSTParser.parse(text, true)
-    t = JuliaFormatter.pretty(x, s)
-    JuliaFormatter.nest!(t, s)
+    t = JuliaFormatter.pretty(style, x, s)
+    JuliaFormatter.nest!(style, t, s)
     s
 end