diff --git a/Helper/QuestionHelper.php b/Helper/QuestionHelper.php index f32813c6c..b40b13191 100644 --- a/Helper/QuestionHelper.php +++ b/Helper/QuestionHelper.php @@ -501,19 +501,7 @@ private function isInteractiveInput($inputStream): bool return self::$stdinIsInteractive; } - if (\function_exists('stream_isatty')) { - return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); - } - - if (\function_exists('posix_isatty')) { - return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r')); - } - - if (!\function_exists('shell_exec')) { - return self::$stdinIsInteractive = true; - } - - return self::$stdinIsInteractive = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null')); + return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); } /** diff --git a/Helper/Table.php b/Helper/Table.php index a7e3fa250..6aad9e95b 100644 --- a/Helper/Table.php +++ b/Helper/Table.php @@ -365,7 +365,8 @@ public function render() for ($i = 0; $i < $maxRows; ++$i) { $cell = (string) ($row[$i] ?? ''); - $parts = explode("\n", $cell); + $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n"; + $parts = explode($eol, $cell); foreach ($parts as $idx => $part) { if ($headers && !$containsColspan) { if (0 === $idx) { @@ -636,9 +637,10 @@ private function buildTableRows(array $rows): TableRows if (!str_contains($cell ?? '', "\n")) { continue; } - $escaped = implode("\n", array_map(OutputFormatter::escapeTrailingBackslash(...), explode("\n", $cell))); + $eol = str_contains($cell ?? '', "\r\n") ? "\r\n" : "\n"; + $escaped = implode($eol, array_map(OutputFormatter::escapeTrailingBackslash(...), explode($eol, $cell))); $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; - $lines = explode("\n", str_replace("\n", "\n", $cell)); + $lines = explode($eol, str_replace($eol, ''.$eol, $cell)); foreach ($lines as $lineKey => $line) { if ($colspan > 1) { $line = new TableCell($line, ['colspan' => $colspan]); @@ -700,8 +702,9 @@ private function fillNextRows(array $rows, int $line): array $nbLines = $cell->getRowspan() - 1; $lines = [$cell]; if (str_contains($cell, "\n")) { - $lines = explode("\n", str_replace("\n", "\n", $cell)); - $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; + $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n"; + $lines = explode($eol, str_replace($eol, ''.$eol.'', $cell)); + $nbLines = \count($lines) > $nbLines ? substr_count($cell, $eol) : $nbLines; $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]); unset($lines[0]); diff --git a/Input/InputOption.php b/Input/InputOption.php index 35a144ffa..bb533801f 100644 --- a/Input/InputOption.php +++ b/Input/InputOption.php @@ -75,7 +75,7 @@ public function __construct(string $name, string|array|null $shortcut = null, ?i throw new InvalidArgumentException('An option name cannot be empty.'); } - if ('' === $shortcut || [] === $shortcut) { + if ('' === $shortcut || [] === $shortcut || false === $shortcut) { $shortcut = null; } diff --git a/Output/StreamOutput.php b/Output/StreamOutput.php index 84bbadc05..218bc9ef2 100644 --- a/Output/StreamOutput.php +++ b/Output/StreamOutput.php @@ -97,50 +97,29 @@ protected function hasColorSupport(): bool return false; } - if (!$this->isTty()) { + // Detect msysgit/mingw and assume this is a tty because detection + // does not work correctly, see https://github.com/composer/composer/issues/9690 + if (!@stream_isatty($this->stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) { return false; } - if (\DIRECTORY_SEPARATOR === '\\' - && \function_exists('sapi_windows_vt100_support') - && @sapi_windows_vt100_support($this->stream) - ) { + if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($this->stream)) { return true; } - return 'Hyper' === getenv('TERM_PROGRAM') + if ('Hyper' === getenv('TERM_PROGRAM') + || false !== getenv('COLORTERM') || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') - || str_starts_with((string) getenv('TERM'), 'xterm'); - } - - /** - * Checks if the stream is a TTY, i.e; whether the output stream is connected to a terminal. - * - * Reference: Composer\Util\Platform::isTty - * https://github.com/composer/composer - */ - private function isTty(): bool - { - // Detect msysgit/mingw and assume this is a tty because detection - // does not work correctly, see https://github.com/composer/composer/issues/9690 - if (\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) { + ) { return true; } - // Modern cross-platform function, includes the fstat fallback so if it is present we trust it - if (\function_exists('stream_isatty')) { - return stream_isatty($this->stream); - } - - // Only trusting this if it is positive, otherwise prefer fstat fallback. - if (\function_exists('posix_isatty') && posix_isatty($this->stream)) { - return true; + if ('dumb' === $term = (string) getenv('TERM')) { + return false; } - $stat = @fstat($this->stream); - - // Check if formatted mode is S_IFCHR - return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157 + return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term); } } diff --git a/Tests/Input/InputOptionTest.php b/Tests/Input/InputOptionTest.php index e7a007a61..7e3fb16da 100644 --- a/Tests/Input/InputOptionTest.php +++ b/Tests/Input/InputOptionTest.php @@ -73,6 +73,8 @@ public function testShortcut() $this->assertEquals('0|z', $option->getShortcut(), '-0 is an acceptable shortcut value when embedded in an array'); $option = new InputOption('foo', '0|z'); $this->assertEquals('0|z', $option->getShortcut(), '-0 is an acceptable shortcut value when embedded in a string-list'); + $option = new InputOption('foo', false); + $this->assertNull($option->getShortcut(), '__construct() makes the shortcut null when given a false as value'); } public function testModes() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy