File Coverage

blib/lib/App/Greple/line.pm
Criterion Covered Total %
statement 29 57 50.8
branch 0 8 0.0
condition 0 3 0.0
subroutine 10 15 66.6
pod 0 3 0.0
total 39 86 45.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             line - Greple module to produce result by line numbers
4              
5             =head1 SYNOPSIS
6              
7             greple -Mline
8              
9             =head1 DESCRIPTION
10              
11             This module allows you to use line numbers to specify patterns or
12             regions which can be used in B options.
13              
14             =over 7
15              
16             =item B<-L>=I
17              
18             Simply, next command will show 200th line with before/after 10 lines
19             of the file:
20              
21             greple -Mline -L 200 -C10 file
22              
23             If you don't like lines displayed with color, use B<--nocolor> option
24             or set colormap to something do nothing like B<--cm=N>.
25              
26             Multiple lines can be specified by joining with comma:
27              
28             greple -Mline -L 10,20,30
29              
30             It is ok to use B<-L> option multiple times, like:
31              
32             greple -Mline -L 10 -L 20 -L 30
33              
34             But this command produce nothing, because each line definitions are
35             taken as a different pattern, and B prints lines only when all
36             patterns matched. You can relax the condition by C<--need 1> option
37             in such case, then you will get expected result. Next example will
38             display 10th, 20th and 30th lines in different colors.
39              
40             greple -Mline -L 10 -L 20 -L 30 --need 1
41              
42             Range can be specified by colon:
43              
44             greple -Mline -L 10:20
45              
46             You can also specify the step with range. Next command will print
47             all even lines from line 10 to 20:
48              
49             greple -Mline -L 10:20:2
50              
51             Any of them can be omitted. Next commands print all, odd and even
52             lines.
53              
54             greple -Mline -L :: # all lines
55             greple -Mline -L ::2 # odd lines
56             greple -Mline -L 2::2 # even lines
57              
58             If start and end number is negative, they are subtracted from the
59             maxmum line number. If the end number is prefixed by plus (`+') sign,
60             it is summed with start number. Next commands print top and last 10
61             lines respectively.
62              
63             greple -Mline -L :+9 # top 10 lines
64             greple -Mline -L -9: # last 10 lines
65              
66             Next example print all lines of the file, each line in four different
67             colors.
68              
69             greple -Mline -L=1::4 -L=2::4 -L=3::4 -L=4::4 --need 1
70              
71             If forth parameter is given, it describes how many lines is included
72             in that step cycle. For example, next command prints top 3 lines in
73             every 10 lines.
74              
75             greple -Mline -L ::10:3
76              
77             When step count is omitted, forth value is used if available. Next
78             command print every 10 lines in different colors.
79              
80             greple -Mline -L :::10 --ci=A /etc/services
81              
82             =item B=I
83              
84             This notation just define function spec, which can be used in
85             patterns, as well as blocks and regions. Actually, B<-L>=I is
86             equivalent to B<--le> B=I.
87              
88             Next command show patterns found in line number 1000-2000 area.
89              
90             greple -Mline --inside L=1000:+1000 pattern
91              
92             Next command prints all 10 line blocks which include the pattern.
93              
94             greple -Mline --block L=:::10 pattern
95              
96             In this case, however, it is faster and easier to use regex.
97              
98             greple --block '(.*\n){1,10}' pattern
99              
100             =item B<--offload>=I
101              
102             Set the offload command to retrieve the desired line numbers. The
103             numbers in the output, starting at the beginning of the line, are
104             treated as line numbers. This is compatible with B output.
105              
106             =back
107              
108             Using this module, it is impossible to give single C in command
109             line arguments. Use like B<--le=L> to search letter C. You have a
110             file named F? Stop substitution by placing C<--> before the target
111             files.
112              
113             =head1 SEE ALSO
114              
115             L
116              
117             =cut
118              
119             package App::Greple::line;
120              
121 1     1   68884 use v5.14;
  1         12  
122 1     1   5 use warnings;
  1         2  
  1         23  
123              
124 1     1   5 use Carp;
  1         2  
  1         70  
125 1     1   7 use List::Util qw(min max reduce);
  1         2  
  1         106  
126 1     1   631 use Data::Dumper;
  1         6938  
  1         64  
127              
128 1     1   7 use Exporter qw(import);
  1         2  
  1         43  
129             our @EXPORT = qw(&line &offload);
130              
131 1     1   6 use List::Util qw(any pairmap);
  1         2  
  1         62  
132 1     1   383 use App::Greple::Common;
  1         2  
  1         143  
133 1     1   416 use App::Greple::Regions qw(match_borders borders_to_regions);
  1         5  
  1         138  
134              
135             sub line_to_region {
136 0     0 0   state $target = -1;
137 0           state @lines;
138 0 0         if ($target != \$_) {
139 0           @lines = ([0, 0], borders_to_regions match_borders qr/^/m);
140 0           $target = \$_;
141             }
142 1     1   449 use Getopt::EX::Numbers;
  1         7736  
  1         471  
143 0           my $numbers = Getopt::EX::Numbers->new(min => 1, max => $#lines);
144 0           my @result = do {
145 0           map { [ $lines[$_->[0]]->[0], $lines[$_->[1]]->[1] ] }
146 0           sort { $a->[0] <=> $b->[0] }
147 0           map { $numbers->parse($_)->range }
148 0           map { split /,+/ }
  0            
149             @_;
150             };
151 0           @result;
152             }
153              
154             sub line {
155 0 0   0 0   my @lines = pairmap { $a ne &FILELABEL ? $a : () } @_;
  0     0      
156 0           line_to_region(@lines);
157             }
158              
159             sub offload {
160 0     0 0   our $offload_command;
161 0           my $result = qx($offload_command || die);
162 0           my @lines = do {
163             map {
164 0           my($a, $b) = @$_;
165 0 0         $a == $b ? "$a" : "$a:$b"
166             }
167 0           map { @$_ }
168             reduce {
169 0 0 0 0     if (@$a > 0 and $a->[-1][1] + 1 == $b) {
170 0           $a->[-1][1] = $b;
171             } else {
172 0           push @$a, [ $b, $b ];
173             }
174 0           $a;
175             }
176 0           [], $result =~ /^\d+/mg;
177             };
178 0           line_to_region(@lines);
179             }
180              
181             1;
182              
183             __DATA__