App-Chained

 view release on metacpan or  search on metacpan

lib/App/Chained.pm  view on Meta::CPAN


Direction about how to use the completion scritp is contained in the generated script.

The completion will work for the top application till a command is input on the command line after that the completion is for the command.

=head3 command specific options

Your sub commands can define an B<options> field. The field should be set to a subroutine reference that returns a string of options the sub command
accepts. The format should be I<-option_name>. One option perl line.

Here is an example of how I added completion to a set sub commands (8 of them). The sub commands do not have a completion script
and rely on the wrapper for completion. 

I first set the B<options> field:

	{
	description => ...
	run => ...
	...
	
	options => sub {return `$name --dump_options`},
	}

I am using the sub command itself to generate the options. This way I don't have to maintain the list by hand (which is possible).

Modifying the sub command itself was trivial and very quick. I modified the following code (example in one of thesub commands)

  die 'Error parsing options!'unless 
    GetOptions
      (
      'master_template_file=s' => \$master_template_file,
      'h|help' => \&display_help, 
      ) ;
      
to  be

  die 'Error parsing options!'unless 
    GetOptions
        (
        'master_template_file=s' => \$master_template_file,
        'h|help' => \&display_help, 
	
       	'dump_options' => 
	  sub 
	  {
	  print join "\n", map {"-$_"} 
	      qw(
		master_template_file
		help
		) ;
	  exit(0) ;
          },
	) ;

Modfying the height or so scripts took only a few minutes.

Noiw I have command completion for all the sub command. Here is an example:

  nadim@naquadim Arch (master)$ ra show -[tab]
  -format                    -include_loaded_from   -master_categories_file                    
  -help                      -include_not_found     -master_template_file
  -include_categories        -include_statistics    -remove_empty_requirement_field_in_categories
  -include_description_data  -include_type          -requirement_fields_filter_file

The I<show> sub command is two order of magnitude easier to use with completion.

I<Arguments> - None

I<Returns> - Nothing - exits with status code B<1> after emitting the completion script on stdout

I<Exceptions> -  None - Exits the program.

=cut

my ($self) = @_ ;

$self->get_options_definitions() ; # generates $self->{getopt_definitions}
my @options = map { s/=.$//sxm ;  "\t-$_ => 0," } keys %{$self->{getopt_definitions}} ;

my @command_options ;
my $sub_apps = $self->{sub_apps} ;

if(defined $sub_apps)
	{
	while(my ($sub_app_name, $sub_app) = each  %{$sub_apps})
		{
		my @sub_app_options ;
		
		if(exists $sub_app->{options} && 'CODE' eq ref($sub_app->{options}))
			{
			@sub_app_options= map {chomp ; $_} $sub_app->{options}($self, $sub_app, []) ;
			}
			
		push @command_options, "\t$sub_app_name =>  [qw(@sub_app_options)]," ;
		}
	}

use File::Basename ;
my ($basename, $path, $ext) = File::Basename::fileparse($PROGRAM_NAME, ('\..*')) ;
my $application_name =  $basename . $ext ;

local $| = 1 ;

my $complete_script =  <<"COMPLETION_SCRIPT" ;

#The perl script has to be executable and somewhere in the path.                                                         
#This script was generated using used your application name

#Add the following line in your I<~/.bashrc> or B<source> them:

_${application_name}_perl_completion()
{                     
local old_ifs="\${IFS}"
local IFS=\$'\\n';      
COMPREPLY=( \$(${application_name}_perl_completion.pl \${COMP_CWORD} \${COMP_WORDS[\@]}) );
IFS="\${old_ifs}"                                                       

return 1;
}        

complete -o default -F _${application_name}_perl_completion $application_name



( run in 2.260 seconds using v1.01-cache-2.11-cpan-ff9377addf4 )