/** * Format text for terminal output. This function behaves like `sprintf`, * except that all the normal conversions (like "%s") will be properly escaped, * and additional conversions are supported: * * %B (Block) * Escapes text, but preserves tabs and newlines. * * %R (Raw String) * Inserts raw, unescaped text. DANGEROUS! * * Particularly, this will escape terminal control characters. */ function tsprintf($pattern) { $args = func_get_args(); $args[0] = PhutilConsoleFormatter::interpretFormat($args[0]); $string = xsprintf('xsprintf_terminal', null, $args); return new PhutilTerminalString($string); }
public static function getDisableANSI() { if (self::$disableANSI === null) { if (phutil_is_windows()) { self::$disableANSI = true; } else { if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) { self::$disableANSI = true; } else { self::$disableANSI = false; } } } return self::$disableANSI; }
public static function getDisableANSI() { if (self::$disableANSI === null) { $term = phutil_utf8_strtolower(getenv("TERM")); if (phutil_is_windows() && $term !== "cygwin" && $term !== "ansi") { self::$disableANSI = true; } else { if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) { self::$disableANSI = true; } else { self::$disableANSI = false; } } } return self::$disableANSI; }
public static function getDisableANSI() { if (self::$disableANSI === null) { $term = phutil_utf8_strtolower(getenv('TERM')); // ansicon enables ANSI support on Windows if (!$term && getenv('ANSICON')) { $term = 'ansi'; } if (phutil_is_windows() && $term !== 'cygwin' && $term !== 'ansi') { self::$disableANSI = true; } else { if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) { self::$disableANSI = true; } else { self::$disableANSI = false; } } } return self::$disableANSI; }
private function getHeader() { $output = ''; if ($this->borders) { $output .= $this->formatSeparator('='); } if (!$this->showHeader) { return $output; } $columns = array(); foreach ($this->columns as $key => $column) { $columns[] = PhutilConsoleFormatter::formatString('**%s**', $this->alignString($column['title'], $this->getWidth($key), idx($column, 'align', self::ALIGN_LEFT))); } $output .= $this->formatRow($columns); if ($this->borders) { $output .= $this->formatSeparator('='); } return $output; }
public function run() { $this->console = PhutilConsole::getConsole(); $this->runRepositoryAPISetup(); if ($this->getArgument('no-diff')) { $this->removeScratchFile('diff-result.json'); $data = $this->runLintUnit(); $this->writeScratchJSONFile('diff-result.json', $data); return 0; } $this->runDiffSetupBasics(); $background = $this->getArgument('background', true); if ($this->isRawDiffSource() || phutil_is_windows()) { $background = false; } if ($background) { $argv = $this->getPassedArguments(); if (!PhutilConsoleFormatter::getDisableANSI()) { array_unshift($argv, '--ansi'); } $script = phutil_get_library_root('arcanist') . '/../scripts/arcanist.php'; if ($argv) { $lint_unit = new ExecFuture('php %s --recon diff --no-diff %Ls', $script, $argv); } else { $lint_unit = new ExecFuture('php %s --recon diff --no-diff', $script); } $lint_unit->write('', true); $lint_unit->start(); } $commit_message = $this->buildCommitMessage(); $this->dispatchEvent(ArcanistEventType::TYPE_DIFF_DIDBUILDMESSAGE, array('message' => $commit_message)); if (!$this->shouldOnlyCreateDiff()) { $revision = $this->buildRevisionFromCommitMessage($commit_message); } if ($background) { $server = new PhutilConsoleServer(); $server->addExecFutureClient($lint_unit); $server->setHandler(array($this, 'handleServerMessage')); $server->run(); list($err) = $lint_unit->resolve(); $data = $this->readScratchJSONFile('diff-result.json'); if ($err || !$data) { throw new Exception('Unable to read results from background linting and unit testing. ' . 'You can try running arc diff again with --background 0'); } } else { $server = $this->console->getServer(); $server->setHandler(array($this, 'handleServerMessage')); $data = $this->runLintUnit(); } $lint_result = $data['lintResult']; $this->unresolvedLint = $data['unresolvedLint']; $this->postponedLinters = $data['postponedLinters']; $unit_result = $data['unitResult']; $this->testResults = $data['testResults']; if ($this->getArgument('nolint')) { $this->excuses['lint'] = $this->getSkipExcuse('Provide explanation for skipping lint or press Enter to abort:', 'lint-excuses'); } if ($this->getArgument('nounit')) { $this->excuses['unit'] = $this->getSkipExcuse('Provide explanation for skipping unit tests or press Enter to abort:', 'unit-excuses'); } $changes = $this->generateChanges(); if (!$changes) { throw new ArcanistUsageException("There are no changes to generate a diff from!"); } $diff_spec = array('changes' => mpull($changes, 'toDictionary'), 'lintStatus' => $this->getLintStatus($lint_result), 'unitStatus' => $this->getUnitStatus($unit_result)) + $this->buildDiffSpecification(); $conduit = $this->getConduit(); $diff_info = $conduit->callMethodSynchronous('differential.creatediff', $diff_spec); $this->diffID = $diff_info['diffid']; $event = $this->dispatchEvent(ArcanistEventType::TYPE_DIFF_WASCREATED, array('diffID' => $diff_info['diffid'], 'lintResult' => $lint_result, 'unitResult' => $unit_result)); $this->updateLintDiffProperty(); $this->updateUnitDiffProperty(); $this->updateLocalDiffProperty(); $this->resolveDiffPropertyUpdates(); $output_json = $this->getArgument('json'); if ($this->shouldOnlyCreateDiff()) { if (!$output_json) { echo phutil_console_format("Created a new Differential diff:\n" . " **Diff URI:** __%s__\n\n", $diff_info['uri']); } else { $human = ob_get_clean(); echo json_encode(array('diffURI' => $diff_info['uri'], 'diffID' => $this->getDiffID(), 'human' => $human)) . "\n"; ob_start(); } } else { $revision['diffid'] = $this->getDiffID(); if ($commit_message->getRevisionID()) { $result = $conduit->callMethodSynchronous('differential.updaterevision', $revision); foreach (array('edit-messages.json', 'update-messages.json') as $file) { $messages = $this->readScratchJSONFile($file); unset($messages[$revision['id']]); $this->writeScratchJSONFile($file, $messages); } echo "Updated an existing Differential revision:\n"; } else { $revision = $this->dispatchWillCreateRevisionEvent($revision); $result = $conduit->callMethodSynchronous('differential.createrevision', $revision); $revised_message = $conduit->callMethodSynchronous('differential.getcommitmessage', array('revision_id' => $result['revisionid'])); if ($this->shouldAmend()) { $repository_api = $this->getRepositoryAPI(); if ($repository_api->supportsAmend()) { echo "Updating commit message...\n"; $repository_api->amendCommit($revised_message); } else { echo "Commit message was not amended. Amending commit message is " . "only supported in git and hg (version 2.2 or newer)"; } } echo "Created a new Differential revision:\n"; } $uri = $result['uri']; echo phutil_console_format(" **Revision URI:** __%s__\n\n", $uri); if ($this->getArgument('plan-changes')) { $conduit->callMethodSynchronous('differential.createcomment', array('revision_id' => $result['revisionid'], 'action' => 'rethink')); echo "Planned changes to the revision.\n"; } } echo "Included changes:\n"; foreach ($changes as $change) { echo ' ' . $change->renderTextSummary() . "\n"; } if ($output_json) { ob_get_clean(); } $this->removeScratchFile('create-message'); return 0; }
/** * Parse "standard" arguments and apply their effects: * * --trace Enable service call tracing. * --no-ansi Disable ANSI color/style sequences. * --xprofile <file> Write out an XHProf profile. * --help Show help. * * @return this * * @phutil-external-symbol function xhprof_enable */ public function parseStandardArguments() { try { $this->parsePartial(array(array('name' => 'trace', 'help' => pht('Trace command execution and show service calls.'), 'standard' => true), array('name' => 'no-ansi', 'help' => pht('Disable ANSI terminal codes, printing plain text with ' . 'no color or style.'), 'conflicts' => array('ansi' => null), 'standard' => true), array('name' => 'ansi', 'help' => pht("Use formatting even in environments which probably " . "don't support it."), 'standard' => true), array('name' => 'xprofile', 'param' => 'profile', 'help' => pht('Profile script execution and write results to a file.'), 'standard' => true), array('name' => 'help', 'short' => 'h', 'help' => pht('Show this help.'), 'standard' => true), array('name' => 'show-standard-options', 'help' => pht('Show every option, including standard options like this one.'), 'standard' => true), array('name' => 'recon', 'help' => pht('Start in remote console mode.'), 'standard' => true))); } catch (PhutilArgumentUsageException $ex) { $this->printUsageException($ex); exit(self::PARSE_ERROR_CODE); } if ($this->getArg('trace')) { PhutilServiceProfiler::installEchoListener(); } if ($this->getArg('no-ansi')) { PhutilConsoleFormatter::disableANSI(true); } if ($this->getArg('ansi')) { PhutilConsoleFormatter::disableANSI(false); } if ($this->getArg('help')) { $this->showHelp = true; } $xprofile = $this->getArg('xprofile'); if ($xprofile) { if (!function_exists('xhprof_enable')) { throw new Exception(pht("To use '%s', you must install XHProf.", '--xprofile')); } xhprof_enable(0); register_shutdown_function(array($this, 'shutdownProfiler')); } $recon = $this->getArg('recon'); if ($recon) { $remote_console = PhutilConsole::newRemoteConsole(); $remote_console->beginRedirectOut(); PhutilConsole::setConsole($remote_console); } else { if ($this->getArg('trace')) { $server = new PhutilConsoleServer(); $server->setEnableLog(true); $console = PhutilConsole::newConsoleForServer($server); PhutilConsole::setConsole($console); } } return $this; }
public static function disableANSI($disable) { self::$disableANSI = $disable; }