Skip to content

Commit c42fe88

Browse files
author
José Valim
committed
Provide Inspect.Algebra.format/2 that returns iodata
1 parent 28d7fc3 commit c42fe88

File tree

6 files changed

+97
-96
lines changed

6 files changed

+97
-96
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* Soft deprecations (no warnings emitted)
1414

1515
* Deprecations
16+
* [Inspect] `Inspect.Algebra.pretty/2` is deprecated in favor of `Inspect.Algebra.format/2` that instead returns iodata. This function was used only by documentation examples and it is unlikely to affect actual code
1617

1718
* Backwards incompatible changes
1819

lib/elixir/lib/inspect/algebra.ex

Lines changed: 62 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ defmodule Inspect.Opts do
2929
3030
* `:pretty` - if set to true enables pretty printing, defaults to false.
3131
32-
* `:width` - defaults to the 80 characters.
32+
* `:width` - defaults to the 80 characters, used when pretty is true or
33+
when printing to IO devices.
3334
"""
3435

3536
defstruct structs: true,
@@ -66,8 +67,8 @@ defmodule Inspect.Algebra do
6667
elements together and render them:
6768
6869
iex> doc = Inspect.Algebra.concat(Inspect.Algebra.empty, "foo")
69-
iex> Inspect.Algebra.pretty(doc, 80)
70-
"foo"
70+
iex> Inspect.Algebra.format(doc, 80)
71+
["foo"]
7172
7273
The functions `nest/2`, `space/2` and `line/2` help you put the
7374
document together into a rigid structure. However, the document
@@ -77,15 +78,15 @@ defmodule Inspect.Algebra do
7778
render it:
7879
7980
iex> doc = Inspect.Algebra.glue("a", " ", "b")
80-
iex> Inspect.Algebra.pretty(doc, 80)
81-
"a b"
81+
iex> Inspect.Algebra.format(doc, 80)
82+
["a", " ", "b"]
8283
8384
Notice the break was represented as is, because we haven't reached
8485
a line limit. Once we do, it is replaced by a newline:
8586
8687
iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b")
87-
iex> Inspect.Algebra.pretty(doc, 10)
88-
"aaaaaaaaaaaaaaaaaaaa\nb"
88+
iex> Inspect.Algebra.format(doc, 10)
89+
["aaaaaaaaaaaaaaaaaaaa", "\n", "b"]
8990
9091
Finally, this module also contains Elixir related functions, a bit
9192
tied to Elixir formatting, namely `surround/3` and `surround_many/5`.
@@ -190,9 +191,10 @@ defmodule Inspect.Algebra do
190191
try do
191192
Process.put(:inspect_trap, true)
192193
res = Inspect.Map.inspect(map, opts)
194+
formatted = IO.iodata_to_binary(format(res, :infinity))
193195
raise ArgumentError,
194196
"Got #{inspect e.__struct__} with message " <>
195-
"\"#{Exception.message(e)}\" while inspecting #{pretty(res, opts.width)}"
197+
"\"#{Exception.message(e)}\" while inspecting #{formatted}"
196198
after
197199
Process.delete(:inspect_trap)
198200
end
@@ -224,9 +226,9 @@ defmodule Inspect.Algebra do
224226
225227
## Examples
226228
227-
iex> doc = Inspect.Algebra.concat "Tasteless", "Artosis"
228-
iex> Inspect.Algebra.pretty(doc, 80)
229-
"TastelessArtosis"
229+
iex> doc = Inspect.Algebra.concat "hello", "world"
230+
iex> Inspect.Algebra.format(doc, 80)
231+
["hello", "world"]
230232
231233
"""
232234
@spec concat(t, t) :: doc_cons
@@ -250,8 +252,8 @@ defmodule Inspect.Algebra do
250252
## Examples
251253
252254
iex> doc = Inspect.Algebra.nest(Inspect.Algebra.glue("hello", "world"), 5)
253-
iex> Inspect.Algebra.pretty(doc, 5)
254-
"hello\n world"
255+
iex> Inspect.Algebra.format(doc, 5)
256+
["hello", "\n ", "world"]
255257
256258
"""
257259
@spec nest(t, non_neg_integer) :: doc_nest
@@ -275,15 +277,15 @@ defmodule Inspect.Algebra do
275277
Let's glue two docs together with a break and then render it:
276278
277279
iex> doc = Inspect.Algebra.glue("a", " ", "b")
278-
iex> Inspect.Algebra.pretty(doc, 80)
279-
"a b"
280+
iex> Inspect.Algebra.format(doc, 80)
281+
["a", " ", "b"]
280282
281283
Notice the break was represented as is, because we haven't reached
282284
a line limit. Once we do, it is replaced by a newline:
283285
284286
iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b")
285-
iex> Inspect.Algebra.pretty(doc, 10)
286-
"aaaaaaaaaaaaaaaaaaaa\nb"
287+
iex> Inspect.Algebra.format(doc, 10)
288+
["aaaaaaaaaaaaaaaaaaaa", "\n", "b"]
287289
288290
"""
289291
@spec break(binary) :: doc_break
@@ -326,10 +328,10 @@ defmodule Inspect.Algebra do
326328
...> "B"
327329
...> )
328330
...> ))
329-
iex> Inspect.Algebra.pretty(doc, 80)
330-
"Hello, A B"
331-
iex> Inspect.Algebra.pretty(doc, 6)
332-
"Hello,\nA B"
331+
iex> Inspect.Algebra.format(doc, 80)
332+
["Hello,", " ", "A", " ", "B"]
333+
iex> Inspect.Algebra.format(doc, 6)
334+
["Hello,", "\n", "A", " ", "B"]
333335
334336
"""
335337
@spec group(t) :: doc_group
@@ -343,8 +345,8 @@ defmodule Inspect.Algebra do
343345
## Examples
344346
345347
iex> doc = Inspect.Algebra.space "Hughes", "Wadler"
346-
iex> Inspect.Algebra.pretty(doc, 80)
347-
"Hughes Wadler"
348+
iex> Inspect.Algebra.format(doc, 80)
349+
["Hughes", " ", "Wadler"]
348350
349351
"""
350352
@spec space(t, t) :: doc_cons
@@ -356,8 +358,8 @@ defmodule Inspect.Algebra do
356358
## Examples
357359
358360
iex> doc = Inspect.Algebra.line "Hughes", "Wadler"
359-
iex> Inspect.Algebra.pretty(doc, 80)
360-
"Hughes\nWadler"
361+
iex> Inspect.Algebra.format(doc, 80)
362+
["Hughes", "\n", "Wadler"]
361363
362364
"""
363365
@spec line(t, t) :: doc_cons
@@ -373,8 +375,8 @@ defmodule Inspect.Algebra do
373375
iex> doc = Inspect.Algebra.folddoc(doc, fn(x,y) ->
374376
...> Inspect.Algebra.concat [x, "!", y]
375377
...> end)
376-
iex> Inspect.Algebra.pretty(doc, 80)
377-
"A!B"
378+
iex> Inspect.Algebra.format(doc, 80)
379+
["A", "!", "B"]
378380
379381
"""
380382
@spec folddoc([t], ((t, t) -> t)) :: t
@@ -394,8 +396,8 @@ defmodule Inspect.Algebra do
394396
## Examples
395397
396398
iex> doc = Inspect.Algebra.surround "[", Inspect.Algebra.glue("a", "b"), "]"
397-
iex> Inspect.Algebra.pretty(doc, 3)
398-
"[a\n b]"
399+
iex> Inspect.Algebra.format(doc, 3)
400+
["[", "a", "\n ", "b", "]"]
399401
400402
"""
401403
@spec surround(binary, t, binary) :: t
@@ -411,15 +413,15 @@ defmodule Inspect.Algebra do
411413
## Examples
412414
413415
iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]", :infinity, &Integer.to_string(&1))
414-
iex> Inspect.Algebra.pretty(doc, 5)
416+
iex> Inspect.Algebra.format(doc, 5) |> IO.iodata_to_binary
415417
"[1,\n 2,\n 3,\n 4,\n 5]"
416418
417419
iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]", 3, &Integer.to_string(&1))
418-
iex> Inspect.Algebra.pretty(doc, 20)
420+
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary
419421
"[1, 2, 3, ...]"
420422
421423
iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]", 3, &Integer.to_string(&1), "!")
422-
iex> Inspect.Algebra.pretty(doc, 20)
424+
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary
423425
"[1! 2! 3! ...]"
424426
425427
"""
@@ -460,50 +462,50 @@ defmodule Inspect.Algebra do
460462
defp decrement(counter), do: counter - 1
461463

462464
@doc """
463-
The pretty printing function.
465+
The formatting function.
464466
465467
Takes the maximum width and a document to print as its arguments
466-
and returns the string representation of the best layout for the
468+
and returns an IO data representation of the best layout for the
467469
document to fit in the given width.
468470
"""
469-
@spec pretty(t, non_neg_integer | :infinity) :: binary
471+
@spec format(t, non_neg_integer | :infinity) :: binary
472+
def format(d, w) do
473+
format(w, 0, [{0, default_mode(w), doc_group(d)}])
474+
end
475+
476+
@doc false
470477
def pretty(d, w) do
471-
sdoc = format w, 0, [{0, default_mode(w), doc_group(d)}]
472-
render(sdoc)
478+
format(d, w) |> IO.iodata_to_binary
473479
end
474480

475481
defp default_mode(:infinity), do: :flat
476482
defp default_mode(_), do: :break
477483

478-
# Rendering and internal helpers
479-
480484
# Record representing the document mode to be rendered: flat or broken
481485
@typep mode :: :flat | :break
482486

483-
@doc false
484487
@spec fits?(integer, [{integer, mode, t}]) :: boolean
485-
def fits?(w, _) when w < 0, do: false
486-
def fits?(_, []), do: true
487-
def fits?(_, [{_, _, :doc_line} | _]), do: true
488-
def fits?(w, [{_, _, :doc_nil} | t]), do: fits?(w, t)
489-
def fits?(w, [{i, m, doc_cons(x, y)} | t]), do: fits?(w, [{i, m, x} | [{i, m, y} | t]])
490-
def fits?(w, [{i, m, doc_nest(x, j)} | t]), do: fits?(w, [{i + j, m, x} | t])
491-
def fits?(w, [{i, _, doc_group(x)} | t]), do: fits?(w, [{i, :flat, x} | t])
492-
def fits?(w, [{_, _, s} | t]) when is_binary(s), do: fits?((w - byte_size s), t)
493-
def fits?(w, [{_, :flat, doc_break(s)} | t]), do: fits?((w - byte_size s), t)
494-
def fits?(_, [{_, :break, doc_break(_)} | _]), do: true
488+
defp fits?(w, _) when w < 0, do: false
489+
defp fits?(_, []), do: true
490+
defp fits?(_, [{_, _, :doc_line} | _]), do: true
491+
defp fits?(w, [{_, _, :doc_nil} | t]), do: fits?(w, t)
492+
defp fits?(w, [{i, m, doc_cons(x, y)} | t]), do: fits?(w, [{i, m, x} | [{i, m, y} | t]])
493+
defp fits?(w, [{i, m, doc_nest(x, j)} | t]), do: fits?(w, [{i + j, m, x} | t])
494+
defp fits?(w, [{i, _, doc_group(x)} | t]), do: fits?(w, [{i, :flat, x} | t])
495+
defp fits?(w, [{_, _, s} | t]) when is_binary(s), do: fits?((w - byte_size s), t)
496+
defp fits?(w, [{_, :flat, doc_break(s)} | t]), do: fits?((w - byte_size s), t)
497+
defp fits?(_, [{_, :break, doc_break(_)} | _]), do: true
495498

496-
@doc false
497499
@spec format(integer | :infinity, integer, [{integer, mode, t}]) :: [binary]
498-
def format(_, _, []), do: []
499-
def format(w, _, [{i, _, :doc_line} | t]), do: [indent(i) | format(w, i, t)]
500-
def format(w, k, [{_, _, :doc_nil} | t]), do: format(w, k, t)
501-
def format(w, k, [{i, m, doc_cons(x, y)} | t]), do: format(w, k, [{i, m, x} | [{i, m, y} | t]])
502-
def format(w, k, [{i, m, doc_nest(x, j)} | t]), do: format(w, k, [{i + j, m, x} | t])
503-
def format(w, k, [{i, m, doc_group(x)} | t]), do: format(w, k, [{i, m, x} | t])
504-
def format(w, k, [{_, _, s} | t]) when is_binary(s), do: [s | format(w, (k + byte_size s), t)]
505-
def format(w, k, [{_, :flat, doc_break(s)} | t]), do: [s | format(w, (k + byte_size s), t)]
506-
def format(w, k, [{i, :break, doc_break(s)} | t]) do
500+
defp format(_, _, []), do: []
501+
defp format(w, _, [{i, _, :doc_line} | t]), do: [indent(i) | format(w, i, t)]
502+
defp format(w, k, [{_, _, :doc_nil} | t]), do: format(w, k, t)
503+
defp format(w, k, [{i, m, doc_cons(x, y)} | t]), do: format(w, k, [{i, m, x} | [{i, m, y} | t]])
504+
defp format(w, k, [{i, m, doc_nest(x, j)} | t]), do: format(w, k, [{i + j, m, x} | t])
505+
defp format(w, k, [{i, m, doc_group(x)} | t]), do: format(w, k, [{i, m, x} | t])
506+
defp format(w, k, [{_, _, s} | t]) when is_binary(s), do: [s | format(w, (k + byte_size s), t)]
507+
defp format(w, k, [{_, :flat, doc_break(s)} | t]), do: [s | format(w, (k + byte_size s), t)]
508+
defp format(w, k, [{i, :break, doc_break(s)} | t]) do
507509
k = k + byte_size(s)
508510

509511
if w == :infinity or fits?(w - k, t) do
@@ -515,10 +517,4 @@ defmodule Inspect.Algebra do
515517

516518
defp indent(0), do: @newline
517519
defp indent(i), do: @newline <> :binary.copy(" ", i)
518-
519-
@doc false
520-
@spec render([binary]) :: binary
521-
def render(sdoc) do
522-
IO.iodata_to_binary sdoc
523-
end
524520
end

lib/elixir/lib/io.ex

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -179,17 +179,13 @@ defmodule IO do
179179
@doc """
180180
Inspects and writes the given argument to the device.
181181
182-
It sets by default pretty printing to true and returns
183-
the item itself.
184-
185-
Note this function does not use the IO device width
186-
because some IO devices does not implement the
187-
appropriate functions. Setting the width must be done
188-
explicitly by passing the `:width` option.
182+
It enables pretty printing by default with width of
183+
80 characters. Th width can be changed by explicitly
184+
passing the `:width` option.
189185
190186
## Examples
191187
192-
IO.inspect Process.list
188+
IO.inspect Process.list, width: 40
193189
194190
"""
195191
@spec inspect(term, Keyword.t) :: term
@@ -202,8 +198,9 @@ defmodule IO do
202198
"""
203199
@spec inspect(device, term, Keyword.t) :: term
204200
def inspect(device, item, opts) when is_list(opts) do
205-
opts = Keyword.put_new(opts, :pretty, true)
206-
puts device, Kernel.inspect(item, opts)
201+
opts = struct(Inspect.Opts, opts)
202+
iodata = Inspect.Algebra.format(Inspect.Algebra.to_doc(item, opts), opts.width)
203+
puts device, iodata
207204
item
208205
end
209206

lib/elixir/lib/kernel.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1438,7 +1438,9 @@ defmodule Kernel do
14381438
true -> opts.width
14391439
false -> :infinity
14401440
end
1441-
Inspect.Algebra.pretty(Inspect.Algebra.to_doc(arg, opts), limit)
1441+
IO.iodata_to_binary(
1442+
Inspect.Algebra.format(Inspect.Algebra.to_doc(arg, opts), limit)
1443+
)
14421444
end
14431445

14441446
@doc """

lib/elixir/src/elixir_dispatch.erl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,5 +521,7 @@ deprecation_message(Warning, Message) ->
521521

522522
deprecation('Elixir.System', 'cmd', 1) ->
523523
"use System.cmd/3 instead";
524+
deprecation('Elixir.Inspect.Algebra', 'pretty', 2) ->
525+
"use Inspect.Algebra.format/2 instead";
524526
deprecation(_, _, _) ->
525527
false.

0 commit comments

Comments
 (0)