File Coverage

blib/lib/Regexp/Common/ANSIescape.pm
Criterion Covered Total %
statement 57 57 100.0
branch n/a
condition n/a
subroutine 19 19 100.0
pod n/a
total 76 76 100.0


line stmt bran cond sub pod time code
1             # Copyright 2008, 2009, 2010, 2011, 2012 Kevin Ryde
2              
3             # This file is part of Regexp-Common-Other.
4             #
5             # Regexp-Common-Other is free software; you can redistribute it and/or
6             # modify it under the terms of the GNU General Public License as published
7             # by the Free Software Foundation; either version 3, or (at your option) any
8             # later version.
9             #
10             # Regexp-Common-Other is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13             # Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Regexp-Common-Other. If not, see .
17              
18             package Regexp::Common::ANSIescape;
19 1     1   21941 use 5.005;
  1         4  
  1         51  
20 1     1   7 use strict;
  1         1  
  1         37  
21 1     1   6 use Carp;
  1         6  
  1         88  
22             # no import(), don't want %RE or builtins, and can call pattern() by full name
23 1     1   6 use Regexp::Common ();
  1         2  
  1         20  
24              
25 1     1   5 use vars '$VERSION';
  1         2  
  1         72  
26             $VERSION = 11;
27              
28             ## no critic (ProhibitEscapedCharacters)
29              
30              
31 1     1   6 use constant CSI_7BIT => "\e\\\x5B"; # ie. Esc and a literal [ char
  1         2  
  1         89  
32 1     1   5 use constant CSI_8BIT => "\x9B";
  1         2  
  1         57  
33              
34             # C1 Esc @ through Esc _
35             # excluding CSI which is Esc 0x5B, and 0x9B
36             # Note \x5C is "\" so doubled to escape.
37             #
38 1     1   5 use constant C1_ALL_7BIT => "\e[\x40-\x5A\\\x5C-\x5F]";
  1         1  
  1         99  
39 1     1   5 use constant C1_ALL_8BIT => "[\x80-\x9A\x9C-\x9F]";
  1         2  
  1         57  
40              
41             # C1 forms taking a string parameter
42             #
43             # DCS Esc P (0x50 / 0x90)
44             # SOS Esc X (0x58 / 0x98)
45             # OSC Esc ] (0x5D / 0x9D)
46             # PM Esc ^ (0x5E / 0x9E)
47             # APC Esc _ (0x5F / 0x9F)
48             #
49             # Note \x5D "]" first in the char class, and \x5E "^" not first.
50             #
51 1     1   4 use constant C1_STR_7BIT => "\e[\x5D\x50\x58\x5E\x5F]";
  1         2  
  1         47  
52 1     1   5 use constant C1_STR_8BIT => "[\x9D\x90\x98\x9E\x9F]";
  1         2  
  1         53  
53              
54             # "character string" is anything except SOS or ST
55 1     1   4 use constant CHAR_STR => "(.|\n)*?";
  1         2  
  1         56  
56              
57             # C1 forms not taking a string parameter
58             # this is C1_ALL except the five in C1_STR (and not CSI 0x5B,0x9B)
59             # Note \x5C "\" doubled to escape.
60             #
61 1     1   5 use constant C1_NST_7BIT => "\e[\x40-\x4F\x51-\x57\x59\x5A\\\x5C]";
  1         1  
  1         43  
62 1     1   18 use constant C1_NST_8BIT => "[\x80-\x8F\x91-\x97\x99\x9A\x9C]";
  1         2  
  1         46  
63              
64             # ST string terminator
65 1     1   5 use constant ST_7BIT => "\e\\\\"; # ie. Esc and a backslash
  1         1  
  1         58  
66 1     1   13 use constant ST_8BIT => "\x9C";
  1         1  
  1         78  
67              
68 1     1   6 use constant CSI_7OR8 => '(?:'. CSI_7BIT .'|'. CSI_8BIT .')';
  1         2  
  1         70  
69 1     1   5 use constant C1_STR_7OR8 => '(?:'. C1_STR_7BIT .'|'. C1_STR_8BIT .')';
  1         2  
  1         69  
70 1     1   5 use constant ST_7OR8 => '(?:'. ST_7BIT .'|'. ST_8BIT .')';
  1         2  
  1         1846  
71              
72              
73             Regexp::Common::pattern
74             (name => ['ANSIescape'],
75             create => sub {
76             my ($self, $flags) = @_;
77              
78             if (exists $flags->{-only7bit} && exists $flags->{-only8bit}) {
79             croak 'ANSIescape: cannot have only7bit and only8bit at the same time';
80             }
81              
82             my @ret;
83             push @ret, (exists $flags->{-only7bit} ? CSI_7BIT # 7-bit only
84             : exists $flags->{-only8bit} ? CSI_8BIT # 8-bit only
85             : CSI_7OR8) # 7bit or 8bit
86             . "(?k:[\x30-\x3F]*)(?k:[\x20-\x2F]*[\x40-\x7E])";
87              
88             if (exists $flags->{-sepstring}) {
89             if (! exists $flags->{-only8bit}) { push @ret, C1_ALL_7BIT; }
90             if (! exists $flags->{-only7bit}) { push @ret, C1_ALL_8BIT; }
91              
92             } else {
93             if (! exists $flags->{-only8bit}) { push @ret, C1_NST_7BIT; }
94             if (! exists $flags->{-only7bit}) { push @ret, C1_NST_8BIT; }
95              
96             if (exists $flags->{-only7bit}) {
97             push @ret, C1_STR_7BIT . CHAR_STR . ST_7BIT; # 7-bit only
98             } elsif (exists $flags->{-only8bit}) {
99             push @ret, C1_STR_8BIT . CHAR_STR . ST_8BIT; # 8-bit only
100             } else {
101             push @ret, C1_STR_7OR8 . CHAR_STR . ST_7OR8; # 7-bit or 8-bit
102             }
103             }
104             return '(?k:' . join('|',@ret) . ')';
105             });
106              
107              
108             # Some stuff which might have distinguished SOS taking "character string"s
109             # from others taking only "command string" chars
110             #
111             # C1_SOS_7BIT => "\e[\x58]";
112             # C1_SOS_8BIT => "[\x98]";
113             # C1_SOS_7OR8 => '(?:'. C1_SOS_7BIT .'|'. C1_SOS_8BIT .')';
114             # # "command string" is Backspace, Tab, LF, VT, FF, CR and printables
115             # CMD_STR => "[\x08-\x0D\x20-\x7E]*?",
116             # push @ret, C1_SOS_7BIT . CHAR_STR . ST_7BIT;
117             # push @ret, C1_SOS_8BIT . CHAR_STR . ST_8BIT;
118             # push @ret, C1_SOS_7OR8 . CHAR_STR . ST_7OR8;
119             #
120              
121             1;
122              
123             __END__