From 3449cb393ff0717ebdc6cdf4e1c1d41154da718a Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Wed, 19 Feb 2025 07:01:12 -0600 Subject: [PATCH] Add a `getSampleProblemCode` method to `SampleProblemParser.pm`. This method is much more efficient than calling `parseSampleProblem` to obtain the code as it does not parse documentation, does not require that the sample problem metadata be parsed first, and it does not need macro POD information. Note that to obtain the code via the `parseSampleProblem` method, 253 files need to be read and parsed (all sample problems and all macros). The `getSampleProblemCode` method only needs to read 1 file, and the parsing of that is more efficient as well. It should be used if all you want is the code as it does not return the documentation and other data returned by the `parseSampleProblem` method. Also remove the unused `$macro_locations` argument to the `parseMetadata` method. --- lib/SampleProblemParser.pm | 43 +++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/SampleProblemParser.pm b/lib/SampleProblemParser.pm index 2aa29e5df..4eb998cd1 100644 --- a/lib/SampleProblemParser.pm +++ b/lib/SampleProblemParser.pm @@ -25,7 +25,7 @@ use File::Basename qw(dirname basename); use File::Find qw(find); use Pandoc; -our @EXPORT_OK = qw(parseSampleProblem generateMetadata); +our @EXPORT_OK = qw(parseSampleProblem generateMetadata getSampleProblemCode); =head1 NAME @@ -150,7 +150,7 @@ sub generateMetadata ($problem_dir, %options) { say "Reading file: $File::Find::name" if $options{verbose}; if ($File::Find::name =~ /\.pg$/) { - my $metadata = parseMetadata($File::Find::name, $problem_dir, $options{macro_locations}); + my $metadata = parseMetadata($File::Find::name, $problem_dir); unless (@{ $metadata->{types} }) { warn "The type of sample problem is missing for $File::Find::name."; return; @@ -175,7 +175,7 @@ my @macros_to_skip = qw( PGstandard.pl ); -sub parseMetadata ($path, $problem_dir, $macro_locations = {}) { +sub parseMetadata ($path, $problem_dir) { open(my $FH, '<:encoding(UTF-8)', $path) or do { warn qq{Could not open file "$path": $!}; return {}; @@ -228,4 +228,41 @@ sub parseMetadata ($path, $problem_dir, $macro_locations = {}) { return $metadata; } +=head2 C + +Parse a PG file with extra documentation comments and strip that all out +returning the clean problem code. This returns the same code that the +C returns, except at much less expense as it does not parse +the documentation, it does not require that the metadata be parsed first, and it +does not need macro POD information. + +=cut + +sub getSampleProblemCode ($file) { + my $filename = basename($file); + open(my $FH, '<:encoding(UTF-8)', $file) or do { + warn qq{Could not open file "$file": $!}; + return ''; + }; + my @file_contents = <$FH>; + close $FH; + + my (@code_rows, $inCode); + + while (my $row = shift @file_contents) { + chomp($row); + $row =~ s/\t/ /g; + if ($row =~ /^#:(.*)?/) { + # This is documentation so skip it. + } elsif ($row =~ /^\s*(END)?DOCUMENT.*$/) { + $inCode = $1 ? 0 : 1; + push(@code_rows, $row); + } elsif ($inCode) { + push(@code_rows, $row); + } + } + + return join("\n", @code_rows); +} + 1;