Skip to content

Commit 06145e9

Browse files
committed
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. These changes are used to implement sample problem editing in the PG problem editor for webwork2 in a corresponding pull request.
1 parent c50623b commit 06145e9

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

lib/SampleProblemParser.pm

+40-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use File::Basename qw(dirname basename);
2525
use File::Find qw(find);
2626
use Pandoc;
2727

28-
our @EXPORT_OK = qw(parseSampleProblem generateMetadata);
28+
our @EXPORT_OK = qw(parseSampleProblem generateMetadata getSampleProblemCode);
2929

3030
=head1 NAME
3131
@@ -150,7 +150,7 @@ sub generateMetadata ($problem_dir, %options) {
150150
say "Reading file: $File::Find::name" if $options{verbose};
151151

152152
if ($File::Find::name =~ /\.pg$/) {
153-
my $metadata = parseMetadata($File::Find::name, $problem_dir, $options{macro_locations});
153+
my $metadata = parseMetadata($File::Find::name, $problem_dir);
154154
unless (@{ $metadata->{types} }) {
155155
warn "The type of sample problem is missing for $File::Find::name.";
156156
return;
@@ -175,7 +175,7 @@ my @macros_to_skip = qw(
175175
PGstandard.pl
176176
);
177177

178-
sub parseMetadata ($path, $problem_dir, $macro_locations = {}) {
178+
sub parseMetadata ($path, $problem_dir) {
179179
open(my $FH, '<:encoding(UTF-8)', $path) or do {
180180
warn qq{Could not open file "$path": $!};
181181
return {};
@@ -228,4 +228,41 @@ sub parseMetadata ($path, $problem_dir, $macro_locations = {}) {
228228
return $metadata;
229229
}
230230

231+
=head2 C<getSampleProblemCode>
232+
233+
Parse a PG file with extra documentation comments and strip that all out
234+
returning the clean problem code. This returns the same code that the
235+
C<parseSampleProblem> returns, except at much less expense as it does not parse
236+
the documentation, it does not require that the metadata be parsed first, and it
237+
does not need macro POD information.
238+
239+
=cut
240+
241+
sub getSampleProblemCode ($file) {
242+
my $filename = basename($file);
243+
open(my $FH, '<:encoding(UTF-8)', $file) or do {
244+
warn qq{Could not open file "$file": $!};
245+
return '';
246+
};
247+
my @file_contents = <$FH>;
248+
close $FH;
249+
250+
my (@code_rows, $inCode);
251+
252+
while (my $row = shift @file_contents) {
253+
chomp($row);
254+
$row =~ s/\t/ /g;
255+
if ($row =~ /^#:(.*)?/) {
256+
# This is documentation so skip it.
257+
} elsif ($row =~ /^\s*(END)?DOCUMENT.*$/) {
258+
$inCode = $1 ? 0 : 1;
259+
push(@code_rows, $row);
260+
} elsif ($inCode) {
261+
push(@code_rows, $row);
262+
}
263+
}
264+
265+
return join("\n", @code_rows);
266+
}
267+
231268
1;

0 commit comments

Comments
 (0)