function drush_complete_match_file

8.0.x complete.inc drush_complete_match_file($last_word, $files)
6.x complete.inc drush_complete_match_file($last_word, $files)
7.x complete.inc drush_complete_match_file($last_word, $files)
5.x complete.inc drush_complete_match_file($last_word, $files)
master complete.inc drush_complete_match_file($last_word, $files)

Retrieves the appropriate list of candidate file/directory completions, filtered by the last word that we are trying to complete.

Parameters

string $last_word: The last word in the argument list (i.e. the subject of completion).

array $files: Array of file specs, each with a pattern and flags subarray.

Return value

array Array of candidate file/directory completions that start with the same characters as the last word. If the last word is empty, return all candidates.

1 call to drush_complete_match_file()
drush_early_complete in includes/complete.inc
Produce autocomplete output.

File

includes/complete.inc, line 296
Provide completion output for shells.

Code

function drush_complete_match_file($last_word, $files) {
  $return = array();
  if ($last_word[0] == '~') {
    // Complete does not do tilde expansion, so we do it here.
    // We shell out (unquoted) to expand the tilde.
    drush_shell_exec('echo ' . $last_word);
    return drush_shell_exec_output();
  }

  $dir = '';
  if (substr($last_word, -1) == '/' && is_dir($last_word)) {
    // If we exactly match a trailing directory, then we use that as the base
    // for the listing. We only do this if a trailing slash is present, since at
    // this stage it is still possible there are other directories that start
    // with this string.
    $dir = $last_word;
  }
  else {
    // Otherwise we discard the last part of the path (this is matched against
    // the list later), and use that as our base.
    $dir = dirname($last_word);
    if (empty($dir) || $dir == '.' && $last_word != '.' && substr($last_word, 0, 2) != './') {
      // We are looking at the current working directory, so unless the user is
      // actually specifying a leading dot we leave the path empty.
      $dir = '';
    }
    else {
      // In all other cases we need to add a trailing slash.
      $dir .= '/';
    }
  }

  foreach ($files as $spec) {
    // We always include GLOB_MARK, as an easy way to detect directories.
    $flags = GLOB_MARK;
    if (isset($spec['flags'])) {
      $flags = $spec['flags'] | GLOB_MARK;
    }
    $listing = glob($dir . $spec['pattern'], $flags);
    $return = array_merge($return, drush_complete_match($last_word, $listing));
  }
  // If we are returning a single item (which will become part of the final
  // command), we need to use the full path, and we need to escape it
  // appropriately.
  if (count($return) == 1) {
    // Escape common shell metacharacters (we don't use escapeshellarg as it
    // single quotes everything, even when unnecessary).
    $item = array_pop($return);
    $item = preg_replace('/[ |&;()<>]/', "\\\\$0", $item);
    if (substr($item, -1) !== '/') {
      // Insert a space after files, since the argument is complete.
      $item = $item . ' ';
    }
    $return = array($item);
  }
  else {
    $firstchar = TRUE;
    if ($last_word[0] == '/') {
      // If we are working with absolute paths, we need to check if the first
      // character of all the completions matches. If it does, then we pass a
      // full path for each match, so the shell completes as far as it can,
      // matching the behaviour with relative paths.
      $pos = strlen($last_word);
      foreach ($return as $id => $item) {
        if ($item[$pos] !== $return[0][$pos]) {
          $firstchar = FALSE;
          continue;
        }
      }
    }
    foreach ($return as $id => $item) {
      // For directories we leave the path alone.
      $slash_pos = strpos($last_word, '/');
      if ($slash_pos === 0 && $firstchar) {
        // With absolute paths where completions share initial characters, we
        // pass in a resolved path.
        $return[$id] = realpath($item);
      }
      else if ($slash_pos !== FALSE && $dir != './') {
        // For files, we pass only the file name, ignoring the false match when
        // the user is using a single dot relative path.
        $return[$id] = basename($item);
      }
    }
  }
  return $return;
}