/** * Displays an array of strings as a menu where a user can enter a number to * choose an option. The array must be a single dimension with either strings * or objects with a `__toString()` method. * * @param array $items The list of items the user can choose from. * @param string $default The index of the default item. * @param string $title The message displayed to the user when prompted. * @return string The index of the chosen item. * @see cli\line() * @see cli\input() * @see cli\err() */ public static function menu($items, $default = false, $title = 'Choose an item') { $map = array_values($items); if ($default && strpos($title, '[') === false && isset($items[$default])) { $title .= ' [' . $items[$default] . ']'; } foreach ($map as $idx => $item) { \cli\Streams::line(' %d. %s', $idx + 1, (string) $item); } \cli\Streams::line(); while (true) { fwrite(static::$out, sprintf('%s: ', $title)); $line = \cli\Streams::input(); if (is_numeric($line)) { $line--; if (isset($map[$line])) { return array_search($map[$line], $items); } if ($line < 0 || $line >= count($map)) { \cli\Streams::err('Invalid menu selection: out of range'); } } else { if (isset($default)) { return $default; } } } }
/** * Shortcut for printing to `STDERR`. The message and parameters are passed * through `sprintf` before output. * * @param string $msg The message to output in `printf` format. With no string, * a newline is printed. * @param mixed ... Either scalar arguments or a single array argument. * @return void */ function err($msg = '') { // func_get_args is empty if no args are passed even with the default above. $args = func_get_args(); if ($args) { call_user_func_array(array('\\cli\\Streams', 'err'), $args); } else { \cli\Streams::err(); } }