our
$VERSION
=
'0.3a_pre1'
;
our
$DEBUG
= 0;
sub
expand {
my
(
$self
,
$string
,
$i_feel_lucky
) =
@_
;
my
(
$l_block
,
$block
);
(
$string
,
$l_block
) =
$self
->_get_last_block(
$string
);
if
(
$l_block
=~ /^\w*$/) {
$block
= [{
context
=>
'_WORDS'
},
$l_block
] }
else
{
$block
=
$self
->{parent}->_resolv_context(
$l_block
,
'BROKEN'
);
push
@{
$block
},
''
if
__is_word_cont(
$block
) &&
$l_block
=~ /\s$/;
}
$block
->[0]{i_feel_lucky} =
$i_feel_lucky
;
$block
->[0]{poss} = [];
$block
=
$self
->_do(
$block
,
$block
->[0]{context});
my
$poss
;
if
(
ref
(
$block
->[0]) eq
'ARRAY'
) {
(
$block
,
$poss
) =
$self
->_unwrap_nested_poss(@{
$block
});
}
else
{
$poss
=
$block
->[0]{poss} }
if
(
scalar
@{
$poss
}) {
my
(
$match
,
$winner
);
if
(
scalar
(@{
$poss
}) == 1) {
$winner
++;
$match
=
shift
@{
$poss
}
}
else
{
$match
=
$poss
->[0];
for
my
$p
(@{
$poss
}) {
while
(
$p
!~ /^\Q
$match
\E/) {
$match
=
substr
(
$match
, 0,
length
(
$match
)-1);
}
last
unless
$match
;
}
}
if
(
$match
) {
my
$m_l_block
=
$self
->_wrap(
$block
,
$match
,
$winner
);
return
(
$block
->[0]{message},
$string
.
$m_l_block
,
$poss
)
if
length
(
$m_l_block
) >
length
(
$l_block
);
}
}
return
(
$block
->[0]{message},
$string
.
$l_block
,
$poss
);
}
sub
_get_last_block {
my
(
$self
,
$string
) =
@_
;
my
@dinge
=
$self
->{parent}{StringParser}->
split
(
'script_gram'
,
$string
);
unless
(
scalar
(
@dinge
) &&
ref
$dinge
[-1]) {
return
(
$string
,
''
) }
my
$block
= ${
$dinge
[-1]};
$string
=~ s/\Q
$block
\E$//;
return
(
$string
,
$block
);
}
sub
_unwrap_nested_poss {
my
(
$self
,
@blocks
) =
@_
;
@blocks
=
grep
{
scalar
@{
$_
->[0]{poss}}}
@blocks
;
my
$poss
= [];
unless
(
scalar
@blocks
) {
unshift
@blocks
, [{}] }
elsif
(
scalar
(
@blocks
) == 1) {
$poss
=
$blocks
[0]->[0]{poss} }
else
{
$poss
= [
map
{ @{
$_
->[0]{poss}} }
@blocks
] }
return
(
$blocks
[0],
$poss
);
}
sub
_do {
my
(
$self
,
$block
,
$try
,
@try
) =
@_
;
print
"_do is gonna try $try ("
.
'i_'
.
lc
(
$try
).
")\n"
if
$DEBUG
;
return
$block
unless
$try
;
my
@re
;
if
(
ref
$try
) {
@re
=
$try
->(
$self
,
$block
,
@try
) }
elsif
(
exists
$self
->{parent}{contexts}{
lc
(
$try
).
'_intel'
}) {
@re
=
$self
->{parent}{contexts}{
lc
(
$try
).
'_intel'
}->(
$self
,
$block
,
@try
)
}
elsif
(
$self
->can(
'i_'
.
lc
(
$try
))) {
my
$sub
=
'i_'
.
lc
(
$try
);
@re
=
$self
->
$sub
(
$block
,
@try
);
}
else
{ error
$try
.
': no such expansion available'
}
unless
(
scalar
@re
) {
return
scalar
(
@try
) ?
$self
->_do(
$block
,
@try
) :
$block
}
elsif
(
scalar
(
@re
) == 1) {
return
$re
[0] }
else
{
$self
->_do(
@re
,
@try
) }
}
sub
_wrap {
my
(
$self
,
$block
,
$string
,
$winner
) =
@_
;
return
''
unless
__is_word_cont(
$block
);
$string
=
$block
->[0]{pref}.
$string
if
$block
->[0]{pref};
$block
->[-1] =
$string
if
@{
$block
};
my
$re
=
join
(
' '
, @{
$block
}[1 .. $
$re
.=
' '
if
$winner
&&
$string
!~ m
return
$re
;
}
sub
__is_word_cont {
grep
{
$_
eq
lc
(
$_
[0]->[0]{context})}
qw/_words cmd sh/
}
sub
i__words {
my
(
$self
,
$block
) =
@_
;
my
@poss
=
$self
->{parent}->list_commands;
push
@poss
, list_path();
for
(
$self
->{parent}{_words_contexts}) {
push
@poss
,
$self
->{parent}{contexts}{
$_
.
'_list'
}->()
if
exists
$self
->{parent}{contexts}{
$_
.
'_list'
};
}
@poss
=
grep
/^\Q
$block
->[-1]\E/,
@poss
;
$block
->[0]{poss} = \
@poss
;
return
$block
;
}
sub
i_sh {
my
(
$self
,
$block
) =
@_
;
return
(
$block
, (
$block
->[-1] =~ /^-/) ?
'_man_opts'
:
'_files_n_dirs'
);
}
sub
i_cmd {
return
(
$_
[1],
'_files_n_dirs'
) }
sub
i__files_n_dirs {
my
(
$self
,
$block
) =
@_
;
my
$arg
=
$block
->[-1];
my
$dir
= (
$arg
=~ s!^(.*/)!!) ? abs_path($1) :
'.'
;
$block
->[0]{pref} = $1;
print
"Expanding files from dir: $dir with arg: -->$arg<--\n"
if
$DEBUG
;
$dir
= get_dir(
$dir
);
$block
->[0]{poss} = [
grep
/^\Q
$arg
\E/,
map
( {
$_
.
'/'
} @{
$dir
->{dirs}} ),
@{
$dir
->{files}},
];
print
"Got "
.
scalar
(@{
$block
->[0]{poss}}).
" matches\n"
if
$DEBUG
;
return
$block
;
}
1;