—package
App::vaporcalc::Role::UI::ParseCmd;
$App::vaporcalc::Role::UI::ParseCmd::VERSION
=
'0.003002'
;
use
Defaults::Modern;
use
Text::ParseWords;
use
Role::Tiny;
requires
'subject_list'
;
method parse_cmd (Str
$str
) {
# e.g.:
# set nic base 100
# nic base set 100
my
(
$subj
,
$verb
);
my
$params
= array;
# FIXME
# alternate approach to find first subj in line:
# split line into words and pairs ARRAY
# > notes add Flavor too strong
# # [ 'notes', 'notes add', 'add', 'add Flavor', 'Flavor', .. ]
# walk for first valid subj
# die if none
# remove subj and pairs from ARRAY
# # [ 'add', 'Flavor', .. ]
# remainder is $pieces
# verb is $pieces->shift
# test for same
my
@subjs
= array(@{
$self
->subject_list })
->nsort_by(
sub
{
length
})
->
reverse
->all;
SUBJ:
for
my
$maybe
(
@subjs
) {
my
$idx
=
index
$str
,
$maybe
;
next
SUBJ
if
$idx
== -1;
no
warnings
'substr'
;
if
(
$idx
> 0) {
my
$prevchar
=
substr
$str
, (
$idx
- 1), 1;
next
SUBJ
unless
$prevchar
eq
' '
;
}
if
( (
my
$pos
=
$idx
+
length
(
$maybe
)) <
length
$str
) {
my
$nextchar
=
substr
$str
,
$pos
, 1;
next
SUBJ
unless
$nextchar
eq
' '
;
}
$subj
=
$maybe
;
substr
$str
,
$idx
,
length
(
$maybe
),
' '
;
my
$pieces
= array(
split
' '
,
$str
);
$verb
=
$pieces
->
shift
;
$params
= array(
Text::ParseWords::parse_line(
'\s+'
, 0,
$pieces
->
join
(
' '
))
);
last
SUBJ
}
unless
(
$subj
) {
App::vaporcalc::Exception->throw(
message
=>
"No subject to operate on"
,
)
}
hash(
subject
=>
$subj
,
verb
=>
$verb
,
params
=>
$params
)->inflate
}
1;
=pod
=head1 NAME
App::vaporcalc::Role::UI::ParseCmd
=head1 SYNOPSIS
package MyCmdParser;
use Moo;
has subject_list => (
is => 'ro',
builder => sub {
[ 'nic base', 'flavor' ]
},
);
with 'App::vaporcalc::Role::UI::ParseCmd';
package main;
my $parser = MyCmdParser->new;
# Same as:
# my $result = $parser->parse_cmd("nic base set 100");
my $result = $parser->parse_cmd("set nic base 100");
my $subj = $result->subject; # 'nic base'
my $verb = $result->verb; # 'set'
my $params = $result->params; # params as a List::Objects::WithUtils::Array
=head1 DESCRIPTION
A L<Moo::Role> for parsing command strings based on a list of valid subjects.
=head2 REQUIRES
=head3 subject_list
The C<subject_list> method is expected to return an ARRAY or ARRAY-type object
containing a list of valid subjects.
=head2 METHODS
=head3 parse_cmd
Given a string, returns an inflated L<List::Objects::WithUtils::Hash>
with C<subject>, C<verb>, and C<params> accessors (see SYNOPSIS).
Used by L<App::vaporcalc::CmdEngine> to parse B<vaporcalc> commands.
=head1 AUTHOR
Jon Portnoy <avenj@cobaltirc.org>
=cut