[Command] fix emojis messing up the line width

add tests + removed irrelevant method
This commit is contained in:
Marion Hurteau 2021-03-19 20:16:44 +01:00 committed by Nicolas Grekas
parent 4c2f77e5b1
commit 36b36dcecc
5 changed files with 39 additions and 10 deletions

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\String\UnicodeString;
/**
* Helper is the base class for all helper classes.
@ -45,7 +46,11 @@ abstract class Helper implements HelperInterface
*/
public static function strlen(?string $string)
{
$string = (string) $string;
$string ?? $string = '';
if (preg_match('//u', $string)) {
return (new UnicodeString($string))->width(false);
}
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return \strlen($string);
@ -59,9 +64,9 @@ abstract class Helper implements HelperInterface
*
* @return string The string subset
*/
public static function substr(string $string, int $from, int $length = null)
public static function substr(?string $string, int $from, int $length = null)
{
$string = (string) $string;
$string ?? $string = '';
if (false === $encoding = mb_detect_encoding($string, null, true)) {
return substr($string, $from, $length);
@ -116,17 +121,23 @@ abstract class Helper implements HelperInterface
return sprintf('%d B', $memory);
}
public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, ?string $string)
{
return self::strlen(self::removeDecoration($formatter, $string));
$string = self::removeDecoration($formatter, $string);
if (preg_match('//u', $string)) {
return (new UnicodeString($string))->width(true);
}
return self::strlen($string);
}
public static function removeDecoration(OutputFormatterInterface $formatter, $string)
public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string)
{
$isDecorated = $formatter->isDecorated();
$formatter->setDecorated(false);
// remove <...> formatting
$string = $formatter->format($string);
$string = $formatter->format($string ?? '');
// remove already formatted characters
$string = preg_replace("/\033\[[^m]*m/", '', $string);
$formatter->setDecorated($isDecorated);

View File

@ -311,7 +311,7 @@ class QuestionHelper extends Helper
$remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))));
$output->write($remainingCharacters);
$fullChoice .= $remainingCharacters;
$i = self::strlen($fullChoice);
$i = (false === $encoding = mb_detect_encoding($fullChoice, null, true)) ? \strlen($fullChoice) : mb_strlen($fullChoice, $encoding);
$matches = array_filter(
$autocomplete($ret),

View File

@ -501,8 +501,6 @@ class SymfonyStyle extends OutputStyle
}
$line = $prefix.$line;
$decorationLength = Helper::strlen($line) - Helper::strlenWithoutDecoration($this->getFormatter(), $line);
$messageLineLength = min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength);
$line .= str_repeat(' ', max($this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line), 0));
if ($style) {

View File

@ -0,0 +1,13 @@
<?php
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
//Ensure texts with emojis don't make longer lines than expected
return function (InputInterface $input, OutputInterface $output) {
$output = new SymfonyStyle($input, $output);
$output->success('Lorem ipsum dolor sit amet');
$output->success('Lorem ipsum dolor sit amet with one emoji 🎉');
$output->success('Lorem ipsum dolor sit amet with so many of them 👩‍🌾👩‍🌾👩‍🌾👩‍🌾👩‍🌾');
};

View File

@ -0,0 +1,7 @@
[OK] Lorem ipsum dolor sit amet
[OK] Lorem ipsum dolor sit amet with one emoji 🎉
[OK] Lorem ipsum dolor sit amet with so many of them 👩‍🌾👩‍🌾👩‍🌾👩‍🌾👩‍🌾