rb8-trepanning 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/ChangeLog +276 -0
- data/Makefile +13 -0
- data/Rakefile +1 -2
- data/app/display.rb +41 -1
- data/app/irb.rb +55 -49
- data/app/options.rb +3 -2
- data/app/run.rb +25 -7
- data/app/util.rb +19 -1
- data/bin/trepan8 +0 -2
- data/data/perldb.bindings +17 -0
- data/interface/script.rb +1 -1
- data/interface/server.rb +1 -1
- data/interface/user.rb +3 -1
- data/{interface/base_intf.rb → interface.rb} +1 -1
- data/io/input.rb +1 -1
- data/io/null_output.rb +1 -1
- data/io/string_array.rb +2 -2
- data/io/tcpclient.rb +1 -1
- data/io/tcpserver.rb +1 -1
- data/{io/base_io.rb → io.rb} +0 -0
- data/lib/debugger.rb +0 -1
- data/lib/trepanning.rb +3 -1
- data/processor/command/alias.rb +13 -2
- data/processor/command/backtrace.rb +2 -1
- data/processor/command/base/subcmd.rb +1 -5
- data/processor/command/base/submgr.rb +1 -1
- data/processor/command/base/subsubcmd.rb +1 -1
- data/processor/command/base/subsubmgr.rb +4 -4
- data/processor/command/break.rb +19 -11
- data/processor/command/catch.rb +1 -1
- data/processor/command/complete.rb +1 -1
- data/processor/command/continue.rb +7 -1
- data/processor/command/directory.rb +2 -2
- data/processor/command/disable.rb +13 -14
- data/processor/command/display.rb +3 -1
- data/processor/command/down.rb +8 -8
- data/processor/command/edit.rb +1 -1
- data/processor/command/enable.rb +21 -22
- data/processor/command/eval.rb +1 -2
- data/processor/command/exit.rb +25 -8
- data/processor/command/finish.rb +7 -2
- data/processor/command/frame.rb +1 -1
- data/processor/command/help.rb +3 -4
- data/processor/command/info.rb +2 -0
- data/processor/command/info_subcmd/files.rb +2 -2
- data/processor/command/info_subcmd/locals.rb +6 -53
- data/processor/command/info_subcmd/source.rb +10 -4
- data/processor/command/info_subcmd/variables.rb +35 -0
- data/processor/command/info_subcmd/variables_subcmd/.gitignore +1 -0
- data/processor/command/info_subcmd/variables_subcmd/class.rb +42 -0
- data/processor/command/info_subcmd/variables_subcmd/constant.rb +42 -0
- data/processor/command/info_subcmd/{globals.rb → variables_subcmd/globals.rb} +22 -17
- data/processor/command/info_subcmd/variables_subcmd/instance.rb +42 -0
- data/processor/command/info_subcmd/variables_subcmd/locals.rb +80 -0
- data/processor/command/kill.rb +8 -7
- data/processor/command/list.rb +2 -2
- data/processor/command/macro.rb +27 -9
- data/processor/command/next.rb +1 -1
- data/processor/command/parsetree.rb +1 -1
- data/processor/command/pp.rb +1 -1
- data/processor/command/pr.rb +1 -1
- data/processor/command/ps.rb +1 -1
- data/processor/command/restart.rb +1 -1
- data/processor/command/save.rb +1 -1
- data/processor/command/set_subcmd/auto.rb +7 -1
- data/processor/command/set_subcmd/different.rb +1 -1
- data/processor/command/set_subcmd/trace.rb +5 -4
- data/processor/command/set_subcmd/trace_subcmd/print.rb +4 -3
- data/processor/command/shell.rb +5 -4
- data/processor/command/show_subcmd/{alias.rb → aliases.rb} +2 -2
- data/processor/command/source.rb +1 -1
- data/processor/command/step.rb +2 -5
- data/processor/command/tbreak.rb +1 -1
- data/processor/command/unalias.rb +13 -8
- data/processor/command/undisplay.rb +13 -9
- data/processor/command/up.rb +12 -14
- data/processor/command.rb +138 -230
- data/processor/display.rb +46 -10
- data/processor/help.rb +5 -3
- data/processor/hook.rb +2 -2
- data/processor/location.rb +25 -0
- data/processor/mock.rb +3 -2
- data/processor/msg.rb +55 -42
- data/processor/old-command.rb +270 -0
- data/processor/{processor.rb → old-processor.rb} +7 -8
- data/processor/running.rb +7 -12
- data/processor/subcmd.rb +15 -41
- data/processor/validate.rb +240 -238
- data/{processor/main.rb → processor.rb} +20 -42
- data/test/data/trace.cmd +6 -0
- data/test/data/trace.right +46 -0
- data/test/integration/helper.rb +2 -0
- data/test/integration/test-trace.rb +29 -0
- data/test/unit/cmd-helper.rb +2 -3
- data/test/unit/test-app-options.rb +13 -11
- data/test/unit/test-app-run.rb +7 -1
- data/test/unit/test-base-cmd.rb +1 -1
- data/test/unit/test-cmd-kill.rb +11 -4
- data/test/unit/test-io-tcpserver.rb +9 -4
- data/test/unit/test-proc-eval.rb +1 -2
- data/test/unit/test-proc-location.rb +26 -32
- data/test/unit/test-subcmd-help.rb +1 -1
- data/trepan8.gemspec +9 -1
- metadata +60 -17
- data/processor/command/base/cmd.rb +0 -177
data/processor/msg.rb
CHANGED
@@ -3,59 +3,72 @@
|
|
3
3
|
require 'rubygems'; require 'require_relative'
|
4
4
|
require_relative '../app/util'
|
5
5
|
require_relative 'virtual'
|
6
|
-
module Trepan
|
7
|
-
class CmdProcessor < VirtualCmdProcessor
|
8
|
-
attr_accessor :ruby_highlighter
|
9
6
|
|
10
|
-
|
11
|
-
message = safe_rep(message) unless opts[:unlimited]
|
12
|
-
if @settings[:highlight] && defined?(Term::ANSIColor)
|
13
|
-
message =
|
14
|
-
Term::ANSIColor.italic + message + Term::ANSIColor.reset
|
15
|
-
end
|
16
|
-
@intf.errmsg(message)
|
17
|
-
end
|
7
|
+
begin require 'term/ansicolor'; rescue LoadError; end
|
18
8
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
9
|
+
class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
10
|
+
attr_accessor :ruby_highlighter
|
11
|
+
|
12
|
+
def confirm(msg, default)
|
13
|
+
@settings[:confirm] ? @dbgr.intf[-1].confirm(msg, default) : true
|
14
|
+
end
|
23
15
|
|
24
|
-
|
16
|
+
def errmsg(message, opts={})
|
17
|
+
if message.kind_of?(Array)
|
18
|
+
message.each do |mess|
|
19
|
+
errmsg(mess, opts)
|
20
|
+
end
|
21
|
+
return
|
22
|
+
else
|
25
23
|
message = safe_rep(message) unless opts[:unlimited]
|
26
|
-
@intf.msg_nocr(message)
|
27
24
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
if @settings[:highlight] && defined?(Term::ANSIColor)
|
26
|
+
message =
|
27
|
+
Term::ANSIColor.italic + message + Term::ANSIColor.reset
|
31
28
|
end
|
29
|
+
@intf.errmsg(message)
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
require 'term/ansicolor'
|
39
|
-
@ruby_highlighter = CodeRay::Duo[:ruby, :term]
|
40
|
-
rescue LoadError
|
41
|
-
return text
|
42
|
-
end
|
43
|
-
end
|
44
|
-
return @ruby_highlighter.encode(text)
|
45
|
-
end
|
32
|
+
def msg(message, opts={})
|
33
|
+
message = safe_rep(message) unless opts[:unlimited]
|
34
|
+
message = ruby_format(message) if opts[:code]
|
35
|
+
@intf.msg(message)
|
36
|
+
end
|
46
37
|
|
47
|
-
|
48
|
-
|
49
|
-
|
38
|
+
def msg_nocr(message, opts={})
|
39
|
+
message = safe_rep(message) unless opts[:unlimited]
|
40
|
+
@intf.msg_nocr(message)
|
41
|
+
end
|
50
42
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
43
|
+
def read_command()
|
44
|
+
@intf.read_command(@prompt)
|
45
|
+
end
|
46
|
+
|
47
|
+
def ruby_format(text)
|
48
|
+
return text unless settings[:highlight]
|
49
|
+
unless @ruby_highlighter
|
50
|
+
begin
|
51
|
+
require 'coderay'
|
52
|
+
require 'term/ansicolor'
|
53
|
+
@ruby_highlighter = CodeRay::Duo[:ruby, :term]
|
54
|
+
rescue LoadError
|
55
|
+
return text
|
56
56
|
end
|
57
|
-
@intf.msg(message)
|
58
57
|
end
|
58
|
+
return @ruby_highlighter.encode(text)
|
59
|
+
end
|
59
60
|
|
61
|
+
def safe_rep(str)
|
62
|
+
Trepan::Util::safe_repr(str, @settings[:maxstring])
|
60
63
|
end
|
64
|
+
|
65
|
+
def section(message, opts={})
|
66
|
+
message = safe_rep(message) unless opts[:unlimited]
|
67
|
+
if @settings[:highlight] && defined?(Term::ANSIColor)
|
68
|
+
message =
|
69
|
+
Term::ANSIColor.bold + message + Term::ANSIColor.reset
|
70
|
+
end
|
71
|
+
@intf.msg(message)
|
72
|
+
end
|
73
|
+
|
61
74
|
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'columnize'
|
3
|
+
require 'require_relative'
|
4
|
+
require_relative './helper'
|
5
|
+
|
6
|
+
module Trepan
|
7
|
+
RUBY_DEBUG_DIR = File.expand_path(File.dirname(__FILE__)) unless
|
8
|
+
defined?(RUBY_DEBUG_DIR)
|
9
|
+
|
10
|
+
# A Trepan::Command object is is the base class for commands that
|
11
|
+
# implement a single debugger command. Individual debugger commands
|
12
|
+
# will be a subclass of this. The singleton class object is the
|
13
|
+
# command manager for all commands.
|
14
|
+
#
|
15
|
+
# Each debugger command is expected to implement the following methods:
|
16
|
+
# _regexp_:: A regular expression which input strings are matched
|
17
|
+
# against. If we have a match, run this command.
|
18
|
+
# It is the ruby-debug programmer's responsibility
|
19
|
+
# to make sure that these regular expressions match disjoint
|
20
|
+
# sets of strings. Otherwise one is arbitrarily used.
|
21
|
+
# _execute_:: Ruby code that implements the command.
|
22
|
+
# _help_:: Should return a String containing descriptive help for
|
23
|
+
# the commmand. Used by the 'help' command Trepan::HelpCommand
|
24
|
+
# _help_command_:: The name of the command listed via help.
|
25
|
+
#
|
26
|
+
# _help_ and _help_command_ methods are singleton methods, not
|
27
|
+
# instance methods like _regexp_ and _execute_.
|
28
|
+
class OldCommand
|
29
|
+
SubcmdStruct=Struct.new(:name, :min, :short_help, :long_help) unless
|
30
|
+
defined?(SubcmdStruct)
|
31
|
+
|
32
|
+
include Columnize
|
33
|
+
|
34
|
+
# Find _param_ in _subcmds_. The _param_ id downcased and can be
|
35
|
+
# abbreviated to the minimum length listed in the subcommands
|
36
|
+
def find(subcmds, param)
|
37
|
+
param.downcase!
|
38
|
+
for try_subcmd in subcmds do
|
39
|
+
if (param.size >= try_subcmd.min) and
|
40
|
+
(try_subcmd.name[0..param.size-1] == param)
|
41
|
+
return try_subcmd
|
42
|
+
end
|
43
|
+
end
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
|
47
|
+
class << self
|
48
|
+
# An Array containing Trepan::Command classes that implment each
|
49
|
+
# of the debugger commands.
|
50
|
+
def commands
|
51
|
+
@commands ||= []
|
52
|
+
end
|
53
|
+
|
54
|
+
DEF_OPTIONS = {
|
55
|
+
:allow_in_control => false,
|
56
|
+
:allow_in_post_mortem => true,
|
57
|
+
:event => true,
|
58
|
+
:always_run => 0,
|
59
|
+
:unknown => false,
|
60
|
+
:need_context => false,
|
61
|
+
} unless defined?(DEF_OPTIONS)
|
62
|
+
|
63
|
+
def inherited(klass)
|
64
|
+
DEF_OPTIONS.each do |o, v|
|
65
|
+
klass.options[o] = v if klass.options[o].nil?
|
66
|
+
end
|
67
|
+
commands << klass
|
68
|
+
end
|
69
|
+
|
70
|
+
# Read in and "include" all the subclasses of the
|
71
|
+
# Trepan::Command class. For example
|
72
|
+
# Trepan::QuitCommand is one of them. The list of Ruby
|
73
|
+
# files to read are all the files that end .rb in directory
|
74
|
+
# Trepan::RUBY_DEBUG_DIR
|
75
|
+
def load_commands
|
76
|
+
Dir[File.join(%W(#{Trepan.const_get(:RUBY_DEBUG_DIR)}
|
77
|
+
command-ruby-debug *))].each do
|
78
|
+
|file|
|
79
|
+
require file if file =~ /\.rb$/
|
80
|
+
end
|
81
|
+
Trepan.constants.grep(/Functions$/).map { |name| Trepan.const_get(name) }.each do |mod|
|
82
|
+
include mod
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def method_missing(meth, *args, &block)
|
87
|
+
if meth.to_s =~ /^(.+?)=$/
|
88
|
+
@options[$1.intern] = args.first
|
89
|
+
else
|
90
|
+
if @options.has_key?(meth)
|
91
|
+
@options[meth]
|
92
|
+
else
|
93
|
+
super
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def options
|
99
|
+
@options ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
def settings_map
|
103
|
+
@@settings_map ||= {}
|
104
|
+
end
|
105
|
+
private :settings_map
|
106
|
+
|
107
|
+
# Returns a Hash of Debugger settings, @settings. If doesn't exist
|
108
|
+
# we create a @settings hash with [] setter and getter and return that.
|
109
|
+
def settings
|
110
|
+
unless true and defined? @settings and @settings
|
111
|
+
@settings = Object.new
|
112
|
+
map = settings_map
|
113
|
+
c = class << @settings; self end
|
114
|
+
if c.respond_to?(:funcall)
|
115
|
+
c.funcall(:define_method, :[]) do |name|
|
116
|
+
raise "No such setting #{name}" unless map.has_key?(name)
|
117
|
+
map[name][:getter].call
|
118
|
+
end
|
119
|
+
else
|
120
|
+
c.send(:define_method, :[]) do |name|
|
121
|
+
raise "No such setting #{name}" unless map.has_key?(name)
|
122
|
+
map[name][:getter].call
|
123
|
+
end
|
124
|
+
end
|
125
|
+
c = class << @settings; self end
|
126
|
+
if c.respond_to?(:funcall)
|
127
|
+
c.funcall(:define_method, :[]=) do |name, value|
|
128
|
+
raise "No such setting #{name}" unless map.has_key?(name)
|
129
|
+
map[name][:setter].call(value)
|
130
|
+
end
|
131
|
+
else
|
132
|
+
c.send(:define_method, :[]=) do |name, value|
|
133
|
+
raise "No such setting #{name}" unless map.has_key?(name)
|
134
|
+
map[name][:setter].call(value)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
@settings
|
139
|
+
end
|
140
|
+
|
141
|
+
def register_setting_var(name, default)
|
142
|
+
var_name = "@@#{name}"
|
143
|
+
class_variable_set(var_name, default)
|
144
|
+
register_setting_get(name) { class_variable_get(var_name) }
|
145
|
+
register_setting_set(name) { |value| class_variable_set(var_name, value) }
|
146
|
+
end
|
147
|
+
|
148
|
+
def register_setting_get(name, &block)
|
149
|
+
settings_map[name] ||= {}
|
150
|
+
settings_map[name][:getter] = block
|
151
|
+
end
|
152
|
+
|
153
|
+
def register_setting_set(name, &block)
|
154
|
+
settings_map[name] ||= {}
|
155
|
+
settings_map[name][:setter] = block
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
register_setting_var(:basename, false) # use basename in showing files?
|
160
|
+
register_setting_var(:callstyle, :last)
|
161
|
+
register_setting_var(:debuggertesting, false)
|
162
|
+
register_setting_var(:force_stepping, false)
|
163
|
+
register_setting_var(:full_path, true)
|
164
|
+
register_setting_var(:listsize, 10) # number of lines in list command
|
165
|
+
register_setting_var(:stack_trace_on_error, false)
|
166
|
+
register_setting_var(:tracing_plus, false) # different linetrace lines?
|
167
|
+
|
168
|
+
# width of line output. Use COLUMNS value if it exists and is
|
169
|
+
# not too rediculously large.
|
170
|
+
width = ENV['COLUMNS'].to_i
|
171
|
+
width = 80 unless width > 10
|
172
|
+
register_setting_var(:width, width)
|
173
|
+
|
174
|
+
if not defined? Trepan::ARGV
|
175
|
+
Trepan::ARGV = ARGV.clone
|
176
|
+
end
|
177
|
+
register_setting_var(:argv, Trepan::ARGV)
|
178
|
+
|
179
|
+
def initialize(state)
|
180
|
+
@state = state
|
181
|
+
end
|
182
|
+
|
183
|
+
def match(input)
|
184
|
+
@match = regexp.match(input)
|
185
|
+
end
|
186
|
+
|
187
|
+
protected
|
188
|
+
|
189
|
+
# FIXME: use delegate?
|
190
|
+
def errmsg(*args)
|
191
|
+
@state.errmsg(*args)
|
192
|
+
end
|
193
|
+
|
194
|
+
def print(*args)
|
195
|
+
@state.print(*args)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Called when we are about to do a dangerous operation. _msg_
|
199
|
+
# contains a prompt message. Return _true_ if confirmed or _false_
|
200
|
+
# if not confirmed.
|
201
|
+
def confirm(msg)
|
202
|
+
@state.confirm(msg) == 'y'
|
203
|
+
end
|
204
|
+
|
205
|
+
# debug_eval like Kernel.eval or Object.instance_eval but using
|
206
|
+
# the bindings for the debugged program. If there is a
|
207
|
+
# syntax-error like exception in running eval, print an
|
208
|
+
# appropriate message and throw :debug_error
|
209
|
+
def debug_eval(str, b = get_binding)
|
210
|
+
begin
|
211
|
+
val = eval(str, b)
|
212
|
+
rescue StandardError, ScriptError => e
|
213
|
+
if OldCommand.settings[:stack_trace_on_error]
|
214
|
+
at = eval("caller(1)", b)
|
215
|
+
print "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
|
216
|
+
for i in at
|
217
|
+
print "\tfrom %s\n", i
|
218
|
+
end
|
219
|
+
else
|
220
|
+
print "#{e.class} Exception: #{e.message}\n"
|
221
|
+
end
|
222
|
+
throw :debug_error
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# debug_eval like Kernel.eval or Object.instance_eval but using
|
227
|
+
# the bindings for the debugged program. If there is a syntax
|
228
|
+
# error kind of exception in running eval, no warning is given and
|
229
|
+
# nil is returned.
|
230
|
+
def debug_silent_eval(str)
|
231
|
+
begin
|
232
|
+
eval(str, get_binding)
|
233
|
+
rescue StandardError, ScriptError
|
234
|
+
nil
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# Return a binding object for the debugged program.
|
239
|
+
def get_binding
|
240
|
+
@state.context.frame_binding(@state.frame_pos)
|
241
|
+
end
|
242
|
+
|
243
|
+
def line_at(file, line)
|
244
|
+
Debugger.line_at(file, line)
|
245
|
+
end
|
246
|
+
|
247
|
+
def get_context(thnum)
|
248
|
+
Debugger.contexts.find{|c| c.thnum == thnum}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
OldCommand.load_commands
|
253
|
+
|
254
|
+
# Returns setting object.
|
255
|
+
# Use Debugger.settings[] and Debugger.settings[]= methods to query and set
|
256
|
+
# debugger settings. These settings are available:
|
257
|
+
#
|
258
|
+
# - :autolist - automatically calls 'list' command on breakpoint
|
259
|
+
# - :autoeval - evaluates input in the current binding if it's not recognized as a debugger command
|
260
|
+
# - :autoirb - automatically calls 'irb' command on breakpoint
|
261
|
+
# - :stack_trace_on_error - shows full stack trace if eval command results with an exception
|
262
|
+
# - :frame_full_path - displays full paths when showing frame stack
|
263
|
+
# - :frame_class_names - displays method's class name when showing frame stack
|
264
|
+
# - :reload_source_on_change - makes 'list' command to always display up-to-date source code
|
265
|
+
# - :force_stepping - stepping command asways move to the new line
|
266
|
+
#
|
267
|
+
def self.settings
|
268
|
+
OldCommand.settings
|
269
|
+
end
|
270
|
+
end
|
@@ -2,9 +2,8 @@ require 'rubygems'
|
|
2
2
|
require 'ruby-debug-base'
|
3
3
|
require 'require_relative'
|
4
4
|
require_relative '../interface/user'
|
5
|
-
require_relative '
|
6
|
-
require_relative '
|
7
|
-
require_relative './main'
|
5
|
+
require_relative 'old-command'
|
6
|
+
require_relative 'default'
|
8
7
|
require_relative '../app/frame'
|
9
8
|
|
10
9
|
# _Trepan_ is the module name space for this debugger.
|
@@ -196,13 +195,13 @@ module Trepan
|
|
196
195
|
Debugger::RDEBUG_FILE == file # Don't trace ourself
|
197
196
|
@last_file = CommandProcessor.canonic_file(file)
|
198
197
|
canonic_file = CommandProcessor.canonic_file(file)
|
199
|
-
unless canonic_file == @last_file and @last_line == line and
|
200
|
-
|
201
|
-
print
|
202
|
-
|
198
|
+
# unless canonic_file == @last_file and @last_line == line and
|
199
|
+
# Command.settings[:tracing_plus]
|
200
|
+
print("Tracing(%d):%s:%s %s" %
|
201
|
+
[context.thnum, canonic_file, line, Debugger.line_at(file, line)])
|
203
202
|
@last_file = canonic_file
|
204
203
|
@last_line = line
|
205
|
-
end
|
204
|
+
# end
|
206
205
|
always_run(context, file, line, 2)
|
207
206
|
end
|
208
207
|
protect :at_tracing
|
data/processor/running.rb
CHANGED
@@ -48,18 +48,13 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
48
48
|
# @next_thread = Thread.current
|
49
49
|
# end
|
50
50
|
|
51
|
-
#
|
52
|
-
#
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
# @stop_condition = condition
|
59
|
-
# @stop_events = opts[:stop_events] if
|
60
|
-
# opts.keys.member?(:stop_events)
|
61
|
-
# @to_method = opts[:to_method]
|
62
|
-
# end
|
51
|
+
# Does whatever needs to be done to set to step program
|
52
|
+
# execution.
|
53
|
+
def step(step_count=1, opts={}, condition=nil)
|
54
|
+
@context.step(step_count, opts[:different_pos])
|
55
|
+
@state.proceed
|
56
|
+
@leave_cmd_loop = true
|
57
|
+
end
|
63
58
|
|
64
59
|
def quit(cmd='quit')
|
65
60
|
@next_level = 32000 # I'm guessing the stack size can't
|
data/processor/subcmd.rb
CHANGED
@@ -14,17 +14,24 @@ module Trepan
|
|
14
14
|
|
15
15
|
# Find subcmd in self.subcmds
|
16
16
|
def lookup(subcmd_prefix, use_regexp=true)
|
17
|
-
compare =
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
compare =
|
18
|
+
if !@cmd.settings[:abbrev]
|
19
|
+
lambda{|name| name.to_s == subcmd_prefix}
|
20
|
+
elsif use_regexp
|
21
|
+
lambda{|name| name.to_s =~ /^#{subcmd_prefix}/}
|
22
|
+
else
|
23
|
+
lambda{|name| 0 == name.to_s.index(subcmd_prefix)}
|
24
|
+
end
|
25
|
+
candidates = []
|
22
26
|
@subcmds.each do |subcmd_name, subcmd|
|
23
27
|
if compare.call(subcmd_name) &&
|
24
28
|
subcmd_prefix.size >= subcmd.class.const_get(:MIN_ABBREV)
|
25
|
-
|
29
|
+
candidates << subcmd
|
26
30
|
end
|
27
31
|
end
|
32
|
+
if candidates.size == 1
|
33
|
+
return candidates.first
|
34
|
+
end
|
28
35
|
return nil
|
29
36
|
end
|
30
37
|
|
@@ -61,48 +68,15 @@ module Trepan
|
|
61
68
|
@cmdlist << subcmd_name
|
62
69
|
end
|
63
70
|
|
64
|
-
# Run subcmd_name with args using obj for the environent
|
65
|
-
def run( subcmd_name, arg)
|
66
|
-
entry=lookup(subcmd_name)
|
67
|
-
if entry
|
68
|
-
entry['callback'].send(arg)
|
69
|
-
else
|
70
|
-
@proc.undefined_cmd(entry.__class__.name, subcmd_name)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
71
|
# help for subcommands
|
75
72
|
# Note: format of help is compatible with ddd.
|
76
73
|
def help(*args)
|
77
|
-
|
78
|
-
msg args
|
79
|
-
subcmd_prefix = args[0]
|
80
|
-
if not subcmd_prefix or subcmd_prefix.size == 0
|
81
|
-
@proc.msg(self.doc)
|
82
|
-
@proc.msg("\nList of %s subcommands:\n" % [@name])
|
83
|
-
@list.each do |subcmd_name|
|
84
|
-
subcmd_helper(subcmd_name, obj, true, true)
|
85
|
-
end
|
86
|
-
|
87
|
-
entry = lookup(subcmd_prefix)
|
88
|
-
if entry and entry.respond_to? :help
|
89
|
-
entry.help(args)
|
90
|
-
else
|
91
|
-
@proc.errmsg("Unknown 'help %s' subcommand %s" %
|
92
|
-
[@name, subcmd_prefix])
|
93
|
-
end
|
94
|
-
end
|
74
|
+
# Not used but tested for.
|
95
75
|
end
|
96
76
|
|
97
77
|
def list
|
98
78
|
@subcmds.keys.sort
|
99
79
|
end
|
100
|
-
|
101
|
-
# Error message when a subcommand doesn't exist.
|
102
|
-
def undefined_subcmd(cmd, subcmd)
|
103
|
-
@proc.errmsg('Undefined "%s" command: "%s". Try "help".' %
|
104
|
-
[cmd, subcmd])
|
105
|
-
end
|
106
80
|
end
|
107
81
|
end
|
108
82
|
|
@@ -111,7 +85,7 @@ if __FILE__ == $0
|
|
111
85
|
|
112
86
|
require 'rubygems'; require 'require_relative'
|
113
87
|
require_relative 'mock'
|
114
|
-
require_relative 'command
|
88
|
+
require_relative 'command'
|
115
89
|
|
116
90
|
class Trepan::TestCommand < Trepan::Command
|
117
91
|
|