File Coverage

blib/lib/Perl/Critic/Policy/Editor/RequireEmacsFileVariables.pm
Criterion Covered Total %
statement 32 32 100.0
branch 6 6 100.0
condition 6 6 100.0
subroutine 11 11 100.0
pod 4 5 80.0
total 59 60 98.3


line stmt bran cond sub pod time code
1             #######################################################################
2             # $URL: http://perlcritic.tigris.org/svn/perlcritic/trunk/distributions/Perl-Critic-More/lib/Perl/Critic/Policy/Editor/RequireEmacsFileVariables.pm $
3             # $Date: 2013-10-29 09:39:11 -0700 (Tue, 29 Oct 2013) $
4             # $Author: thaljef $
5             # $Revision: 4222 $
6             ########################################################################
7              
8             package Perl::Critic::Policy::Editor::RequireEmacsFileVariables;
9              
10 6     6   5476 use 5.006001;
  6         21  
  6         273  
11              
12 6     6   33 use strict;
  6         11  
  6         182  
13 6     6   34 use warnings;
  6         12  
  6         156  
14              
15 6     6   44 use Readonly;
  6         12  
  6         309  
16              
17 6     6   33 use Perl::Critic::Utils qw{ :severities };
  6         11  
  6         387  
18 6     6   6967 use base 'Perl::Critic::Policy';
  6         12  
  6         2748  
19              
20             our $VERSION = '1.003';
21              
22             # This constant is hard-coded in emacs file.el
23             Readonly::Scalar my $LOOK_BYTES_FROM_END => 3000;
24              
25             #---------------------------------------------------------------------------
26              
27             Readonly::Scalar my $DESC =>
28             'Use Emacs file variables to declare coding style';
29             Readonly::Scalar my $EXPL => 'Emacs can read per-file settings';
30              
31             #---------------------------------------------------------------------------
32              
33 6     6 1 378 sub default_severity { return $SEVERITY_LOW }
34 1     1 1 98 sub default_themes { return qw< more readability editor > }
35 13     13 1 51809 sub applies_to { return 'PPI::Document' }
36 14     14 0 46452 sub supported_parameters { return () }
37              
38             #---------------------------------------------------------------------------
39              
40             sub violates {
41 13     13 1 119 my ( $self, $elem, $doc ) = @_;
42              
43 13         63 my $code = $doc->serialize();
44              
45             ## Look for first line file vars. Example:
46             # #! /usr/bin/perl -w -*- cperl; cperl-indent-level: 4 -*-
47              
48 13         1448 my $one_line_local_var = qr/-[*]- .* -[*]-/xms;
49              
50             # Note: If PPI changes away from native newlines, this may break
51 13         63 my ( $first_line, $second_line )
52             = $code =~ m/\A ([^\n]*) (?: \n ([^\n]*) )? /xms;
53 13 100       93 return if $first_line =~ m/$one_line_local_var/xms;
54             return
55 8 100 100     80 if ( $second_line
      100        
56             && $first_line =~ m/\A \#!/xms
57             && $second_line =~ m/$one_line_local_var/xms );
58              
59             ## Look for end of doc file vars Example:
60             # Local Variables:
61             # mode: cperl
62             # End:
63 7         22 my $last_page = substr $code, -$LOOK_BYTES_FROM_END;
64              
65             # Remove anything not on the last page, as delimited by "^L", aka
66             # "\f", aka formfeed.
67 7         28 $last_page =~ s/ .* \f//xms;
68              
69             # This regex is transliterated from emacs22 files.el
70             # Note that the [ \t]* before "End:" appears to be wrong, but is
71             # added for compatibility
72              
73             ## Due to the backreferences, this is almost impossible to subdivide.
74             ## no critic (ProhibitComplexRegexes)
75 7 100       44 return if $last_page =~ m<
76             ^ ([^\n]*) Local [ ] Variables: [ \t]* ([^\n]*) $
77             .*?
78             ^ \1 [ \t]* End: [ \t]* \2 $
79             >ixms;
80             ## use critic
81              
82 5         24 return $self->violation( $DESC, $EXPL, $doc );
83             }
84              
85             1;
86              
87             __END__
88              
89             #---------------------------------------------------------------------------
90              
91             =pod
92              
93             =for stopwords elisp emacs formfeed syntaxes files.el
94              
95             =head1 NAME
96              
97             Perl::Critic::Policy::Editor::RequireEmacsFileVariables - Per-file editor settings.
98              
99             =head1 AFFILIATION
100              
101             This policy is part of L<Perl::Critic::More|Perl::Critic::More>, a bleeding
102             edge supplement to L<Perl::Critic|Perl::Critic>.
103              
104             =head1 DESCRIPTION
105              
106             Many text editors know how to find magic strings in files that
107             indicate settings that work best for that file. For example, the file
108             can indicate that it expects four-character indentation.
109              
110             In emacs, this magic string is called "File Variables". There are two
111             syntaxes:
112             C<-*- ... -*-> (single-line)
113             and
114             C<Local Variables:\n...\nEnd:> (multi-line).
115             Both syntaxes allow leading and trailing text on the line.
116              
117             The single-line syntax must be used on the first line of the file to
118             be recognized, or on the second line if the first line is a shebang.
119             The following examples are explicitly allowed by Perl:
120              
121             #!perl -w -*- cperl -*-
122             #!perl -w # -*- cperl -*-
123             #!perl # -*- cperl -*-
124              
125             The multi-line syntax must be used "in the last page" (that is, after
126             the last formfeed) at the end of the file. As of Emacs21, the "end of
127             the file" is hard-coded to be the last 3000 bytes of the file (in the
128             hack-local-variables function in F<files.el>). In this syntax, each line
129             must begin and end with the same prefix/suffix pair. That pair is
130             defined by the text before and after the "Local Variables:" string.
131              
132             =head1 SEE ALSO
133              
134             L<Perl::Critic::Policy::Editor::RequireViModeline|Perl::Critic::Policy::Editor::RequireViModeline>
135              
136             L<http://www.gnu.org/software/emacs/manual/html_node/File-Variables.html>
137              
138             In Emacs, you can view the "File Variables" info node by typing:
139             C<Help-key>, C<i>, C<g>, C<(emacs)File Variables>
140             (where C<Help-key> is often C<C-h> or C<F1>.)
141              
142             Alternatively, you can execute the following elisp:
143             (info "(emacs)File Variables")
144              
145             =head1 AUTHOR
146              
147             Chris Dolan <cdolan@cpan.org>
148              
149             Michael Wolf <MichaelRWolf@att.net>
150              
151             =head1 COPYRIGHT
152              
153             Copyright (c) 2006-2008 Chris Dolan
154              
155             This program is free software; you can redistribute it and/or modify
156             it under the same terms as Perl itself. The full text of this license
157             can be found in the LICENSE file included with this module.
158              
159             =cut
160              
161            
162              
163             # Local Variables:
164             # mode: cperl
165             # cperl-indent-level: 4
166             # fill-column: 78
167             # indent-tabs-mode: nil
168             # c-indentation-style: bsd
169             # End:
170             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :