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   43393 use strict;
  1         2  
  1         33  
2 1     1   3 use warnings;
  1         1  
  1         49  
3              
4             package Syntax::Feature::Qi;
5              
6             our $VERSION = '0.2004'; # VERSION
7             # ABSTRACT: Remove the same indendation from all lines in a string
8              
9 1     1   499 use Devel::Declare 0.006007 ();
  1         7155  
  1         35  
10 1     1   11 use B::Hooks::EndOfScope 0.09;
  1         24  
  1         9  
11 1     1   100 use Sub::Install 0.925 qw/install_sub/;
  1         15  
  1         6  
12 1     1   833 use Devel::Declare::Context::Simple;
  1         1812  
  1         24  
13 1     1   5 use namespace::clean;
  1         1  
  1         7  
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 10 my $class = shift;
20 1         6 my %args = @_;
21              
22 1         2 my $target = $args{'into'};
23              
24 2         3 Devel::Declare->setup_for($target => {
25             map {
26 1         2 my $name = $_;
27             ($name => {
28             const => sub {
29 16     16   1023 my $context = Devel::Declare::Context::Simple->new;
30 16         277 $context->init(@_);
31 16         135 return $class->_transform($name, $context);
32             },
33 2         24 });
34             } @new_ops
35             });
36 1         37 foreach my $name (@new_ops) {
37 2         72 install_sub {
38             into => $target,
39             as => $name,
40             code => $class->_run_callback,
41             };
42             }
43             on_scope_end {
44 1     1   117 namespace::clean->clean_subroutines($target, @new_ops);
45 1         56 };
46 1         21 return 1;
47             }
48              
49             sub _run_callback {
50              
51             return sub ($) {
52 16     16   2334 my $string = shift;
53 16 50       91 return $string if $string =~ m{\A\s*\Z}ms;
54              
55 16 50       93 my $remove_indent = $string =~ m{\A(\h*)\S} ? $1
    100          
56             : $string =~ m{\A\s*\n(\h*)\S} ? $1
57             : ''
58             ;
59 16         188 $string =~ s{^$remove_indent}{}gms;
60 16         89 return $string;
61 2     2   15 };
62             }
63              
64             sub _transform {
65 16     16   24 my $class = shift;
66 16         18 my $name = shift;
67 16         12 my $ctx = shift;
68              
69 16         37 $ctx->skip_declarator;
70 16         317 my $length = Devel::Declare::toke_scan_str($ctx->offset);
71 16         269 my $string = Devel::Declare::get_lex_stuff;
72 16         23 Devel::Declare::clear_lex_stuff;
73 16         26 my $linestr = $ctx->get_linestr;
74 16         80 my $quoted = substr $linestr, $ctx->offset, $length;
75 16         58 my $spaced = '';
76 16         60 $quoted =~ m{^(\s*)}sm;
77 16         35 $spaced = $1;
78 16         64 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         39 substr($linestr, $ctx->offset, $length) = $new;
85 16         73 $ctx->set_linestr($linestr);
86 16         287 return 1;
87             }
88              
89             1;
90              
91             __END__