@@ -31,7 +31,6 @@ class CliDumper extends AbstractDumper
3131 'num ' => '1;38;5;38 ' ,
3232 'const ' => '1;38;5;208 ' ,
3333 'str ' => '1;38;5;113 ' ,
34- 'cchr ' => '7 ' ,
3534 'note ' => '38;5;38 ' ,
3635 'ref ' => '38;5;247 ' ,
3736 'public ' => '' ,
@@ -42,7 +41,15 @@ class CliDumper extends AbstractDumper
4241 'index ' => '38;5;38 ' ,
4342 );
4443
45- protected static $ controlCharsRx = '/[\x00-\x1F\x7F]/ ' ;
44+ protected static $ controlCharsRx = '/[\x00-\x1F\x7F]+/ ' ;
45+ protected static $ controlCharsMap = array (
46+ "\t" => '\t ' ,
47+ "\n" => '\n ' ,
48+ "\v" => '\v ' ,
49+ "\f" => '\f ' ,
50+ "\r" => '\r ' ,
51+ "\033" => '\e ' ,
52+ );
4653
4754 /**
4855 * {@inheritdoc}
@@ -146,7 +153,7 @@ public function dumpScalar(Cursor $cursor, $type, $value)
146153
147154 $ this ->line .= $ this ->style ($ style , $ value , $ attr );
148155
149- $ this ->dumpLine ($ cursor ->depth );
156+ $ this ->dumpLine ($ cursor ->depth , true );
150157 }
151158
152159 /**
@@ -161,13 +168,17 @@ public function dumpString(Cursor $cursor, $str, $bin, $cut)
161168 }
162169 if ('' === $ str ) {
163170 $ this ->line .= '"" ' ;
164- $ this ->dumpLine ($ cursor ->depth );
171+ $ this ->dumpLine ($ cursor ->depth , true );
165172 } else {
166173 $ attr = array (
167- 'length ' => function_exists ( ' iconv_strlen ' ) && 0 <= $ cut ? iconv_strlen ($ str , 'UTF-8 ' ) + $ cut : 0 ,
174+ 'length ' => 0 <= $ cut && function_exists ( ' iconv_strlen ' ) ? iconv_strlen ($ str , 'UTF-8 ' ) + $ cut : 0 ,
168175 'binary ' => $ bin ,
169176 );
170177 $ str = explode ("\n" , $ str );
178+ if (isset ($ str [1 ]) && !isset ($ str [2 ]) && !isset ($ str [1 ][0 ])) {
179+ unset($ str [1 ]);
180+ $ str [0 ] .= "\n" ;
181+ }
171182 $ m = count ($ str ) - 1 ;
172183 $ i = $ lineCut = 0 ;
173184
@@ -183,20 +194,30 @@ public function dumpString(Cursor $cursor, $str, $bin, $cut)
183194 }
184195
185196 foreach ($ str as $ str ) {
197+ if ($ i < $ m ) {
198+ $ str .= "\n" ;
199+ }
186200 if (0 < $ this ->maxStringWidth && $ this ->maxStringWidth < $ len = iconv_strlen ($ str , 'UTF-8 ' )) {
187201 $ str = iconv_substr ($ str , 0 , $ this ->maxStringWidth , 'UTF-8 ' );
188202 $ lineCut = $ len - $ this ->maxStringWidth ;
189203 }
190-
191- if ($ m ) {
204+ if ($ m && 0 < $ cursor ->depth ) {
192205 $ this ->line .= $ this ->indentPad ;
193206 }
194- $ this ->line .= $ this ->style ('str ' , $ str , $ attr );
195-
207+ if ('' !== $ str ) {
208+ $ this ->line .= $ this ->style ('str ' , $ str , $ attr );
209+ }
196210 if ($ i ++ == $ m ) {
197- $ this ->line .= '" ' ;
198211 if ($ m ) {
199- $ this ->line .= '"" ' ;
212+ if ('' !== $ str ) {
213+ $ this ->dumpLine ($ cursor ->depth );
214+ if (0 < $ cursor ->depth ) {
215+ $ this ->line .= $ this ->indentPad ;
216+ }
217+ }
218+ $ this ->line .= '""" ' ;
219+ } else {
220+ $ this ->line .= '" ' ;
200221 }
201222 if ($ cut < 0 ) {
202223 $ this ->line .= '… ' ;
@@ -210,7 +231,7 @@ public function dumpString(Cursor $cursor, $str, $bin, $cut)
210231 $ lineCut = 0 ;
211232 }
212233
213- $ this ->dumpLine ($ cursor ->depth );
234+ $ this ->dumpLine ($ cursor ->depth , $ i > $ m );
214235 }
215236 }
216237 }
@@ -228,7 +249,7 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild)
228249 if (Cursor::HASH_OBJECT === $ type ) {
229250 $ prefix = 'stdClass ' !== $ class ? $ this ->style ('note ' , $ class ).' { ' : '{ ' ;
230251 } elseif (Cursor::HASH_RESOURCE === $ type ) {
231- $ prefix = $ this ->style ('note ' , ' : ' . $ class). ' { ' ;
252+ $ prefix = $ this ->style ('note ' , $ class. ' resource ' ).( $ hasChild ? ' { ' : ' ' ) ;
232253 } else {
233254 $ prefix = $ class ? $ this ->style ('note ' , 'array: ' .$ class ).' [ ' : '[ ' ;
234255 }
@@ -237,6 +258,8 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild)
237258 $ prefix .= $ this ->style ('ref ' , (Cursor::HASH_RESOURCE === $ type ? '@ ' : '# ' ).(0 < $ cursor ->softRefHandle ? $ cursor ->softRefHandle : $ cursor ->softRefTo ), array ('count ' => $ cursor ->softRefCount ));
238259 } elseif ($ cursor ->hardRefTo && !$ cursor ->refIndex && $ class ) {
239260 $ prefix .= $ this ->style ('ref ' , '& ' .$ cursor ->hardRefTo , array ('count ' => $ cursor ->hardRefCount ));
261+ } elseif (!$ hasChild && Cursor::HASH_RESOURCE === $ type ) {
262+ $ prefix = substr ($ prefix , 0 , -1 );
240263 }
241264
242265 $ this ->line .= $ prefix ;
@@ -252,8 +275,8 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild)
252275 public function leaveHash (Cursor $ cursor , $ type , $ class , $ hasChild , $ cut )
253276 {
254277 $ this ->dumpEllipsis ($ cursor , $ hasChild , $ cut );
255- $ this ->line .= Cursor::HASH_OBJECT === $ type || Cursor::HASH_RESOURCE === $ type ? '} ' : '] ' ;
256- $ this ->dumpLine ($ cursor ->depth );
278+ $ this ->line .= Cursor::HASH_OBJECT === $ type ? ' } ' : ( Cursor::HASH_RESOURCE !== $ type ? '] ' : ( $ hasChild ? ' } ' : '' )) ;
279+ $ this ->dumpLine ($ cursor ->depth , true );
257280 }
258281
259282 /**
@@ -360,12 +383,34 @@ protected function style($style, $value, $attr = array())
360383 }
361384
362385 $ style = $ this ->styles [$ style ];
363- $ cchr = $ this ->colors ? "\033[m \033[ {$ style }; {$ this ->styles ['cchr ' ]}m%s \033[m \033[ {$ style }m " : '%s ' ;
364- $ value = preg_replace_callback (self ::$ controlCharsRx , function ($ r ) use ($ cchr ) {
365- return sprintf ($ cchr , "\x7F" === $ r [0 ] ? '? ' : chr (64 + ord ($ r [0 ])));
366- }, $ value );
367386
368- return $ this ->colors ? sprintf ("\033[%sm%s \033[m \033[%sm " , $ style , $ value , $ this ->styles ['default ' ]) : $ value ;
387+ $ map = static ::$ controlCharsMap ;
388+ $ startCchr = $ this ->colors ? "\033[m \033[ {$ this ->styles ['default ' ]}m " : '' ;
389+ $ endCchr = $ this ->colors ? "\033[m \033[ {$ style }m " : '' ;
390+ $ value = preg_replace_callback (static ::$ controlCharsRx , function ($ c ) use ($ map , $ startCchr , $ endCchr ) {
391+ $ s = $ startCchr ;
392+ $ c = $ c [$ i = 0 ];
393+ do {
394+ $ s .= isset ($ map [$ c [$ i ]]) ? $ map [$ c [$ i ]] : sprintf ('\x%02X ' , ord ($ c [$ i ]));
395+
6D38
} while (isset ($ c [++$ i ]));
396+
397+ return $ s .$ endCchr ;
398+ }, $ value , -1 , $ cchrCount );
399+
400+ if ($ this ->colors ) {
401+ if ($ cchrCount && "\033" === $ value [0 ]) {
402+ $ value = substr ($ value , strlen ($ startCchr ));
403+ } else {
404+ $ value = "\033[ {$ style }m " .$ value ;
405+ }
406+ if ($ cchrCount && $ endCchr === substr ($ value , -strlen ($ endCchr ))) {
407+ $ value = substr ($ value , 0 , -strlen ($ endCchr ));
408+ } else {
409+ $ value .= "\033[ {$ this ->styles ['default ' ]}m " ;
410+ }
411+ }
412+
413+ return $ value ;
369414 }
370415
371416 /**
@@ -418,7 +463,7 @@ protected function supportsColors()
418463 /**
419464 * {@inheritdoc}
420465 */
421- protected function dumpLine ($ depth )
466+ protected function dumpLine ($ depth, $ endOfValue = false )
422467 {
423468 if ($ this ->colors ) {
424469 $ this ->line = sprintf ("\033[%sm%s \033[m " , $ this ->styles ['default ' ], $ this ->line );
0 commit comments