Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions .perltidyrc
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# PBP .perltidyrc file
-l=120 # Max line width is 120 cols
-et=4 # Use tabs instead of spaces.
-i=4 # Indent level is 4 cols
-ci=4 # Continuation indent is 4 cols
-b # Write the file inline and create a .bak file
-vt=0 # Minimal vertical tightness
-cti=0 # No extra indentation for closing brackets
-pt=2 # Maximum parenthesis tightness
-bt=1 # Medium brace tightness
-sbt=1 # Medium square bracket tightness
-bbt=1 # Medium block brace tightness
-nsfs # No space before semicolons
-nolq # Don't outdent long quoted strings
-mbl=1 # Do not allow multiple empty lines
-ce # Cuddled else
-cb # Cuddled blocks
-nbbc # Do not add blank lines before full length comments
-nbot # No line break on ternary
-nlop # No logical padding (this causes mixed tabs and spaces)
-wn # Weld nested containers
-xci # Extended continuation indentation
-l=120 # Max line width is 120 cols
-et=4 # Use tabs instead of spaces.
-i=4 # Indent level is 4 cols
-ci=4 # Continuation indent is 4 cols
-b # Write the file inline and create a .bak file
-vt=0 # Minimal vertical tightness
-cti=0 # No extra indentation for closing brackets
-pt=2 # Maximum parenthesis tightness
-bt=1 # Medium brace tightness
-sbt=1 # Medium square bracket tightness
-bbt=1 # Medium block brace tightness
-nsfs # No space before semicolons
-nolq # Don't outdent long quoted strings
-mbl=1 # Do not allow multiple empty lines
-ce # Cuddled else
-cb # Cuddled blocks
-nbbc # Do not add blank lines before full length comments
-nbot # No line break on ternary
-nlop # No logical padding (this causes mixed tabs and spaces)
-wn # Weld nested containers
-xci # Extended continuation indentation
-vxl='q' # No vertical alignment of qw quotes
71 changes: 9 additions & 62 deletions bin/perltidy-pg.pl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ =head1 NAME

=head1 SYNOPSIS

pg-perltidy.pl [options] file1 file2 ...
pg-perltidy.pl [options] file1 file2 ...

=head1 DESCRIPTION

Expand All @@ -32,74 +32,21 @@ =head1 OPTIONS
perltidy documentation for details.

Note that if the -pro=file option is not given, then this script will attempt to
use the .perltidyrc file in the PG root directory for this option. For this to
work the PG_ROOT environment variable must be set, and the .perltidyrc file in
the PG root directory must be readable.
use the perltidy-pg.rc file in the PG bin directory for this option. For this to
work the the perltidy-pg.rc file in the PG bin directory must be readable.

=cut

use strict;
use warnings;

use Perl::Tidy;
use Mojo::File qw(curfile);

# Apply the same preprocessing as the PG Translator, except for the removal of everything after ENDDOCUMENT.
my $prefilter = sub {
my $evalString = shift // '';

$evalString =~ s/\n\h*END_TEXT[\h;]*\n/\nEND_TEXT\n/g;
$evalString =~ s/\n\h*END_PGML[\h;]*\n/\nEND_PGML\n/g;
$evalString =~ s/\n\h*END_PGML_SOLUTION[\h;]*\n/\nEND_PGML_SOLUTION\n/g;
$evalString =~ s/\n\h*END_PGML_HINT[\h;]*\n/\nEND_PGML_HINT\n/g;
$evalString =~ s/\n\h*END_SOLUTION[\h;]*\n/\nEND_SOLUTION\n/g;
$evalString =~ s/\n\h*END_HINT[\h;]*\n/\nEND_HINT\n/g;
$evalString =~ s/\n\h*BEGIN_TEXT[\h;]*\n/\nSTATEMENT\(EV3P\(<<'END_TEXT'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_PGML[\h;]*\n/\nSTATEMENT\(PGML::Format2\(<<'END_PGML'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_PGML_SOLUTION[\h;]*\n/\nSOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_PGML_HINT[\h;]*\n/\nHINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_SOLUTION[\h;]*\n/\nSOLUTION\(EV3P\(<<'END_SOLUTION'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_HINT[\h;]*\n/\nHINT\(EV3P\(<<'END_HINT'\)\);\n/g;
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_TIKZ[\h;]*\n/\n$1->tex\(<<END_TIKZ\);\n/g;
$evalString =~ s/\n\h*END_TIKZ[\h;]*\n/\nEND_TIKZ\n/g;
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_LATEX_IMAGE[\h;]*\n/\n$1->tex\(<<END_LATEX_IMAGE\);\n/g;
$evalString =~ s/\n\h*END_LATEX_IMAGE[\h;]*\n/\nEND_LATEX_IMAGE\n/g;

$evalString =~ s/\\/\\\\/g;
$evalString =~ s/~~/\\/g;

return $evalString;
};

# Reverse the above preprocessing after perltidy is run. This does not reverse the clean up of
# horizontal whitespace and semicolons done in the preprocessing stage.
my $postfilter = sub {
my $evalString = shift // '';

$evalString =~ s/\h*STATEMENT\(EV3P\(<<'END_TEXT'\)\);/BEGIN_TEXT/g;
$evalString =~ s/\h*STATEMENT\(PGML::Format2\(<<'END_PGML'\)\);/BEGIN_PGML/g;
$evalString =~ s/\h*SOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);/BEGIN_PGML_SOLUTION/g;
$evalString =~ s/\h*HINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);/BEGIN_PGML_HINT/g;
$evalString =~ s/\h*SOLUTION\(EV3P\(<<'END_SOLUTION'\)\);/BEGIN_SOLUTION/g;
$evalString =~ s/\h*HINT\(EV3P\(<<'END_HINT'\)\);/BEGIN_HINT/g;
$evalString =~ s/(.*)->tex\(<<END_TIKZ\);/$1->BEGIN_TIKZ/g;
$evalString =~ s/(.*)->tex\(<<END_LATEX_IMAGE\);/$1->BEGIN_LATEX_IMAGE/g;

# Care is needed to reverse the preprocessing here.
# First in all occurences of an odd number of backslashes the first backslash is replaced with two tildes.
$evalString =~ s/(?<!\\) \\ ((?:\\{2})*) (?!\\)/~~$1/gx;
# Then all pairs of backslashes are replaced with a single backslash.
$evalString =~ s/\\\\/\\/g;

return $evalString;
};

# Get the options that were passed. If the profile option was not set, then set it to be the
# .perltidyrc file in the root pg directory.
my %options;
Perl::Tidy::perltidy(dump_options => \%options);
unshift(@ARGV, "-pro=$ENV{PG_ROOT}/.perltidyrc")
if !defined $options{profile} && defined $ENV{PG_ROOT} && -r "$ENV{PG_ROOT}/.perltidyrc";

Perl::Tidy::perltidy(prefilter => $prefilter, postfilter => $postfilter);
use lib curfile->dirname->dirname . '/lib';

use WeBWorK::PG::Tidy qw(pgtidy);

pgtidy();

1;
22 changes: 22 additions & 0 deletions bin/perltidy-pg.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# PBP .perltidyrc file
-l=80 # Max line width is 80 cols
-i=4 # Indent level is 4 cols
-ci=4 # Continuation indent is 4 cols
-b # Write the file inline and create a .bak file
-vt=0 # Minimal vertical tightness
-cti=0 # No extra indentation for closing brackets
-pt=2 # Maximum parenthesis tightness
-bt=1 # Medium brace tightness
-sbt=1 # Medium square bracket tightness
-bbt=1 # Medium block brace tightness
-nsfs # No space before semicolons
-nolq # Don't outdent long quoted strings
-mbl=1 # Do not allow multiple empty lines
-ce # Cuddled else
-cb # Cuddled blocks
-nbbc # Do not add blank lines before full length comments
-nbot # No line break on ternary
-nlop # No logical padding (this causes mixed tabs and spaces)
-wn # Weld nested containers
-xci # Extended continuation indentation
-vxl='q' # No vertical alignment of qw quotes
18 changes: 11 additions & 7 deletions bin/run-perltidy.pl
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ =head1 DESCRIPTION

=head1 OPTIONS

For this script to work the PG_ROOT environment variable must be set, and the
.perltidyrc file in the PG root directory must be readable.
For this script to work the the .perltidyrc file in the pg root directory
must be readable. Note that the pg root directory is automatically detected.

This script accepts all of the options that are accepted by perltidy. See the
perltidy documentation for details.
Expand All @@ -47,7 +47,7 @@ =head1 OPTIONS

Finally, if no files are passed on the command line, then perltidy will be
executed on all files with the extensions C<.pl>, C<.pm>, or C<.t> in the
PG_ROOT directory. If files are passed on the command line, then perltidy will
pg root directory. If files are passed on the command line, then perltidy will
only be executed on the listed files.

=cut
Expand All @@ -58,11 +58,15 @@ =head1 OPTIONS

use Perl::Tidy;
use File::Find qw(find);
use Mojo::File qw(curfile);

my $pg_root = curfile->dirname->dirname;

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

my $verbose = 0;
my (@args, @files);
Expand All @@ -84,7 +88,7 @@ =head1 OPTIONS
for (@files) {
push(@args, $_);
say "Tidying file: $_" if $verbose;
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$ENV{PG_ROOT}/.perltidyrc");
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$pg_root/.perltidyrc");
pop(@args);
}
} else {
Expand All @@ -106,12 +110,12 @@ =head1 OPTIONS
say "Tidying file: $path" if $verbose;

push(@args, $path);
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$ENV{PG_ROOT}/.perltidyrc");
Perl::Tidy::perltidy(argv => \@args, perltidyrc => "$pg_root/.perltidyrc");
pop(@args);
},
no_chdir => 1
},
$ENV{PG_ROOT}
$pg_root
);
}

Expand Down
112 changes: 112 additions & 0 deletions lib/WeBWorK/PG/Tidy.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
################################################################################
# WeBWorK Online Homework Delivery System
# Copyright &copy; 2000-2023 The WeBWorK Project, https://github.com/openwebwork
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of either: (a) the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version, or (b) the "Artistic License" which comes with this package.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
# Artistic License for more details.
################################################################################

=head1 NAME

WeBWorK::PG::Tidy -- perltidy pg problem files.

=head1 DESCRIPTION

perltidy pg problem files.

=head1 OPTIONS

This module is a wrapper around Perl::Tidy and just calls C<Perl::Tidy::perltidy>.
Any options passed on the command line are passed to Perl::Tidy::perltidy See
the L<Perl::Tidy::perltidy> documentation for details.

Note that if the C<-pro=file> option is not given, then this module will attempt
to use the perltidy-pg.rc file in the PG bin directory for this option. For
this to work the perltidy-pg.rc file in the PG bin directory must be readable.

=cut

package WeBWorK::PG::Tidy;
use parent qw(Exporter);

use strict;
use warnings;

use Perl::Tidy;
use Mojo::File qw(curfile);

our @EXPORT = qw(pgtidy);

my $perltidy_pg_rc = curfile->dirname->dirname->dirname->dirname . '/bin/perltidy-pg.rc';

# Apply the same preprocessing as the PG Translator, except for the removal of everything after ENDDOCUMENT.
my $prefilter = sub {
my $evalString = shift // '';

$evalString =~ s/\n\h*END_TEXT[\h;]*\n/\nEND_TEXT\n/g;
$evalString =~ s/\n\h*END_PGML[\h;]*\n/\nEND_PGML\n/g;
$evalString =~ s/\n\h*END_PGML_SOLUTION[\h;]*\n/\nEND_PGML_SOLUTION\n/g;
$evalString =~ s/\n\h*END_PGML_HINT[\h;]*\n/\nEND_PGML_HINT\n/g;
$evalString =~ s/\n\h*END_SOLUTION[\h;]*\n/\nEND_SOLUTION\n/g;
$evalString =~ s/\n\h*END_HINT[\h;]*\n/\nEND_HINT\n/g;
$evalString =~ s/\n\h*BEGIN_TEXT[\h;]*\n/\nSTATEMENT\(EV3P\(<<'END_TEXT'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_PGML[\h;]*\n/\nSTATEMENT\(PGML::Format2\(<<'END_PGML'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_PGML_SOLUTION[\h;]*\n/\nSOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_PGML_HINT[\h;]*\n/\nHINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_SOLUTION[\h;]*\n/\nSOLUTION\(EV3P\(<<'END_SOLUTION'\)\);\n/g;
$evalString =~ s/\n\h*BEGIN_HINT[\h;]*\n/\nHINT\(EV3P\(<<'END_HINT'\)\);\n/g;
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_TIKZ[\h;]*\n/\n$1->tex\(<<END_TIKZ\);\n/g;
$evalString =~ s/\n\h*END_TIKZ[\h;]*\n/\nEND_TIKZ\n/g;
$evalString =~ s/\n\h*(.*)\h*->\h*BEGIN_LATEX_IMAGE[\h;]*\n/\n$1->tex\(<<END_LATEX_IMAGE\);\n/g;
$evalString =~ s/\n\h*END_LATEX_IMAGE[\h;]*\n/\nEND_LATEX_IMAGE\n/g;

$evalString =~ s/\\/\\\\/g;
$evalString =~ s/~~/\\/g;

return $evalString;
};

# Reverse the above preprocessing after perltidy is run. This does not reverse the clean up of
# horizontal whitespace and semicolons done in the preprocessing stage.
my $postfilter = sub {
my $evalString = shift // '';

$evalString =~ s/\h*STATEMENT\(EV3P\(<<'END_TEXT'\)\);/BEGIN_TEXT/g;
$evalString =~ s/\h*STATEMENT\(PGML::Format2\(<<'END_PGML'\)\);/BEGIN_PGML/g;
$evalString =~ s/\h*SOLUTION\(PGML::Format2\(<<'END_PGML_SOLUTION'\)\);/BEGIN_PGML_SOLUTION/g;
$evalString =~ s/\h*HINT\(PGML::Format2\(<<'END_PGML_HINT'\)\);/BEGIN_PGML_HINT/g;
$evalString =~ s/\h*SOLUTION\(EV3P\(<<'END_SOLUTION'\)\);/BEGIN_SOLUTION/g;
$evalString =~ s/\h*HINT\(EV3P\(<<'END_HINT'\)\);/BEGIN_HINT/g;
$evalString =~ s/(.*)->tex\(<<END_TIKZ\);/$1->BEGIN_TIKZ/g;
$evalString =~ s/(.*)->tex\(<<END_LATEX_IMAGE\);/$1->BEGIN_LATEX_IMAGE/g;

# Care is needed to reverse the preprocessing here.
# First in all occurences of an odd number of backslashes the first backslash is replaced with two tildes.
$evalString =~ s/(?<!\\) \\ ((?:\\{2})*) (?!\\)/~~$1/gx;
# Then all pairs of backslashes are replaced with a single backslash.
$evalString =~ s/\\\\/\\/g;

return $evalString;
};

sub pgtidy {
my %options = @_;

local @ARGV = @ARGV;

# Get the options that were passed. If the profile option was not set, then set it to be the
# perltidy-pg.rc file in the root pg directory.
Perl::Tidy::perltidy(dump_options => \my %internal_options);
unshift(@ARGV, "-pro=$perltidy_pg_rc") if !defined $internal_options{profile} && -r $perltidy_pg_rc;

return Perl::Tidy::perltidy(prefilter => $prefilter, postfilter => $postfilter, %options);
}

1;