-/**
- * Exits with a message. In general, you should use drush_set_error() instead of
- * this function. That lets drush proceed with other tasks.
- * TODO: Exit with a correct status code.
- */
-function drush_die($msg = NULL, $status = NULL) {
- die($msg ? "drush: $msg\n" : '');
-}
-
-/**
- * Check to see if the provided line is a "#!/usr/bin/env drush"
- * "shebang" script line.
- */
-function _drush_is_drush_shebang_line($line) {
- return ((substr($line,0,2) == '#!') && (strstr($line, 'drush') !== FALSE));
-}
-
-/**
- * Check to see if the provided script file is a "#!/usr/bin/env drush"
- * "shebang" script line.
- */
-function _drush_is_drush_shebang_script($script_filename) {
- $result = FALSE;
-
- if (file_exists($script_filename)) {
- $fp = fopen($script_filename, "r");
- if ($fp !== FALSE) {
- $line = fgets($fp);
- $result = _drush_is_drush_shebang_line($line);
- fclose($fp);
- }
- }
-
- return $result;
-}
-
-/**
- * @defgroup userinput Get input from the user.
- * @{
- */
-
-/**
- * Asks the user a basic yes/no question.
- *
- * @param string $msg
- * The question to ask.
- * @param int $indent
- * The number of spaces to indent the message.
- *
- * @return bool
- * TRUE if the user enters "y" or FALSE if "n".
- */
-function drush_confirm($msg, $indent = 0) {
- drush_print_prompt((string)$msg . " (y/n): ", $indent);
-
- // Automatically accept confirmations if the --yes argument was supplied.
- if (drush_get_context('DRUSH_AFFIRMATIVE')) {
- drush_print("y");
- return TRUE;
- }
- // Automatically cancel confirmations if the --no argument was supplied.
- elseif (drush_get_context('DRUSH_NEGATIVE')) {
- drush_print("n");
- return FALSE;
- }
- // See http://drupal.org/node/499758 before changing this.
- $stdin = fopen("php://stdin","r");
-
- while ($line = fgets($stdin)) {
- $line = trim($line);
- if ($line == 'y') {
- return TRUE;
- }
- if ($line == 'n') {
- return FALSE;
- }
- drush_print_prompt((string)$msg . " (y/n): ", $indent);
- }
-}
-
-/**
- * Ask the user to select an item from a list.
- * From a provided associative array, drush_choice will
- * display all of the questions, numbered from 1 to N,
- * and return the item the user selected. "0" is always
- * cancel; entering a blank line is also interpreted
- * as cancelling.
- *
- * @param $options
- * A list of questions to display to the user. The
- * KEYS of the array are the result codes to return to the
- * caller; the VALUES are the messages to display on
- * each line. Special keys of the form '-- something --' can be
- * provided as separator between choices groups. Separator keys
- * don't alter the numbering.
- * @param $prompt
- * The message to display to the user prompting for input.
- * @param $label
- * Controls the display of each line. Defaults to
- * '!value', which displays the value of each item
- * in the $options array to the user. Use '!key' to
- * display the key instead. In some instances, it may
- * be useful to display both the key and the value; for
- * example, if the key is a user id and the value is the
- * user name, use '!value (uid=!key)'.
- */
-function drush_choice($options, $prompt = 'Enter a number.', $label = '!value', $widths = array()) {
- drush_print(dt($prompt));
-
- // Preflight so that all rows will be padded out to the same number of columns
- $array_pad = 0;
- foreach ($options as $key => $option) {
- if (is_array($option) && (count($option) > $array_pad)) {
- $array_pad = count($option);
- }
- }
-
- $rows[] = array_pad(array('[0]', ':', 'Cancel'), $array_pad + 2, '');
- $selection_number = 0;
- foreach ($options as $key => $option) {
- if ((substr($key, 0, 3) == '-- ') && (substr($key, -3) == ' --')) {
- $rows[] = array_pad(array('', '', $option), $array_pad + 2, '');
- }
- else {
- $selection_number++;
- $row = array("[$selection_number]", ':');
- if (is_array($option)) {
- $row = array_merge($row, $option);
- }
- else {
- $row[] = dt($label, array('!number' => $selection_number, '!key' => $key, '!value' => $option));
- }
- $rows[] = $row;
- $selection_list[$selection_number] = $key;
- }
- }
- drush_print_table($rows, FALSE, $widths);
- drush_print_pipe(array_keys($options));
-
- // If the user specified --choice, then make an
- // automatic selection. Cancel if the choice is
- // not an available option.
- if (($choice = drush_get_option('choice', FALSE)) !== FALSE) {
- // First check to see if $choice is one of the symbolic options
- if (array_key_exists($choice, $options)) {
- return $choice;
- }
- // Next handle numeric selections
- elseif (array_key_exists($choice, $selection_list)) {
- return $selection_list[$choice];
- }
- return FALSE;
- }
-
- // If the user specified --no, then cancel; also avoid
- // getting hung up waiting for user input in --pipe and
- // backend modes. If none of these apply, then wait,
- // for user input and return the selected result.
- if (!drush_get_context('DRUSH_NEGATIVE') && !drush_get_context('DRUSH_AFFIRMATIVE') && !drush_get_context('DRUSH_PIPE')) {
- while ($line = trim(fgets(STDIN))) {
- if (array_key_exists($line, $selection_list)) {
- return $selection_list[$line];
- }
- }
- }
- // We will allow --yes to confirm input if there is only
- // one choice; otherwise, --yes will cancel to avoid ambiguity
- if (drush_get_context('DRUSH_AFFIRMATIVE') && (count($options) == 1)) {
- return $selection_list[1];
- }
- return FALSE;
-}
-
-/**
- * Ask the user to select multiple items from a list.
- * This is a wrapper around drush_choice, that repeats the selection process,
- * allowing users to toggle a number of items in a list. The number of values
- * that can be constrained by both min and max: the user will only be allowed
- * finalize selection once the minimum number has been selected, and the oldest
- * selected value will "drop off" the list, if they exceed the maximum number.
- *
- * @param $options
- * Same as drush_choice() (see above).
- * @param $defaults
- * This can take 3 forms:
- * - FALSE: (Default) All options are unselected by default.
- * - TRUE: All options are selected by default.
- * - Array of $options keys to be selected by default.
- * @param $prompt
- * Same as drush_choice() (see above).
- * @param $label
- * Same as drush_choice() (see above).
- * @param $mark
- * Controls how selected values are marked. Defaults to '!value (selected)'.
- * @param $min
- * Constraint on minimum number of selections. Defaults to zero. When fewer
- * options than this are selected, no final options will be available.
- * @param $max
- * Constraint on minimum number of selections. Defaults to NULL (unlimited).
- * If the a new selection causes this value to be exceeded, the oldest
- * previously selected value is automatically unselected.
- * @param $final_options
- * An array of additional options in the same format as $options.
- * When the minimum number of selections is met, this array is merged into the
- * array of options. If the user selects one of these values and the
- * selection process will complete (the key for the final option is included
- * in the return value). If this is an empty array (default), then a built in
- * final option of "Done" will be added to the available options (in this case
- * no additional keys are added to the return value).
- */
-function drush_choice_multiple($options, $defaults = FALSE, $prompt = 'Select some numbers.', $label = '!value', $mark = '!value (selected)', $min = 0, $max = NULL, $final_options = array()) {
- $selections = array();
- // Load default selections.
- if (is_array($defaults)) {
- $selections = $defaults;
- }
- elseif ($defaults === TRUE) {
- $selections = array_keys($options);
- }
- $complete = FALSE;
- $final_builtin = array();
- if (empty($final_options)) {
- $final_builtin['done'] = dt('Done');
- }
- $final_options_keys = array_keys($final_options);
- while (TRUE) {
- $current_options = $options;
- // Mark selections.
- foreach ($selections as $selection) {
- $current_options[$selection] = dt($mark, array('!key' => $selection, '!value' => $options[$selection]));
- }
- // Add final options, if the minimum number of selections has been reached.
- if (count($selections) >= $min) {
- $current_options = array_merge($current_options, $final_options, $final_builtin);
- }
- $toggle = drush_choice($current_options, $prompt, $label);
- if ($toggle === FALSE) {
- return FALSE;
- }
- // Don't include the built in final option in the return value.
- if (count($selections) >= $min && empty($final_options) && $toggle == 'done') {
- return $selections;
- }
- // Toggle the selected value.
- $item = array_search($toggle, $selections);
- if ($item === FALSE) {
- array_unshift($selections, $toggle);
- }
- else {
- unset($selections[$item]);
- }
- // If the user selected one of the final options, return.
- if (count($selections) >= $min && in_array($toggle, $final_options_keys)) {
- return $selections;
- }
- // If the user selected too many options, drop the oldest selection.
- if (isset($max) && count($selections) > $max) {
- array_pop($selections);
- }
- }
-}
-
-/**
- * Prompt the user for input
- *
- * The input can be anything that fits on a single line (not only y/n),
- * so we can't use drush_confirm()
- *
- * @param $prompt
- * The text which is displayed to the user.
- * @param $default
- * The default value of the input.
- * @param $required
- * If TRUE, user may continue even when no value is in the input.
- * @param $password
- * If TRUE, surpress printing of the input.
- *
- * @see drush_confirm()
- */
-function drush_prompt($prompt, $default = NULL, $required = TRUE, $password = FALSE) {
- if (isset($default)) {
- $prompt .= " [" . $default . "]";
- }
- $prompt .= ": ";
-
- drush_print_prompt($prompt);
-
- if (drush_get_context('DRUSH_AFFIRMATIVE')) {
- return $default;
- }
-
- $stdin = fopen('php://stdin', 'r');
-
- if ($password) drush_shell_exec("stty -echo");
-
- stream_set_blocking($stdin, TRUE);
- while (($line = fgets($stdin)) !== FALSE) {
- $line = trim($line);
- if ($line === "") {
- $line = $default;
- }
- if ($line || !$required) {
- break;
- }
- drush_print_prompt($prompt);
- }
- fclose($stdin);
- if ($password) {
- drush_shell_exec("stty echo");
- print "\n";
- }
- return $line;
-}
-
-/**
- * @} End of "defgroup userinput".
- */
-