#!perl
use
5.026;
use
open
qw(:std :utf8)
;
our
$VERSION
=
'0.014'
;
binmode
STDOUT,
':utf8'
;
my
%r
= (
u
=>
qr/(?:U\+?(?<hex>[0-9A-F]+))/
i,
h
=>
qr/(?:0x(?<hex>[0-9A-F]+))/
i,
d
=>
qr/(?:(?<int>[0-9]+))/
,
);
my
%transformation
= (
'hex'
=>
sub
{
hex
$_
[0] },
'int'
=>
sub
{
$_
[0] },
);
my
$codeset
= langinfo(CODESET);
@ARGV
=
map
{ decode
$codeset
,
$_
}
@ARGV
;
run(
@ARGV
)
unless
caller
;
sub
run (
@args
) {
foreach
(
@args
) {
say
"Processing $_"
;
if
( / \A (?:
$r
{u} |
$r
{h} |
$r
{d} ) \z /x ) {
my
(
$key
) =
keys
%+;
my
$code
=
$transformation
{
$key
}( $+{
$key
} );
output(
$code
,
'code point'
);
}
elsif
( / \A ([A-Z\s]{2,}) \z /ix ) {
my
$code
=
eval
{ charnames::vianame(
uc
($1) ) };
unless
(
defined
$code
) {
say
"\tCouldn't match <$1> to a code name"
;
next
;
}
output(
$code
,
'name'
);
}
elsif
( / \A (\X) \z /x ) {
output(
ord
( $1 ),
'grapheme'
);
}
elsif
( / \A r: ([A-Z\s]{2,}) \z /ix ) {
state
$names
= name_list();
say
"In elsif"
;
$pattern
=
eval
{
qr/$pattern/
i };
if
( $@ ) {
warn
"Invalid pattern --> $pattern ---> $@\n"
;
exit
(4);
}
foreach
my
$name
(
keys
$names
->%* ) {
say
"Tring $name"
;
next
unless
$name
=~ m/
$pattern
/;
output(
$names
->{
$name
},
'pattern'
);
}
}
else
{
say
"\tInvalid character, codepoint, or pattern --> $_\n"
;
next
;
}
}
}
sub
name_list () {
state
$names
= {
map
{ charnames::viacode(
$_
),
$_
} 0 .. 0x3FFFF };
return
$names
;
}
sub
output (
$code
,
$match
) {
my
$hex
=
sprintf
'U+%04X'
,
$code
;
my
$char
=
chr
(
$code
);
$char
=
'<unprintable>'
if
$char
!~ /\p{Print}/;
$char
=
'<whitespace>'
if
$char
=~ /\p{Space}/;
$char
=
'<control>'
if
$char
=~ /\p{Control}/;
my
$name
= charnames::viacode(
$code
) //
'<no name found>'
;
print
<<~
"HERE"
;
match type
$match
code point
$hex
decimal
$code
name
$name
character
$char
HERE
}