@@ -46,9 +46,8 @@ defmodule Inspect.Opts do
46
46
* `:limit` - limits the number of items that are inspected for tuples,
47
47
bitstrings, maps, lists and any other collection of items, with the exception of
48
48
printable strings and printable charlists which use the `:printable_limit` option.
49
- If you don't want to limit the number of items to a particular number,
50
- use `:infinity`. It accepts a positive integer or `:infinity`.
51
- Defaults to `50`.
49
+ It accepts a positive integer or `:infinity`. It defaults to 100 since
50
+ `Elixir v1.19.0`, as it has better defaults to deal with nested collections.
52
51
53
52
* `:pretty` - if set to `true` enables pretty printing. Defaults to `false`.
54
53
@@ -91,7 +90,7 @@ defmodule Inspect.Opts do
91
90
charlists: :infer ,
92
91
custom_options: [ ] ,
93
92
inspect_fun: & Inspect . inspect / 2 ,
94
- limit: 50 ,
93
+ limit: 100 ,
95
94
pretty: false ,
96
95
printable_limit: 4096 ,
97
96
safe: true ,
@@ -332,7 +331,6 @@ defmodule Inspect.Algebra do
332
331
when is_binary ( doc ) or doc in [ :doc_nil , :doc_line ] or
333
332
( is_tuple ( doc ) and elem ( doc , 0 ) in @ docs )
334
333
335
- defguardp is_limit ( limit ) when limit == :infinity or ( is_integer ( limit ) and limit >= 0 )
336
334
defguardp is_width ( width ) when width == :infinity or ( is_integer ( width ) and width >= 0 )
337
335
338
336
# Elixir + Inspect.Opts conveniences
@@ -341,11 +339,28 @@ defmodule Inspect.Algebra do
341
339
@ doc """
342
340
Converts an Elixir term to an algebra document
343
341
according to the `Inspect` protocol.
342
+
343
+ In practice, one must prefer to use `to_doc_with_opts/2`
344
+ over this function, as `to_doc_with_opts/2` returns the
345
+ updated options from inspection.
344
346
"""
345
347
@ spec to_doc ( any , Inspect.Opts . t ( ) ) :: t
346
- def to_doc ( term , opts )
348
+ def to_doc ( term , opts ) do
349
+ to_doc_with_opts ( term , opts ) |> elem ( 0 )
350
+ end
351
+
352
+ @ doc """
353
+ Converts an Elixir term to an algebra document
354
+ according to the `Inspect` protocol, alongside the updated options.
355
+
356
+ This function is used when implementing the inspect protocol for
357
+ a given type and you must convert nested terms to documents too.
358
+ """
359
+ @ doc since: "1.19.0"
360
+ @ spec to_doc_with_opts ( any , Inspect.Opts . t ( ) ) :: { t , Inspect.Opts . t ( ) }
361
+ def to_doc_with_opts ( term , opts )
347
362
348
- def to_doc ( % _ { } = struct , % Inspect.Opts { inspect_fun: fun } = opts ) do
363
+ def to_doc_with_opts ( % _ { } = struct , % Inspect.Opts { inspect_fun: fun } = opts ) do
349
364
if opts . structs do
350
365
try do
351
366
fun . ( struct , opts )
@@ -363,13 +378,15 @@ defmodule Inspect.Algebra do
363
378
try do
364
379
Process . put ( :inspect_trap , true )
365
380
366
- inspected_struct =
367
- struct
368
- |> Inspect.Map . inspect_as_map ( % {
381
+ { doc_struct , _opts } =
382
+ Inspect.Map . inspect_as_map ( struct , % {
369
383
opts
370
384
| syntax_colors: [ ] ,
371
385
inspect_fun: Inspect.Opts . default_inspect_fun ( )
372
386
} )
387
+
388
+ inspected_struct =
389
+ doc_struct
373
390
|> format ( opts . width )
374
391
|> IO . iodata_to_binary ( )
375
392
@@ -394,10 +411,29 @@ defmodule Inspect.Algebra do
394
411
else
395
412
Inspect.Map . inspect_as_map ( struct , opts )
396
413
end
414
+ |> pack_opts ( opts )
415
+ end
416
+
417
+ def to_doc_with_opts ( arg , % Inspect.Opts { inspect_fun: fun } = opts ) do
418
+ fun . ( arg , opts ) |> pack_opts ( opts )
397
419
end
398
420
399
- def to_doc ( arg , % Inspect.Opts { inspect_fun: fun } = opts ) do
400
- fun . ( arg , opts )
421
+ defp pack_opts ( { _doc , % Inspect.Opts { } } = doc_opts , _opts ) , do: doc_opts
422
+ defp pack_opts ( doc , opts ) , do: { doc , opts }
423
+
424
+ @ doc ~S"""
425
+ Wraps `collection` in `left` and `right` according to limit and contents
426
+ and returns only the container document.
427
+
428
+ In practice, one must prefer to use `container_doc_with_opts/6`
429
+ over this function, as `container_doc_with_opts/6` returns the
430
+ updated options from inspection.
431
+ """
432
+ @ doc since: "1.6.0"
433
+ @ spec container_doc ( t , [ term ] , t , Inspect.Opts . t ( ) , ( term , Inspect.Opts . t ( ) -> t ) , keyword ( ) ) ::
434
+ t
435
+ def container_doc ( left , collection , right , inspect_opts , fun , opts \\ [ ] ) do
436
+ container_doc_with_opts ( left , collection , right , inspect_opts , fun , opts ) |> elem ( 0 )
401
437
end
402
438
403
439
@ doc ~S"""
@@ -412,6 +448,8 @@ defmodule Inspect.Algebra do
412
448
The limit in the given `inspect_opts` is respected and when reached this
413
449
function stops processing and outputs `"..."` instead.
414
450
451
+ It returns a tuple with the algebra document and the updated options.
452
+
415
453
## Options
416
454
417
455
* `:separator` - the separator used between each doc
@@ -423,79 +461,99 @@ defmodule Inspect.Algebra do
423
461
424
462
iex> inspect_opts = %Inspect.Opts{limit: :infinity}
425
463
iex> fun = fn i, _opts -> to_string(i) end
426
- iex> doc = Inspect.Algebra.container_doc ("[", Enum.to_list(1..5), "]", inspect_opts, fun)
464
+ iex> { doc, _opts} = Inspect.Algebra.container_doc_with_opts ("[", Enum.to_list(1..5), "]", inspect_opts, fun)
427
465
iex> Inspect.Algebra.format(doc, 5) |> IO.iodata_to_binary()
428
466
"[1,\n 2,\n 3,\n 4,\n 5]"
429
467
430
468
iex> inspect_opts = %Inspect.Opts{limit: 3}
431
469
iex> fun = fn i, _opts -> to_string(i) end
432
- iex> doc = Inspect.Algebra.container_doc ("[", Enum.to_list(1..5), "]", inspect_opts, fun)
470
+ iex> { doc, _opts} = Inspect.Algebra.container_doc_with_opts ("[", Enum.to_list(1..5), "]", inspect_opts, fun)
433
471
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary()
434
472
"[1, 2, 3, ...]"
435
473
436
474
iex> inspect_opts = %Inspect.Opts{limit: 3}
437
475
iex> fun = fn i, _opts -> to_string(i) end
438
476
iex> opts = [separator: "!"]
439
- iex> doc = Inspect.Algebra.container_doc ("[", Enum.to_list(1..5), "]", inspect_opts, fun, opts)
477
+ iex> { doc, _opts} = Inspect.Algebra.container_doc_with_opts ("[", Enum.to_list(1..5), "]", inspect_opts, fun, opts)
440
478
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary()
441
479
"[1! 2! 3! ...]"
442
480
443
481
"""
444
- @ doc since: "1.6.0"
445
- @ spec container_doc ( t , [ term ] , t , Inspect.Opts . t ( ) , ( term , Inspect.Opts . t ( ) -> t ) , keyword ( ) ) ::
446
- t
447
- def container_doc ( left , collection , right , inspect_opts , fun , opts \\ [ ] )
482
+ @ doc since: "1.19.0"
483
+ @ spec container_doc_with_opts (
484
+ t ,
485
+ [ term ] ,
486
+ t ,
487
+ Inspect.Opts . t ( ) ,
488
+ ( term , Inspect.Opts . t ( ) -> t ) ,
489
+ keyword ( )
490
+ ) ::
491
+ { t , Inspect.Opts . t ( ) }
492
+ def container_doc_with_opts ( left , collection , right , inspect_opts , fun , opts \\ [ ] )
448
493
when is_doc ( left ) and is_list ( collection ) and is_doc ( right ) and is_function ( fun , 2 ) and
449
494
is_list ( opts ) do
450
495
case collection do
451
496
[ ] ->
452
- concat ( left , right )
497
+ { concat ( left , right ) , inspect_opts }
453
498
454
499
_ ->
455
500
break = Keyword . get ( opts , :break , :maybe )
456
501
separator = Keyword . get ( opts , :separator , @ container_separator )
457
502
458
- { docs , simple? } =
459
- container_each ( collection , inspect_opts . limit , inspect_opts , fun , [ ] , break == :maybe )
503
+ { docs , simple? , inspect_opts } =
504
+ container_each ( collection , inspect_opts , fun , [ ] , break == :maybe )
460
505
461
506
flex? = simple? or break == :flex
462
507
docs = fold ( docs , & join ( & 1 , & 2 , flex? , separator ) )
463
508
464
- case flex? do
465
- true -> group ( concat ( concat ( left , nest ( docs , 1 ) ) , right ) )
466
- false -> group ( glue ( nest ( glue ( left , "" , docs ) , 2 ) , "" , right ) )
467
- end
509
+ group =
510
+ case flex? do
511
+ true -> group ( concat ( concat ( left , nest ( docs , 1 ) ) , right ) )
512
+ false -> group ( glue ( nest ( glue ( left , "" , docs ) , 2 ) , "" , right ) )
513
+ end
514
+
515
+ { group , inspect_opts }
468
516
end
469
517
end
470
518
471
- defp container_each ( [ ] , _limit , _opts , _fun , acc , simple? ) do
472
- { :lists . reverse ( acc ) , simple? }
519
+ defp container_each ( [ ] , opts , _fun , acc , simple? ) do
520
+ { :lists . reverse ( acc ) , simple? , opts }
473
521
end
474
522
475
- defp container_each ( _ , 0 , _opts , _fun , acc , simple? ) do
476
- { :lists . reverse ( [ "..." | acc ] ) , simple? }
523
+ defp container_each ( _ , opts , _fun , acc , simple? ) when opts . limit <= 0 do
524
+ { :lists . reverse ( [ "..." | acc ] ) , simple? , opts }
477
525
end
478
526
479
- defp container_each ( [ term | terms ] , limit , opts , fun , acc , simple? )
480
- when is_list ( terms ) and is_limit ( limit ) do
481
- new_limit = decrement ( limit )
482
- doc = fun . ( term , % { opts | limit: new_limit } )
483
- limit = if doc == :doc_nil , do: limit , else: new_limit
484
- container_each ( terms , limit , opts , fun , [ doc | acc ] , simple? and simple? ( doc ) )
527
+ defp container_each ( [ term | terms ] , opts , fun , acc , simple? ) when is_list ( terms ) do
528
+ { doc , opts } = call_container_fun ( fun , term , opts )
529
+ container_each ( terms , opts , fun , [ doc | acc ] , simple? and simple? ( doc ) )
485
530
end
486
531
487
- defp container_each ( [ left | right ] , limit , opts , fun , acc , simple? ) when is_limit ( limit ) do
488
- limit = decrement ( limit )
489
- left = fun . ( left , % { opts | limit: limit } )
490
- right = fun . ( right , % { opts | limit: limit } )
532
+ defp container_each ( [ left | right ] , opts , fun , acc , simple? ) do
533
+ { left , opts } = call_container_fun ( fun , left , opts )
534
+ { right , _opts } = call_container_fun ( fun , right , opts )
491
535
simple? = simple? and simple? ( left ) and simple? ( right )
492
-
493
536
doc = join ( left , right , simple? , @ tail_separator )
494
- { :lists . reverse ( [ doc | acc ] ) , simple? }
537
+ { :lists . reverse ( [ doc | acc ] ) , simple? , opts }
538
+ end
539
+
540
+ defp call_container_fun ( fun , term , % { limit: bounded } = opts )
541
+ when bounded <= 0 or bounded == :infinity do
542
+ case fun . ( term , opts ) do
543
+ { doc , % Inspect.Opts { } = opts } -> { doc , opts }
544
+ doc -> { doc , opts }
545
+ end
495
546
end
496
547
497
- defp decrement ( :infinity ) , do: :infinity
498
- defp decrement ( counter ) , do: counter - 1
548
+ defp call_container_fun ( fun , term , % { limit: limit } = opts ) do
549
+ changed_opts = % { opts | limit: limit - 1 }
550
+
551
+ case fun . ( term , changed_opts ) do
552
+ { doc , % Inspect.Opts { } = opts } -> { doc , opts }
553
+ :doc_nil -> { :doc_nil , opts }
554
+ doc -> { doc , changed_opts }
555
+ end
556
+ end
499
557
500
558
defp join ( :doc_nil , :doc_nil , _ , _ ) , do: :doc_nil
501
559
defp join ( left , :doc_nil , _ , _ ) , do: left
0 commit comments