3 // This file is part of Moodle - http://moodle.org/
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * Command line utility functions and classes
23 * @copyright 2009 Petr Skoda (http://skodak.org)
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 // NOTE: no MOODLE_INTERNAL test here, sometimes we use this before requiring Moodle libs!
30 * Write a text to the given stream
32 * @param string $text text to be written
33 * @param resource $stream output stream to be written to, defaults to STDOUT
35 function cli_write($text, $stream=STDOUT
) {
36 fwrite($stream, $text);
40 * Write a text followed by an end of line symbol to the given stream
42 * @param string $text text to be written
43 * @param resource $stream output stream to be written to, defaults to STDOUT
45 function cli_writeln($text, $stream=STDOUT
) {
46 cli_write($text.PHP_EOL
, $stream);
51 * @param string $prompt text prompt, should include possible options
52 * @param string $default default value when enter pressed
53 * @param array $options list of allowed options, empty means any text
54 * @param bool $casesensitive true if options are case sensitive
55 * @return string entered text
57 function cli_input($prompt, $default='', array $options=null, $casesensitiveoptions=false) {
60 $input = fread(STDIN
, 2048);
61 $input = trim($input);
66 if (!$casesensitiveoptions) {
67 $input = strtolower($input);
69 if (!in_array($input, $options)) {
70 cli_writeln(get_string('cliincorrectvalueretry', 'admin'));
71 return cli_input($prompt, $default, $options, $casesensitiveoptions);
78 * Returns cli script parameters.
79 * @param array $longoptions array of --style options ex:('verbose'=>false)
80 * @param array $shortmapping array describing mapping of short to long style options ex:('h'=>'help', 'v'=>'verbose')
81 * @return array array of arrays, options, unrecognised as optionlongname=>value
83 function cli_get_params(array $longoptions, array $shortmapping=null) {
84 $shortmapping = (array)$shortmapping;
86 $unrecognized = array();
88 if (empty($_SERVER['argv'])) {
89 // bad luck, we can continue in interactive mode ;-)
90 return array($options, $unrecognized);
92 $rawoptions = $_SERVER['argv'];
94 //remove anything after '--', options can not be there
95 if (($key = array_search('--', $rawoptions)) !== false) {
96 $rawoptions = array_slice($rawoptions, 0, $key);
100 unset($rawoptions[0]);
101 foreach ($rawoptions as $raw) {
102 if (substr($raw, 0, 2) === '--') {
103 $value = substr($raw, 2);
104 $parts = explode('=', $value);
105 if (count($parts) == 1) {
106 $key = reset($parts);
109 $key = array_shift($parts);
110 $value = implode('=', $parts);
112 if (array_key_exists($key, $longoptions)) {
113 $options[$key] = $value;
115 $unrecognized[] = $raw;
118 } else if (substr($raw, 0, 1) === '-') {
119 $value = substr($raw, 1);
120 $parts = explode('=', $value);
121 if (count($parts) == 1) {
122 $key = reset($parts);
125 $key = array_shift($parts);
126 $value = implode('=', $parts);
128 if (array_key_exists($key, $shortmapping)) {
129 $options[$shortmapping[$key]] = $value;
131 $unrecognized[] = $raw;
134 $unrecognized[] = $raw;
139 foreach ($longoptions as $key=>$default) {
140 if (!array_key_exists($key, $options)) {
141 $options[$key] = $default;
145 return array($options, $unrecognized);
149 * Print or return section separator string
150 * @param bool $return false means print, true return as string
151 * @return mixed void or string
153 function cli_separator($return=false) {
154 $separator = str_repeat('-', 79).PHP_EOL
;
158 cli_write($separator);
163 * Print or return section heading string
164 * @param string $string text
165 * @param bool $return false means print, true return as string
166 * @return mixed void or string
168 function cli_heading($string, $return=false) {
169 $string = "== $string ==".PHP_EOL
;
178 * Write error notification
182 function cli_problem($text) {
183 cli_writeln($text, STDERR
);
187 * Write to standard error output and exit with the given code
189 * @param string $text
190 * @param int $errorcode
191 * @return void (does not return)
193 function cli_error($text, $errorcode=1) {
194 cli_writeln($text.PHP_EOL
, STDERR
);
199 * Print an ASCII version of the Moodle logo.
201 * @param int $padding left padding of the logo
202 * @param bool $return should we print directly (false) or return the string (true)
203 * @return mixed void or string
205 function cli_logo($padding=2, $return=false) {
210 '/____/-.---_ .---. .---. .-.| || | .---. ',
211 '| | _ _ |/ _ \\/ _ \\/ _ || |/ __ \\',
212 '* | | | | | || |_| || |_| || |_| || || |___/',
213 ' |_| |_| |_|\\_____/\\_____/\\_____||_|\\_____)',
218 foreach ($lines as $line) {
219 $logo .= str_repeat(' ', $padding);
232 * Substitute cursor, colour, and bell placeholders in a CLI output to ANSI escape characters when ANSI is available.
234 * @param string $message
237 function cli_ansi_format(string $message): string {
244 // Cursor movement: https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html.
245 "<cursor:save>" => "\033[s",
246 "<cursor:restore>" => "\033[u",
247 "<cursor:up>" => "\033[1A",
248 "<cursor:down>" => "\033[1B",
249 "<cursor:forward>" => "\033[1C",
250 "<cursor:back>" => "\033[1D",
256 'darkGray' => '1;30',
258 'lightRed' => '1;31',
260 'lightGreen' => '1;32',
263 'lightYellow' => '0;93',
265 'lightBlue' => '1;34',
267 'lightPurple' => '1;35',
269 'lightCyan' => '1;36',
270 'lightGray' => '0;37',
284 foreach ($colours as $colour => $code) {
285 $replacements["<colour:{$colour}>"] = "\033[{$code}m";
287 foreach ($bgcolours as $colour => $code) {
288 $replacements["<bgcolour:{$colour}>"] = "\033[{$code}m";
291 // Windows don't support ANSI code by default, but does if ANSICON is available.
292 $isansicon = getenv('ANSICON');
293 if (($CFG->ostype
=== 'WINDOWS') && empty($isansicon)) {
294 return str_replace(array_keys($replacements), '', $message);
297 return str_replace(array_keys($replacements), array_values($replacements), $message);