@@ -16,6 +16,9 @@ defmodule Jason.Formatter do
16
16
| { :after_colon , iodata }
17
17
]
18
18
19
+ import Record
20
+ defrecordp :opts , [ :indent , :line , :record , :colon ]
21
+
19
22
@ doc ~S"""
20
23
Returns a binary containing a pretty-printed representation of
21
24
JSON-encoded `iodata`.
@@ -61,12 +64,14 @@ defmodule Jason.Formatter do
61
64
"""
62
65
@ spec pretty_print_to_iodata ( iodata , opts ) :: iodata
63
66
def pretty_print_to_iodata ( iodata , opts \\ [ ] ) do
67
+ opts = parse_opts ( opts , opts ( indent: " " , line: "\n " , record: nil , colon: " " ) )
68
+ opts = opts ( opts , record: opts ( opts , :record ) || opts ( opts , :line ) )
69
+
64
70
depth = 0
65
71
in_str = false
66
72
in_bs = false
67
73
empty = false
68
74
first = true
69
- opts = normalize_opts ( opts )
70
75
71
76
{ output , _state } = pp_iodata ( iodata , [ ] , depth , in_str , in_bs , empty , first , opts )
72
77
@@ -103,36 +108,36 @@ defmodule Jason.Formatter do
103
108
"""
104
109
@ spec minimize_to_iodata ( iodata , opts ) :: iodata
105
110
def minimize_to_iodata ( iodata , opts ) do
106
- pretty_print_to_iodata (
107
- iodata ,
108
- indent: "" ,
109
- line_separator: "" ,
110
- record_separator: opts [ :record_separator ] || "\n " ,
111
- after_colon: ""
112
- )
111
+ opts = parse_opts ( opts , opts ( indent: [ ] , line: [ ] , record: "\n " , colon: [ ] ) )
112
+
113
+ depth = 0
114
+ in_str = false
115
+ in_bs = false
116
+ empty = false
117
+ first = true
118
+
119
+ { output , _state } = pp_iodata ( iodata , [ ] , depth , in_str , in_bs , empty , first , opts )
120
+
121
+ output
113
122
end
114
123
115
- ## Returns a copy of `opts` with defaults applied
116
- @ spec normalize_opts ( keyword ) :: opts
117
- defp normalize_opts ( opts ) do
118
- [
119
- indent: opts [ :indent ] || " " ,
120
- line_separator: opts [ :line_separator ] || "\n " ,
121
- record_separator: opts [ :record_separator ] || opts [ :line_separator ] || "\n " ,
122
- after_colon: opts [ :after_colon ] || " "
123
- ]
124
+ defp parse_opts ( opts , defaults ) do
125
+ Enum . reduce ( opts , defaults , fn
126
+ { :indent , indent } , opts -> opts ( opts , indent: indent )
127
+ { :line_separator , line } , opts -> opts ( opts , line: line , record: opts ( opts , :record ) || line )
128
+ { :record_separator , record } , opts -> opts ( opts , record: record )
129
+ { :after_colon , colon } , opts -> opts ( opts , colon: colon )
130
+ end )
124
131
end
125
132
126
133
## Returns an iolist containing `depth` instances of `opts[:indent]`
127
- @ spec tab ( opts , non_neg_integer , iolist ) :: iolist
128
- defp tab ( opts , depth , output \\ [ ] ) do
129
- if depth < 1 do
130
- output
131
- else
132
- tab ( opts , depth - 1 , [ opts [ :indent ] | output ] )
133
- end
134
+ for depth <- 1 .. 16 do
135
+ defp tab ( " " , unquote ( depth ) ) , do: unquote ( String . duplicate ( " " , depth ) )
134
136
end
135
137
138
+ defp tab ( [ ] , _ ) , do: ""
139
+ defp tab ( indent , depth ) , do: List . duplicate ( indent , depth )
140
+
136
141
@ typep pp_state :: {
137
142
## depth -- current nesting depth
138
143
non_neg_integer ,
@@ -262,8 +267,8 @@ defmodule Jason.Formatter do
262
267
out =
263
268
cond do
264
269
first -> byte
265
- empty -> [ opts [ :line_separator ] , tab ( opts , depth ) , byte ]
266
- depth == 0 -> [ opts [ :record_separator ] , byte ]
270
+ empty -> [ opts ( opts , :line ) , tab ( opts ( opts , :indent ) , depth ) , byte ]
271
+ depth == 0 -> [ opts ( opts , :record ) , byte ]
267
272
true -> byte
268
273
end
269
274
@@ -285,28 +290,28 @@ defmodule Jason.Formatter do
285
290
defp pp_byte ( byte , rest , output , depth , in_str , in_bs , false = empty , first , opts )
286
291
when byte in '}]' do
287
292
depth = depth - 1
288
- out = [ opts [ :line_separator ] , tab ( opts , depth ) , byte ]
293
+ out = [ opts ( opts , :line ) , tab ( opts ( opts , :indent ) , depth ) , byte ]
289
294
pp_iodata ( rest , [ output , out ] , depth , in_str , in_bs , empty , first , opts )
290
295
end
291
296
292
297
## out of string, comma
293
298
defp pp_byte ( byte , rest , output , depth , in_str , in_bs , _empty , first , opts )
294
299
when byte in ',' do
295
300
empty = false
296
- out = [ byte , opts [ :line_separator ] , tab ( opts , depth ) ]
301
+ out = [ byte , opts ( opts , :line ) , tab ( opts ( opts , :indent ) , depth ) ]
297
302
pp_iodata ( rest , [ output , out ] , depth , in_str , in_bs , empty , first , opts )
298
303
end
299
304
300
305
## out of string, colon
301
306
defp pp_byte ( byte , rest , output , depth , in_str , in_bs , empty , first , opts )
302
307
when byte in ':' do
303
- out = [ byte , opts [ :after_colon ] ]
308
+ out = [ byte , opts ( opts , :colon ) ]
304
309
pp_iodata ( rest , [ output , out ] , depth , in_str , in_bs , empty , first , opts )
305
310
end
306
311
307
312
## out of string, other character (maybe start quote)
308
313
defp pp_byte ( byte , rest , output , depth , _in_str , in_bs , empty , first , opts ) do
309
- out = if empty , do: [ opts [ :line_separator ] , tab ( opts , depth ) , byte ] , else: byte
314
+ out = if empty , do: [ opts ( opts , :line ) , tab ( opts ( opts , :indent ) , depth ) , byte ] , else: byte
310
315
in_str = byte in '"'
311
316
empty = false
312
317
pp_iodata ( rest , [ output , out ] , depth , in_str , in_bs , empty , first , opts )
0 commit comments