line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
|
|
|
|
# Copyright (C) 2014 Rocky Bernstein <rocky@cpan.org> |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
# Part of Devel::Trepan::CmdProcessor that loads up debugger commands from |
5
|
|
|
|
|
|
|
# builtin and user directories. |
6
|
|
|
|
|
|
|
# Top-level command completion routines. |
7
|
12
|
|
|
12
|
|
85
|
use rlib '../../..'; |
|
12
|
|
|
|
|
29
|
|
|
12
|
|
|
|
|
111
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package Devel::Trepan::CmdProcessor; |
10
|
12
|
|
|
12
|
|
4222
|
use warnings; use strict; |
|
12
|
|
|
12
|
|
32
|
|
|
12
|
|
|
|
|
297
|
|
|
12
|
|
|
|
|
76
|
|
|
12
|
|
|
|
|
30
|
|
|
12
|
|
|
|
|
276
|
|
11
|
12
|
|
|
12
|
|
59
|
no warnings 'redefine'; |
|
12
|
|
|
|
|
28
|
|
|
12
|
|
|
|
|
417
|
|
12
|
12
|
|
|
12
|
|
3524
|
use Devel::Trepan::Complete; |
|
12
|
|
|
|
|
40
|
|
|
12
|
|
|
|
|
15291
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my $_list_complete_i = -1; |
15
|
|
|
|
|
|
|
sub list_complete($$$) |
16
|
|
|
|
|
|
|
{ |
17
|
0
|
|
|
0
|
0
|
0
|
my($self, $text, $state) = @_; |
18
|
|
|
|
|
|
|
# clear counter at the first call |
19
|
0
|
|
|
|
|
0
|
eval { state $_list_complete_i = -1; |
|
0
|
|
|
|
|
0
|
|
20
|
0
|
|
|
|
|
0
|
$_list_complete_i++;; |
21
|
|
|
|
|
|
|
}; |
22
|
0
|
|
|
|
|
0
|
my $cw = $self->{completions}; |
23
|
0
|
|
|
|
|
0
|
for (; $_list_complete_i <= $#{$cw}; $_list_complete_i++) { |
|
0
|
|
|
|
|
0
|
|
24
|
0
|
0
|
0
|
|
|
0
|
return $cw->[$_list_complete_i] |
25
|
|
|
|
|
|
|
if defined $cw->[$_list_complete_i] and ($cw->[$_list_complete_i] =~ /^\Q$text/); |
26
|
|
|
|
|
|
|
} |
27
|
0
|
|
|
|
|
0
|
return undef; |
28
|
|
|
|
|
|
|
}; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my ($_last_line, $_last_start, $_last_end, @_last_return, $_last_token); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Handle initial completion. We draw from the commands, aliases, |
34
|
|
|
|
|
|
|
# and macros for completion. However we won't include aliases which |
35
|
|
|
|
|
|
|
# are prefixes of other commands. |
36
|
|
|
|
|
|
|
sub complete($$$$$) |
37
|
|
|
|
|
|
|
{ |
38
|
18
|
|
|
18
|
0
|
9991
|
my ($self, $text, $line, $start, $end) = @_; |
39
|
18
|
|
|
|
|
48
|
$self->{leading_str} = $line; |
40
|
|
|
|
|
|
|
|
41
|
18
|
100
|
|
|
|
57
|
$_last_line = '' unless defined $_last_line; |
42
|
18
|
100
|
|
|
|
68
|
$_last_start = -1 unless defined $_last_start; |
43
|
18
|
100
|
|
|
|
55
|
$_last_end = -1 unless defined $_last_end; |
44
|
18
|
100
|
|
|
|
56
|
$_last_token = '' unless defined $_last_token; |
45
|
18
|
100
|
66
|
|
|
178
|
$_last_token = '' unless |
46
|
|
|
|
|
|
|
$_last_start < length($line) && |
47
|
|
|
|
|
|
|
0 == index(substr($line, $_last_start), $_last_token); |
48
|
|
|
|
|
|
|
# print "\ntext: $text, line: $line, start: $start, end: $end\n"; |
49
|
|
|
|
|
|
|
# print "\nlast_line: $_last_line, last_start: $_last_start, last_end: $last_end\n"; |
50
|
18
|
|
|
|
|
39
|
my $stripped_line; |
51
|
18
|
|
|
|
|
129
|
($stripped_line = $line) =~ s/\s*$//; |
52
|
18
|
50
|
33
|
|
|
88
|
if ($_last_line eq $stripped_line && $stripped_line) { |
53
|
0
|
|
|
|
|
0
|
$self->{completions} = \@_last_return; |
54
|
0
|
|
|
|
|
0
|
return @_last_return; |
55
|
|
|
|
|
|
|
} |
56
|
18
|
|
|
|
|
54
|
($_last_line, $_last_start, $_last_end) = ($line, $start, $end); |
57
|
|
|
|
|
|
|
|
58
|
18
|
|
|
|
|
40
|
my @commands = sort keys %{$self->{commands}}; |
|
18
|
|
|
|
|
405
|
|
59
|
18
|
|
|
|
|
117
|
my ($next_blank_pos, $token) = |
60
|
|
|
|
|
|
|
Devel::Trepan::Complete::next_token($line, 0); |
61
|
18
|
0
|
33
|
|
|
59
|
if (!$token && !$_last_token) { |
62
|
0
|
|
|
|
|
0
|
@_last_return = @commands; |
63
|
0
|
|
|
|
|
0
|
$_last_token = $_last_return[0]; |
64
|
0
|
|
|
|
|
0
|
$_last_line = $line . $_last_token; |
65
|
0
|
|
|
|
|
0
|
$_last_end += length($_last_token); |
66
|
0
|
|
|
|
|
0
|
$self->{completions} = \@_last_return; |
67
|
0
|
|
|
|
|
0
|
return (@commands); |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
18
|
|
33
|
|
|
51
|
$token ||= $_last_token; |
71
|
18
|
|
|
|
|
73
|
my @match_pairs = complete_token_with_next($self->{commands}, $token); |
72
|
|
|
|
|
|
|
|
73
|
18
|
|
|
|
|
48
|
my $match_hash = {}; |
74
|
18
|
|
|
|
|
48
|
for my $pair (@match_pairs) { |
75
|
22
|
|
|
|
|
83
|
$match_hash->{$pair->[0]} = $pair->[1]; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
my @alias_pairs = complete_token_filtered_with_next($self->{aliases}, |
79
|
|
|
|
|
|
|
$token, $match_hash, |
80
|
18
|
|
|
|
|
74
|
$self->{commands}); |
81
|
18
|
|
|
|
|
45
|
push @match_pairs, @alias_pairs; |
82
|
18
|
100
|
|
|
|
55
|
if ($next_blank_pos >= length($line)) { |
83
|
4
|
|
|
|
|
13
|
@_last_return = sort map {$_->[0]} @match_pairs; |
|
9
|
|
|
|
|
38
|
|
84
|
4
|
|
|
|
|
14
|
$_last_token = $_last_return[0]; |
85
|
4
|
50
|
|
|
|
16
|
if (defined($_last_token)) { |
86
|
4
|
|
|
|
|
13
|
$_last_line = $line . $_last_token; |
87
|
4
|
|
|
|
|
11
|
$_last_end += length($_last_token); |
88
|
|
|
|
|
|
|
} |
89
|
4
|
0
|
33
|
|
|
22
|
if (scalar @_last_return == 0 && $self->{settings}{autoeval}) { |
90
|
0
|
|
|
|
|
0
|
return Devel::Trepan::Complete::complete_subs($stripped_line); |
91
|
|
|
|
|
|
|
} |
92
|
4
|
|
|
|
|
15
|
$self->{completions} = \@_last_return; |
93
|
4
|
|
|
|
|
42
|
return @_last_return; |
94
|
|
|
|
|
|
|
} else { |
95
|
14
|
|
|
|
|
40
|
for my $pair (@alias_pairs) { |
96
|
0
|
|
|
|
|
0
|
$match_hash->{$pair->[0]} = $pair->[1]; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
} |
99
|
14
|
50
|
|
|
|
47
|
if (scalar(@match_pairs) > 1) { |
100
|
|
|
|
|
|
|
# FIXME: figure out what to do here. |
101
|
|
|
|
|
|
|
# Matched multiple items in the middle of the string |
102
|
|
|
|
|
|
|
# We can't handle this so do nothing. |
103
|
0
|
|
|
|
|
0
|
return (); |
104
|
|
|
|
|
|
|
# return match_pairs.map do |name, cmd| |
105
|
|
|
|
|
|
|
# ["#{name} #{args[1..-1].join(' ')}"] |
106
|
|
|
|
|
|
|
# } |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
# scalar @match_pairs == 1 |
109
|
14
|
|
|
|
|
66
|
@_last_return = $self->next_complete($line, $next_blank_pos, |
110
|
|
|
|
|
|
|
$match_pairs[0]->[1], |
111
|
|
|
|
|
|
|
$token); |
112
|
|
|
|
|
|
|
|
113
|
14
|
|
|
|
|
45
|
$self->{completions} = \@_last_return; |
114
|
14
|
50
|
66
|
|
|
59
|
if (scalar @_last_return == 0 && $self->{settings}{autoeval}) { |
115
|
2
|
|
|
|
|
8
|
return Devel::Trepan::Complete::complete_subs($stripped_line); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
12
|
|
|
|
|
106
|
return @_last_return; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub next_complete($$$$$) |
122
|
|
|
|
|
|
|
{ |
123
|
20
|
|
|
20
|
0
|
56
|
my($self, $str, $next_blank_pos, $cmd, $last_token) = @_; |
124
|
|
|
|
|
|
|
|
125
|
20
|
|
|
|
|
37
|
my $token; |
126
|
20
|
|
|
|
|
66
|
($next_blank_pos, $token) = |
127
|
|
|
|
|
|
|
Devel::Trepan::Complete::next_token($str, $next_blank_pos); |
128
|
20
|
50
|
66
|
|
|
89
|
return () if !$token && !$last_token; |
129
|
20
|
50
|
|
|
|
58
|
return () unless defined($cmd); |
130
|
20
|
50
|
|
|
|
106
|
return @{$cmd} if ref($cmd) eq 'ARRAY'; |
|
0
|
|
|
|
|
0
|
|
131
|
20
|
100
|
|
|
|
66
|
return $cmd->($token) if (ref($cmd) eq 'CODE'); |
132
|
|
|
|
|
|
|
|
133
|
19
|
100
|
|
|
|
164
|
if ($cmd->can("complete_token_with_next")) { |
|
|
50
|
|
|
|
|
|
134
|
15
|
|
|
|
|
69
|
my @match_pairs = $cmd->complete_token_with_next($token); |
135
|
15
|
50
|
|
|
|
57
|
return () unless scalar @match_pairs; |
136
|
15
|
100
|
|
|
|
48
|
if ($next_blank_pos >= length($str)) { |
137
|
9
|
|
|
|
|
25
|
return map {$_->[0]} @match_pairs; |
|
37
|
|
|
|
|
139
|
|
138
|
|
|
|
|
|
|
} else { |
139
|
6
|
50
|
|
|
|
16
|
if (scalar @match_pairs == 1) { |
140
|
6
|
50
|
66
|
|
|
37
|
if ($next_blank_pos == length($str)-1 |
|
|
50
|
|
|
|
|
|
141
|
|
|
|
|
|
|
&& ' ' ne substr($str, length($str)-1)) { |
142
|
0
|
|
|
|
|
0
|
return map {$_->[0]} @match_pairs; |
|
0
|
|
|
|
|
0
|
|
143
|
|
|
|
|
|
|
} elsif ($match_pairs[0]->[0] eq $token) { |
144
|
6
|
|
|
|
|
27
|
return $self->next_complete($str, $next_blank_pos, |
145
|
|
|
|
|
|
|
$match_pairs[0]->[1], |
146
|
|
|
|
|
|
|
$token); |
147
|
|
|
|
|
|
|
} else { |
148
|
0
|
|
|
|
|
0
|
return (); |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
} else { |
151
|
|
|
|
|
|
|
# FIXME: figure out what to do here. |
152
|
|
|
|
|
|
|
# Matched multiple items in the middle of the string |
153
|
|
|
|
|
|
|
# We can't handle this so do nothing. |
154
|
0
|
|
|
|
|
0
|
return (); |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
} elsif ($cmd->can('complete')) { |
158
|
4
|
|
|
|
|
14
|
my @matches = $cmd->complete($token); |
159
|
4
|
50
|
|
|
|
15
|
return () unless scalar @matches; |
160
|
4
|
50
|
|
|
|
19
|
if (substr($str, $next_blank_pos) =~ /\s*$/ ) { |
161
|
4
|
100
|
100
|
|
|
24
|
if (1 == scalar(@matches) && $matches[0] eq $token) { |
162
|
|
|
|
|
|
|
# Nothing more to complete. |
163
|
2
|
|
|
|
|
8
|
return (); |
164
|
|
|
|
|
|
|
} else { |
165
|
2
|
|
|
|
|
9
|
return @matches; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
} else { |
168
|
|
|
|
|
|
|
# FIXME: figure out what to do here. |
169
|
|
|
|
|
|
|
# Matched multiple items in the middle of the string |
170
|
|
|
|
|
|
|
# We can't handle this so do nothing. |
171
|
0
|
|
|
|
|
|
return (); |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
} else { |
174
|
0
|
|
|
|
|
|
return (); |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub filename_complete($$) { |
179
|
0
|
|
|
0
|
0
|
|
my ($self, $prefix) = @_; |
180
|
0
|
|
|
|
|
|
$self->{interfaces}[-1]->rl_filename_list($prefix); |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
unless (caller) { |
184
|
|
|
|
|
|
|
require Devel::Trepan::CmdProcessor; |
185
|
|
|
|
|
|
|
my $cmdproc = Devel::Trepan::CmdProcessor->new; |
186
|
|
|
|
|
|
|
# $cmdproc->run_cmd(['list', 5]); # Invalid - nonstring arg |
187
|
|
|
|
|
|
|
printf "complete('s') => %s\n", join(', ', $cmdproc->complete("s", 's', 0, 1)); |
188
|
|
|
|
|
|
|
printf "complete('') => %s\n", join(', ', $cmdproc->complete("", '', 0, 1)); |
189
|
|
|
|
|
|
|
printf "complete('help se') => %s\n", join(', ', $cmdproc->complete("help se", 'help se', 0, 1)); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
eval { |
192
|
|
|
|
|
|
|
sub complete_it($$) { |
193
|
0
|
|
|
0
|
0
|
|
my ($cmdproc, $str) = @_; |
194
|
0
|
|
|
|
|
|
my @c = $cmdproc->complete($str, $str, 0, length($str)); |
195
|
0
|
|
|
|
|
|
printf "complete('$str') => %s\n", join(', ', @c); |
196
|
0
|
|
|
|
|
|
return @c; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
}; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
my @c = complete_it($cmdproc, "set "); |
201
|
|
|
|
|
|
|
@c = complete_it($cmdproc, "help set base"); |
202
|
|
|
|
|
|
|
@c = complete_it($cmdproc, "set basename on "); |
203
|
|
|
|
|
|
|
my $str = './'; |
204
|
|
|
|
|
|
|
@c = $cmdproc->filename_complete($str); |
205
|
|
|
|
|
|
|
printf "complete('$str') => %s\n", join(', ', @c); |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
1; |