php-yaoi/php-yaoi

View on GitHub
src/Cli/Command/Completion.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

namespace Yaoi\Cli\Command;

use Yaoi\Cli\Option;
use Yaoi\Command;
use Yaoi\View\Hardcoded;

class Completion extends Hardcoded
{
    protected $command;

    public function __construct(Command $command) {
        $this->command = $command;
    }

    /** @var  PrepareDefinition */
    private $prep;
    private $optionsValues = array();
    private $argumentsShift;
    private $requiredArguments = array();
    private $optionsStrings = array();

    private function prepareRequiredArguments()
    {
        $this->requiredArguments = array(
            $this->argumentsShift => '',
        );

        foreach ($this->prep->requiredArguments as $index => $argument) {
            $index += $this->argumentsShift;

            if ($argument->type === Option::TYPE_ENUM) {
                $this->requiredArguments[$index] = '';
                foreach ($argument->enumValues as $value) {
                    $this->requiredArguments[$index] .= '"' . $value . '" ';
                }
            } else {
                $this->requiredArguments[$index] = '';
            }
        }
    }

    private function prepareOptions()
    {
        $this->optionsStrings = array(
            Runner::GROUP_MISC => '',
            Runner::GROUP_DEFAULT => '',
        );

        $this->optionsValues = array();

        foreach ($this->prep->optionsArray as $option) {
            if ($option instanceof Option && $option->isUnnamed) {
                continue;
            }

            $group = $option->group === Runner::GROUP_MISC
                ? Runner::GROUP_MISC
                : Runner::GROUP_DEFAULT;

            $this->optionsStrings [$group] .= '"' . Runner::OPTION_NAME . $option->getPublicName() . '" ';

            if ($option->type === Option::TYPE_VALUE) {
                $this->optionsValues [Runner::OPTION_NAME . $option->getPublicName()] = '';
            } elseif ($option->type === Option::TYPE_ENUM) {
                $this->optionsValues [Runner::OPTION_NAME . $option->getPublicName()] = '"' . implode('" "', $option->enumValues) . '" ';
            }
        }

    }

    protected function renderDefinition(Command\Definition $definition, $argumentsShift = 1)
    {
        $this->prep = new PrepareDefinition((array)$definition->options);
        $this->argumentsShift = $argumentsShift;

        $this->prepareRequiredArguments();
        $this->prepareOptions();

        $this->echoBash();
    }


    private function echoBash() {
        ?>
for opt in <?php echo $this->optionsStrings[Runner::GROUP_MISC] ?>; do
    if [[ $opt == $prev ]]; then
        return 0
    fi
done

<?php foreach ($this->requiredArguments as $index => $values) { ?>
if [ $COMP_CWORD = <?php echo $index ?> ]; then
    options=(<?php echo $values ?>)
fi
<?php } ?>

if [ $COMP_CWORD = <?php echo $this->argumentsShift ?> ]; then
    if [[ ${cur} == -* ]] ; then
        options+=(<?php echo $this->optionsStrings[Runner::GROUP_MISC] ?>)
    fi
fi

<?php if ($this->optionsStrings[Runner::GROUP_DEFAULT]) { ?>
for opt in <?php echo $this->optionsStrings[Runner::GROUP_DEFAULT] ?>; do
    skip=
    for word in "${COMP_WORDS[@]}"; do
        if [[ $opt == $word ]]; then
            skip=1
            break;
        fi
    done
    [[ -n $skip ]] || options+=("$opt");
done

<?php
    }
        if (!empty($this->optionsValues)) { ?>
case "$prev" in
<?php foreach ($this->optionsValues as $name => $values) { ?>
    "<?php echo $name ?>")
    options=(<?php echo $values; ?>)
    ;;
<?php } ?>
esac
<?php }

    }


    public function render()
    {
        $def = $this->command->definition();
        $bashFunction = str_replace('-', '_', $def->name);

        ?>
#!/bin/bash

# Bash Completion for <?php echo $def->description?>

_<?php echo $bashFunction ?>() {
COMPREPLY=()
local self=${COMP_WORDS[0]}
local first=${COMP_WORDS[1]}
local cur=${COMP_WORDS[COMP_CWORD]}
local prev=${COMP_WORDS[COMP_CWORD-1]}
local options=()

<?php $this->renderDefinition($def); ?>

if [[ ${cur} == -* ]] ; then
    COMPREPLY=( $( compgen -W "${options[*]}" -- $cur) )
    return 0
fi

COMPREPLY=( $( compgen -W "${options[*]}" -- $cur) )
}

complete -F _<?php echo $bashFunction ?> <?php echo $def->name ?>

<?php
}

}