Skip to content

Commit

Permalink
Factorise completion + complete all installed packages
Browse files Browse the repository at this point in the history
  • Loading branch information
GromNaN committed Dec 1, 2021
1 parent b93530d commit 825c21f
Show file tree
Hide file tree
Showing 18 changed files with 191 additions and 57 deletions.
13 changes: 13 additions & 0 deletions src/Composer/Command/ArchiveCommand.php
Expand Up @@ -26,6 +26,8 @@
use Composer\Util\Filesystem;
use Composer\Util\Loop;
use Composer\Util\ProcessExecutor;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand All @@ -38,6 +40,17 @@
*/
class ArchiveCommand extends BaseCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($this->completeAvailablePackage($input, $suggestions)) {
return;
}

if ($input->mustSuggestOptionValuesFor('format')) {
$suggestions->suggestValues(array('tar', 'zip'));
}
}

/**
* @return void
*/
Expand Down
86 changes: 86 additions & 0 deletions src/Composer/Command/BaseCommand.php
Expand Up @@ -18,10 +18,19 @@
use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Plugin\PreCommandRunEvent;
use Composer\Package\Version\VersionParser;
use Composer\Plugin\PluginEvents;
use Composer\Repository\CompositeRepository;
use Composer\Repository\InstalledRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\RootPackageRepository;
use Composer\Util\Platform;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -218,6 +227,83 @@ protected function getPreferredInstallOptions(Config $config, InputInterface $in
return array($preferSource, $preferDist);
}

/**
* @return bool
*/
protected function completePreferInstall(CompletionInput $input, CompletionSuggestions $suggestions)
{
if ($input->mustSuggestOptionValuesFor('prefer-install')) {
$suggestions->suggestValues(array('dist', 'source', 'auto'));

return true;
}

return false;
}

/**
* @return bool
*/
protected function completeInstalledPackage(CompletionInput $input, CompletionSuggestions $suggestions, $withPlatform = false)
{
if (!$input->mustSuggestArgumentValuesFor('packages') &&
!$input->mustSuggestArgumentValuesFor('package') &&
!$input->mustSuggestOptionValuesFor('ignore')
) {
return false;
}

$composer = $this->getComposer();
$installedRepos = array(
new RootPackageRepository(clone $composer->getPackage()),
);

$locker = $composer->getLocker();
if ($locker->isLocked()) {
if ($withPlatform) {
$installedRepos[] = new PlatformRepository(array(), $locker->getPlatformOverrides());
}
$installedRepos[] = $locker->getLockedRepository(true);
} else {
if ($withPlatform) {
$installedRepos[] = new PlatformRepository(array(), $composer->getConfig()->get('platform') ?: array());
}
$installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
}

$installedRepo = new InstalledRepository($installedRepos);
$suggestions->suggestValues(array_map(function (PackageInterface $package) {
return $package->getName();
}, $installedRepo->getPackages()));

return true;
}

/**
* @return bool
*/
protected function completeAvailablePackage(CompletionInput $input, CompletionSuggestions $suggestions)
{
if (!$input->mustSuggestArgumentValuesFor('packages') &&
!$input->mustSuggestArgumentValuesFor('package') &&
!$input->mustSuggestOptionValuesFor('require') &&
!$input->mustSuggestOptionValuesFor('require-dev')
) {
return false;
}

$composer = $this->getComposer();
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());

$packages = $repos->search('^'.$input->getCompletionValue(), RepositoryInterface::SEARCH_NAME);

foreach (array_slice($packages, 0, 150) as $package) {
$suggestions->suggestValue($package['name']);
}

return true;
}

/**
* @param array<string, string> $requirements
*
Expand Down
7 changes: 7 additions & 0 deletions src/Composer/Command/CreateProjectCommand.php
Expand Up @@ -32,6 +32,8 @@
use Composer\Repository\RepositorySet;
use Composer\Script\ScriptEvents;
use Composer\Util\Silencer;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand All @@ -54,6 +56,11 @@
*/
class CreateProjectCommand extends BaseCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->completeAvailablePackage($input, $suggestions) || $this->completePreferInstall($input, $suggestions);
}

/**
* @var SuggestedPackagesReporter
*/
Expand Down
5 changes: 1 addition & 4 deletions src/Composer/Command/DependsCommand.php
Expand Up @@ -26,10 +26,7 @@ class DependsCommand extends BaseDependencyCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestArgumentValuesFor(self::ARGUMENT_PACKAGE)) {
$rootPackage = $this->getComposer(true, $input->getOption('no-plugins'))->getPackage();
$suggestions->suggestValues(array_merge(array_keys($rootPackage->getRequires()), array_keys($rootPackage->getDevRequires())));
}
$this->completeInstalledPackage($input, $suggestions);
}

/**
Expand Down
19 changes: 11 additions & 8 deletions src/Composer/Command/ExecCommand.php
Expand Up @@ -27,7 +27,7 @@ class ExecCommand extends BaseCommand
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestArgumentValuesFor('binary')) {
$suggestions->suggestValues($this->getBinaries());
$suggestions->suggestValues($this->getBinaries(false));
}
}

Expand Down Expand Up @@ -65,7 +65,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
{
$composer = $this->getComposer();
if ($input->getOption('list') || !$input->getArgument('binary')) {
$bins = $this->getBinaries();
$bins = $this->getBinaries(true);
if (!$bins) {
$binDir = $composer->getConfig()->get('bin-dir');

Expand Down Expand Up @@ -109,27 +109,30 @@ protected function execute(InputInterface $input, OutputInterface $output)
}

/**
* @param bool $forDisplay
* @return string[]
*/
private function getBinaries()
private function getBinaries($forDisplay)
{
$composer = $this->getComposer();
$binDir = $composer->getConfig()->get('bin-dir');
$bins = glob($binDir . '/*');
$bins = array_merge($bins, array_map(function ($e) {
return "$e (local)";
}, $composer->getPackage()->getBinaries()));
$localBins = $composer->getPackage()->getBinaries();
if ($forDisplay) {
$localBins = array_map(function ($e) {
return "$e (local)";
}, $localBins);
}

$binaries = array();
foreach ($bins as $bin) {
foreach (array_merge($bins, $localBins) as $bin) {
// skip .bat copies
if (isset($previousBin) && $bin === $previousBin.'.bat') {
continue;
}

$previousBin = $bin;
$binaries[] = basename($bin);

}

return $binaries;
Expand Down
21 changes: 21 additions & 0 deletions src/Composer/Command/GlobalCommand.php
Expand Up @@ -15,6 +15,9 @@
use Composer\Factory;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\StringInput;
Expand All @@ -25,6 +28,24 @@
*/
class GlobalCommand extends BaseCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$application = $this->getApplication();
if ($input->mustSuggestArgumentValuesFor('command-name')) {
$suggestions->suggestValues(array_filter(array_map(function (Command $command) {
return $command->isHidden() ? null : $command->getName();
}, $application->all())));

return;
}

// @todo delegation is tricky
if ($application->has($command = $input->getArgument('command'))) {
$input = CompletionInput::fromString(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', rtrim($input->__toString(), '|'), 1), 3);
$this->getApplication()->get($command)->complete($input, $suggestions);
}
}

/**
* @return void
*/
Expand Down
7 changes: 7 additions & 0 deletions src/Composer/Command/HomeCommand.php
Expand Up @@ -18,6 +18,8 @@
use Composer\Repository\RepositoryFactory;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -28,6 +30,11 @@
*/
class HomeCommand extends BaseCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->completeInstalledPackage($input, $suggestions);
}

/**
* @inheritDoc
*
Expand Down
7 changes: 7 additions & 0 deletions src/Composer/Command/InitCommand.php
Expand Up @@ -31,6 +31,8 @@
use Composer\Util\ProcessExecutor;
use Composer\Semver\Constraint\Constraint;
use Composer\Util\Silencer;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand All @@ -54,6 +56,11 @@ class InitCommand extends BaseCommand
/** @var RepositorySet[] */
private $repositorySets;

public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->completeAvailablePackage($input, $suggestions);
}

/**
* @inheritDoc
*
Expand Down
12 changes: 5 additions & 7 deletions src/Composer/Command/InstallCommand.php
Expand Up @@ -32,6 +32,11 @@
*/
class InstallCommand extends BaseCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->completePreferInstall($input, $suggestions);
}

/**
* @return void
*/
Expand Down Expand Up @@ -142,11 +147,4 @@ protected function execute(InputInterface $input, OutputInterface $output)

return $install->run();
}

public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestOptionValuesFor('prefer-install')) {
$suggestions->suggestValues(array('dist', 'source', 'auto'));
}
}
}
5 changes: 1 addition & 4 deletions src/Composer/Command/OutdatedCommand.php
Expand Up @@ -27,10 +27,7 @@ class OutdatedCommand extends ShowCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestArgumentValuesFor('package') || $input->mustSuggestOptionValuesFor('ignore')) {
$rootPackage = $this->getComposer(true, $input->getOption('no-plugins'))->getPackage();
$suggestions->suggestValues(array_merge(array_keys($rootPackage->getRequires()), array_keys($rootPackage->getDevRequires())));
}
$this->completeInstalledPackage($input, $suggestions);
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/Composer/Command/ProhibitsCommand.php
Expand Up @@ -12,6 +12,8 @@

namespace Composer\Command;

use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -22,6 +24,11 @@
*/
class ProhibitsCommand extends BaseDependencyCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->completeAvailablePackage($input, $suggestions);
}

/**
* Configure command metadata.
*
Expand Down
7 changes: 7 additions & 0 deletions src/Composer/Command/ReinstallCommand.php
Expand Up @@ -20,6 +20,8 @@
use Composer\Package\BasePackage;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -30,6 +32,11 @@
*/
class ReinstallCommand extends BaseCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->completeInstalledPackage($input, $suggestions) || $this->completePreferInstall($input, $suggestions);
}

/**
* @return void
*/
Expand Down
5 changes: 1 addition & 4 deletions src/Composer/Command/RemoveCommand.php
Expand Up @@ -36,10 +36,7 @@ class RemoveCommand extends BaseCommand
{
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestArgumentValuesFor('packages')) {
$rootPackage = $this->getComposer(true, $input->getOption('no-plugins'))->getPackage();
$suggestions->suggestValues(array_merge(array_keys($rootPackage->getRequires()), array_keys($rootPackage->getDevRequires())));
}
$this->completeInstalledPackage($input, $suggestions);
}

/**
Expand Down

0 comments on commit 825c21f

Please sign in to comment.