Skip to content

Commit 651fa85

Browse files
committed
Perltidy improvements
The `bin/run-perltidy.pl` script is set up the same as the corresponding webwork2 script to autodetect the pg root directory and no longer depends on the PG_ROOT environment variable. A new perltidyrc file (`bin/perltidy-pg.rc`) is added. This is used for perl tidying pg code. The only differences are that spaces are used for indentation, and a line limit of 80 characters is used instead of 120. The `WeBWorK::PG::Tidy` module is added. This module is a wrapper around the `Perl::Tidy` module that basically does everything the `bin/perltidy-pg.pl` script did before. That script now just calls the exported `pgtidy` method. This module will also be used by the webwork2 PG problem editor to tidy PG problem code.
1 parent 2fb9715 commit 651fa85

File tree

5 files changed

+175
-90
lines changed

5 files changed

+175
-90
lines changed

.perltidyrc

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
# PBP .perltidyrc file
2-
-l=120 # Max line width is 120 cols
3-
-et=4 # Use tabs instead of spaces.
4-
-i=4 # Indent level is 4 cols
5-
-ci=4 # Continuation indent is 4 cols
6-
-b # Write the file inline and create a .bak file
7-
-vt=0 # Minimal vertical tightness
8-
-cti=0 # No extra indentation for closing brackets
9-
-pt=2 # Maximum parenthesis tightness
10-
-bt=1 # Medium brace tightness
11-
-sbt=1 # Medium square bracket tightness
12-
-bbt=1 # Medium block brace tightness
13-
-nsfs # No space before semicolons
14-
-nolq # Don't outdent long quoted strings
15-
-mbl=1 # Do not allow multiple empty lines
16-
-ce # Cuddled else
17-
-cb # Cuddled blocks
18-
-nbbc # Do not add blank lines before full length comments
19-
-nbot # No line break on ternary
20-
-nlop # No logical padding (this causes mixed tabs and spaces)
21-
-wn # Weld nested containers
22-
-xci # Extended continuation indentation
2+
-l=120 # Max line width is 120 cols
3+
-et=4 # Use tabs instead of spaces.
4+
-i=4 # Indent level is 4 cols
5+
-ci=4 # Continuation indent is 4 cols
6+
-b # Write the file inline and create a .bak file
7+
-vt=0 # Minimal vertical tightness
8+
-cti=0 # No extra indentation for closing brackets
9+
-pt=2 # Maximum parenthesis tightness
10+
-bt=1 # Medium brace tightness
11+
-sbt=1 # Medium square bracket tightness
12+
-bbt=1 # Medium block brace tightness
13+
-nsfs # No space before semicolons
14+
-nolq # Don't outdent long quoted strings
15+
-mbl=1 # Do not allow multiple empty lines
16+
-ce # Cuddled else
17+
-cb # Cuddled blocks
18+
-nbbc # Do not add blank lines before full length comments
19+
-nbot # No line break on ternary
20+
-nlop # No logical padding (this causes mixed tabs and spaces)
21+
-wn # Weld nested containers
22+
-xci # Extended continuation indentation
2323
-vxl='q' # No vertical alignment of qw quotes

bin/perltidy-pg.pl

Lines changed: 9 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ =head1 NAME
2020
2121
=head1 SYNOPSIS
2222
23-
pg-perltidy.pl [options] file1 file2 ...
23+
pg-perltidy.pl [options] file1 file2 ...
2424
2525
=head1 DESCRIPTION
2626
@@ -32,74 +32,21 @@ =head1 OPTIONS
3232
perltidy documentation for details.
3333
3434
Note that if the -pro=file option is not given, then this script will attempt to
35-
use the .perltidyrc file in the PG root directory for this option. For this to
36-
work the PG_ROOT environment variable must be set, and the .perltidyrc file in
37-
the PG root directory must be readable.
35+
use the perltidy-pg.rc file in the PG bin directory for this option. For this to
36+
work the the perltidy-pg.rc file in the PG bin directory must be readable.
3837
3938
=cut
4039

4140
use strict;
4241
use warnings;
4342

4443
use Perl::Tidy;
44+
use Mojo::File qw(curfile);
4545

46-
# Apply the same preprocessing as the PG Translator, except for the removal of everything after ENDDOCUMENT.
47-
my $prefilter = sub {
48-
my $evalString = shift // '';
49-
50-
$evalString =~ s/\n\h*END_TEXT[\h;]*\n/\nEND_TEXT\n/g;
51-
$evalString =~ s/\n\h*END_PGML[\h;]*\n/\nEND_PGML\n/g;
52-
$evalString =~ s/\n\h*END_PGML_SOLUTION[\h;]*\n/\nEND_PGML_SOLUTION\n/g;
53-
$evalString =~ s/\n\h*END_PGML_HINT[\h;]*\n/\nEND_PGML_HINT\n/g;
54-
$evalString =~ s/\n\h*END_SOLUTION[\h;]*\n/\nEND_SOLUTION\n/g;
55-
$evalString =~ s/\n\h*END_HINT[\h;]*\n/\nEND_HINT\n/g;
56-
$evalString =~ s/\n\h*BEGIN_TEXT[\h;]*\n/\nSTATEMENT\(EV3P\(<<'END_TEXT'\)\);\n/g;
57-
$evalString =~ s/\n\h*BEGIN_PGML[\h;]*\n/\nSTATEMENT\(PGML::Format2\(<<'END_PGML'\)\);\n/g;
58-
$evalString =~ s/\n\h*BEGIN_PGML_SOLUTION[\h;]*\n/\nSOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);\n/g;
59-
$evalString =~ s/\n\h*BEGIN_PGML_HINT[\h;]*\n/\nHINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);\n/g;
60-
$evalString =~ s/\n\h*BEGIN_SOLUTION[\h;]*\n/\nSOLUTION\(EV3P\(<<'END_SOLUTION'\)\);\n/g;
61-
$evalString =~ s/\n\h*BEGIN_HINT[\h;]*\n/\nHINT\(EV3P\(<<'END_HINT'\)\);\n/g;
62-
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_TIKZ[\h;]*\n/\n$1->tex\(<<END_TIKZ\);\n/g;
63-
$evalString =~ s/\n\h*END_TIKZ[\h;]*\n/\nEND_TIKZ\n/g;
64-
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_LATEX_IMAGE[\h;]*\n/\n$1->tex\(<<END_LATEX_IMAGE\);\n/g;
65-
$evalString =~ s/\n\h*END_LATEX_IMAGE[\h;]*\n/\nEND_LATEX_IMAGE\n/g;
66-
67-
$evalString =~ s/\\/\\\\/g;
68-
$evalString =~ s/~~/\\/g;
69-
70-
return $evalString;
71-
};
72-
73-
# Reverse the above preprocessing after perltidy is run. This does not reverse the clean up of
74-
# horizontal whitespace and semicolons done in the preprocessing stage.
75-
my $postfilter = sub {
76-
my $evalString = shift // '';
77-
78-
$evalString =~ s/\h*STATEMENT\(EV3P\(<<'END_TEXT'\)\);/BEGIN_TEXT/g;
79-
$evalString =~ s/\h*STATEMENT\(PGML::Format2\(<<'END_PGML'\)\);/BEGIN_PGML/g;
80-
$evalString =~ s/\h*SOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);/BEGIN_PGML_SOLUTION/g;
81-
$evalString =~ s/\h*HINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);/BEGIN_PGML_HINT/g;
82-
$evalString =~ s/\h*SOLUTION\(EV3P\(<<'END_SOLUTION'\)\);/BEGIN_SOLUTION/g;
83-
$evalString =~ s/\h*HINT\(EV3P\(<<'END_HINT'\)\);/BEGIN_HINT/g;
84-
$evalString =~ s/(.*)->tex\(<<END_TIKZ\);/$1->BEGIN_TIKZ/g;
85-
$evalString =~ s/(.*)->tex\(<<END_LATEX_IMAGE\);/$1->BEGIN_LATEX_IMAGE/g;
86-
87-
# Care is needed to reverse the preprocessing here.
88-
# First in all occurences of an odd number of backslashes the first backslash is replaced with two tildes.
89-
$evalString =~ s/(?<!\\) \\ ((?:\\{2})*) (?!\\)/~~$1/gx;
90-
# Then all pairs of backslashes are replaced with a single backslash.
91-
$evalString =~ s/\\\\/\\/g;
92-
93-
return $evalString;
94-
};
95-
96-
# Get the options that were passed. If the profile option was not set, then set it to be the
97-
# .perltidyrc file in the root pg directory.
98-
my %options;
99-
Perl::Tidy::perltidy(dump_options => \%options);
100-
unshift(@ARGV, "-pro=$ENV{PG_ROOT}/.perltidyrc")
101-
if !defined $options{profile} && defined $ENV{PG_ROOT} && -r "$ENV{PG_ROOT}/.perltidyrc";
102-
103-
Perl::Tidy::perltidy(prefilter => $prefilter, postfilter => $postfilter);
46+
use lib curfile->dirname->dirname . '/lib';
47+
48+
use WeBWorK::PG::Tidy qw(pgtidy);
49+
50+
pgtidy();
10451

10552
1;

bin/perltidy-pg.rc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# PBP .perltidyrc file
2+
-l=80 # Max line width is 80 cols
3+
-i=4 # Indent level is 4 cols
4+
-ci=4 # Continuation indent is 4 cols
5+
-b # Write the file inline and create a .bak file
6+
-vt=0 # Minimal vertical tightness
7+
-cti=0 # No extra indentation for closing brackets
8+
-pt=2 # Maximum parenthesis tightness
9+
-bt=1 # Medium brace tightness
10+
-sbt=1 # Medium square bracket tightness
11+
-bbt=1 # Medium block brace tightness
12+
-nsfs # No space before semicolons
13+
-nolq # Don't outdent long quoted strings
14+
-mbl=1 # Do not allow multiple empty lines
15+
-ce # Cuddled else
16+
-cb # Cuddled blocks
17+
-nbbc # Do not add blank lines before full length comments
18+
-nbot # No line break on ternary
19+
-nlop # No logical padding (this causes mixed tabs and spaces)
20+
-wn # Weld nested containers
21+
-xci # Extended continuation indentation
22+
-vxl='q' # No vertical alignment of qw quotes

bin/run-perltidy.pl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ =head1 DESCRIPTION
2828
2929
=head1 OPTIONS
3030
31-
For this script to work the PG_ROOT environment variable must be set, and the
32-
.perltidyrc file in the PG root directory must be readable.
31+
For this script to work the the .perltidyrc file in the pg root directory
32+
must be readable. Note that the pg root directory is automatically detected.
3333
3434
This script accepts all of the options that are accepted by perltidy. See the
3535
perltidy documentation for details.
@@ -47,7 +47,7 @@ =head1 OPTIONS
4747
4848
Finally, if no files are passed on the command line, then perltidy will be
4949
executed on all files with the extensions C<.pl>, C<.pm>, or C<.t> in the
50-
PG_ROOT directory. If files are passed on the command line, then perltidy will
50+
pg root directory. If files are passed on the command line, then perltidy will
5151
only be executed on the listed files.
5252
5353
=cut
@@ -58,11 +58,15 @@ =head1 OPTIONS
5858

5959
use Perl::Tidy;
6060
use File::Find qw(find);
61+
use Mojo::File qw(curfile);
62+
63+
my $pg_root = curfile->dirname->dirname;
6164

6265
die "Version 20220613 or newer of perltidy is required for this script.\n"
6366
. "The installed version is $Perl::Tidy::VERSION.\n"
6467
unless $Perl::Tidy::VERSION >= 20220613;
65-
die "The pg directory must be defined in PG_ROOT.\n" unless -e $ENV{PG_ROOT} && -r "$ENV{PG_ROOT}/.perltidyrc";
68+
die "The .perltidyrc file in the pg root directory is not readable.\n"
69+
unless -r "$pg_root/.perltidyrc";
6670

6771
my $verbose = 0;
6872
my (@args, @files);
@@ -84,7 +88,7 @@ =head1 OPTIONS
8488
for (@files) {
8589
push(@args, $_);
8690
say "Tidying file: $_" if $verbose;
87-
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$ENV{PG_ROOT}/.perltidyrc");
91+
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$pg_root/.perltidyrc");
8892
pop(@args);
8993
}
9094
} else {
@@ -106,12 +110,12 @@ =head1 OPTIONS
106110
say "Tidying file: $path" if $verbose;
107111

108112
push(@args, $path);
109-
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$ENV{PG_ROOT}/.perltidyrc");
113+
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$pg_root/.perltidyrc");
110114
pop(@args);
111115
},
112116
no_chdir => 1
113117
},
114-
$ENV{PG_ROOT}
118+
$pg_root
115119
);
116120
}
117121

lib/WeBWorK/PG/Tidy.pm

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
################################################################################
2+
# WeBWorK Online Homework Delivery System
3+
# Copyright &copy; 2000-2023 The WeBWorK Project, https://github.com/openwebwork
4+
#
5+
# This program is free software; you can redistribute it and/or modify it under
6+
# the terms of either: (a) the GNU General Public License as published by the
7+
# Free Software Foundation; either version 2, or (at your option) any later
8+
# version, or (b) the "Artistic License" which comes with this package.
9+
#
10+
# This program is distributed in the hope that it will be useful, but WITHOUT
11+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12+
# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
13+
# Artistic License for more details.
14+
################################################################################
15+
16+
=head1 NAME
17+
18+
WeBWorK::PG::Tidy -- perltidy pg problem files.
19+
20+
=head1 DESCRIPTION
21+
22+
perltidy pg problem files.
23+
24+
=head1 OPTIONS
25+
26+
This module is a wrapper around Perl::Tidy and just calls C<Perl::Tidy::perltidy>.
27+
Any options passed on the command line are passed to Perl::Tidy::perltidy See
28+
the L<Perl::Tidy::perltidy> documentation for details.
29+
30+
Note that if the C<-pro=file> option is not given, then this module will attempt
31+
to use the perltidy-pg.rc file in the PG bin directory for this option. For
32+
this to work the perltidy-pg.rc file in the PG bin directory must be readable.
33+
34+
=cut
35+
36+
package WeBWorK::PG::Tidy;
37+
use parent qw(Exporter);
38+
39+
use strict;
40+
use warnings;
41+
42+
use Perl::Tidy;
43+
use Mojo::File qw(curfile);
44+
45+
our @EXPORT = qw(pgtidy);
46+
47+
my $perltidy_pg_rc = curfile->dirname->dirname->dirname->dirname . '/bin/perltidy-pg.rc';
48+
49+
# Apply the same preprocessing as the PG Translator, except for the removal of everything after ENDDOCUMENT.
50+
my $prefilter = sub {
51+
my $evalString = shift // '';
52+
53+
$evalString =~ s/\n\h*END_TEXT[\h;]*\n/\nEND_TEXT\n/g;
54+
$evalString =~ s/\n\h*END_PGML[\h;]*\n/\nEND_PGML\n/g;
55+
$evalString =~ s/\n\h*END_PGML_SOLUTION[\h;]*\n/\nEND_PGML_SOLUTION\n/g;
56+
$evalString =~ s/\n\h*END_PGML_HINT[\h;]*\n/\nEND_PGML_HINT\n/g;
57+
$evalString =~ s/\n\h*END_SOLUTION[\h;]*\n/\nEND_SOLUTION\n/g;
58+
$evalString =~ s/\n\h*END_HINT[\h;]*\n/\nEND_HINT\n/g;
59+
$evalString =~ s/\n\h*BEGIN_TEXT[\h;]*\n/\nSTATEMENT\(EV3P\(<<'END_TEXT'\)\);\n/g;
60+
$evalString =~ s/\n\h*BEGIN_PGML[\h;]*\n/\nSTATEMENT\(PGML::Format2\(<<'END_PGML'\)\);\n/g;
61+
$evalString =~ s/\n\h*BEGIN_PGML_SOLUTION[\h;]*\n/\nSOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);\n/g;
62+
$evalString =~ s/\n\h*BEGIN_PGML_HINT[\h;]*\n/\nHINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);\n/g;
63+
$evalString =~ s/\n\h*BEGIN_SOLUTION[\h;]*\n/\nSOLUTION\(EV3P\(<<'END_SOLUTION'\)\);\n/g;
64+
$evalString =~ s/\n\h*BEGIN_HINT[\h;]*\n/\nHINT\(EV3P\(<<'END_HINT'\)\);\n/g;
65+
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_TIKZ[\h;]*\n/\n$1->tex\(<<END_TIKZ\);\n/g;
66+
$evalString =~ s/\n\h*END_TIKZ[\h;]*\n/\nEND_TIKZ\n/g;
67+
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_LATEX_IMAGE[\h;]*\n/\n$1->tex\(<<END_LATEX_IMAGE\);\n/g;
68+
$evalString =~ s/\n\h*END_LATEX_IMAGE[\h;]*\n/\nEND_LATEX_IMAGE\n/g;
69+
70+
$evalString =~ s/\\/\\\\/g;
71+
$evalString =~ s/~~/\\/g;
72+
73+
return $evalString;
74+
};
75+
76+
# Reverse the above preprocessing after perltidy is run. This does not reverse the clean up of
77+
# horizontal whitespace and semicolons done in the preprocessing stage.
78+
my $postfilter = sub {
79+
my $evalString = shift // '';
80+
81+
$evalString =~ s/\h*STATEMENT\(EV3P\(<<'END_TEXT'\)\);/BEGIN_TEXT/g;
82+
$evalString =~ s/\h*STATEMENT\(PGML::Format2\(<<'END_PGML'\)\);/BEGIN_PGML/g;
83+
$evalString =~ s/\h*SOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);/BEGIN_PGML_SOLUTION/g;
84+
$evalString =~ s/\h*HINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);/BEGIN_PGML_HINT/g;
85+
$evalString =~ s/\h*SOLUTION\(EV3P\(<<'END_SOLUTION'\)\);/BEGIN_SOLUTION/g;
86+
$evalString =~ s/\h*HINT\(EV3P\(<<'END_HINT'\)\);/BEGIN_HINT/g;
87+
$evalString =~ s/(.*)->tex\(<<END_TIKZ\);/$1->BEGIN_TIKZ/g;
88+
$evalString =~ s/(.*)->tex\(<<END_LATEX_IMAGE\);/$1->BEGIN_LATEX_IMAGE/g;
89+
90+
# Care is needed to reverse the preprocessing here.
91+
# First in all occurences of an odd number of backslashes the first backslash is replaced with two tildes.
92+
$evalString =~ s/(?<!\\) \\ ((?:\\{2})*) (?!\\)/~~$1/gx;
93+
# Then all pairs of backslashes are replaced with a single backslash.
94+
$evalString =~ s/\\\\/\\/g;
95+
96+
return $evalString;
97+
};
98+
99+
sub pgtidy {
100+
my %options = @_;
101+
102+
local @ARGV = @ARGV;
103+
104+
# Get the options that were passed. If the profile option was not set, then set it to be the
105+
# perltidy-pg.rc file in the root pg directory.
106+
Perl::Tidy::perltidy(dump_options => \my %internal_options);
107+
unshift(@ARGV, "-pro=$perltidy_pg_rc") if !defined $internal_options{profile} && -r $perltidy_pg_rc;
108+
109+
return Perl::Tidy::perltidy(prefilter => $prefilter, postfilter => $postfilter, %options);
110+
}
111+
112+
1;

0 commit comments

Comments
 (0)