File: perltidyrc_dump.pl

package info (click to toggle)
perltidy 20140328-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,900 kB
  • ctags: 646
  • sloc: perl: 19,605; makefile: 4
file content (319 lines) | stat: -rw-r--r-- 11,181 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#!/usr/bin/perl -w
use strict;

# This program reads .perltidyrc files and writes them back out
# into a standard format (but comments will be lost).
#
# It also demonstrates how to use the perltidy 'options-dump' and related call
# parameters to read a .perltidyrc file, convert to long names, put it in a
# hash, and write back to standard output in sorted order.  Requires
# Perl::Tidy.
#
# Steve Hancock, June 2006
#
my $usage = <<EOM;
 usage:
 perltidyrc_dump.pl [-d -s -q -h] [ filename ]
  filename is the name of a .perltidyrc config file to dump, or
   if no filename is given, find and dump the system default .perltidyrc.
  -d delete options which are the same as Perl::Tidy defaults 
     (default is to keep them)
  -s write short parameter names
     (default is long names with short name in side comment)
  -q quiet: no comments 
  -h help
EOM
use Getopt::Std;
my %my_opts;
my $cmdline = $0 . " " . join " ", @ARGV;
getopts( 'hdsq', \%my_opts ) or die "$usage";
if ( $my_opts{h} ) { die "$usage" }
if ( @ARGV > 1 )   { die "$usage" }

my $config_file = $ARGV[0];
my (
    $error_message, $rOpts,          $rGetopt_flags,
    $rsections,     $rabbreviations, $rOpts_default,
    $rabbreviations_default,

) = read_perltidyrc($config_file);

# always check the error message first
if ($error_message) {
    die "$error_message\n";
}

# make a list of perltidyrc options which are same as default
my %equals_default;
foreach my $long_name ( keys %{$rOpts} ) {
    my $val = $rOpts->{$long_name};
    if ( defined( $rOpts_default->{$long_name} ) ) {
        my $val2 = $rOpts_default->{$long_name};
        if ( defined($val2) && defined($val) ) {
            $equals_default{$long_name} = ( $val2 eq $val );
        }
    }
}

# Optional: minimize the perltidyrc file length by deleting long_names
# in $rOpts which are also in $rOpts_default and have the same value.
# This would be useful if a perltidyrc file has been constructed from a
# full parameter dump, for example.
if ( $my_opts{d} ) {
    foreach my $long_name ( keys %{$rOpts} ) {
        delete $rOpts->{$long_name} if $equals_default{$long_name};
    }
}

# find user-defined abbreviations
my %abbreviations_user;
foreach my $key ( keys %$rabbreviations ) {
    unless ( $rabbreviations_default->{$key} ) {
        $abbreviations_user{$key} = $rabbreviations->{$key};
    }
}

# dump the options, if any
if ( %$rOpts || %abbreviations_user ) {
    dump_options( $cmdline, \%my_opts, $rOpts, $rGetopt_flags, $rsections,
        $rabbreviations, \%equals_default, \%abbreviations_user );
}
else {
    if ($config_file) {
        print STDERR <<EOM;
No configuration parameters seen in file: $config_file
EOM
    }
    else {
        print STDERR <<EOM;
No .perltidyrc file found, use perltidy -dpro to see locations checked.
EOM
    }
}

sub dump_options {

    # write the options back out as a valid .perltidyrc file
    # This version writes long names by sections
    my ( $cmdline, $rmy_opts, $rOpts, $rGetopt_flags, $rsections,
        $rabbreviations, $requals_default, $rabbreviations_user )
      = @_;

    # $rOpts is a reference to the hash returned by Getopt::Long
    # $rGetopt_flags are the flags passed to Getopt::Long
    # $rsections is a hash giving manual section {long_name}

    # build a hash giving section->long_name->parameter_value
    # so that we can write parameters by section
    my %section_and_name;
    my $rsection_name_value = \%section_and_name;
    my %saw_section;
    foreach my $long_name ( keys %{$rOpts} ) {
        my $section = $rsections->{$long_name};
        $section = "UNKNOWN" unless ($section);    # shouldn't happen

        # build a hash giving section->long_name->parameter_value
        $rsection_name_value->{$section}->{$long_name} = $rOpts->{$long_name};

        # remember what sections are in this hash
        $saw_section{$section}++;
    }

    # build a table for long_name->short_name abbreviations
    my %short_name;
    foreach my $abbrev ( keys %{$rabbreviations} ) {
        foreach my $abbrev ( sort keys %$rabbreviations ) {
            my @list = @{ $$rabbreviations{$abbrev} };

            # an abbreviation may expand into one or more other words,
            # but only those that expand to a single word (which must be
            # one of the long names) are the short names that we want
            # here.
            next unless @list == 1;
            my $long_name = $list[0];
            $short_name{$long_name} = $abbrev;
        }
    }

    unless ( $rmy_opts->{q} ) {
        my $date = localtime();
        print "# perltidy configuration file created $date\n";
        print "# using: $cmdline\n";
    }

    # loop to write section-by-section
    foreach my $section ( sort keys %saw_section ) {
        unless ( $rmy_opts->{q} ) {
            print "\n";

            # remove leading section number, which is there
            # for sorting, i.e.,
            # 1. Basic formatting options -> Basic formatting options
            my $trimmed_section = $section;
            $trimmed_section =~ s/^\d+\. //;
            print "# $trimmed_section\n";
        }

        # loop over all long names for this section
        my $rname_value = $rsection_name_value->{$section};
        foreach my $long_name ( sort keys %{$rname_value} ) {

            # pull out getopt flag and actual parameter value
            my $flag  = $rGetopt_flags->{$long_name};
            my $value = $rname_value->{$long_name};

            # turn this it back into a parameter
            my $prefix       = '--';
            my $short_prefix = '-';
            my $suffix       = "";
            if ($flag) {
                if ( $flag =~ /^=/ ) {
                    if ( $value !~ /^\d+$/ ) { $value = '"' . $value . '"' }
                    $suffix = "=" . $value;
                }
                elsif ( $flag =~ /^!/ ) {
                    $prefix       .= "no" unless ($value);
                    $short_prefix .= "n"  unless ($value);
                }
                elsif ( $flag =~ /^:/ ) {
                    if ( $value !~ /^\d+$/ ) { $value = '"' . $value . '"' }
                    $suffix = "=" . $value;
                }
                else {

                    # shouldn't happen
                    print
"# ERROR in dump_options: unrecognized flag $flag for $long_name\n";
                }
            }

            # print the long version of the parameter
            # with the short version as a side comment
            my $short_name   = $short_name{$long_name};
            my $short_option = $short_prefix . $short_name . $suffix;
            my $long_option  = $prefix . $long_name . $suffix;
            my $note = $requals_default->{$long_name} ? "  [=default]" : "";
            if ( $rmy_opts->{s} ) {
                print $short_option. "\n";
            }
            else {
                my $side_comment = "";
                unless ( $rmy_opts->{q} ) {
                    my $spaces = 40 - length($long_option);
                    $spaces = 2 if ( $spaces < 2 );
                    $side_comment =
                      ' ' x $spaces . '# ' . $short_option . $note;
                }
                print $long_option . $side_comment . "\n";
            }
        }
    }

    if ( %{$rabbreviations_user} ) {
        unless ( $rmy_opts->{q} ) {
            print "\n";
            print "# Abbreviations\n";
        }
        foreach my $key ( keys %$rabbreviations_user ) {
            my @vals = @{ $rabbreviations_user->{$key} };
            print $key. ' {' . join( ' ', @vals ) . '}' . "\n";
        }
    }
}

sub read_perltidyrc {

    # Example routine to have Perl::Tidy read and validate perltidyrc
    # file, and return related flags and abbreviations.
    #
    # input parameter -
    #   $config_file is the name of a .perltidyrc file we want to read
    #   or a reference to a string or array containing the .perltidyrc file
    #   if not defined, Perl::Tidy will try to find the user's .perltidyrc
    # output parameters -
    #   $error_message will be blank unless an error occurs
    #   $rOpts - reference to the hash of options in the .perlticyrc
    # NOTE:
    #   Perl::Tidy will croak or die on certain severe errors

    my ($config_file) = @_;
    my $error_message = "";
    my %Opts;    # any options found will be put here

    # the module must be installed for this to work
    eval "use Perl::Tidy";
    if ($@) {
        $error_message = "Perl::Tidy not installed\n";
        return ( $error_message, \%Opts );
    }

    # be sure this version supports this
    my $version = $Perl::Tidy::VERSION;
    if ( $version < 20060528 ) {
        $error_message = "perltidy version $version cannot read options\n";
        return ( $error_message, \%Opts );
    }

    my $stderr = "";    # try to capture error messages
    my $argv   = "";    # do not let perltidy see our @ARGV

    # we are going to make two calls to perltidy...
    # first with an empty .perltidyrc to get the default parameters
    my $empty_file = "";    # this will be our .perltidyrc file
    my %Opts_default;       # this will receive the default options hash
    my %abbreviations_default;
    my $err = Perl::Tidy::perltidy(
        perltidyrc         => \$empty_file,
        dump_options       => \%Opts_default,
        dump_options_type  => 'full',                  # 'full' gives everything
        dump_abbreviations => \%abbreviations_default,
        stderr             => \$stderr,
        argv               => \$argv,
    );
    if ($err) {
        die "Error calling perltidy\n";
    }

    # now we call with a .perltidyrc file to get its parameters
    my %Getopt_flags;
    my %sections;
    my %abbreviations;
    Perl::Tidy::perltidy(
        perltidyrc            => $config_file,
        dump_options          => \%Opts,
        dump_options_type     => 'perltidyrc',      # default is 'perltidyrc'
        dump_getopt_flags     => \%Getopt_flags,
        dump_options_category => \%sections,
        dump_abbreviations    => \%abbreviations,
        stderr                => \$stderr,
        argv                  => \$argv,
    );

    # try to capture any errors generated by perltidy call
    # but for severe errors it will typically croak
    $error_message .= $stderr;

    # debug: show how everything is stored by printing it out
    my $DEBUG = 0;
    if ($DEBUG) {
        print "---Getopt Parameters---\n";
        foreach my $key ( sort keys %Getopt_flags ) {
            print "$key$Getopt_flags{$key}\n";
        }
        print "---Manual Sections---\n";
        foreach my $key ( sort keys %sections ) {
            print "$key -> $sections{$key}\n";
        }
        print "---Abbreviations---\n";
        foreach my $key ( sort keys %abbreviations ) {
            my @names = @{ $abbreviations{$key} };
            print "$key -> {@names}\n";
            unless ( $abbreviations_default{$key} ) {
                print "NOTE: $key is user defined\n";
            }
        }
    }

    return ( $error_message, \%Opts, \%Getopt_flags, \%sections,
        \%abbreviations, \%Opts_default, \%abbreviations_default, );
}