File Coverage

blib/lib/App/unichar.pm
Criterion Covered Total %
statement 26 72 36.1
branch 0 20 0.0
condition 0 2 0.0
subroutine 9 12 75.0
pod 0 3 0.0
total 35 109 32.1


line stmt bran cond sub pod time code
1             #!perl
2              
3             package App::unichar;
4              
5 1     1   267756 use 5.026;
  1         2  
6 1     1   544 use utf8;
  1         257  
  1         6  
7 1     1   29 use warnings;
  1         2  
  1         39  
8 1     1   883 use open qw(:std :utf8);
  1         1261  
  1         7  
9 1     1   600 use experimental qw(signatures);
  1         1314  
  1         4  
10              
11             our $VERSION = '0.014';
12              
13             =encoding utf8
14              
15             =pod
16              
17             =head1 NAME
18              
19             App::unichar - get info about a character
20              
21             =head1 SYNOPSIS
22              
23             Call it as a program with a name, character, or hex code number:
24              
25             % perl lib/App/unichar.pm 'CHECK MARK'
26             Processing CHECK MARK
27             match type name
28             code point U+2713
29             decimal 10003
30             name CHECK MARK
31             character ✓
32              
33             % perl lib/App/unichar.pm ✓
34             Processing ✓
35             match type grapheme
36             code point U+2713
37             decimal 10003
38             name CHECK MARK
39             character ✓
40              
41             % perl lib/App/unichar.pm 0x2713
42             Processing 0x2713
43             match type code point
44             code point U+2713
45             decimal 10003
46             name CHECK MARK
47             character ✓
48              
49             =head1 DESCRIPTION
50              
51             I use this as a little command-line program to quickly convert between
52             values of characters.
53              
54             =head1 AUTHOR
55              
56             brian d foy, C.
57              
58             =head1 SOURCE AVAILABILITY
59              
60             This module is in Github:
61              
62             https://github.com/briandfoy/app-unichar
63              
64             =head1 COPYRIGHT & LICENSE
65              
66             Copyright 2011-2024 brian d foy
67              
68             This module is licensed under the Artistic License 2.0.
69              
70             =cut
71              
72 1     1   189 use Encode qw(decode);
  1         2  
  1         92  
73 1     1   563 use I18N::Langinfo qw(langinfo CODESET);
  1         834  
  1         139  
74              
75 1     1   861 use charnames ();
  1         11146  
  1         48  
76 1     1   10 use List::Util;
  1         2  
  1         41348  
77              
78             binmode STDOUT, ':utf8';
79              
80             my %r = (
81             u => qr/(?:U\+?(?[0-9A-F]+))/i,
82             h => qr/(?:0x(?[0-9A-F]+))/i,
83             d => qr/(?:(?[0-9]+))/,
84             );
85              
86             my %transformation = (
87             'hex' => sub { hex $_[0] },
88             'int' => sub { $_[0] },
89             );
90              
91             my $codeset = langinfo(CODESET);
92             @ARGV = map { decode $codeset, $_ } @ARGV;
93              
94             run( @ARGV ) unless caller;
95              
96 0     0 0   sub run (@args) {
  0            
  0            
97 0           foreach ( @args ) {
98 0           say "Processing $_";
99              
100 0 0         if( / \A (?: $r{u} | $r{h} | $r{d} ) \z /x ) {
    0          
    0          
    0          
101 0           my( $key ) = keys %+;
102 0           my $code = $transformation{$key}( $+{$key} );
103 0           output( $code, 'code point' );
104             }
105             elsif( / \A ([A-Z\s]{2,}) \z /ix ) {
106 0           my $code = eval { charnames::vianame( uc($1) ) };
  0            
107 0 0         unless( defined $code ) {
108 0           say "\tCouldn't match <$1> to a code name";
109 0           next;
110             }
111 0           output( $code, 'name' );
112             }
113             elsif( / \A (\X) \z /x ) {
114 0           output( ord( $1 ), 'grapheme' );
115             }
116             elsif( / \A r: ([A-Z\s]{2,}) \z /ix ) { # new regex mode
117 0           state $names = name_list();
118 0           say "In elsif";
119 0           my $pattern = s/\Ar://r;
120 0           $pattern = eval{ qr/$pattern/i };
  0            
121 0 0         if( $@ ) {
122 0           warn "Invalid pattern --> $pattern ---> $@\n";
123 0           exit(4);
124             }
125              
126 0           foreach my $name ( keys $names->%* ) {
127 0           say "Tring $name";
128 0 0         next unless $name =~ m/$pattern/;
129 0           output( $names->{$name}, 'pattern' );
130             }
131             }
132             else {
133 0           say "\tInvalid character, codepoint, or pattern --> $_\n";
134 0           next;
135             }
136             }
137             }
138              
139 0     0 0   sub name_list () {
  0            
140 0           state $names = { map { charnames::viacode($_), $_ } 0 .. 0x3FFFF };
  0            
141 0           return $names;
142             }
143              
144 0     0 0   sub output ( $code, $match ) {
  0            
  0            
  0            
145 0           my $hex = sprintf 'U+%04X', $code;
146 0           my $char = chr( $code );
147 0 0         $char = '' if $char !~ /\p{Print}/;
148 0 0         $char = '' if $char =~ /\p{Space}/;
149 0 0         $char = '' if $char =~ /\p{Control}/;
150              
151 0   0       my $name = charnames::viacode( $code ) // '';
152              
153 0           print <<~"HERE";
154             match type $match
155             code point $hex
156             decimal $code
157             name $name
158             character $char
159              
160             HERE
161              
162             }