Browse Source

Merge pull request #12959 from yiisoft/bash-completion

Added bash completion file for ./yii commands
tags/2.0.11
Carsten Brandt 8 years ago committed by GitHub
parent
commit
7fead4f011
  1. 58
      contrib/completion/bash/yii
  2. 38
      contrib/completion/zsh/_yii
  3. 44
      docs/guide/tutorial-console.md
  4. 1
      framework/CHANGELOG.md
  5. 104
      framework/console/controllers/HelpController.php
  6. 75
      tests/framework/console/controllers/HelpControllerTest.php

58
contrib/completion/bash/yii

@ -0,0 +1,58 @@
# This file implements bash completion for the ./yii command file.
# It completes the commands available by the ./yii command.
# See also:
# - https://debian-administration.org/article/317/An_introduction_to_bash_completion_part_2 on how this works.
# - https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html
# - http://www.yiiframework.com/doc-2.0/guide-tutorial-console.html#bash-completion
#
# Usage:
# Temporarily you can source this file in you bash by typing: source yii
# For permanent availability, copy or link this file to /etc/bash_completion.d/
#
_yii()
{
local cur opts yii command
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
yii="${COMP_WORDS[0]}"
# exit if ./yii does not exist
test -f $yii || return 0
# lookup for command
for word in ${COMP_WORDS[@]:1}; do
if [[ $word != -* ]]; then
command=$word
break
fi
done
[[ $cur == $command ]] && state="command"
[[ $cur != $command ]] && state="option"
[[ $cur = *=* ]] && state="value"
case $state in
command)
# complete command/route if not given
# fetch available commands from ./yii help/list command
opts=$($yii help/list 2> /dev/null)
;;
option)
# fetch available options from ./yii help/list-action-options command
opts=$($yii help/list-action-options $command 2> /dev/null | grep -o '^--[a-zA-Z0-9]*')
;;
value)
# TODO allow normal file completion after an option, e.g. --migrationPath=...
;;
esac
# generate completion suggestions
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
}
# register completion for the ./yii command
# you may adjust this line if your command file is named differently
complete -F _yii ./yii yii

38
contrib/completion/zsh/_yii

@ -0,0 +1,38 @@
#compdef yii
_yii() {
local state command lastArgument commands options executive
lastArgument=${words[${#words[@]}]}
executive=$words[1]
# lookup for command
for word in ${words[@]:1}; do
if [[ $word != -* ]]; then
command=$word
break
fi
done
[[ $lastArgument == $command ]] && state="command"
[[ $lastArgument != $command ]] && state="option"
case $state in
command)
commands=("${(@f)$(${executive} help/list 2>/dev/null)}")
_describe 'command' commands
;;
option)
options=("${(@f)$(${executive} help/usage ${command} 2>/dev/null)}")
_message -r "$options"
suboptions=("${(@f)$(${executive} help/list-action-options ${command} 2>/dev/null)}")
_describe -V -o -t suboption 'action options' suboptions
;;
*)
esac
}
compdef _yii yii

44
docs/guide/tutorial-console.md

@ -107,6 +107,50 @@ You can see an example of this in the advanced project template.
> ```
Console command completion <span id="console-command-completion"></span>
---------------
Auto-completion of command arguments is a useful thing when working with the shell.
Since version 2.0.11, the `./yii` command provides auto completion for the bash out of the box.
### Bash completion
Make sure bash completion is installed. For most of installations it is available by default.
Place the completion script in `/etc/bash_completion.d/`:
curl -L https://raw.githubusercontent.com/yiisoft/yii2/blob/master/contrib/completion/bash/yii > /etc/bash_completion.d/yii
Check the [Bash Manual](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html) for
other ways of including completion script to your environment.
### ZSH completion
Put the completion script in directory for completions, using e.g. `~/.zsh/completion/`
```
mkdir -p ~/.zsh/completion
curl -L https://raw.githubusercontent.com/yiisoft/yii2/blob/master/contrib/completion/zsh/_yii > ~/.zsh/completion/_yii
```
Include the directory in the `$fpath`, e.g. by adding it to `~/.zshrc`
```
fpath=(~/.zsh/completion $fpath)
```
Make sure `compinit` is loaded or do it by adding in `~/.zshrc`
```
autoload -Uz compinit && compinit -i
```
Then reload your shell
```
exec $SHELL -l
```
Creating your own console commands <span id="create-command"></span>
----------------------------------

1
framework/CHANGELOG.md

@ -28,6 +28,7 @@ Yii Framework 2 Change Log
- Bug #13089: Fixed `yii\console\controllers\AssetController::adjustCssUrl()` breaks URL reference specification (`url(#id)`) (vitalyzhakov)
- Bug #7727: Fixed truncateHtml leaving extra tags (developeruz)
- Bug #13118: Fixed `handleAction()` function in `yii.js` to handle attribute `data-pjax=0` as disabled PJAX (silverfire)
- Enh #475: Added Bash and Zsh completion support for the `./yii` command (cebe, silverfire)
- Enh #6373: Introduce `yii\db\Query::emulateExecution()` to force returning an empty result for a query (klimov-paul)
- Enh #6809: Added `yii\caching\Cache::$defaultDuration` property, allowing to set custom default cache duration (sdkiller)
- Enh #7333: Improved error message for `yii\di\Instance::ensure()` when a component does not exist (cebe)

104
framework/console/controllers/HelpController.php

@ -69,6 +69,110 @@ class HelpController extends Controller
}
/**
* List all available controllers and actions in machine readable format.
* This is used for shell completion.
* @since 2.0.11
*/
public function actionList()
{
$commands = $this->getCommandDescriptions();
foreach ($commands as $command => $description) {
$result = Yii::$app->createController($command);
if ($result === false || !($result[0] instanceof Controller)) {
continue;
}
/** @var $controller Controller */
list($controller, $actionID) = $result;
$actions = $this->getActions($controller);
if (!empty($actions)) {
$prefix = $controller->getUniqueId();
$this->stdout("$prefix\n");
foreach ($actions as $action) {
$this->stdout("$prefix/$action\n");
}
}
}
}
/**
* List all available options for the $action in machine readable format.
* This is used for shell completion.
*
* @param string $action route to action
* @since 2.0.11
*/
public function actionListActionOptions($action)
{
$result = Yii::$app->createController($action);
if ($result === false || !($result[0] instanceof Controller)) {
return;
}
/** @var Controller $controller */
list($controller, $actionID) = $result;
$action = $controller->createAction($actionID);
if ($action === null) {
return;
}
$arguments = $controller->getActionArgsHelp($action);
foreach ($arguments as $argument => $help) {
$description = str_replace("\n", '', addcslashes($help['comment'], ':')) ?: $argument;
$this->stdout($argument . ':' . $description . "\n");
}
$this->stdout("\n");
$options = $controller->getActionOptionsHelp($action);
foreach ($options as $argument => $help) {
$description = str_replace("\n", '', addcslashes($help['comment'], ':')) ?: $argument;
$this->stdout('--' . $argument . ':' . $description . "\n");
}
}
/**
* Displays usage information for $action
*
* @param string $action route to action
* @since 2.0.11
*/
public function actionUsage($action)
{
$result = Yii::$app->createController($action);
if ($result === false || !($result[0] instanceof Controller)) {
return;
}
/** @var Controller $controller */
list($controller, $actionID) = $result;
$action = $controller->createAction($actionID);
if ($action === null) {
return;
}
$scriptName = $this->getScriptName();
if ($action->id === $controller->defaultAction) {
$this->stdout($scriptName . ' ' . $this->ansiFormat($controller->getUniqueId(), Console::FG_YELLOW));
} else {
$this->stdout($scriptName . ' ' . $this->ansiFormat($action->getUniqueId(), Console::FG_YELLOW));
}
$args = $controller->getActionArgsHelp($action);
foreach ($args as $name => $arg) {
if ($arg['required']) {
$this->stdout(' <' . $name . '>', Console::FG_CYAN);
} else {
$this->stdout(' [' . $name . ']', Console::FG_CYAN);
}
}
$this->stdout("\n");
return;
}
/**
* Returns all available command names.
* @return array all available command names
*/

75
tests/framework/console/controllers/HelpControllerTest.php

@ -45,6 +45,79 @@ class HelpControllerTest extends TestCase
return $controller->flushStdOutBuffer();
}
public function testActionList()
{
$this->mockApplication([
'enableCoreCommands' => false,
'controllerMap' => [
'migrate' => 'yii\console\controllers\MigrateController',
'cache' => 'yii\console\controllers\CacheController',
],
]);
$result = Console::stripAnsiFormat($this->runControllerAction('list'));
$this->assertEquals(<<<STRING
cache
cache/flush
cache/flush-all
cache/flush-schema
cache/index
help
help/index
help/list
help/list-action-options
help/usage
migrate
migrate/create
migrate/down
migrate/history
migrate/mark
migrate/new
migrate/redo
migrate/to
migrate/up
STRING
, $result);
}
public function testActionListActionOptions()
{
$this->mockApplication([
'enableCoreCommands' => false,
'controllerMap' => [
'migrate' => 'yii\console\controllers\MigrateController',
'cache' => 'yii\console\controllers\CacheController',
],
]);
$result = Console::stripAnsiFormat($this->runControllerAction('list-action-options', ['action' => 'help/list-action-options']));
$this->assertEquals(<<<STRING
action:route to action
--interactive: whether to run the command interactively.
--color: whether to enable ANSI color in the output.If not set, ANSI color will only be enabled for terminals that support it.
--help: whether to display help information about current command.
STRING
, $result);
}
public function testActionUsage()
{
$this->mockApplication([
'enableCoreCommands' => false,
'controllerMap' => [
'migrate' => 'yii\console\controllers\MigrateController',
'cache' => 'yii\console\controllers\CacheController',
],
]);
$result = Console::stripAnsiFormat($this->runControllerAction('usage', ['action' => 'help/list-action-options']));
$this->assertEquals(<<<STRING
bootstrap.php help/list-action-options <action>
STRING
, $result);
}
public function testActionIndex()
{
$result = Console::stripAnsiFormat($this->runControllerAction('index'));
@ -56,7 +129,7 @@ class HelpControllerTest extends TestCase
public function testActionIndexWithHelpCommand()
{
$result = Console::stripAnsiFormat($this->runControllerAction('index', ['command' => 'help']));
$result = Console::stripAnsiFormat($this->runControllerAction('index', ['command' => 'help/index']));
$this->assertContains('Displays available commands or the detailed information', $result);
$this->assertContains('bootstrap.php help [command] [...options...]', $result);
$this->assertContains('--appconfig: string', $result);

Loading…
Cancel
Save