diff --git a/lib/App/Yath.pm b/lib/App/Yath.pm index 08e988cfe..50b801489 100644 --- a/lib/App/Yath.pm +++ b/lib/App/Yath.pm @@ -31,6 +31,7 @@ use Getopt::Yath::Term qw/USE_COLOR color fit_to_width/; use App::Yath::Options::Yath; use App::Yath::ConfigFile; +use App::Yath::Util qw/paged_print/; use Carp qw/croak/; use Time::HiRes qw/time/; @@ -81,10 +82,13 @@ sub cli_help { my $cmd_class = $self->command; $options //= $self->options; - my $cmd = $cmd_class ? $cmd_class->name : 'COMMAND'; my $help = ""; + + my $no_cmd = 0; + my $cmd = "COMMAND"; if ($cmd_class) { + $cmd = $cmd_class->name // 'COMMAND'; if ($self->use_color) { $help .= "\n"; $help .= color('bold white') . "Command selected: "; @@ -97,11 +101,16 @@ sub cli_help { else { $help .= "\nCommand selected: $cmd ($cmd_class)\n"; } - - my @desc = map { fit_to_width(" ", $_) } split /\n\n/, $cmd_class->description; - $help .= join "\n\n" => @desc; + } + else { + $no_cmd = 1; + require App::Yath::Command::help; + $cmd_class //= 'App::Yath::Command::help'; } + my @desc = map { fit_to_width(" ", $_) } split /\n\n/, $cmd_class->description; + $help .= join "\n\n" => @desc; + my $opts = $options->docs('cli', groups => {':{' => '}:'}, group => $params{group}, settings => $settings, color => $self->use_color); my $script = File::Spec->abs2rel($settings->yath->script // $0); @@ -147,7 +156,15 @@ sub cli_help { ); } - return "${usage}\n${help}\n${opts}\n${end}"; + my $cmds = ""; + if ($no_cmd) { + $settings->create_group('help'); + $settings->help->create_option(verbose => 0); + my $it = App::Yath::Command::help->new(settings => $settings); + $cmds = $it->command_table; + } + + return "${usage}\n${help}\n${opts}\n${end}\n${cmds}"; } sub _strip_color { @@ -631,7 +648,7 @@ sub handle_debug { $cli_params{group} = $group if $group && $group ne '1'; $help .= $self->cli_help($yath_options, %cli_params); - $self->page_out($help); + paged_print($help); $exit //= 0; } @@ -653,7 +670,7 @@ sub handle_debug { param => '--show-opts=GROUP_NAME', ) if $group eq '1'; - $self->page_out($out); + paged_print($out); $exit //= 0; } @@ -664,21 +681,6 @@ sub handle_debug { } } -sub page_out { - my $self = shift; - my ($out) = @_; - - if (eval { require IO::Pager; 1 }) { - local $SIG{PIPE} = sub {}; - local $ENV{LESS} = "-r"; - my $pager = IO::Pager->new(*STDOUT); - $pager->print($out); - } - else { - print $out; - } -} - sub version_info { my $self = shift; diff --git a/lib/App/Yath/Command.pm b/lib/App/Yath/Command.pm index 5d44654ab..73f16ceba 100644 --- a/lib/App/Yath/Command.pm +++ b/lib/App/Yath/Command.pm @@ -15,7 +15,6 @@ sub args_include_tests { 0 } sub internal_only { 0 } sub summary { "No Summary" } sub description { "No Description" } -sub group { "Z-FIXME" } sub cli_args { } sub cli_dot { } @@ -24,7 +23,24 @@ sub load_plugins { 0 } sub load_resources { 0 } sub load_renderers { 0 } -sub name { $_[0] =~ m/([^:=]+)(?:=.*)?$/; $1 || $_[0] } +sub name { + my $class_or_self = shift; + my $class = ref($class_or_self) || $class_or_self; + + if ($class =~ m/^App::Yath::Command::(.+)$/) { + my $out = $1; + $out =~ s/::/-/g; + return $out; + } + + return $class; +} + +sub group { + my $name = $_[0]->name; + return if $_[0]->name =~ m/^(.+)-/; + return 'Z-FIXME'; +} sub set_dot_args { croak "set_dot_args is not implemented" } diff --git a/lib/App/Yath/Command/abort.pm b/lib/App/Yath/Command/abort.pm index 608e2acda..42b168cd1 100644 --- a/lib/App/Yath/Command/abort.pm +++ b/lib/App/Yath/Command/abort.pm @@ -11,7 +11,7 @@ use Test2::Harness::Util::HashBase; sub group { 'daemon' } -sub summary { "Kill the runner and any running or pending tests" } +sub summary { "Remove any pending tests, will not stop currently running tests, leaves the runner active" } sub cli_args { "" } sub description { diff --git a/lib/App/Yath/Command/client/publish.pm b/lib/App/Yath/Command/client/publish.pm index 9e7acbfef..e51498147 100644 --- a/lib/App/Yath/Command/client/publish.pm +++ b/lib/App/Yath/Command/client/publish.pm @@ -19,11 +19,13 @@ include_options( 'App::Yath::Options::Publish' => [qw/mode/], ); -sub summary { "Publish a log file to a yath server" } +sub group { ['web client', 'log parsing'] } + +sub summary { "Publish a log file to a yath web server" } sub description { return <<" EOT"; -Publish a log file to a yath server. (API key is required) +Publish a log file to a yath web server. (API key is required) EOT } diff --git a/lib/App/Yath/Command/client/recent.pm b/lib/App/Yath/Command/client/recent.pm index 4f937d972..d35757f9d 100644 --- a/lib/App/Yath/Command/client/recent.pm +++ b/lib/App/Yath/Command/client/recent.pm @@ -15,11 +15,13 @@ include_options( 'App::Yath::Options::WebClient', ); -sub summary { "Show a list of recent runs on a yath server" } +sub summary { "Show a list of recent runs on a yath web server" } + +sub group { ['web client', 'history'] } sub description { return <<" EOT"; -This command will find the last several runs from a yath server +This command will find the last several runs from a yath web server EOT } diff --git a/lib/App/Yath/Command/db.pm b/lib/App/Yath/Command/db.pm index 7a4f31e78..ce43d5547 100644 --- a/lib/App/Yath/Command/db.pm +++ b/lib/App/Yath/Command/db.pm @@ -12,7 +12,7 @@ use Test2::Harness::Util::HashBase; sub summary { "Start a yath database server" } sub description { "Starts a database that can be used to temporarily store data (data is deleted when server shuts down)" } -sub group { "db" } +sub group { "database" } sub cli_args { "" } diff --git a/lib/App/Yath/Command/db/importer.pm b/lib/App/Yath/Command/db/importer.pm index 62c219d71..7798a3912 100644 --- a/lib/App/Yath/Command/db/importer.pm +++ b/lib/App/Yath/Command/db/importer.pm @@ -6,7 +6,7 @@ our $VERSION = '2.000000'; sub summary { "Start an importer process that will wait for uploaded logs to import" } sub description { "Start an importer process that will wait for uploaded logs to import" } -sub group { "db" } +sub group { "database" } use App::Yath::Schema::Util qw/schema_config_from_settings/; diff --git a/lib/App/Yath/Command/db/publish.pm b/lib/App/Yath/Command/db/publish.pm index c3e4af06e..82a3a5446 100644 --- a/lib/App/Yath/Command/db/publish.pm +++ b/lib/App/Yath/Command/db/publish.pm @@ -23,12 +23,9 @@ include_options( 'App::Yath::Options::Publish', ); -sub summary { "Publish a log file directly to a yath database" } - -sub group { 'log' } - -sub cli_args { "[--] event_log.jsonl[.gz|.bz2]" } - +sub summary { "Publish a log file directly to a yath database" } +sub group { ["database", 'log parsing'] } +sub cli_args { "[--] event_log.jsonl[.gz|.bz2]" } sub description { "Publish a log file directly to a yath database" } sub run { diff --git a/lib/App/Yath/Command/db/recent.pm b/lib/App/Yath/Command/db/recent.pm index 76a8f1053..091fa8a8f 100644 --- a/lib/App/Yath/Command/db/recent.pm +++ b/lib/App/Yath/Command/db/recent.pm @@ -7,6 +7,7 @@ our $VERSION = '2.000000'; use parent 'App::Yath::Command::recent'; use Test2::Harness::Util::HashBase; +sub group { ["database", 'history'] } sub summary { "Show a list of recent runs in the database" } sub description { diff --git a/lib/App/Yath/Command/db/sweeper.pm b/lib/App/Yath/Command/db/sweeper.pm index 5914b820b..32463d022 100644 --- a/lib/App/Yath/Command/db/sweeper.pm +++ b/lib/App/Yath/Command/db/sweeper.pm @@ -10,7 +10,7 @@ use App::Yath::Schema::Util qw/schema_config_from_settings/; sub summary { "Sweep a database" } sub description { "Deletes old data from a database" } -sub group { "db" } +sub group { "database" } use parent 'App::Yath::Command'; use Getopt::Yath; diff --git a/lib/App/Yath/Command/db/sync.pm b/lib/App/Yath/Command/db/sync.pm index afe25782a..0ade0b28d 100644 --- a/lib/App/Yath/Command/db/sync.pm +++ b/lib/App/Yath/Command/db/sync.pm @@ -14,7 +14,7 @@ use Test2::Harness::Util::HashBase; sub summary { "Sync runs and associated data from one db to another" } sub description { "Sync runs and associated data from one db to another" } -sub group { "db" } +sub group { "database" } sub cli_args { "" } diff --git a/lib/App/Yath/Command/failed.pm b/lib/App/Yath/Command/failed.pm index d67bba76f..c1ffa36af 100644 --- a/lib/App/Yath/Command/failed.pm +++ b/lib/App/Yath/Command/failed.pm @@ -23,7 +23,7 @@ option_group {group => 'failed', category => 'Command Options'} => sub { sub summary { "Show the failed tests from an event log" } -sub group { 'log' } +sub group { 'log parsing' } sub cli_args { "[--] event_log.jsonl[.gz|.bz2]" } diff --git a/lib/App/Yath/Command/help.pm b/lib/App/Yath/Command/help.pm index 474c3a5dd..b7fc89457 100644 --- a/lib/App/Yath/Command/help.pm +++ b/lib/App/Yath/Command/help.pm @@ -10,6 +10,7 @@ use parent 'App::Yath::Command'; use Test2::Harness::Util::HashBase qw/<_command_info_hash/; use Test2::Harness::Util qw/find_libraries mod2file/; +use App::Yath::Util qw/paged_print/; use List::Util(); use File::Spec(); @@ -30,6 +31,7 @@ option_group {group => 'help', category => "Help Options"} => sub { type => 'Count', short => 'v', description => "Show commands that would normally be omitted such as internal and deprecated", + initialize => 0, ); }; @@ -68,7 +70,11 @@ sub command_info_hash { next if $internal && !$hs->verbose; my $name = $lib->name; my $group = $internal ? 'z internal only' : $lib->group; - push @{$commands{$group}} => [$name, $lib->summary]; + $group = [$group] unless ref $group; + for my $g (@$group) { + next if $g =~ m/deprecated/ && !$hs->verbose; + push @{$commands{$g}} => [$name, $hs->verbose ? ($lib) : (), $lib->summary]; + } } return $self->{+_COMMAND_INFO_HASH} = \%commands; @@ -82,25 +88,37 @@ sub run { my $script = File::Spec->abs2rel($self->settings->yath->script // $0); - print "\nUsage: $script help [-v] [COMMAND]\n"; + paged_print( + "\nUsage: $script help [-v] [COMMAND]\n", + $self->command_table, + ); + + return 0; +} + +sub command_table { + my $self = shift; my $command_info_hash = $self->command_info_hash; - for my $group (sort keys %$command_info_hash) { + + my $out = ""; + + for my $group (reverse sort keys %$command_info_hash) { my $set = $command_info_hash->{$group}; my $printable = $group; $printable =~ s/^\s+//g; $printable =~ s/\s+$//g; - $printable =~ s/^z\s+//g; - print "\n\n" . ucfirst($printable) . " commands:\n"; + $printable =~ s/^z\s+//ig; + $printable =~ s/^z-//ig; + $out .= "\n" . uc($printable) . " COMMANDS:\n"; - my $table = Term::Table->new( - rows => [ sort { $a->[0] cmp $b->[0] } @$set ], - ); - print map { "$_\n" } $table->render; + my $rows = [ sort { $a->[0] cmp $b->[0] } @$set ]; + my $table = Term::Table->new(rows => $rows); + $out .= join '' => map { "$_\n" } $table->render; } - return 0; + return $out; } sub command_help { @@ -113,7 +131,7 @@ sub command_help { my $app = App::Yath->new(command => $cmd_class, settings => $self->settings); $app->options->include($cmd_class->options); - print $app->cli_help(); + paged_print($app->cli_help()); return 0; } diff --git a/lib/App/Yath/Command/init.pm b/lib/App/Yath/Command/init.pm index 89678b212..56e2200b0 100644 --- a/lib/App/Yath/Command/init.pm +++ b/lib/App/Yath/Command/init.pm @@ -9,7 +9,7 @@ our $VERSION = '2.000000'; use Test2::Harness::Util qw/open_file/; use App::Yath::Util qw/is_generated_test_pl/; -sub group { 'zinit' } +sub group { 'z-init' } sub summary { "Create/update test.pl to run tests via Test2::Harness" } diff --git a/lib/App/Yath/Command/kill.pm b/lib/App/Yath/Command/kill.pm index 17ade2cb1..b04263cf8 100644 --- a/lib/App/Yath/Command/kill.pm +++ b/lib/App/Yath/Command/kill.pm @@ -11,7 +11,7 @@ use Test2::Harness::Util::HashBase; sub group { 'daemon' } -sub summary { "Kill the runner and any running or pending tests" } +sub summary { "Immediately kill the runner and any running or pending tests" } sub cli_args { "" } sub description { diff --git a/lib/App/Yath/Command/recent.pm b/lib/App/Yath/Command/recent.pm index f2fad143a..4d8721660 100644 --- a/lib/App/Yath/Command/recent.pm +++ b/lib/App/Yath/Command/recent.pm @@ -20,9 +20,9 @@ include_options( 'App::Yath::Options::DB', ); -sub summary { "Show a list of recent runs (using logs, database and/or server" } +sub summary { "Show a list of recent runs (using logs, database and/or web server)" } -sub group { 'recent' } +sub group { 'history' } sub cli_args { "" } diff --git a/lib/App/Yath/Command/replay.pm b/lib/App/Yath/Command/replay.pm index 0c4b0913a..6c761c4e2 100644 --- a/lib/App/Yath/Command/replay.pm +++ b/lib/App/Yath/Command/replay.pm @@ -39,7 +39,7 @@ sub load_plugins { 0 } sub load_resources { 0 } sub args_include_tests { 0 } -sub group { 'log' } +sub group { 'log parsing' } sub summary { "Replay a test run from an event log" } diff --git a/lib/App/Yath/Command/speedtag.pm b/lib/App/Yath/Command/speedtag.pm index b329c180f..fb715cff4 100644 --- a/lib/App/Yath/Command/speedtag.pm +++ b/lib/App/Yath/Command/speedtag.pm @@ -47,7 +47,7 @@ option_group {group => 'speedtag', category => 'Speedtag Options'} => sub { ); }; -sub group { 'log' } +sub group { 'log parsing' } sub summary { "Tag tests with duration (short medium long) using a source log" } diff --git a/lib/App/Yath/Command/stop.pm b/lib/App/Yath/Command/stop.pm index 727b9e406..d86f6df28 100644 --- a/lib/App/Yath/Command/stop.pm +++ b/lib/App/Yath/Command/stop.pm @@ -11,7 +11,7 @@ use Test2::Harness::Util::HashBase; sub group { 'daemon' } -sub summary { "Kill the runner and any running or pending tests" } +sub summary { "Wait for running tests to complete, then end runner and abort any pending tests" } sub cli_args { "" } sub description { diff --git a/lib/App/Yath/Command/times.pm b/lib/App/Yath/Command/times.pm index bb7cb0b38..7901d7420 100644 --- a/lib/App/Yath/Command/times.pm +++ b/lib/App/Yath/Command/times.pm @@ -21,7 +21,7 @@ include_options( sub summary { "Get times from a test log" } -sub group { 'log' } +sub group { 'log parsing' } sub cli_args { "[--] event_log.jsonl[.gz|.bz2] [Field1] [Field2]" } diff --git a/lib/App/Yath/Util.pm b/lib/App/Yath/Util.pm index 0204ab288..154517f49 100644 --- a/lib/App/Yath/Util.pm +++ b/lib/App/Yath/Util.pm @@ -13,10 +13,25 @@ use Importer Importer => 'import'; use Config qw/%Config/; use Carp qw/croak/; +BEGIN { + if (eval { require IO::Pager; 1 }) { + *paged_print = sub { + local $SIG{PIPE} = sub {}; + local $ENV{LESS} = "-r"; + my $pager = IO::Pager->new(*STDOUT); + $pager->print($_) for @_; + }; + } + else { + *paged_print = sub { print @_ }; + } +} + our @EXPORT_OK = qw{ is_generated_test_pl find_yath share_dir share_file + paged_print }; sub share_file {