Skip to content

Commit f801127

Browse files
committed
Update documentation to include CompletionAwareInterface
Also: * Update composer branch-alias for 0.5.0 release
1 parent d856b82 commit f801127

File tree

5 files changed

+124
-47
lines changed

5 files changed

+124
-47
lines changed

README.md

Lines changed: 95 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@
88
[![Latest Unstable Version](https://poser.pugx.org/stecman/symfony-console-completion/v/unstable.svg)](https://packagist.org/packages/stecman/symfony-console-completion)
99
[![License](https://poser.pugx.org/stecman/symfony-console-completion/license.svg)](https://packagist.org/packages/stecman/symfony-console-completion)
1010

11-
This package provides automatic (tab) completion in BASH and ZSH for Symfony Console Component based applications. With zero configuration, this package allows completion of available command names and the options they provide. Custom completion behaviour can be added for option and argument values by name.
11+
This package provides automatic (tab) completion in BASH and ZSH for Symfony Console Component based applications. With zero configuration, this package allows completion of available command names and the options they provide. User code can define custom completion behaviour for arugment and option values.
1212

1313
Example of zero-config use with Composer:
1414

1515
![Composer BASH completion](https://i.imgur.com/MoDWkby.gif)
1616

1717
## Zero-config use
1818

19-
If you don't need any custom completion behaviour, all you need to do is add the completion command to your application's available commands:
19+
If you don't need any custom completion behaviour, you can simply add the completion command to your application:
2020

21-
1. Install `stecman/symfony-console-completion` through composer
21+
1. Install `stecman/symfony-console-completion` using composer
2222
2. Add an instance of `CompletionCommand` to your application's `Application::getDefaultCommands()` method:
23+
2324
```php
2425
protected function getDefaultCommands()
2526
{
@@ -42,48 +43,83 @@ If you don't need any custom completion behaviour, all you need to do is add the
4243
eval $([program] _completion --generate-hook)
4344
```
4445

45-
By default this registers completion for the absolute path to you application. You can specify a command name to complete for instead using the `-p` option, which is useful if you're using an alias to run the program.
46+
By default this registers completion for the absolute path to you application, which will work if the program on accessible on your PATH. You can specify a program name to complete for instead using the `--program` option, which is required if you're using an alias to run the program.
47+
48+
4. If you want the completion to apply automatically for all new shell sessions, add the command from step 3 to your shell's profile (eg. `~/.bash_profile` or `~/.zshrc`)
4649

47-
4. Add the command from step 3 to your bash profile if you want the completion to apply automatically for all new terminal sessions.
50+
Note: The type of shell (ZSH/BASH) is automatically detected using the `SHELL` environment variable at run time. In some circumstances, you may need to explicitly specify the shell type with the `--shell-type` option.
4851

49-
Note: If `[program]` is an alias you will need to specify the aliased name with the `-p|--program` option, as completion may not work otherwise: `_completion --generate-hook -p [myalias]`.
5052

51-
Second note: The type of shell (ZSH/BASH) is automatically detected using the `SHELL` environment variable at run time. In some circumstances, you may need to explicitly specify the shell type with the `--shell-type` option.
53+
## How it works
5254

53-
### How it works
55+
The `--generate-hook` option of `CompletionCommand` generates a small shell script that registers a function with your shell's completion system to act as a bridge to the completion command in your application. When you request completion for your program (by pressing tab with your program name as the first word on the command line), the bridge function is run; passing the current command line contents and cursor position to `[program] _completion`, and feeding the resulting output back to the shell.
5456

55-
The `--generate-hook` option of `CompletionCommand` generates a few lines of BASH that, when executed, register your application as a completion handler for your itself in the current shell session. When you request completion for your program (by pressing tab), the completion command on your application is run with no arguments: `[program] _completion`. This uses environment variables set by BASH to get the current command line contents and cursor position, then completes from your console command definitions.
5657

58+
## Defining value completions
5759

58-
## Custom completion
60+
By default, no completion results will be returned for option and argument values. There are two ways of defining custom completion values for values: extend `CompletionCommand`, or implement `CompletionAwareInterface` interface.
5961

60-
Custom completion behaviour for argument and option values can be added by sub-classing `CompletionCommand`.
62+
### Implementing `CompletionAwareInterface`
6163

62-
The following examples are for an application with this signature: `myapp (walk|run) [-w|--weather=""] direction`
64+
`CompletionAwareInterface` allows a command to be responsible for completing its own option and argument values. When completion is run with a command name specified (eg. `myapp mycommand ...`) and the named command implements this interface, the appropriate interface method is called automatically:
6365

6466
```php
65-
class MyCompletionCommand extends CompletionCommand {
67+
class MyCommand extends Command impements CompletionAwareInterface
68+
{
69+
...
70+
71+
public function completeOptionValues($optionName, CompletionContext $context)
72+
{
73+
if ($optionName == 'some-option') {
74+
return ['myvalue', 'other-value', 'word'];
75+
}
76+
}
6677

67-
protected function runCompletion()
78+
public function completeArgumentValues($argumentName, CompletionContext $context)
6879
{
69-
$this->handler->addHandlers(array(
80+
if ($argumentName == 'package') {
81+
return $this->getPackageNamesFromDatabase($context->getCurrentWord());
82+
}
83+
}
84+
}
85+
```
86+
87+
This method of generating completions doesn't support use of `CompletionInterface` implementations at the moment, which make it easy to share completion behaviour between commands. To use this functionality, you'll need write your value completions by extending `CompletionCommand`.
88+
89+
90+
### Extending `CompletionCommand`
91+
92+
Argument and option value completions can also be defined by extending `CompletionCommand` and overriding the `configureCompletion` method:
93+
94+
```php
95+
class MyCompletionCommand extends CompletionCommand
96+
{
97+
protected function configureCompletion(CompletionHandler $handler)
98+
{
99+
$handler->addHandlers(array(
70100
// Instances of Completion go here.
71101
// See below for examples.
72102
));
73-
return $this->handler->runCompletion();
74103
}
75104
}
76105
```
77106

107+
#### The `Completion` class
108+
109+
The following snippets demonstrate how the `Completion` class works with `CompletionHandler`, and some possible configurations. The examples are for an application with the signature:
110+
111+
`myapp (walk|run) [-w|--weather=""] direction`
112+
113+
78114
##### Command-specific argument completion with an array
79115

80116
```php
81-
$this->handler->addHandler(
117+
$handler->addHandler(
82118
new Completion(
83-
'walk',
84-
'direction',
85-
Completion::TYPE_ARGUMENT,
86-
array(
119+
'walk', // match command name
120+
'direction', // match argument/option name
121+
Completion::TYPE_ARGUMENT, // match definition type (option/argument)
122+
array( // array or callback for results
87123
'north',
88124
'east',
89125
'south',
@@ -93,46 +129,48 @@ $this->handler->addHandler(
93129
);
94130
```
95131

96-
This will complete for this:
132+
This will complete the `direction` argument for this:
133+
97134
```bash
98135
$ myapp walk [tab]
99136
```
100137

101138
but not this:
139+
102140
```bash
103141
$ myapp run [tab]
104142
```
105143

106144
##### Non-command-specific (global) argument completion with a function
107145

108146
```php
109-
$this->handler->addHandler(
110-
Completion::makeGlobalHandler(
147+
$handler->addHandler(
148+
new Completion(
149+
Completion::ALL_COMMANDS,
111150
'direction',
112151
Completion::TYPE_ARGUMENT,
113152
function() {
114-
$values = array();
115-
116-
// Fill the array up with stuff
117-
return $values;
153+
return range(1, 10);
118154
}
119155
)
120156
);
121157
```
122158

123-
This will complete for both commands:
159+
This will complete the `direction` argument for both commands:
160+
124161
```bash
125162
$ myapp walk [tab]
126163
$ myapp run [tab]
127164
```
128165

129166
##### Option completion
130167

131-
Option handlers work the same way as argument handlers, except you use `Completion::TYPE_OPTION` for the type..
168+
Option handlers work the same way as argument handlers, except you use `Completion::TYPE_OPTION` for the type.
132169

133170
```php
134-
$this->handler->addHandler(
135-
Completion::makeGlobalHandler(
171+
$handler->addHandler(
172+
new Completion(
173+
Completion::ALL_COMMANDS,
136174
'weather',
137175
Completion::TYPE_OPTION,
138176
array(
@@ -144,10 +182,30 @@ $this->handler->addHandler(
144182
);
145183
```
146184

147-
### Example: completing references from a Git repository
185+
##### Completing the for both arguments and options
186+
187+
To have a completion run for both options and arguments matching the specified name, you can use the type `Completion::ALL_TYPES`. Combining this with `Completion::ALL_COMMANDS` and consistent option/argument naming throughout your application, it's easy to share completion behaviour between commands, options and arguments:
188+
189+
```php
190+
$handler->addHandler(
191+
new Completion(
192+
Completion::ALL_COMMANDS,
193+
'pacakge',
194+
Completion::ALL_TYPES,
195+
function() {
196+
// ...
197+
}
198+
)
199+
);
200+
```
201+
202+
## Example completions
203+
204+
### Completing references from a Git repository
148205

149206
```php
150-
Completion::makeGlobalHandler(
207+
new Completion(
208+
Completion::ALL_COMMANDS,
151209
'ref',
152210
Completion::TYPE_OPTION,
153211
function () {
@@ -159,9 +217,9 @@ Completion::makeGlobalHandler(
159217
)
160218
```
161219

162-
### Example: completing filesystem paths
220+
### Completing filesystem paths
163221

164-
This library provides the completion class `ShellPathCompletion` which defers path completion to the shell's built-in path completion behaviour rather than implementing it in PHP.
222+
This library provides the completion implementation `ShellPathCompletion` which defers path completion to the shell's built-in path completion behaviour rather than implementing it in PHP.
165223

166224
```php
167225
new Completion\ShellPathCompletion(
@@ -176,3 +234,4 @@ new Completion\ShellPathCompletion(
176234

177235
* Option shortcuts are not offered as completion options, however requesting completion (ie. pressing tab) on a valid option shortcut will complete.
178236
* Completion is not implemented for the `--option="value"` style of passing a value to an option, however `--option value` and `--option "value"` work and are functionally identical.
237+
* Value completion is always run for options marked as `InputOption::VALUE_OPTIONAL` since there is currently no way to determine the desired behaviour from the command line contents (ie. skip the optional value or complete for it)

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
},
2323
"extra": {
2424
"branch-alias": {
25-
"dev-master": "0.4.x-dev"
25+
"dev-master": "0.5.x-dev"
2626
}
2727
}
2828
}

src/Completion/CompletionAwareInterface.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,19 @@ interface CompletionAwareInterface
88
{
99

1010
/**
11-
* Returns possible option values.
12-
*
13-
* @param string $optionName Option name.
14-
* @param CompletionContext $context Completion context.
11+
* Return possible values for the named option
1512
*
13+
* @param string $optionName
14+
* @param CompletionContext $context
1615
* @return array
1716
*/
1817
public function completeOptionValues($optionName, CompletionContext $context);
1918

2019
/**
21-
* Returns possible argument values.
22-
*
23-
* @param string $argumentName Argument name.
24-
* @param CompletionContext $context Completion context.
20+
* Return possible values for the named argument
2521
*
22+
* @param string $argumentName
23+
* @param CompletionContext $context
2624
* @return array
2725
*/
2826
public function completeArgumentValues($argumentName, CompletionContext $context);

src/CompletionCommand.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,30 @@ protected function execute(InputInterface $input, OutputInterface $output)
7474
}
7575
}
7676

77+
/**
78+
* Run the completion handler and return a filtered list of results
79+
*
80+
* @return string[]
81+
*/
7782
protected function runCompletion()
7883
{
84+
$this->configureCompletion($this->handler);
7985
return $this->handler->runCompletion();
8086
}
8187

88+
/**
89+
* Configure the CompletionHandler instance before it is run
90+
*
91+
* @param CompletionHandler $handler
92+
*/
93+
protected function configureCompletion(CompletionHandler $handler)
94+
{
95+
// Override this method to configure custom value completions
96+
}
97+
8298
/**
8399
* Determine the shell type for use with HookFactory
100+
*
84101
* @return string
85102
*/
86103
protected function getShellType()

src/CompletionHandler.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class CompletionHandler
3030

3131
/**
3232
* Array of completion helpers.
33-
* @var Completion[]
33+
* @var CompletionInterface[]
3434
*/
3535
protected $helpers = array();
3636

@@ -54,13 +54,16 @@ public function getContext()
5454
}
5555

5656
/**
57-
* @param Completion[] $array
57+
* @param CompletionInterface[] $array
5858
*/
5959
public function addHandlers(array $array)
6060
{
6161
$this->helpers = array_merge($this->helpers, $array);
6262
}
6363

64+
/**
65+
* @param CompletionInterface $helper
66+
*/
6467
public function addHandler(CompletionInterface $helper)
6568
{
6669
$this->helpers[] = $helper;

0 commit comments

Comments
 (0)