Skip to content

Commit

Permalink
feat(command): add support for global command's
Browse files Browse the repository at this point in the history
  • Loading branch information
c4spar committed May 28, 2020
1 parent 1d814e2 commit ec42c7a
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 49 deletions.
20 changes: 20 additions & 0 deletions examples/command/global-commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env -S deno run

import { Command } from '../../packages/command/lib/command.ts';

await new Command()
.version( '0.1.0' )

.command( 'global [val:string]' )
.description( 'global ...' )
.global()
.action( console.log )

.command( 'command1', new Command()
.description( 'Some sub command.' )

.command( 'command2', new Command()
.description( 'Some nested sub command.' )
)
)
.parse( Deno.args );
37 changes: 36 additions & 1 deletion packages/command/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
- [Action handler](#action-handler)
- [Sub-commands](#sub-commands)
- [Specify the argument syntax](#specify-the-argument-syntax)
- [Global commands](#global-commands)
- [Hidden commands](#hidden-commands)
- [Git-style executable sub-commands](#git-style-executable-sub-commands)
- [Override exit handling](#override-exit-handling)
Expand Down Expand Up @@ -482,7 +483,7 @@ You ordered a pizza with sauce and parmesan cheese

### Global options

To share options with child commands with the `global` option.
To share options with child commands you can use the `global` option.

```typescript
#!/usr/bin/env -S deno run
Expand Down Expand Up @@ -815,6 +816,40 @@ rmdir dir2
rmdir dir3
```

### Global commands

To share commands with child commands you can use the `.global()` method.

```typescript
#!/usr/bin/env -S deno run

import { Command } from 'https://deno.land/x/cliffy/command.ts';

await new Command()
.version( '0.1.0' )

.command( 'global [val:string]' )
.description( 'global ...' )
.global()
.action( console.log )

.command( 'command1', new Command()
.description( 'Some sub command.' )

.command( 'command2', new Command()
.description( 'Some nested sub command.' )
)
)
.parse( Deno.args );
```

```
$ deno run https://deno.land/x/cliffy/examples/command/global-commands.ts command1 command2 global test
{} test
```

```
### Hidden commands
To exclude commands's from the help and completion command's you can use the `.hidden()` method.
Expand Down
5 changes: 3 additions & 2 deletions packages/command/commands/completions/complete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ export class CompleteCommand extends DefaultCommand {
.type( 'command', new CommandListType( this.parent ) )
.action( async ( options: IFlags, action: string, commandNames: string[] ) => {

let cmd: BaseCommand = commandNames
.reduce( ( cmd: BaseCommand, name: string ): BaseCommand => cmd.getCommand( name ), parent );
let cmd: BaseCommand | undefined = commandNames
.reduce( ( cmd: BaseCommand | undefined, name: string ): BaseCommand | undefined =>
cmd?.getCommand( name, false ), parent );

if ( !cmd ) {
console.error( `Auto-completion failed. Command not found: ${ commandNames.join( ' ' ) }` );
Expand Down
22 changes: 11 additions & 11 deletions packages/command/commands/completions/zsh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ compdef _${ snakeCase( this.parent.getPath() ) } ${ this.parent.getPath() }
*/
private generateCompletions( command: BaseCommand, root?: boolean ): string {

if ( !command.hasCommands() && !command.hasOptions() && !command.hasArguments() ) {
if ( !command.hasCommands( false ) && !command.hasOptions() && !command.hasArguments() ) {
return '';
}

Expand All @@ -105,14 +105,14 @@ function _${ snakeCase( command.getPath() ) }() {`
+ this.generateArgumentCompletions( command )
+ this.generateActions( command )
+ `\n}\n\n`
+ command.getCommands()
.map( subCommand => this.generateCompletions( subCommand ) )
.join( '' );
+ command.getCommands( false )
.map( subCommand => this.generateCompletions( subCommand ) )
.join( '' );
}

protected generateCommandCompletions( command: BaseCommand ): string {

const commands = command.getCommands();
const commands = command.getCommands( false );

let completions: string = commands
.map( ( subCommand: BaseCommand ) =>
Expand Down Expand Up @@ -150,10 +150,10 @@ function _${ snakeCase( command.getPath() ) }() {`

protected generateSubCommandCompletions( command: BaseCommand ): string {

if ( command.hasCommands() ) {
if ( command.hasCommands( false ) ) {

const actions: string = command
.getCommands()
.getCommands( false )
.map( ( command: BaseCommand ) => `${ command.getName() }) _${ snakeCase( command.getPath() ) } ;;` )
.join( '\n ' );

Expand All @@ -180,11 +180,11 @@ function _${ snakeCase( command.getPath() ) }() {`
argsCommand += ` \\\n ${ options.join( ' \\\n ' ) }`;
}

if ( command.hasCommands() || command.hasArguments() ) {
if ( command.hasCommands( false ) || command.hasArguments() ) {
argsCommand += ` \\\n '${ ++argIndex }: :_commands'`;
}

if ( command.hasArguments() || command.hasCommands() ) {
if ( command.hasArguments() || command.hasCommands( false ) ) {

const args: string[] = [];

Expand All @@ -199,7 +199,7 @@ function _${ snakeCase( command.getPath() ) }() {`

argsCommand += args.map( ( arg: string ) => `\\\n '${ arg }'` ).join( '' );

if ( command.hasCommands() ) {
if ( command.hasCommands( false ) ) {
argsCommand += ` \\\n '*:: :->command_args'`;
}
}
Expand Down Expand Up @@ -289,7 +289,7 @@ function _${ snakeCase( command.getPath() ) }() {`
`${ name }) __${ snakeCase( this.parent.getName() ) }_script ${ action.arg.name } ${ action.arg.action } ${ action.cmd } ;;` );
}

if ( command.hasCommands() ) {
if ( command.hasCommands( false ) ) {
actions.unshift( `command_args) _command_args ;;` );
}

Expand Down
10 changes: 7 additions & 3 deletions packages/command/commands/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ export class HelpCommand extends BaseCommand implements IHelpCommand {
*/
public getHelp( name?: string ): string {

const cmd: BaseCommand = name ? this.parent.getCommand( name ) : this.parent;
const cmd: BaseCommand | undefined = name ? this.parent.getCommand( name, false ) : this.parent;

if ( !cmd ) {
throw this.error( new Error( `Sub-command not found: ${ name }` ) );
}

let output = '';
const indent = 2;
Expand Down Expand Up @@ -72,7 +76,7 @@ export class HelpCommand extends BaseCommand implements IHelpCommand {
}

// Commands
if ( cmd.hasCommands() ) {
if ( cmd.hasCommands( false ) ) {
renderLabel( 'Commands' );
output += Table.from( getCommands() )
.padding( [ 2, 2, 1, 2 ] )
Expand Down Expand Up @@ -141,7 +145,7 @@ export class HelpCommand extends BaseCommand implements IHelpCommand {
const getCommands = (): string[][] => {

return [
...cmd.getCommands().map( ( command: BaseCommand ) => [
...cmd.getCommands( false ).map( ( command: BaseCommand ) => [
[ command.getName(), ...command.getAliases() ].map( name => blue( name ) ).join( ', ' ),
this.highlight( command.getArgsDefinition() || '' ),
red( bold( '-' ) ),
Expand Down

0 comments on commit ec42c7a

Please sign in to comment.