123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- # ------------------------------------------------------------------------------
- # (C) Crown copyright Met Office. All rights reserved.
- # For further details please refer to the file COPYRIGHT.txt
- # which you should have received as part of this distribution.
- # ------------------------------------------------------------------------------
- use strict;
- use warnings;
- package Fcm::CLI::Invoker::Help;
- use base qw{Fcm::CLI::Invoker};
- use Carp qw{croak};
- use Fcm::CLI::Exception;
- use Fcm::CLI::Config;
- use Fcm::Config;
- use Fcm::Util qw{run_command};
- use IO::File;
- ################################################################################
- # Invokes the sub-system
- sub invoke {
- my ($self) = @_;
- my @subcommand_names = $self->get_arguments();
- if (@subcommand_names) {
- for my $subcommand_name (@subcommand_names) {
- my $help_string = $self->_get_help_for($subcommand_name);
- if (!defined($help_string)) {
- croak(Fcm::CLI::Exception->new({message => sprintf(
- "%s: unknown command", $subcommand_name,
- )}));
- }
- print($help_string, "\n");
- }
- }
- else {
- print($self->_get_help());
- }
- }
- ################################################################################
- # Returns the help string for a subcommand matching $subcommand_name
- sub _get_help_for {
- my ($self, $subcommand_name) = @_;
- my $subcommand
- = Fcm::CLI::Config->instance()->get_subcommand_of($subcommand_name);
- if (!$subcommand) {
- return;
- }
- if ($subcommand->is_vc()) {
- my $invoker = $subcommand->get_invoker($subcommand_name);
- local(@ARGV) = '--help';
- $invoker->invoke();
- return q{};
- }
- my $prog = Fcm::Config->instance()->setting('FCM_COMMAND');
- # FIXME: can do with using Text::Template or Perl6::Form
- my $help = sprintf(
- "%s %s: %s\n",
- $prog,
- $subcommand->as_string(),
- $subcommand->get_synopsis(),
- );
- $help .= sprintf(
- "usage: %s %s %s\n",
- $prog, $subcommand->get_names()->[0], $subcommand->get_usage(),
- );
- if ($subcommand->get_description()) {
- my @lines = (q{}, split("\n", $subcommand->get_description()), q{});
- $help .= join(qq{\n }, @lines) . "\n";
- }
- if ($subcommand->get_options()) {
- $help .= "Valid options:\n";
- my $max_length_of_name = 0;
- my @option_names;
- for my $option ($subcommand->get_options()) {
- if (length($option->get_name()) > $max_length_of_name) {
- $max_length_of_name = length($option->get_name());
- }
- }
- for my $option ($subcommand->get_options()) {
- $help .= sprintf(
- " --%s%s%s%s : %s\n",
- $option->get_name(),
- q{ } x ($max_length_of_name - length($option->get_name())),
- (
- $option->get_letter()
- ? q{ [-} . $option->get_letter() . q{]} : q{ }
- ),
- ($option->has_arg() ? q{ arg} : q{ } x 4),
- $option->get_description(),
- );
- }
- }
- return $help;
- }
- ################################################################################
- # Returns the general help string
- sub _get_help {
- my ($self) = @_;
- my $release = $self->_get_release();
- # FIXME: can do with using Text::Template or Perl6::Form
- my $prog = Fcm::Config->instance()->setting('FCM_COMMAND');
- my $return = sprintf(
- qq{usage: %s <subcommand> [options] [args]\n}
- . qq{Flexible configuration management system, release %s.\n}
- . qq{Type "%s help <subcommand>" for help on a specific subcommand\n}
- . qq{\n}
- . qq{Available subcommands:\n}
- ,
- $prog, $release, $prog,
- );
- for my $subcommand (Fcm::CLI::Config->instance()->get_core_subcommands()) {
- $return .= sprintf(qq{ %s\n}, $subcommand->as_string());
- }
- my @lines = run_command(
- [qw/svn help/], DEVNULL => 1, METHOD => 'qx', ERROR => 'ignore',
- );
- if (@lines) {
- for my $subcommand (Fcm::CLI::Config->instance()->get_vc_subcommands()) {
- if (defined($subcommand->get_synopsis())) {
- $return .= sprintf(qq{ %s\n}, $subcommand->as_string());
- }
- else {
- $return .= qq{ <version control system commands, see below>\n};
- }
- }
- $return .= "\n=> svn help\n". join(q{}, @lines);
- }
- return $return;
- }
- ################################################################################
- # Returns the release number of the current program
- sub _get_release {
- my ($self) = @_;
- my $release = Fcm::Config->instance()->setting('FCM_RELEASE');
- my $rev_file = Fcm::Config->instance()->setting('FCM_REV_FILE');
- if (-r $rev_file) {
- my $handle = IO::File->new($rev_file, 'r');
- if ($handle) {
- my $rev = $handle->getline();
- $handle->close();
- chomp($rev);
- if ($rev) {
- $release .= qq{ (r$rev)};
- }
- }
- }
- return $release;
- }
- 1;
- __END__
- =head1 NAME
- Fcm::CLI::Invoker::Help
- =head1 SYNOPSIS
- use Fcm::CLI::Invoker::Help;
- $invoker = Fcm::CLI::Invoker::Help->new({
- command => $command,
- options => \%options,
- arguments => $arguments,
- });
- $invoker->invoke();
- =head1 DESCRIPTION
- This class extends L<Fcm::CLI::Invoker|Fcm::CLI::Invoker> an inherits all its
- methods. An object of this class is used to provide help on the command line
- interface.
- =head1 METHODS
- See L<Fcm::CLI::Invoker|Fcm::CLI::Invoker> for a list of inherited methods.
- =over 4
- =item invoke()
- Provides help. If a subcommand name is specified in the argument, provides help
- for the specified subcommand. If a subcommand name is not specified, provides
- general CLI help.
- =back
- =head1 DIAGNOSTICS
- =over 4
- =item L<Fcm::CLI::Exception|Fcm::CLI::Exception>
- The invoke() method can croak() with this exception if the specified subcommand
- cannot be identified.
- =back
- =head1 TO DO
- Unit tests.
- Separate logic in this module with that of L<Fcm::CLI::Config|Fcm::CLI::Config>.
- Decouples help formatter with this invoker.
- =head1 SEE ALSO
- L<Fcm::CLI::Exception|Fcm::CLI::Exception>,
- L<Fcm::CLI::Subcommand|Fcm::CLI::Subcommand>
- =head1 COPYRIGHT
- E<169> Crown copyright Met Office. All rights reserved.
- =cut
|