Skip to content

Commit d0c869d

Browse files
committed
Use record for options in formatter
1 parent e9659ed commit d0c869d

File tree

1 file changed

+35
-30
lines changed

1 file changed

+35
-30
lines changed

lib/formatter.ex

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ defmodule Jason.Formatter do
1616
| {:after_colon, iodata}
1717
]
1818

19+
import Record
20+
defrecordp :opts, [:indent, :line, :record, :colon]
21+
1922
@doc ~S"""
2023
Returns a binary containing a pretty-printed representation of
2124
JSON-encoded `iodata`.
@@ -61,12 +64,14 @@ defmodule Jason.Formatter do
6164
"""
6265
@spec pretty_print_to_iodata(iodata, opts) :: iodata
6366
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+
6470
depth = 0
6571
in_str = false
6672
in_bs = false
6773
empty = false
6874
first = true
69-
opts = normalize_opts(opts)
7075

7176
{output, _state} = pp_iodata(iodata, [], depth, in_str, in_bs, empty, first, opts)
7277

@@ -103,36 +108,36 @@ defmodule Jason.Formatter do
103108
"""
104109
@spec minimize_to_iodata(iodata, opts) :: iodata
105110
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
113122
end
114123

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)
124131
end
125132

126133
## 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))
134136
end
135137

138+
defp tab([], _), do: ""
139+
defp tab(indent, depth), do: List.duplicate(indent, depth)
140+
136141
@typep pp_state :: {
137142
## depth -- current nesting depth
138143
non_neg_integer,
@@ -262,8 +267,8 @@ defmodule Jason.Formatter do
262267
out =
263268
cond do
264269
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]
267272
true -> byte
268273
end
269274

@@ -285,28 +290,28 @@ defmodule Jason.Formatter do
285290
defp pp_byte(byte, rest, output, depth, in_str, in_bs, false = empty, first, opts)
286291
when byte in '}]' do
287292
depth = depth - 1
288-
out = [opts[:line_separator], tab(opts, depth), byte]
293+
out = [opts(opts, :line), tab(opts(opts, :indent), depth), byte]
289294
pp_iodata(rest, [output, out], depth, in_str, in_bs, empty, first, opts)
290295
end
291296

292297
## out of string, comma
293298
defp pp_byte(byte, rest, output, depth, in_str, in_bs, _empty, first, opts)
294299
when byte in ',' do
295300
empty = false
296-
out = [byte, opts[:line_separator], tab(opts, depth)]
301+
out = [byte, opts(opts, :line), tab(opts(opts, :indent), depth)]
297302
pp_iodata(rest, [output, out], depth, in_str, in_bs, empty, first, opts)
298303
end
299304

300305
## out of string, colon
301306
defp pp_byte(byte, rest, output, depth, in_str, in_bs, empty, first, opts)
302307
when byte in ':' do
303-
out = [byte, opts[:after_colon]]
308+
out = [byte, opts(opts, :colon)]
304309
pp_iodata(rest, [output, out], depth, in_str, in_bs, empty, first, opts)
305310
end
306311

307312
## out of string, other character (maybe start quote)
308313
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
310315
in_str = byte in '"'
311316
empty = false
312317
pp_iodata(rest, [output, out], depth, in_str, in_bs, empty, first, opts)

0 commit comments

Comments
 (0)