From 3b6de41db9ab8d8a9165ec5134375461577508ef Mon Sep 17 00:00:00 2001 From: Isla Waters Date: Mon, 3 Mar 2025 08:41:26 -0500 Subject: [PATCH] Properly handle line breaks in column value Before this code tried to replace newlines with empty spaces, but it didn't always work because the new value would only use the replaced string if additional wrapping needed to be done due to size constraints. This updates the code to properly handle new lines in all content by creating an extra row for each one, using the same logic that already existed for wrapping longer content. See https://github.com/wp-cli/entity-command/issues/262 for an example of the currently broken behavior that this PR fixes --- lib/cli/table/Ascii.php | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/cli/table/Ascii.php b/lib/cli/table/Ascii.php index ff5c3d9..b2505e6 100644 --- a/lib/cli/table/Ascii.php +++ b/lib/cli/table/Ascii.php @@ -136,31 +136,32 @@ public function row( array $row ) { if ( count( $row ) > 0 ) { $extra_rows = array_fill( 0, count( $row ), array() ); - foreach( $row as $col => $value ) { - $value = $value ?: ''; - $value = str_replace( array( "\r\n", "\n" ), ' ', $value ); - - $col_width = $this->_widths[ $col ]; - $encoding = function_exists( 'mb_detect_encoding' ) ? mb_detect_encoding( $value, null, true /*strict*/ ) : false; + foreach ( $row as $col => $value ) { + $value = $value ?: ''; + $col_width = $this->_widths[ $col ]; + $encoding = function_exists( 'mb_detect_encoding' ) ? mb_detect_encoding( $value, null, true /*strict*/ ) : false; $original_val_width = Colors::width( $value, self::isPreColorized( $col ), $encoding ); - if ( $col_width && $original_val_width > $col_width ) { - $row[ $col ] = \cli\safe_substr( $value, 0, $col_width, true /*is_width*/, $encoding ); - $value = \cli\safe_substr( $value, \cli\safe_strlen( $row[ $col ], $encoding ), null /*length*/, false /*is_width*/, $encoding ); - $i = 0; - do { - $extra_value = \cli\safe_substr( $value, 0, $col_width, true /*is_width*/, $encoding ); - $val_width = Colors::width( $extra_value, self::isPreColorized( $col ), $encoding ); - if ( $val_width ) { - $extra_rows[ $col ][] = $extra_value; - $value = \cli\safe_substr( $value, \cli\safe_strlen( $extra_value, $encoding ), null /*length*/, false /*is_width*/, $encoding ); - $i++; - if ( $i > $extra_row_count ) { - $extra_row_count = $i; + if ( $col_width && ( $original_val_width > $col_width || strpos( $value, "\n" ) !== false ) ) { + $split_lines = preg_split( '/\r\n|\n/', $value ); + + $wrapped_lines = []; + foreach ( $split_lines as $line ) { + do { + $wrapped_value = \cli\safe_substr( $line, 0, $col_width, true /*is_width*/, $encoding ); + $val_width = Colors::width( $wrapped_value, self::isPreColorized( $col ), $encoding ); + if ( $val_width ) { + $wrapped_lines[] = $wrapped_value; + $line = \cli\safe_substr( $line, \cli\safe_strlen( $wrapped_value, $encoding ), null /*length*/, false /*is_width*/, $encoding ); } - } - } while( $value ); - } + } while ( $line ); + } + $row[ $col ] = array_shift( $wrapped_lines ); + foreach ( $wrapped_lines as $wrapped_line ) { + $extra_rows[ $col ][] = $wrapped_line; + ++$extra_row_count; + } + } } }