Perl - Listing the Secret Words

Well, if we want to get all of the secret words, then we could steal some code from the init_words() subroutine

	while (defined($filename = glob("*.secret"))) {
		open (WORDSLIST, $filename) || die "can't open $filename: $!";
		if (-M WORDSLIST < 7.0) {
			chomp ($name);
			$word = <WORDSLIST>;
			chomp ($word);

			[*** NEW STUFF WILL GO HERE ***]

		}
		close (WORDSLIST) || die "couldn't close $filename: $!";
	}

Now we can use Perl's report generating tools.  First, we'll define a format somewhere in the program (usually near the end, like a subroutine).  By the time we get to the place marked [*** NEW STUFF WILL GO HERE ***] in the snippet of code above, we know three things:  the name of the file (in $filename), someone's name (in $name), and that person's secret word (in $word).  Here's what the format could look like:

	format STDOUT =
	@<<<<<<<<<<<<<<< @<<<<<<<<< @<<<<<<<<<<<
	$filename, $name, $word
	.

The format definition begins with format STDOUT =, and ends with a single period.  The two lines between are the format itself.  The first line of this format is a field definition line that specifies the number, length, and type of the fields.  For this format, we have three fields.  The line following a field definition line is always a field value line.  The value line gives a list of expressions that will be evaluated when this format is used, and the results of those expressions will be plugged into the fields defined in the previous line.

We invoke this format with the write function, as follows:

#!/usr/bin/perl
while (defined($filename = glob("*.secret"))) {
	open (WORDSLIST, $filename) || die "can't open $filename: $!";
	if (-M WORDSLIST < 7.0) {
		while ($name = <WORDSLIST>) {
			chomp ($name);
			$word = <WORDSLIST>;
			chomp ($word);
			write; # invoke format STDOUT to STDOUT
		}
	}
	close (WORDSLIST) || die "couldn't close $filename: $!";
}
format STDOUT =
@<<<<<<<<<<<<<<< @<<<<<<<<< @<<<<<<<<<<<
$filename, $name, $word
.

When the format is invoked, Perl evaluates the field expressions and generates a line that it sends to the STDOUT filehandle.  Because write is invoked once each time through the loop, we'll get a series of lines with text in columns, one line for each secret word entry.

Hmm.  We didn't label the columns.  That's easy enough.  We just need to add a top-of-page format, like so:

format STDOUT_TOP =
Page @<<
$%

Filename         Name       Word
================ ========== ============
.

This format is named STDOUT_TOP, and will be used initially at the first invocation of the STDOUT format, and again every time 60 lines of output to STDOUT have been generated.  The column headings here line up with the columns from the STDOUT format, so everything comes out tidy.

The first line of this format shows some constant text (Page) along with a three-character field definition.  The following line is a field value line, here with one expression.  This expression is the $% variable, which holds the number of pages printed - a very useful value in top-of-page formats.

The third line of the format is blank.  Because this line does not contain any fields, the line following it is not a field value line.  This blank line is copied directly to the output, creating a blank line between the page number and the column headers below.

The last two lines of the format also contain no fields, so they are copied as is directly to the output.  So this format generates four lines, one of which has a part that changes from page to page.  Just tack this format definition onto the previous program to get it to work.  Perl notices the top-of-page format automatically.

As you might already imagine, Perl allows for more sophistication in the report generating tools.  In later lessons, we'll revisit Formats again and see fields that are centered or right-justified as well as a filled paragraph area.

Considering that the *.secret files may become outdated, as we're scanning through the current directory, let's go one more step and rename any old files to old.*.secret.  That way a directory listing will quickly show us which files are too old, simply by name.

Do you suppose that Perl has a rename function which we could use?

See you next lesson!