File Coverage

blib/lib/Syntax/Feature/Qi.pm
Criterion Covered Total %
statement 59 59 100.0
branch 5 6 83.3
condition n/a
subroutine 14 14 100.0
pod 0 1 0.0
total 78 80 97.5


line stmt bran cond sub pod time code
1 1     1   33572 use 5.10.0;
  1         2  
2 1     1   3 use strict;
  1         1  
  1         15  
3 1     1   2 use warnings;
  1         1  
  1         45  
4              
5             package Syntax::Feature::Qi;
6              
7             # ABSTRACT: Remove the same indendation from all lines in a string
8             our $AUTHORITY = 'cpan:CSSON'; # AUTHORITY
9             our $VERSION = '1.0000';
10              
11 1     1   405 use Devel::Declare();
  1         3596  
  1         20  
12 1     1   4 use B::Hooks::EndOfScope;
  1         1  
  1         6  
13 1     1   53 use Sub::Install qw/install_sub/;
  1         1  
  1         5  
14 1     1   460 use Devel::Declare::Context::Simple;
  1         1251  
  1         22  
15 1     1   5 use namespace::clean;
  1         1  
  1         4  
16              
17             my %quote_op = qw(qi q qqi qq);
18             my @new_ops = keys %quote_op;
19              
20             sub install {
21 1     1 0 3 my $class = shift;
22 1         3 my %args = @_;
23              
24 1         1 my $target = $args{'into'};
25              
26             Devel::Declare->setup_for($target => {
27             map {
28 1         1 my $name = $_;
  2         2  
29             ($name => {
30             const => sub {
31 17     17   657 my $context = Devel::Declare::Context::Simple->new;
32 17         71 $context->init(@_);
33 17         99 return $class->_transform($name, $context);
34             },
35 2         20 });
36             } @new_ops
37             });
38 1         21 foreach my $name (@new_ops) {
39 2         42 install_sub {
40             into => $target,
41             as => $name,
42             code => $class->_run_callback,
43             };
44             }
45             on_scope_end {
46 1     1   99 namespace::clean->clean_subroutines($target, @new_ops);
47 1         31 };
48 1         11 return 1;
49             }
50              
51             sub _run_callback {
52              
53             return sub ($) {
54 17     17   1138 my $string = shift;
55 17 100       66 return $string if $string =~ m{\A\s*\Z}ms;
56              
57 16 50       60 my $remove_indent = $string =~ m{\A(\h*)\S} ? $1
    100          
58             : $string =~ m{\A\s*\n(\h*)\S} ? $1
59             : ''
60             ;
61 16         141 $string =~ s{^$remove_indent}{}gms;
62 16         60 return $string;
63 2     2   8 };
64             }
65              
66             sub _transform {
67 17     17   13 my $class = shift;
68 17         10 my $name = shift;
69 17         14 my $ctx = shift;
70              
71 17         24 $ctx->skip_declarator;
72 17         228 my $length = Devel::Declare::toke_scan_str($ctx->offset);
73 17         91 my $string = Devel::Declare::get_lex_stuff;
74 17         19 Devel::Declare::clear_lex_stuff;
75 17         20 my $linestr = $ctx->get_linestr;
76 17         58 my $quoted = substr $linestr, $ctx->offset, $length;
77 17         42 my $spaced = '';
78 17         41 $quoted =~ m{^(\s*)}sm;
79 17         24 $spaced = $1;
80             my $new = sprintf '(%s)', join '',
81 17         55 $quote_op{$name},
82             $spaced,
83             substr($quoted, length($spaced), 1),
84             $string,
85             substr($quoted, -1, 1);
86 17         22 substr($linestr, $ctx->offset, $length) = $new;
87 17         57 $ctx->set_linestr($linestr);
88 17         158 return 1;
89             }
90              
91             1;
92              
93             __END__