File Coverage

blib/lib/Syntax/Feature/Qi.pm
Criterion Covered Total %
statement 57 57 100.0
branch 4 6 66.6
condition n/a
subroutine 13 13 100.0
pod 0 1 0.0
total 74 77 96.1


line stmt bran cond sub pod time code
1 1     1   39828 use strict;
  1         3  
  1         36  
2 1     1   4 use warnings;
  1         1  
  1         44  
3              
4             package Syntax::Feature::Qi;
5              
6             our $VERSION = '0.2002'; # VERSION
7             # ABSTRACT: Remove the same indendation from all lines in a string
8              
9 1     1   1888 use Devel::Declare 0.006007 ();
  1         26021  
  1         32  
10 1     1   9 use B::Hooks::EndOfScope 0.09;
  1         17  
  1         6  
11 1     1   88 use Sub::Install 0.925 qw/install_sub/;
  1         14  
  1         6  
12 1     1   833 use Devel::Declare::Context::Simple;
  1         1629  
  1         39  
13 1     1   6 use namespace::clean;
  1         2  
  1         9  
14              
15             my %quote_op = qw(qi q qqi qq);
16             my @new_ops = keys %quote_op;
17              
18             sub install {
19 1     1 0 11 my $class = shift;
20 1         6 my %args = @_;
21              
22 1         2 my $target = $args{'into'};
23              
24 2         2 Devel::Declare->setup_for($target => {
25             map {
26 1         2 my $name = $_;
27             ($name => {
28             const => sub {
29 16     16   821 my $context = Devel::Declare::Context::Simple->new;
30 16         112 $context->init(@_);
31 16         105 return $class->_transform($name, $context);
32             },
33 2         19 });
34             } @new_ops
35             });
36 1         31 foreach my $name (@new_ops) {
37 2         55 install_sub {
38             into => $target,
39             as => $name,
40             code => $class->_run_callback,
41             };
42             }
43             on_scope_end {
44 1     1   109 namespace::clean->clean_subroutines($target, @new_ops);
45 1         31 };
46 1         15 return 1;
47             }
48              
49             sub _run_callback {
50              
51             return sub ($) {
52 16     16   1312 my $string = shift;
53 16 50       70 return $string if $string =~ m{\A\s*\Z}ms;
54              
55 16 50       70 my $remove_indent = $string =~ m{\A(\h*)\S} ? $1
    100          
56             : $string =~ m{\A\s*\n(\h*)\S} ? $1
57             : ''
58             ;
59 16         153 $string =~ s{^$remove_indent}{}gms;
60 16         69 return $string;
61 2     2   12 };
62             }
63              
64             sub _transform {
65 16     16   19 my $class = shift;
66 16         14 my $name = shift;
67 16         12 my $ctx = shift;
68              
69 16         23 $ctx->skip_declarator;
70 16         253 my $length = Devel::Declare::toke_scan_str($ctx->offset);
71 16         165 my $string = Devel::Declare::get_lex_stuff;
72 16         18 Devel::Declare::clear_lex_stuff;
73 16         26 my $linestr = $ctx->get_linestr;
74 16         65 my $quoted = substr $linestr, $ctx->offset, $length;
75 16         44 my $spaced = '';
76 16         46 $quoted =~ m{^(\s*)}sm;
77 16         26 $spaced = $1;
78 16         52 my $new = sprintf '(%s)', join '',
79             $quote_op{$name},
80             $spaced,
81             substr($quoted, length($spaced), 1),
82             $string,
83             substr($quoted, -1, 1);
84 16         31 substr($linestr, $ctx->offset, $length) = $new;
85 16         55 $ctx->set_linestr($linestr);
86 16         201 return 1;
87             }
88              
89             1;
90              
91             __END__
92              
93             =pod
94              
95             =encoding utf-8
96              
97             =head1 NAME
98              
99             Syntax::Feature::Qi - Remove the same indendation from all lines in a string
100              
101             =head1 VERSION
102              
103             Version 0.2002, released 2015-01-17.
104              
105             =head1 SYNOPSIS
106              
107             use syntax 'qi';
108              
109             say qi{
110             This is a sub routine:
111             sub printme {
112             print shift;
113             }
114             };
115              
116             # is exactly the same as
117              
118             say qi{
119             This is a sub routine:
120             sub printme {
121             print shift;
122             }
123             };
124              
125             =head1 DESCRIPTION
126              
127             This is a syntax extension to be used with L<syntax>.
128              
129             It provides two quote-like operators, C<qi> and C<qqi>. They are drop-in replacements for C<q> and C<qq>, respectively.
130              
131             They work like this: First they find the first line in the string with a non-white space character. It saves the
132             white space from the beginning of that line up to that character, and then it tries to remove the exact same whitespace from
133             all other lines in the string.
134              
135             =head1 SEE ALSO
136              
137             =over 4
138              
139             =item *
140              
141             L<Syntax::Feature::Ql> (which served as a base for this)
142              
143             =item *
144              
145             L<Syntax::Feature::Qs>
146              
147             =item *
148              
149             L<String::Nudge>
150              
151             =item *
152              
153             L<syntax>
154              
155             =back
156              
157             =head1 SOURCE
158              
159             L<https://github.com/Csson/p5-Syntax-Feature-Qi>
160              
161             =head1 HOMEPAGE
162              
163             L<https://metacpan.org/release/Syntax-Feature-Qi>
164              
165             =head1 AUTHOR
166              
167             Erik Carlsson <info@code301.com>
168              
169             =head1 COPYRIGHT AND LICENSE
170              
171             This software is copyright (c) 2015 by Erik Carlsson.
172              
173             This is free software; you can redistribute it and/or modify it under
174             the same terms as the Perl 5 programming language system itself.
175              
176             =cut