bug #40524 [Console] fix emojis messing up the line width (MarionLeHerisson)
This PR was submitted for the 5.x branch but it was merged into the 5.2 branch instead.
Discussion
----------
[Console] fix emojis messing up the line width
| Q | A
| ------------- | ---
| Branch? | 5.2
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | Fix https://github.com/symfony/symfony/issues/37904
| License | MIT
Description
========
The emojis, because they take as much space as two characters, would cause the console to display too many spaces to complete a line, which made it uneven, as described in the issue.
The fix uses the `width` function instead of `strlen`. To answer @ogizanagi's comment, yes it does work with "composed" emojis.
Before :
![image](https://user-images.githubusercontent.com/11477247/111832081-9d72b100-88f0-11eb-8eda-65ee480c898d.png)
After :
![image](https://user-images.githubusercontent.com/11477247/111832103-a6638280-88f0-11eb-802e-838d97f61c81.png)
Other changes
==========
Removed two unused lines of code, the value of `$messageLineLength` was never used.
Note
====
I'd like to add some tests, but I don't know how since I think this depends on console client width ?
Thanks for your reviews 🙏
Commits
-------
36b36dcecc
[Command] fix emojis messing up the line width
This commit is contained in:
commit
1044c0bd4b
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
@ -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 👩🌾👩🌾👩🌾👩🌾👩🌾');
|
||||
};
|
@ -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 👩🌾👩🌾👩🌾👩🌾👩🌾
|
||||
|
Reference in New Issue
Block a user