Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions WebFiori/Cli/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@

if ($argsCount != 0 && gettype($_[$argsCount - 1]) == 'array') {
//Last index contains formatting options.
$_[$argsCount - 1]['ansi'] = $this->isArgProvided('--ansi');
$_[$argsCount - 1]['ansi'] = $this->isAnsiEnabled();
$str = Formatter::format($str, $_[$argsCount - 1]);
}
call_user_func_array([$this->getOutputStream(), 'println'], $this->_createPassArray($str, $_));
Expand Down Expand Up @@ -906,7 +906,7 @@
$formattingOptions = $_[$argCount - 1];
}

$formattingOptions['ansi'] = $this->isArgProvided('--ansi');
$formattingOptions['ansi'] = $this->isAnsiEnabled();

$formattedStr = Formatter::format($str, $formattingOptions);

Expand Down Expand Up @@ -1602,6 +1602,24 @@
// Default fallback
return 80;
}

/**
* Checks if ANSI output is enabled for this command.
*
* Uses the Runner's resolved ANSI value if available, falls back to
* checking if --ansi argument is provided.
*
* @return bool True if ANSI output should be used.
*/
private function isAnsiEnabled(): bool {
$owner = $this->getOwner();

Check warning on line 1615 in WebFiori/Cli/Command.php

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename "$owner" which has the same name as the field declared at line 60.

See more on https://sonarcloud.io/project/issues?id=WebFiori_cli&issues=AZ6-g45FSbdpGM9Kjple&open=AZ6-g45FSbdpGM9Kjple&pullRequest=53

if ($owner !== null) {
return $owner->isAnsi();
}

return $this->isArgProvided('--ansi');
}
private function parseArgsHelper() : bool {
$options = $this->getArgs();
$invalidArgsVals = [];
Expand Down
113 changes: 94 additions & 19 deletions WebFiori/Cli/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,16 @@ public function __construct() {
ArgumentOption::OPTIONAL => true,
ArgumentOption::DESCRIPTION => 'Force the use of ANSI output.'
]);
$this->addArg('--no-color', [
ArgumentOption::OPTIONAL => true,
ArgumentOption::DESCRIPTION => 'Disable ANSI colored output.'
]);
$this->setBeforeStart(function (Runner $r) {
if (count($r->getArgsVector()) == 0) {
$r->setArgsVector($_SERVER['argv']);
}
$r->checkIsInteractive();
$r->resolveAnsi();
});
$this->register(new HelpCommand(), ['-h']);
$this->setDefaultCommand('help');
Expand Down Expand Up @@ -610,6 +615,18 @@ public function hasArg(string $name): bool {
return false;
}

/**
* Returns whether ANSI output is currently enabled.
*
* If not explicitly forced via --ansi or --no-color, this checks whether
* the output stream is a real terminal (StdOut) and applies TTY detection.
*
* @return bool True if ANSI output is enabled, false otherwise.
*/
public function isAnsi(): bool {
return $this->isAnsi;
}

/**
* Check if auto-discovery is enabled.
*
Expand Down Expand Up @@ -796,8 +813,12 @@ public function runCommand(?Command $c = null, array $args = [], bool $ansi = fa
}
}

if ($ansi) {
$args[] = '--ansi';
if ($ansi || in_array('--ansi', $args)) {
$this->isAnsi = true;
}

if (in_array('--no-color', $args)) {
$this->isAnsi = false;
}
$this->setArgV($args);
$this->setActiveCommand($c);
Expand Down Expand Up @@ -1074,6 +1095,35 @@ public function setSignalHandler(int $signal, callable $handler): Runner {
return $this;
}

/**
* Determines if ANSI output should be used based on environment detection.
*
* Resolution precedence:
* 1. NO_COLOR env variable → false
* 2. posix_isatty(STDOUT) on Unix → true if TTY
* 3. Windows terminal env checks (ANSICON, ConEmuANSI, TERM)
* 4. Default → false
*
* @return bool True if ANSI should be enabled by default.
*/
public static function shouldUseAnsi(): bool {
if (getenv('NO_COLOR') !== false || isset($_SERVER['NO_COLOR'])) {
return false;
}

if (function_exists('posix_isatty')) {
return defined('STDOUT') ? posix_isatty(STDOUT) : false;
}

if (DIRECTORY_SEPARATOR === '\\') {
return getenv('ANSICON') !== false
|| getenv('ConEmuANSI') === 'ON'
|| getenv('TERM') === 'xterm';
}

return false;
}

/**
* Start command line process.
*
Expand All @@ -1087,7 +1137,11 @@ public function start(): int {
}

if ($this->isInteractive()) {
$this->isAnsi = in_array('--ansi', $this->getArgsVector());
if (in_array('--no-color', $this->getArgsVector())) {
$this->isAnsi = false;
} elseif (in_array('--ansi', $this->getArgsVector())) {
$this->isAnsi = true;
}
$this->printMsg('Running in interactive mode.', '>>', 'blue');
$this->printMsg("Type command name or 'exit' to close.", ">>", 'blue');
$this->printMsg('', '>>', 'blue');
Expand Down Expand Up @@ -1126,6 +1180,7 @@ private function invokeAfterExc(): void {
call_user_func_array($funcArr['func'], array_merge([$this], $funcArr['params']));
}
}

/**
* Preprocesses arguments to handle help patterns like 'command help' or 'command -h'.
*
Expand Down Expand Up @@ -1173,9 +1228,7 @@ private function readInteractive(): array {

$argsArr = strlen($input) != 0 ? explode(' ', $input) : [];

if (in_array('--ansi', $argsArr)) {
$argsArr = array_diff($argsArr, ['--ansi']);
}
$argsArr = $this->removeAnsiArgs($argsArr);

// Preprocess help patterns
$argsArr = $this->preprocessHelpPattern($argsArr);
Expand Down Expand Up @@ -1227,6 +1280,30 @@ private function registerCommandSignalHandlers(Command $c): void {
}
}
}
/**
* Removes --ansi and --no-color flags from an arguments array.
*
* @param array $argsArr The arguments array.
*
* @return array The filtered arguments array.
*/
private function removeAnsiArgs(array $argsArr): array {
$tempArgs = [];

foreach ($argsArr as $argName => $val) {
if (gettype($argName) == 'integer') {
if ($val != '--ansi' && $val != '--no-color') {
$tempArgs[] = $val;
}
} else {
if ($argName != '--ansi' && $argName != '--no-color') {
$tempArgs[$argName] = $val;
}
}
}

return $tempArgs;
}

private function removeCommandSignalHandlers(Command $c): void {
if ($this->signalHandler !== null) {
Expand All @@ -1237,6 +1314,12 @@ private function removeCommandSignalHandlers(Command $c): void {
}
}

private function resolveAnsi(): void {
if ($this->outputStream instanceof StdOut) {
$this->isAnsi = self::shouldUseAnsi();
}
}

/**
* Run the command line as single run.
*
Expand All @@ -1245,22 +1328,14 @@ private function removeCommandSignalHandlers(Command $c): void {
private function run(): int {
$argsArr = array_slice($this->getArgsVector(), 1);

if (in_array('--ansi', $argsArr)) {
if (in_array('--no-color', $argsArr)) {
$this->isAnsi = false;
} elseif (in_array('--ansi', $argsArr)) {
$this->isAnsi = true;
$tempArgs = [];

foreach ($argsArr as $argName => $val) {
if (gettype($argName) == 'integer') {
if ($val != '--ansi') {
$tempArgs[] = $val;
}
} else {
$tempArgs[$argName] = $val;
}
}
$argsArr = $tempArgs;
}

$argsArr = $this->removeAnsiArgs($argsArr);

// Preprocess help patterns for non-interactive mode
$argsArr = $this->preprocessHelpPattern($argsArr);

Expand Down
46 changes: 23 additions & 23 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"include-v-in-tag":true,
"tag-separator": "-",
"changelog-path": "CHANGELOG.md",
"changelog-sections": [
{ "type": "feat", "section": "Features" },
{ "type": "feature", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "perf", "section": "Performance Improvements" },
{ "type": "revert", "section": "Reverts" },
{ "type": "docs", "section": "Documentation" },
{ "type": "style", "section": "Styles" },
{ "type": "chore", "section": "Miscellaneous Chores" },
{ "type": "refactor", "section": "Code Refactoring" },
{ "type": "test", "section": "Testing" },
{ "type": "build", "section": "Build System" },
{ "type": "ci", "section": "Continuous Integration" },
{ "type": "ui", "section": "User Interface" },
{ "type": "database", "section": "Database Changes" },
{ "type": "email", "section": "Email Notifications Changes" }
]
}
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"include-v-in-tag": true,
"tag-separator": "-",
"changelog-path": "CHANGELOG.md",
"changelog-sections": [
{ "type": "feat", "section": "Features", "hidden": false },
{ "type": "feature", "section": "Features", "hidden": false },
{ "type": "fix", "section": "Bug Fixes", "hidden": false },
{ "type": "perf", "section": "Performance Improvements", "hidden": false },
{ "type": "revert", "section": "Reverts", "hidden": false },
{ "type": "docs", "section": "Documentation", "hidden": false },
{ "type": "style", "section": "Styles", "hidden": false },
{ "type": "chore", "section": "Miscellaneous Chores", "hidden": false },
{ "type": "refactor", "section": "Code Refactoring", "hidden": false },
{ "type": "test", "section": "Testing", "hidden": false },
{ "type": "build", "section": "Build System", "hidden": false },
{ "type": "ci", "section": "Continuous Integration", "hidden": false },
{ "type": "ui", "section": "User Interface", "hidden": false },
{ "type": "database", "section": "Database Changes", "hidden": false },
{ "type": "email", "section": "Email Notifications Changes", "hidden": false }
]
}
Loading
Loading