In the last article I told you we'll add a manual to our calculator, let's see some ways to interact with the Perl documentation system to achieve this.
The command to look at calculator's documentation will be "man", and as I assume most people should have used perldoc, I shall start by using this command to display a manual.
Perl has long has the ability to execute system commands in several ways, one of which is the "`" operator, if you write something like:
1 my @out = `ls -l`the array @out will end with each of the output lines of the command, you can also execute commands and use its output as input to a program using open:
1 open $fd, "-|", "ls -ls" or die "Error: $!" 2 while ( readline $fd ) { 3 # $_ contiene una lĂnea de la salida del comando 4 }which is surprising, though not highly recommended in these days, although I use it over and over at work, where I solve lots of things just doing little programs in Perl.
But today I am interested in the "system" function that I will use as the first way to add a manual for our calculator. Since I don' t want to complicate the issue showing how to write a manual, I will use the Statistics::Descriptive's manual, the solution is to add a line to last article's program:
21 when ("man") { system("perldoc Statistics::Descriptive") }and that's it, such is Perl, there is nothing easier, some may say it is dirty, but it was definitively easy. When we use "system" perl sends the command directly to the shell, so is better to use it in this way:
21 when ("man") { system("/usr/bin/perldoc", "Statistics::Descriptive") }when system receives a list, perl executes the first element and pass the remaining ones as arguments, avoiding some security glitches that could occur, but the command isn't searched through the PATH, so you must pass the full path to the command executable.
It is not a big surprise that the perldoc command is also written in Perl, so we probably can reuse the code for this program in our calculator. Looking into the program you will realize that perldoc is a very simple program, in fact, the two important lines are:
1 use Pod::Perldoc; 2 Pod::Perldoc->run();So all the perldoc's functionality is packed inside a Perl object!, this is a major pattern of Perl culture, allowing any application to be easily reused by another, and that is exactly what we want do, unfortunately someone forgot to document
Pod::Perldoc
so I got to look at the source code for hints about how may I integrate it into the calculator, I came up with the following:21 when ("man") { Pod::Perldoc->new(args => ["Statistics::Descriptive"])->process }and of course we must declare the use of the class, which I did at the beginning of the program:
6 use Pod::Perldoc;The real job was to learn how
Pod::Perldoc
works and it took me less than 2 minutes to get there using the excelent perl debugger.Finally I took some time to refactor the code a little bit, improve the "help" command, and left the full program like this:
1 #!/usr/bin/perl 2 3 use Modern::Perl; 4 use Scalar::Util qw( looks_like_number ); 5 use Statistics::Descriptive; 6 use Pod::Perldoc; 7 8 use constant SYNTAX_ERROR => "Error: tipee 'help' para ayuda"; 9 10 my %FUNCS = map { $_ => 1 } qw( sum mean count variance standard_deviation 11 min mindex max maxdex sample_range median harmonic_mean geometric_mean 12 mode trimmed_mean clear ); 13 14 my @COMMANDS = qw( exit quit help man ); 15 16 sub help { 17 say "Comandos: " . join( ", ", @COMMANDS ); 18 say "Funciones: " . join( ", ", keys %FUNCS ); 19 } 20 21 sub man { 22 Pod::Perldoc->new(args => \@_)->process 23 } 24 25 my $s = Statistics::Descriptive::Full->new(); 26 while (1) { 27 print "Listo> "; 28 my $command = readline(STDIN) // last; 29 $command =~ s/^\s+//; $command =~ s/\s+$//; 30 given ($command) { 31 when ( looks_like_number($_) ) { $s->add_data($command) } 32 when (%FUNCS) { say "$command = " . $s->$command } 33 when ("man") { man "Statistics::Descriptive" } 34 when ( [ "exit", "quit" ] ) { last } 35 when ("help") { help } 36 default { say SYNTAX_ERROR } 37 } 38 }In the next article I will add more features to make calculator more user friendly.
No comments:
Post a Comment