App-Cmd icon indicating copy to clipboard operation
App-Cmd copied to clipboard

subdispatch commands are promoted to top level commands

Open djerius opened this issue 10 years ago • 3 comments

I'm playing (and not succeeding terribly well) at getting subcommands to work. My expectation is that subcommands live in a namespace which is private to their parent commands. However, that doesn't appear to be so. Here's some test code:

#!/usr/bin/env perl

MyApp->run;

package MyApp;
use App::Cmd::Setup -app;

package MyApp::Command::first;
use base 'App::Cmd::Subdispatch';

sub execute { print __PACKAGE__, "\n" }

package MyApp::Command::first::init;
use base 'App::Cmd::Command';

sub execute { print __PACKAGE__, "\n" }

package MyApp::Command::second;
use base 'App::Cmd::Subdispatch';

sub execute { print __PACKAGE__, "\n" }

package MyApp::Command::second::init;
use base 'App::Cmd::Command';

sub execute { print __PACKAGE__, "\n" };

Executing that code leads to the following error message:

two plugins for command init: MyApp::Command::second::init and MyApp::Command::first::init

If I remove the definition of second::init, I get the following

Available commands:

  commands: list the application's commands
      help: display a command's help screen

     first: (unknown)
      init: (unknown)
    second: (unknown)

And I can execute first::init as if it were a top-level command:

$ ./tpan init
MyApp::Command::first::init

Which isn't what I'd expect. Am I going about this the wrong way?

Thanks.

djerius avatar Mar 30 '14 02:03 djerius

I have also seen subdispatch commands being treated as top-level commands. I also did not expect that behavior.

jtrowe avatar Apr 30 '14 19:04 jtrowe

Hello, I encounter the same problem.

I have the following setup:

.
./NestedCmd
./NestedCmd/Command
./NestedCmd/Command/first.pm
./NestedCmd/Command/first
./NestedCmd/Command/first/Command
./NestedCmd/Command/first/Command/second.pm
./nestedcmd.pl
./NestedCmd.pm
  • nestedcmd.pl
#!/usr/bin/env perl

use NestedCmd;

NestedCmd->run;

  • NestedCmd.pm
package NestedCmd 0.1;

use App::Cmd::Setup -app;

1;

  • NestedCmd/Command/first.pm
package NestedCmd::Command::first 0.1;

use parent 'App::Cmd::Subdispatch';

1;
  • NestedCmd/Command/first/Command/second.pm
package NestedCmd::Command::first::Command::second;

use NestedCmd::Command::first -command;

sub execute {
    print __PACKAGE__ . "\n";
}

1;

I got the following error when i start this:

Can't locate NestedCmd/Command/first/Command.pm in @INC (you may need to install the NestedCmd::Command::first::Command module) (@INC contains: /usr/local/lib/cperl/site_cperl/5.22.2/x86_64-linux /usr/local/lib/cperl/site_cperl/5.22.2 /usr/local/lib/cperl/5.22.2/x86_64-linux /usr/local/lib/cperl/5.22.2 .) at NestedCmd/Command/first/Command/second.pm line 3.
BEGIN failed--compilation aborted at NestedCmd/Command/first/Command/second.pm line 3.
Compilation failed in require at /usr/local/lib/cperl/site_cperl/5.22.2/App/Cmd.pm line 194.
        App::Cmd::_command("NestedCmd", undef) called at /usr/local/lib/cperl/site_cperl/5.22.2/App/Cmd.pm line 171
        App::Cmd::new("NestedCmd") called at /usr/local/lib/cperl/site_cperl/5.22.2/App/Cmd.pm line 314
        App::Cmd::run("NestedCmd") called at ./nestedcmd.pl line 5

I'ts seems to work when i replace use NestedCmd::Command::first -command; with use App::Cmd::Setup -command; ... but the second command is in the top-level too ...

nestedcmd.pl <command> [-?h] [long options...]
        -? -h --help    show help

Available commands:

  commands: list the application's commands
      help: display a command's help screen

     first: (unknown)
    second: (unknown)
nestedcmd.pl first

Available commands:

  commands: list the application's commands
      help: display a command's help screen

    second: (unknown)

So I override should_ignore() in NestedCmd (and it works):

sub should_ignore {
  my ($self, $command_class) = @_;

  $command_class =~ /^NestedCmd::Command::.*::/;
}

Could you confirm that:

  • this is the right way to do it.
  • this will work with future versions of your module.

?

Thanks.

le-garff-yoann avatar Feb 09 '16 13:02 le-garff-yoann

In case someone still has trouble with this - in the App module, you can set the max depth to limit the listing of subcommands:

sub _module_pluggable_options {
  return (max_depth => 3);
}

larabr avatar Dec 27 '19 16:12 larabr