File Coverage

blib/lib/App/Greple/frame.pm
Criterion Covered Total %
statement 17 41 41.4
branch 0 20 0.0
condition 0 8 0.0
subroutine 6 13 46.1
pod 1 6 16.6
total 24 88 27.2


line stmt bran cond sub pod time code
1             package App::Greple::frame;
2              
3             our $VERSION = "0.07";
4              
5             =encoding utf-8
6              
7             =head1 NAME
8              
9             App::Greple::frame - Greple frame output module
10              
11             =head1 SYNOPSIS
12              
13             greple -Mframe --frame ...
14              
15             =head1 DESCRIPTION
16              
17             Greple -Mframe module provide a capability to put surrounding frames
18             for each blocks.
19              
20             C, C and C frames are printed for blocks.
21              
22             By default B<--join-blocks> option is enabled to collect consecutive
23             lines into a single block. If you don't like this, override it by
24             B<--no-join-blocks> option.
25              
26             =head1 OPTIONS
27              
28             =over 7
29              
30             =item B<--frame>
31              
32             =for comment
33             =item B<--frame-fold>
34              
35             Set frame and fold long lines with frame-friendly prefix string.
36             Folding width is taken from the terminal. Or you can specify the
37             width by calling B function with module option.
38              
39             =item B<--set-frame-width>=I<#>
40              
41             Set frame width. You have to put this option before B<--frame>
42             option. See B function in L section.
43              
44             =begin comment
45              
46             =item B<--frame-simple>
47              
48             Set frame without folding.
49              
50             =end comment
51              
52             =back
53              
54             =begin comment
55              
56             Put next line in your F<~/.greplerc> to autoload B module.
57              
58             autoload -Mframe --frame
59              
60             Then you can use B<--frame> option whenever you want.
61              
62             =end comment
63              
64             =begin html
65              
66            

67              
68             =end html
69              
70             =head1 FUNCTION
71              
72             =over 7
73              
74             =item B(B=I)
75              
76             Set terminal width to I. Use like this:
77              
78             greple -Mframe::set(width=80) ...
79              
80             greple -Mframe::set=width=80 ...
81              
82             If non-digit character is found in the value part, it is considered as
83             a Reverse Polish Notation, starting terminal width pushed on the
84             stack. RPN C<2/3-> means C.
85              
86             You can use like this:
87              
88             greple -Mframe::set=width=2/3- --frame --uc '(\w+::)+\w+' --git | ansicolumn -PC2
89              
90             =begin html
91              
92            

93              
94             =end html
95              
96             =back
97              
98             =head1 SEE ALSO
99              
100             L
101              
102             L
103              
104             =head1 AUTHOR
105              
106             Kazumasa Utashiro
107              
108             =head1 LICENSE
109              
110             Copyright 2022 Kazumasa Utashiro.
111              
112             This library is free software; you can redistribute it and/or modify
113             it under the same terms as Perl itself.
114              
115             =cut
116              
117 1     1   804 use 5.014;
  1         3  
118 1     1   4 use warnings;
  1         2  
  1         32  
119 1     1   594 use utf8;
  1         12  
  1         4  
120 1     1   460 use Data::Dumper;
  1         5881  
  1         118  
121              
122             my($mod, $argv);
123             my($head, $blockend, $file_start, $file_end);
124              
125             my %param = (
126             width => undef,
127             column => undef,
128             fold => '',
129             );
130              
131             sub terminal_width {
132 1     1   474 use Term::ReadKey;
  1         1908  
  1         486  
133 0     0 0   my $default = 80;
134 0           my @size;
135 0 0         if (open my $tty, ">", "/dev/tty") {
136             # Term::ReadKey 2.31 on macOS 10.15 has a bug in argument handling
137             # and the latest version 2.38 fails to install.
138             # This code should work on both versions.
139 0           @size = GetTerminalSize $tty, $tty;
140             }
141 0 0         $size[0] or $default;
142             }
143              
144             sub finalize {
145 0     0 0   ($mod, $argv) = @_;
146             }
147              
148             my %frame_base = (
149             top => ' ┌─' ,
150             middle => ' ⋮ ├╶' ,
151             bottom => '──────┴─' ,
152             );
153              
154             sub opt_frame {
155 0     0 0   my $pos = shift;
156 0   0       my $width = $param{width} //= terminal_width;
157 0 0         local $_ = $frame_base{$pos} or die;
158 0 0         if ((my $rest = $width - length) > 0) {
159 0           $_ .= (substr($_, -1, 1) x $rest);
160             }
161 0           $_;
162             }
163              
164             my %rpn = (
165             width => { init => sub { terminal_width } },
166             column => { init => sub { terminal_width } },
167             );
168             sub rpn {
169 0     0 0   my($k, $v) = @_;
170             require Getopt::EX::RPN
171 0 0         and Getopt::EX::RPN->import('rpn_calc');
172 0   0       my $init = $rpn{$k}->{init} // die;
173 0 0         my @init = ref $init ? $init->() : $init ? $init : ();
    0          
174 0 0         int(rpn_calc(@init, $v)) or die "$v: format error\n";
175             }
176              
177             sub set {
178 0     0 1   while (my($k, $v) = splice(@_, 0, 2)) {
179 0 0         exists $param{$k} or next;
180 0 0 0       $v = rpn($k, $v) if $rpn{$k} and $v =~ /\D/;
181 0           $param{$k} = $v;
182             }
183 0           ();
184             }
185              
186             sub get {
187 1     1   12 use List::Util qw(pairmap);
  1         2  
  1         157  
188 0     0 0   pairmap { $param{$a} } @_;
  0     0      
189             }
190              
191             1;
192              
193             __DATA__