@@ -192,7 +192,7 @@ defmodule Inspect.Algebra do
192
192
193
193
iex> doc = Inspect.Algebra.concat(Inspect.Algebra.empty(), "foo")
194
194
iex> Inspect.Algebra.format(doc, 80)
195
- [ "foo"]
195
+ "foo"
196
196
197
197
The functions `nest/2`, `space/2` and `line/2` help you put the
198
198
document together into a rigid structure. However, the document
@@ -205,15 +205,15 @@ defmodule Inspect.Algebra do
205
205
iex> doc = Inspect.Algebra.glue("a", " ", "b")
206
206
iex> doc = Inspect.Algebra.group(doc)
207
207
iex> Inspect.Algebra.format(doc, 80)
208
- ["a", " ", "b"]
208
+ "a b"
209
209
210
210
Note that the break was represented as is, because we haven't reached
211
211
a line limit. Once we do, it is replaced by a newline:
212
212
213
213
iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b")
214
214
iex> doc = Inspect.Algebra.group(doc)
215
215
iex> Inspect.Algebra.format(doc, 10)
216
- [ "aaaaaaaaaaaaaaaaaaaa", "\n", "b"]
216
+ "aaaaaaaaaaaaaaaaaaaa\nb"
217
217
218
218
This module uses the byte size to compute how much space there is
219
219
left. If your document contains strings, then those need to be
@@ -279,7 +279,7 @@ defmodule Inspect.Algebra do
279
279
quote do: [ unquote ( left ) | unquote ( right ) ]
280
280
end
281
281
282
- @ typep doc_string :: { :doc_string , t , non_neg_integer }
282
+ @ typep doc_string :: { :doc_string , binary , non_neg_integer }
283
283
defmacrop doc_string ( string , length ) do
284
284
quote do: { :doc_string , unquote ( string ) , unquote ( length ) }
285
285
end
@@ -665,7 +665,7 @@ defmodule Inspect.Algebra do
665
665
iex> doc = Inspect.Algebra.glue("olá", " ", "mundo")
666
666
iex> doc = Inspect.Algebra.group(doc)
667
667
iex> Inspect.Algebra.format(doc, 9)
668
- [ "olá", "\n", "mundo"]
668
+ "olá\nmundo"
669
669
670
670
However, if we use `string`, then the string length is
671
671
used, instead of byte size, correctly fitting:
@@ -674,7 +674,7 @@ defmodule Inspect.Algebra do
674
674
iex> doc = Inspect.Algebra.glue(string, " ", "mundo")
675
675
iex> doc = Inspect.Algebra.group(doc)
676
676
iex> Inspect.Algebra.format(doc, 9)
677
- [ "olá", " ", " mundo"]
677
+ "olá mundo"
678
678
679
679
"""
680
680
@ doc since: "1.6.0"
@@ -690,7 +690,7 @@ defmodule Inspect.Algebra do
690
690
691
691
iex> doc = Inspect.Algebra.concat("hello", "world")
692
692
iex> Inspect.Algebra.format(doc, 80)
693
- ["hello", "world"]
693
+ "helloworld"
694
694
695
695
"""
696
696
@ spec concat ( t , t ) :: t
@@ -705,10 +705,10 @@ defmodule Inspect.Algebra do
705
705
706
706
iex> doc = Inspect.Algebra.glue("hello", "world") |> Inspect.Algebra.group()
707
707
iex> Inspect.Algebra.format(doc, 10)
708
- [ "hello", "\n", "world"]
708
+ "hello\nworld"
709
709
iex> doc = Inspect.Algebra.no_limit(doc)
710
710
iex> Inspect.Algebra.format(doc, 10)
711
- [ "hello", " ", " world"]
711
+ "hello world"
712
712
713
713
"""
714
714
@ doc since: "1.14.0"
@@ -724,7 +724,7 @@ defmodule Inspect.Algebra do
724
724
725
725
iex> doc = Inspect.Algebra.concat(["a", "b", "c"])
726
726
iex> Inspect.Algebra.format(doc, 80)
727
- ["a", "b", "c"]
727
+ "abc"
728
728
729
729
"""
730
730
@ spec concat ( [ t ] ) :: t
@@ -758,7 +758,7 @@ defmodule Inspect.Algebra do
758
758
iex> doc = Inspect.Algebra.nest(Inspect.Algebra.glue("hello", "world"), 5)
759
759
iex> doc = Inspect.Algebra.group(doc)
760
760
iex> Inspect.Algebra.format(doc, 5)
761
- [ "hello", " \n ", " world"]
761
+ "hello\n world"
762
762
763
763
"""
764
764
@ spec nest ( t , non_neg_integer | :cursor | :reset , :always | :break ) :: doc_nest | t
@@ -794,7 +794,7 @@ defmodule Inspect.Algebra do
794
794
795
795
iex> doc = Inspect.Algebra.concat(["a", Inspect.Algebra.break("\t"), "b"])
796
796
iex> Inspect.Algebra.format(doc, 80)
797
- ["a", "\t", "b"]
797
+ "a\tb"
798
798
799
799
Note that the break was represented with the given string, because we didn't
800
800
reach a line limit. Once we do, it is replaced by a newline:
@@ -803,7 +803,7 @@ defmodule Inspect.Algebra do
803
803
iex> doc = Inspect.Algebra.concat([String.duplicate("a", 20), break, "b"])
804
804
iex> doc = Inspect.Algebra.group(doc)
805
805
iex> Inspect.Algebra.format(doc, 10)
806
- [ "aaaaaaaaaaaaaaaaaaaa", "\n", "b"]
806
+ "aaaaaaaaaaaaaaaaaaaa\nb"
807
807
808
808
"""
809
809
@ spec break ( binary ) :: doc_break
@@ -898,11 +898,11 @@ defmodule Inspect.Algebra do
898
898
899
899
iex> doc = Inspect.Algebra.glue("hello", "world")
900
900
iex> Inspect.Algebra.format(doc, 80)
901
- [ "hello", " ", " world"]
901
+ "hello world"
902
902
903
903
iex> doc = Inspect.Algebra.glue("hello", "\t", "world")
904
904
iex> Inspect.Algebra.format(doc, 80)
905
- [ "hello", "\t", "world"]
905
+ "hello\tworld"
906
906
907
907
"""
908
908
@ spec glue ( t , binary , t ) :: t
@@ -961,9 +961,9 @@ defmodule Inspect.Algebra do
961
961
...> )
962
962
...> )
963
963
iex> Inspect.Algebra.format(doc, 80)
964
- [ "Hello,", " ", "A", " ", "B"]
964
+ "Hello, A B"
965
965
iex> Inspect.Algebra.format(doc, 6)
966
- [ "Hello,", "\n", "A", "\n", "B"]
966
+ "Hello,\nA\nB"
967
967
968
968
## Mode examples
969
969
@@ -1018,7 +1018,7 @@ defmodule Inspect.Algebra do
1018
1018
1019
1019
iex> doc = Inspect.Algebra.space("Hughes", "Wadler")
1020
1020
iex> Inspect.Algebra.format(doc, 5)
1021
- [ "Hughes", " ", " Wadler"]
1021
+ "Hughes Wadler"
1022
1022
1023
1023
"""
1024
1024
@ spec space ( t , t ) :: t
@@ -1040,7 +1040,7 @@ defmodule Inspect.Algebra do
1040
1040
...> "Wadler"
1041
1041
...> )
1042
1042
iex> Inspect.Algebra.format(doc, 80)
1043
- [ "Hughes", "\n", "Wadler"]
1043
+ "Hughes\nWadler"
1044
1044
1045
1045
"""
1046
1046
@ doc since: "1.6.0"
@@ -1056,7 +1056,7 @@ defmodule Inspect.Algebra do
1056
1056
1057
1057
iex> doc = Inspect.Algebra.line("Hughes", "Wadler")
1058
1058
iex> Inspect.Algebra.format(doc, 80)
1059
- [ "Hughes", "\n", "Wadler"]
1059
+ "Hughes\nWadler"
1060
1060
1061
1061
"""
1062
1062
@ spec line ( t , t ) :: t
@@ -1081,7 +1081,7 @@ defmodule Inspect.Algebra do
1081
1081
...> Inspect.Algebra.concat([doc, "!", acc])
1082
1082
...> end)
1083
1083
iex> Inspect.Algebra.format(docs, 80)
1084
- ["A", "!", "B", "!", "C"]
1084
+ "A!B!C"
1085
1085
1086
1086
"""
1087
1087
@ doc since: "1.18.0"
@@ -1115,7 +1115,7 @@ defmodule Inspect.Algebra do
1115
1115
"""
1116
1116
@ spec format ( t , non_neg_integer | :infinity ) :: iodata
1117
1117
def format ( doc , width ) when is_doc ( doc ) and is_width ( width ) do
1118
- format ( width , 0 , [ { 0 , :flat , doc } ] )
1118
+ format ( width , 0 , [ { 0 , :flat , doc } ] , << >> )
1119
1119
end
1120
1120
1121
1121
# Type representing the document mode to be rendered:
@@ -1225,95 +1225,117 @@ defmodule Inspect.Algebra do
1225
1225
@ spec format (
1226
1226
width :: non_neg_integer ( ) | :infinity ,
1227
1227
column :: non_neg_integer ( ) ,
1228
- [ { integer , mode , t } | :group_over ]
1229
- ) :: [ binary ]
1230
- defp format ( _ , _ , [ ] ) , do: [ ]
1231
- defp format ( w , k , [ { _ , _ , doc_nil ( ) } | t ] ) , do: format ( w , k , t )
1232
- defp format ( w , _ , [ { i , _ , doc_line ( ) } | t ] ) , do: [ indent ( i ) | format ( w , i , t ) ]
1233
- defp format ( w , k , [ { i , m , doc_cons ( x , y ) } | t ] ) , do: format ( w , k , [ { i , m , x } , { i , m , y } | t ] )
1234
- defp format ( w , k , [ { i , m , doc_color ( x , c ) } | t ] ) , do: [ c | format ( w , k , [ { i , m , x } | t ] ) ]
1235
- defp format ( w , k , [ { _ , _ , doc_string ( s , l ) } | t ] ) , do: [ s | format ( w , k + l , t ) ]
1236
- defp format ( w , k , [ { _ , _ , s } | t ] ) when is_binary ( s ) , do: [ s | format ( w , k + byte_size ( s ) , t ) ]
1237
- defp format ( w , k , [ { i , m , doc_force ( x ) } | t ] ) , do: format ( w , k , [ { i , m , x } | t ] )
1238
- defp format ( w , k , [ { i , m , doc_fits ( x , _ ) } | t ] ) , do: format ( w , k , [ { i , m , x } | t ] )
1239
- defp format ( w , _ , [ { i , _ , doc_collapse ( max ) } | t ] ) , do: collapse ( format ( w , i , t ) , max , 0 , i )
1228
+ [ { integer , mode , t } | :group_over ] ,
1229
+ binary
1230
+ ) :: iodata
1231
+ defp format ( _ , _ , [ ] , acc ) , do: acc
1232
+
1233
+ defp format ( w , k , [ { _ , _ , doc_nil ( ) } | t ] , acc ) ,
1234
+ do: format ( w , k , t , acc )
1235
+
1236
+ defp format ( w , _ , [ { i , _ , doc_line ( ) } | t ] , acc ) ,
1237
+ do: format ( w , i , t , << acc :: binary , indent ( i ) :: binary >> )
1238
+
1239
+ defp format ( w , k , [ { i , m , doc_cons ( x , y ) } | t ] , acc ) ,
1240
+ do: format ( w , k , [ { i , m , x } , { i , m , y } | t ] , acc )
1241
+
1242
+ defp format ( w , k , [ { i , m , doc_color ( x , c ) } | t ] , acc ) ,
1243
+ do: format ( w , k , [ { i , m , x } | t ] , << acc :: binary , c :: binary >> )
1244
+
1245
+ defp format ( w , k , [ { _ , _ , doc_string ( s , l ) } | t ] , acc ) ,
1246
+ do: format ( w , k + l , t , << acc :: binary , s :: binary >> )
1247
+
1248
+ defp format ( w , k , [ { _ , _ , s } | t ] , acc ) when is_binary ( s ) ,
1249
+ do: format ( w , k + byte_size ( s ) , t , << acc :: binary , s :: binary >> )
1250
+
1251
+ defp format ( w , k , [ { i , m , doc_force ( x ) } | t ] , acc ) ,
1252
+ do: format ( w , k , [ { i , m , x } | t ] , acc )
1253
+
1254
+ defp format ( w , k , [ { i , m , doc_fits ( x , _ ) } | t ] , acc ) ,
1255
+ do: format ( w , k , [ { i , m , x } | t ] , acc )
1256
+
1257
+ defp format ( w , _ , [ { i , _ , doc_collapse ( max ) } | t ] , acc ) ,
1258
+ do: [ acc | collapse ( List . wrap ( format ( w , i , t , << >> ) ) , max , 0 , i ) ]
1240
1259
1241
1260
# Flex breaks are conditional to the document and the mode
1242
- defp format ( w , k , [ { i , m , doc_break ( s , :flex ) } | t ] ) do
1261
+ defp format ( w , k , [ { i , m , doc_break ( s , :flex ) } | t ] , acc ) do
1243
1262
k = k + byte_size ( s )
1244
1263
1245
1264
if w == :infinity or m == :flat or fits? ( w , k , true , t ) do
1246
- [ s | format ( w , k , t ) ]
1265
+ format ( w , k , t , << acc :: binary , s :: binary >> )
1247
1266
else
1248
- [ indent ( i ) | format ( w , i , t ) ]
1267
+ format ( w , i , t , << acc :: binary , indent ( i ) :: binary >> )
1249
1268
end
1250
1269
end
1251
1270
1252
1271
# Strict breaks are conditional to the mode
1253
- defp format ( w , k , [ { i , mode , doc_break ( s , :strict ) } | t ] ) do
1272
+ defp format ( w , k , [ { i , mode , doc_break ( s , :strict ) } | t ] , acc ) do
1254
1273
if mode == :break do
1255
- [ indent ( i ) | format ( w , i , t ) ]
1274
+ format ( w , i , t , << acc :: binary , indent ( i ) :: binary >> )
1256
1275
else
1257
- [ s | format ( w , k + byte_size ( s ) , t ) ]
1276
+ format ( w , k + byte_size ( s ) , t , << acc :: binary , s :: binary >> )
1258
1277
end
1259
1278
end
1260
1279
1261
1280
# Nesting is conditional to the mode.
1262
- defp format ( w , k , [ { i , mode , doc_nest ( x , j , nest ) } | t ] ) do
1281
+ defp format ( w , k , [ { i , mode , doc_nest ( x , j , nest ) } | t ] , acc ) do
1263
1282
if nest == :always or ( nest == :break and mode == :break ) do
1264
- format ( w , k , [ { apply_nesting ( i , k , j ) , mode , x } | t ] )
1283
+ format ( w , k , [ { apply_nesting ( i , k , j ) , mode , x } | t ] , acc )
1265
1284
else
1266
- format ( w , k , [ { i , mode , x } | t ] )
1285
+ format ( w , k , [ { i , mode , x } | t ] , acc )
1267
1286
end
1268
1287
end
1269
1288
1270
1289
# Groups must do the fitting decision.
1271
- defp format ( w , k , [ :group_over | t ] ) do
1272
- format ( w , k , t )
1290
+ defp format ( w , k , [ :group_over | t ] , acc ) do
1291
+ format ( w , k , t , acc )
1273
1292
end
1274
1293
1275
1294
# TODO: Deprecate me in Elixir v1.23
1276
- defp format ( w , k , [ { i , :break , doc_group ( x , :inherit ) } | t ] ) do
1277
- format ( w , k , [ { i , :break , x } | t ] )
1295
+ defp format ( w , k , [ { i , :break , doc_group ( x , :inherit ) } | t ] , acc ) do
1296
+ format ( w , k , [ { i , :break , x } | t ] , acc )
1278
1297
end
1279
1298
1280
- defp format ( w , k , [ { i , :flat , doc_group ( x , :optimistic ) } | t ] ) do
1299
+ defp format ( w , k , [ { i , :flat , doc_group ( x , :optimistic ) } | t ] , acc ) do
1281
1300
if w == :infinity or fits? ( w , k , false , [ { i , :flat , x } | t ] ) do
1282
- format ( w , k , [ { i , :flat , x } , :group_over | t ] )
1301
+ format ( w , k , [ { i , :flat , x } , :group_over | t ] , acc )
1283
1302
else
1284
- format ( w , k , [ { i , :break , x } , :group_over | t ] )
1303
+ format ( w , k , [ { i , :break , x } , :group_over | t ] , acc )
1285
1304
end
1286
1305
end
1287
1306
1288
- defp format ( w , k , [ { i , _ , doc_group ( x , _ ) } | t ] ) do
1307
+ defp format ( w , k , [ { i , _ , doc_group ( x , _ ) } | t ] , acc ) do
1289
1308
if w == :infinity or fits? ( w , k , false , [ { i , :flat , x } ] ) do
1290
- format ( w , k , [ { i , :flat , x } , :group_over | t ] )
1309
+ format ( w , k , [ { i , :flat , x } , :group_over | t ] , acc )
1291
1310
else
1292
- format ( w , k , [ { i , :break , x } , :group_over | t ] )
1311
+ format ( w , k , [ { i , :break , x } , :group_over | t ] , acc )
1293
1312
end
1294
1313
end
1295
1314
1296
1315
# Limit is set to infinity and then reverts
1297
- defp format ( w , k , [ { i , m , doc_limit ( x , :infinity ) } | t ] ) when w != :infinity do
1298
- format ( :infinity , k , [ { i , :flat , x } , { i , m , doc_limit ( empty ( ) , w ) } | t ] )
1316
+ defp format ( w , k , [ { i , m , doc_limit ( x , :infinity ) } | t ] , acc ) when w != :infinity do
1317
+ format ( :infinity , k , [ { i , :flat , x } , { i , m , doc_limit ( empty ( ) , w ) } | t ] , acc )
1299
1318
end
1300
1319
1301
- defp format ( _w , k , [ { i , m , doc_limit ( x , w ) } | t ] ) do
1302
- format ( w , k , [ { i , m , x } | t ] )
1320
+ defp format ( _w , k , [ { i , m , doc_limit ( x , w ) } | t ] , acc ) do
1321
+ format ( w , k , [ { i , m , x } | t ] , acc )
1303
1322
end
1304
1323
1305
- defp collapse ( [ "\n " <> _ | t ] , max , count , i ) do
1306
- collapse ( t , max , count + 1 , i )
1324
+ defp collapse ( [ "\n " <> rest | t ] , max , count , i ) do
1325
+ collapse ( [ strip_whitespace ( rest ) | t ] , max , count + 1 , i )
1307
1326
end
1308
1327
1309
1328
defp collapse ( [ "" | t ] , max , count , i ) do
1310
1329
collapse ( t , max , count , i )
1311
1330
end
1312
1331
1313
1332
defp collapse ( t , max , count , i ) do
1314
- [ :binary . copy ( "\n " , min ( max , count ) ) <> :binary . copy ( " " , i ) | t ]
1333
+ [ :binary . copy ( "\n " , min ( max , count ) ) , :binary . copy ( " " , i ) | t ]
1315
1334
end
1316
1335
1336
+ defp strip_whitespace ( " " <> rest ) , do: strip_whitespace ( rest )
1337
+ defp strip_whitespace ( rest ) , do: rest
1338
+
1317
1339
defp apply_nesting ( _ , k , :cursor ) , do: k
1318
1340
defp apply_nesting ( _ , _ , :reset ) , do: 0
1319
1341
defp apply_nesting ( i , _ , j ) , do: i + j
0 commit comments