@@ -202,19 +202,42 @@ defimpl Inspect, for: BitString do
202
202
else
203
203
<< byte :: size ( 8 ) , h :: binary >> = head
204
204
t = << h :: binary , t :: binary >>
205
- escape ( t , char , << binary :: binary , octify ( byte ) :: binary >> )
205
+ escape ( t , char , << binary :: binary , escape_char ( byte ) :: binary >> )
206
206
end
207
207
end
208
208
defp escape ( << h , t :: binary >> , char , binary ) do
209
- escape ( t , char , << binary :: binary , octify ( h ) :: binary >> )
209
+ escape ( t , char , << binary :: binary , escape_char ( h ) :: binary >> )
210
210
end
211
211
defp escape ( << >> , _char , binary ) , do: binary
212
212
213
+
214
+ @ doc false
215
+ # also used by Regex
216
+ def escape_char ( char ) when char in ?\0 00 .. ?\3 77 ,
217
+ do: octify ( char )
218
+
219
+ def escape_char ( char ) , do: hexify ( char )
220
+
213
221
defp octify ( byte ) do
214
222
<< hi :: size ( 2 ) , mi :: size ( 3 ) , lo :: size ( 3 ) >> = << byte >>
215
223
<< ?\\ , ?0 + hi , ?0 + mi , ?0 + lo >>
216
224
end
217
225
226
+ defp hexify ( char ) when char < 0x10000 do
227
+ << a :: 4 , b :: 4 , c :: 4 , d :: 4 >> = << char :: size ( 16 ) >>
228
+ << ?\\ , ?x , ?{ , to_hex ( a ) , to_hex ( b ) , to_hex ( c ) , to_hex ( d ) , ?} >>
229
+ end
230
+
231
+ defp hexify ( char ) when char < 0x1000000 do
232
+ << a :: 4 , b :: 4 , c :: 4 , d :: 4 , e :: 4 , f :: 4 >> = << char :: size ( 24 ) >>
233
+ << ?\\ , ?x , ?{ , to_hex ( a ) , to_hex ( b ) , to_hex ( c ) ,
234
+ to_hex ( d ) , to_hex ( e ) , to_hex ( f ) , ?} >>
235
+ end
236
+
237
+ defp to_hex ( c ) when c in 0 .. 9 , do: ?0 + c
238
+ defp to_hex ( c ) when c in 10 .. 15 , do: ?a + c - 10
239
+
240
+
218
241
defp append ( << h , t :: binary >> , binary ) , do: append ( t , << binary :: binary , h >> )
219
242
defp append ( << >> , binary ) , do: binary
220
243
@@ -419,9 +442,57 @@ defimpl Inspect, for: Float do
419
442
end
420
443
421
444
defimpl Inspect , for: Regex do
422
- def inspect ( regex , opts ) do
423
- concat [ "~r" , to_doc ( regex . source , opts ) , regex . opts ]
445
+ def inspect ( regex , _opts ) do
446
+ delim = ?/
447
+ concat [ "~r" ,
448
+ << delim , escape ( regex . source , delim ) :: binary , delim >> ,
449
+ regex . opts ]
424
450
end
451
+
452
+
453
+ defp escape ( bin , term ) ,
454
+ do: escape ( bin , << >> , term )
455
+
456
+ defp escape ( << ?\\ , term >> <> rest , buf , term ) ,
457
+ do: escape ( rest , buf <> << ?\\ , term >> , term )
458
+
459
+ defp escape ( << term >> <> rest , buf , term ) ,
460
+ do: escape ( rest , buf <> << ?\\ , term >> , term )
461
+
462
+ # the list of characters is from `String.printable?` impl
463
+ # minus characters treated specially by regex: \s, \d, \b, \e
464
+
465
+ defp escape ( << ?\n >> <> rest , buf , term ) ,
466
+ do: escape ( rest , << buf :: binary , ?\\ , ?n >> , term )
467
+
468
+ defp escape ( << ?\r >> <> rest , buf , term ) ,
469
+ do: escape ( rest , << buf :: binary , ?\\ , ?r >> , term )
470
+
471
+ defp escape ( << ?\t >> <> rest , buf , term ) ,
472
+ do: escape ( rest , << buf :: binary , ?\\ , ?t >> , term )
473
+
474
+ defp escape ( << ?\v >> <> rest , buf , term ) ,
475
+ do: escape ( rest , << buf :: binary , ?\\ , ?v >> , term )
476
+
477
+ defp escape ( << ?\f >> <> rest , buf , term ) ,
478
+ do: escape ( rest , << buf :: binary , ?\\ , ?f >> , term )
479
+
480
+ defp escape ( << ?\a >> <> rest , buf , term ) ,
481
+ do: escape ( rest , << buf :: binary , ?\\ , ?a >> , term )
482
+
483
+ defp escape ( << c :: utf8 >> <> rest , buf , term ) do
484
+ charstr = << c :: utf8 >>
485
+ if String . printable? ( charstr ) and not c in [ ?\d , ?\b , ?\e ] do
486
+ escape ( rest , buf <> charstr , term )
487
+ else
488
+ escape ( rest , buf <> Inspect.BitString . escape_char ( c ) , term )
489
+ end
490
+ end
491
+
492
+ defp escape ( << c >> <> rest , buf , term ) ,
493
+ do: escape ( rest , << buf :: binary , Inspect.BitString . escape_char ( c ) >> , term )
494
+
495
+ defp escape ( << >> , buf , _ ) , do: buf
425
496
end
426
497
427
498
defimpl Inspect , for: Function do
0 commit comments