I want my script to print a help message when it is run with the --help command line option. Based on the Getopt::Std documentation, this sub should do the trick:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
use Getopt::Std;
sub HELP_MESSAGE {
say "HELP MESSAGE";
}
But it prints nothing. I also tried adding this, out of curiosity:
for (#ARGV) {
HELP_MESSAGE() if /--help/;
}
It actually works, but seems rather sloppy. I know using the -h flag would be quite simple, but I would like to have both.
The documentation of Getopt::Std says
If - is not a recognized switch letter, getopts() supports arguments --help and --version. If main::HELP_MESSAGE() and/or main::VERSION_MESSAGE() are defined, they are called; ...
So try this:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
use Getopt::Std;
$Getopt::Std::STANDARD_HELP_VERSION = 1;
our $VERSION = 0.1;
getopts(''); # <<< You forgot this line, and `getopt()` DOES NOT work
sub HELP_MESSAGE {
say "HELP MESSAGE";
}
Test run:
$ ./t00.pl --help
./t00.pl version 0.1 calling Getopt::Std::getopts (version 1.07),
running under Perl version 5.16.3.
HELP MESSAGE
Related
I am migrating an old toolchain to a new system and now I get plenty of notifications given is experimental or when is experimental.
$ perl -e 'use v5.10; given (12) { when (12) { print "Hello World" }}'
given is experimental at -e line 1.
when is experimental at -e line 1.
Hello World
I would like my new system to be fully compatible with the old one. By this I mean the exact same output.
Is there a way to mute these notifications without touching the oneliners nor the scripts?
First of all, note that smartmatching will be removed or changed in a backwards incompatible manner. This may affect your given statements.
To use given+when without warnings, one need the following:
# 5.10+
use feature qw( switch );
no if $] >= 5.018, warnings => qw( experimental::smartmatch );
or
# 5.18+
use feature qw( switch );
no warnings qw( experimental::smartmatch );
experimental provides a shortcut for those two statements.
use experimental qw( switch );
Finally, you ask how to add this to your programs without changing them (and presumably without changing Perl). That leaves monkeypatching.
I wouldn't recommend it. It's far easier to write a couple of one-liners to automatically fix up your programs that rewritting Perl's behaviour on the fly.
But if you want to go in that direction, the simplest solution is probably to write a $SIG{__WARN__} handler that filters out the undesired warnings.
$SIG{__WARN__} = sub {
warn($_[0]) if $_[0] !~ /^(?:given|when) is experimental at /;
};
(Of course, that won't work if your program makes use of $SIG{__WARN__} already.)
To get it loaded without changing your programs or one-liners, all you have to do is place the patch in a module, and tell Perl to load the module as follows:
export PERL5OPT=-MMonkey::SilenceSwitchWarning
$ cat Monkey/SilenceSwitchWarning.pm
package Monkey::SilenceSwitchWarning;
use strict;
use warnings;
$SIG{__WARN__} = sub {
warn($_[0]) if $_[0] !~ /^(?:given|when) is experimental at /;
};
1;
$ perl -e 'use v5.10; given (12) { when (12) { print "Hello World\n" }}'
given is experimental at -e line 1.
when is experimental at -e line 1.
Hello World
$ export PERL5OPT=-MMonkey::SilenceSwitchWarning
$ perl -e 'use v5.10; given (12) { when (12) { print "Hello World\n" }}'
Hello World
no warnings 'experimental';
...works in version 5.22 at least.
I have a Perl module named McuEnc.pm which is located at /home/eric/temp directory:
package McuEnc;
use 5.010;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK = qw(key_enc data_enc data_dec);
sub key_enc { some code }
sub data_enc { some code }
sub data_dec { some code }
1;
I have a Perl script named test.pl which is also located at /home/eric/temp directory:
use 5.010;
use strict;
use warnings;
use McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
I have changed working directory to /home/eric/temp. Now if I run test.pl script, it runs correctly. But if I create a new directory /home/eric/temp/My and move the McuEnc.pm file into it and then modify the test.pl script as follwoing:
use 5.010;
use strict;
use warnings;
use My::McuEnc qw(key_enc data_enc data_dec);
key_enc("1111");
...
then I'm getting the following error when I run test.pl again:
Undefined subroutine &main::key_enc called at ./test line 6.
However, I can still call the subroutine correctly with:
McuEnc::key_enc("1111");
So why I'm getting the error message? what is wrong?
This was answered by Sobrique in the comments, but it was never posted as an official answer:
"The use statement doesn't match the package statement. Try package My::McuEnc instead"
I'm trying to get color (colour) output using prove / TAP::Harness with Active state Perl on Windows 7.
The actual tests run fine, its just that there is no colour output.
I get a similar problem using Strawberry Perl and WinXP.
I am unable to use a *nix and cygwin or other thirdparty xterm both of which do
colour the output.
I know its a little picky thing but I think I've become addicted to the "green" :-)
Is there a simple fix? - couldn't see anything on the Activate state site - I was thinking of raising a bug.
Any guidance on debugging or what to check?
Is it worth writing my own formatter?
Thanks in advance for your help.
More detail on installed modules and approaches tried...
These are installed and to the best of my knowledge working
Win32::Console::ANSI;
Term::ANSIColor;
This test script worked:
#!/usr/bin/perl
use strict;
use warnings;
use Win32::Console::ANSI;
use Term::ANSIColor;
print "One fish\n";
print "Two fish\n";
print color("red"), "Red Fish\n", color("reset");
print color("blue"), "Blue Fish\n", color("reset");
I have tried:
prove
prove -c
and using the following test harness programs with and without formatter but
I was under the assumption colour was on by default.
#!/usr/bin/perl
use strict;
use warnings;
use TAP::Harness;
my #tests = glob( 't/*.t' );
my $harness = TAP::Harness->new();
$harness->runtests( #tests );
I have also install the HTML formatter and that appears to be working.
prove --formatter=TAP::Formatter::HTML
Running:
prove --formatter=TAP::Formatter::Color
Gives
Can't locate object method "verbosity" via package "TAP::Formatter::Color" at x:/Perl/site/lib/TAP/Harness.pm line 679.
Thanks
Mike
It appears to be a bug1 in TAP::Formatter::Color. It's attaching to the console's STDOUT handle but the messages that should be colored are on STDERR.
This:
my $console = Win32::Console->new( STD_OUTPUT_HANDLE() );
Should be this instead:
my $console = Win32::Console->new( STD_ERROR_HANDLE() );
Also, despite what the documentation says, --color is not the default on Windows. App::Prove (which is what's behind the "prove" executable) explicitly sets the default to false for Windows:
sub _color_default {
my $self = shift;
return -t STDOUT && !$ENV{HARNESS_NOTTY} && !IS_WIN32;
}
1. The bug was fixed in Test::Harness v3.41
Is there a standard way of adding a help function to a script? The simplest way would maybe to take an argument and print some text if it's "-help" or something. Does anyone have any examples on how to do this?
Thanks!
Consider Getopt::Long plus Pod::Usage. My usual pattern for writing CLI tools:
#!/usr/bin/env perl
# ABSTRACT: Short tool description
# PODNAME: toolname
use autodie;
use strict;
use utf8;
use warnings qw(all);
use Getopt::Long;
use Pod::Usage;
# VERSION
=head1 SYNOPSIS
toolname [options] files
=head1 DESCRIPTION
...
=cut
GetOptions(
q(help) => \my $help,
q(verbose) => \my $verbose,
) or pod2usage(q(-verbose) => 1);
pod2usage(q(-verbose) => 1) if $help;
# Actual code below
easy to use this :
if( $ARGV[0] eq '-h' || $ARGV[0] eq '-help')
{
help();
exit;
}
sub help { print "My help blah blah blah\n";
}
Take a look at https://github.com/qazwart/SVN-Watcher-Hook/blob/master/svn-watch.pl. I use a technique to combine the Getopt::Long module and the Pod::Usage module.
The main action occurs in lines 97 through 106 and in lines 108 through 110.
The Getopt::Long is a very common module to use since it handles command line arguments with easy. Using Pod documentation is rarer. However, all CPAN modules and all Perl built in modules use Pod documentation, so if you don't know it, learn it. POD is not very difficult to learn, and it's built into Perl, so all Perl programs can be self-documenting. You can print out the POD documentation of any program by using the perldoc command. Try this:
$ perldoc File::Find
You can also use the pod2html, pod2text and other types of translation commands to print POD documentation into HTML, etc.
Before I knew about POD, I would put something like this at the top of my program:
########################################################
# USAGE
#
my $USAGE =<<USAGE;
Usage:
foo [ -baz -fu <bar>] [-help]
where:
baz: yadda, yadda, yadda
fu: yadda, yadda, yadda
help: Prints out this helpful message
USAGE
#
######################################################
Then, in my program, I could do this:
if ($help) {
print "$USAGE\n";
exit 0;
}
This way, someone could look at the code and read the usage text. This would also be the same text that would print out when you used the -help parameter.
The way I do this is to utilise Getopt::Std to find an -h flag from the command line arguments.
use strict;
use warnings;
use Getopt::Std;
my %args;
getopts('h', \%args);
my $help = "help goes here. You can use
more than one line to format the text";
die $help if $args{h};
# otherwise continue with script...
A more sophisticated approach is to use POD::usage, although I have not tried this way personally.
I have a failing test on 5.8.8, I don't understand why, esp when it works in more recent versions (perhaps it was just a bug) (here's a link to the full code)
use strict;
use warnings;
use Test::More;
my $fname = 'Fo';
my $content = do { local $/ ; <DATA> };
like $content, qr/^$fname $/xms, q[includes first name];
done_testing;
__DATA__
use strict;
use warnings;
use Test::More;
# generated by Dist::Zilla::Plugin::Test::PodSpelling bootstrapped version
eval "use Test::Spelling 0.12; use Pod::Wordlist::hanekomu; 1" or die $#;
add_stopwords(<DATA>);
all_pod_files_spelling_ok('bin', 'lib');
__DATA__
Fo
oer
bar
on all recent versions of perl this works fine. but in 5.8.8 the test fails. I found that by removing the ^ and $ the code works, its like Perls regex engine is ignoring the /m but the documentation says it was supported.
Why does this not work? and what is the most correct way to fix it? (note: I believe that the test should check that these elements are on a line by themselves )
This is bug RT#7781. It was fixed in 5.8.9 and 5.10.0.
Workarounds:
qr/^/m is equivalent to qr/(?:^|(?<=\n))/
qr/$/m is equivalent to qr/(?=\n|\z)/