byebug 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/GUIDE.md +209 -0
- data/README.md +11 -2
- data/Rakefile +12 -0
- data/ext/byebug/byebug.c +50 -53
- data/ext/byebug/context.c +0 -24
- data/lib/byebug.rb +23 -7
- data/lib/byebug/command.rb +35 -24
- data/lib/byebug/commands/breakpoints.rb +24 -35
- data/lib/byebug/commands/catchpoint.rb +13 -17
- data/lib/byebug/commands/condition.rb +14 -19
- data/lib/byebug/commands/continue.rb +5 -7
- data/lib/byebug/commands/display.rb +3 -3
- data/lib/byebug/commands/edit.rb +1 -1
- data/lib/byebug/commands/enable.rb +18 -45
- data/lib/byebug/commands/eval.rb +1 -1
- data/lib/byebug/commands/finish.rb +1 -1
- data/lib/byebug/commands/frame.rb +24 -22
- data/lib/byebug/commands/info.rb +91 -122
- data/lib/byebug/commands/jump.rb +3 -8
- data/lib/byebug/commands/list.rb +2 -2
- data/lib/byebug/commands/method.rb +6 -8
- data/lib/byebug/commands/save.rb +1 -1
- data/lib/byebug/commands/set.rb +0 -12
- data/lib/byebug/commands/show.rb +9 -21
- data/lib/byebug/commands/variables.rb +3 -3
- data/lib/byebug/context.rb +13 -2
- data/lib/byebug/interface.rb +13 -7
- data/lib/byebug/processor.rb +23 -25
- data/lib/byebug/version.rb +1 -1
- data/old_doc/primes.rb +1 -4
- data/test/continue_test.rb +2 -9
- data/test/examples/list.rb +1 -1
- data/test/examples/trace.rb +1 -0
- data/test/help_test.rb +1 -1
- data/test/info_test.rb +3 -3
- data/test/list_test.rb +7 -1
- data/test/method_test.rb +0 -1
- data/test/show_test.rb +8 -0
- data/test/support/matchers.rb +4 -2
- data/test/trace_test.rb +18 -1
- metadata +2 -2
data/lib/byebug/commands/eval.rb
CHANGED
@@ -16,10 +16,11 @@ module Byebug
|
|
16
16
|
end
|
17
17
|
|
18
18
|
if abs_frame_pos >= context.stack_size then
|
19
|
-
|
20
|
-
|
19
|
+
return \
|
20
|
+
errmsg "Adjusting would put us beyond the oldest (initial) frame.\n"
|
21
21
|
elsif abs_frame_pos < 0 then
|
22
|
-
|
22
|
+
return \
|
23
|
+
errmsg "Adjusting would put us beyond the newest (innermost) frame.\n"
|
23
24
|
return
|
24
25
|
end
|
25
26
|
|
@@ -28,25 +29,26 @@ module Byebug
|
|
28
29
|
@state.frame_pos = abs_frame_pos
|
29
30
|
end
|
30
31
|
|
31
|
-
@state.file = context.frame_file
|
32
|
-
@state.line = context.frame_line
|
32
|
+
@state.file = @state.context.frame_file @state.frame_pos
|
33
|
+
@state.line = @state.context.frame_line @state.frame_pos
|
33
34
|
|
34
|
-
print_frame
|
35
|
+
print_frame @state.frame_pos, false
|
35
36
|
end
|
36
37
|
|
37
|
-
def get_frame_call(prefix, pos
|
38
|
-
id = context.frame_method(pos)
|
38
|
+
def get_frame_call(prefix, pos)
|
39
|
+
id = @state.context.frame_method(pos)
|
39
40
|
return "<main>" unless id
|
40
41
|
|
41
|
-
klass = context.frame_class(pos)
|
42
|
+
klass = @state.context.frame_class(pos)
|
43
|
+
|
42
44
|
if Command.settings[:callstyle] != :short && klass
|
43
45
|
call_str = "#{klass}.#{id.id2name}"
|
44
46
|
else
|
45
47
|
call_str = "#{id.id2name}"
|
46
48
|
end
|
47
49
|
|
48
|
-
args = context.frame_args
|
49
|
-
locals = context.frame_locals
|
50
|
+
args = @state.context.frame_args pos
|
51
|
+
locals = @state.context.frame_locals pos
|
50
52
|
if args.any?
|
51
53
|
call_str += "("
|
52
54
|
args.each_with_index do |name, i|
|
@@ -60,7 +62,7 @@ module Byebug
|
|
60
62
|
end
|
61
63
|
call_str += "#{name}##{klass}, "
|
62
64
|
when :tracked
|
63
|
-
arg_info = context.frame_args_info
|
65
|
+
arg_info = context.frame_args_info pos
|
64
66
|
if arg_info && arg_info.size > i
|
65
67
|
call_str += "#{name}: #{arg_info[i].inspect}, "
|
66
68
|
else
|
@@ -84,10 +86,9 @@ module Byebug
|
|
84
86
|
end
|
85
87
|
end
|
86
88
|
|
87
|
-
def print_frame(pos, mark_current = true
|
88
|
-
file = context.frame_file
|
89
|
-
line = context.frame_line
|
90
|
-
klass = context.frame_class(pos)
|
89
|
+
def print_frame(pos, mark_current = true)
|
90
|
+
file = @state.context.frame_file pos
|
91
|
+
line = @state.context.frame_line pos
|
91
92
|
|
92
93
|
unless Command.settings[:frame_fullpath]
|
93
94
|
path_components = file.split(/[\\\/]/)
|
@@ -104,7 +105,7 @@ module Byebug
|
|
104
105
|
end
|
105
106
|
|
106
107
|
frame_str += sprintf "#%-2d ", pos
|
107
|
-
frame_str += get_frame_call
|
108
|
+
frame_str += get_frame_call frame_str, pos
|
108
109
|
file_line = "at #{CommandProcessor.canonic_file(file)}:#{line}"
|
109
110
|
if frame_str.size + file_line.size + 1 > Command.settings[:width]
|
110
111
|
frame_str += "\n #{file_line}\n"
|
@@ -129,9 +130,10 @@ module Byebug
|
|
129
130
|
# ignoring additional caller entries. sentinal is set by byebug, but if it's
|
130
131
|
# nil then additional entries are presumably ones that we haven't recorded
|
131
132
|
# in context
|
132
|
-
def truncated_callstack?(
|
133
|
-
recorded_size = context.stack_size
|
134
|
-
to_find_fl =
|
133
|
+
def truncated_callstack?(sentinal=nil, cs=caller)
|
134
|
+
recorded_size = @state.context.stack_size
|
135
|
+
to_find_fl =
|
136
|
+
"#{@state.context.frame_file(0)}:#{@state.context.frame_line(0)}"
|
135
137
|
top_discard = false
|
136
138
|
cs.each_with_index do |fl, i|
|
137
139
|
fl.gsub!(/in `.*'$/, '')
|
@@ -166,7 +168,7 @@ module Byebug
|
|
166
168
|
|
167
169
|
def execute
|
168
170
|
print_backtrace
|
169
|
-
if truncated_callstack?(
|
171
|
+
if truncated_callstack?(Byebug.start_sentinal)
|
170
172
|
print \
|
171
173
|
"Warning: saved frames may be incomplete; compare with caller(0)\n"
|
172
174
|
end
|
@@ -261,7 +263,7 @@ module Byebug
|
|
261
263
|
%w(frame)
|
262
264
|
end
|
263
265
|
|
264
|
-
def
|
266
|
+
def description
|
265
267
|
%{
|
266
268
|
f[rame][ frame-number]
|
267
269
|
|
data/lib/byebug/commands/info.rb
CHANGED
@@ -2,10 +2,8 @@ module Byebug
|
|
2
2
|
|
3
3
|
module InfoFunctions
|
4
4
|
def info_catch(*args)
|
5
|
-
unless @state.context
|
6
|
-
|
7
|
-
return
|
8
|
-
end
|
5
|
+
return print "No frame selected.\n" unless @state.context
|
6
|
+
|
9
7
|
if Byebug.catchpoints and not Byebug.catchpoints.empty?
|
10
8
|
Byebug.catchpoints.each do |exception, hits|
|
11
9
|
print "#{exception}: #{exception.is_a?(Class)}\n"
|
@@ -69,7 +67,7 @@ module Byebug
|
|
69
67
|
end
|
70
68
|
|
71
69
|
def execute
|
72
|
-
return help(
|
70
|
+
return print InfoCommand.help(nil) unless @match[1]
|
73
71
|
|
74
72
|
args = @match[1].split(/[ \t]+/)
|
75
73
|
param = args.shift
|
@@ -82,12 +80,11 @@ module Byebug
|
|
82
80
|
end
|
83
81
|
|
84
82
|
def info_args(*args)
|
85
|
-
unless @state.context
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
args = @state.context.frame_args(@state.frame_pos)
|
83
|
+
return errmsg "No frame selected.\n" unless @state.context
|
84
|
+
|
85
|
+
locals = @state.context.frame_locals
|
86
|
+
args = @state.context.frame_args
|
87
|
+
|
91
88
|
args.each do |name|
|
92
89
|
s = "#{name} = #{locals[name].inspect}"
|
93
90
|
pad_with_dots(s)
|
@@ -95,8 +92,20 @@ module Byebug
|
|
95
92
|
end
|
96
93
|
end
|
97
94
|
|
95
|
+
def info_breakpoint(brkpt)
|
96
|
+
expr = brkpt.expr.nil? ? '' : " if #{brkpt.expr}"
|
97
|
+
print "%-3d %-3s at %s:%s%s\n" %
|
98
|
+
[brkpt.id, brkpt.enabled? ? 'y' : 'n', brkpt.source, brkpt.pos, expr]
|
99
|
+
hits = brkpt.hit_count
|
100
|
+
if hits > 0
|
101
|
+
s = (hits > 1) ? 's' : ''
|
102
|
+
print "\tbreakpoint already hit #{hits} time#{s}\n"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
private :info_breakpoint
|
106
|
+
|
98
107
|
def info_breakpoints(*args)
|
99
|
-
return
|
108
|
+
return errmsg "\"info breakpoints\" not available here.\n" unless
|
100
109
|
@state.context
|
101
110
|
|
102
111
|
return print "No breakpoints.\n" if Byebug.breakpoints.empty?
|
@@ -109,50 +118,34 @@ module Byebug
|
|
109
118
|
brkpts.empty?
|
110
119
|
end
|
111
120
|
print "Num Enb What\n"
|
112
|
-
brkpts.each
|
113
|
-
print "%-3d %-3s at %s:%s%s\n", b.id,
|
114
|
-
b.enabled? ? 'y' : 'n',
|
115
|
-
b.source,
|
116
|
-
b.pos,
|
117
|
-
b.expr.nil? ? '' : " if #{b.expr}"
|
118
|
-
hits = b.hit_count
|
119
|
-
if hits > 0
|
120
|
-
s = (hits > 1) ? 's' : ''
|
121
|
-
print "\tbreakpoint already hit #{hits} time#{s}\n"
|
122
|
-
end
|
123
|
-
end
|
121
|
+
brkpts.each { |b| info_breakpoint(b) }
|
124
122
|
end
|
125
123
|
|
126
124
|
def info_display(*args)
|
127
|
-
unless
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
else
|
141
|
-
print "There are no auto-display expressions now.\n"
|
125
|
+
return errmsg "\"info display\" not available here.\n" unless
|
126
|
+
@state.context
|
127
|
+
|
128
|
+
return print "There are no auto-display expressions now.\n" unless
|
129
|
+
@state.display.find{|d| d[0]}
|
130
|
+
|
131
|
+
print "Auto-display expressions now in effect:\n" \
|
132
|
+
"Num Enb Expression\n"
|
133
|
+
n = 1
|
134
|
+
for d in @state.display
|
135
|
+
print "%3d: %s %s\n" % [n, (d[0] ? 'y' : 'n'), d[1]]
|
136
|
+
n += 1
|
142
137
|
end
|
143
138
|
end
|
144
139
|
|
145
140
|
def info_file_path(file)
|
146
141
|
path = LineCache.path(file)
|
147
|
-
if path != file
|
148
|
-
print " - #{path}"
|
149
|
-
end
|
142
|
+
print " - #{path}" if path and path != file
|
150
143
|
end
|
151
144
|
private :info_file_path
|
152
145
|
|
153
146
|
def info_file_lines(file)
|
154
147
|
lines = LineCache.size(file)
|
155
|
-
print "\t
|
148
|
+
print "\t #{lines} lines\n" if lines
|
156
149
|
end
|
157
150
|
private :info_file_lines
|
158
151
|
|
@@ -167,80 +160,69 @@ module Byebug
|
|
167
160
|
|
168
161
|
def info_file_mtime(file)
|
169
162
|
stat = LineCache.stat(file)
|
170
|
-
print "\t
|
163
|
+
print "\t#{stat.mtime}\n" if stat
|
171
164
|
end
|
172
165
|
private :info_file_mtime
|
173
166
|
|
174
167
|
def info_file_sha1(file)
|
175
|
-
print "\t
|
168
|
+
print "\t#{LineCache.sha1(file)}\n"
|
176
169
|
end
|
177
170
|
private :info_file_sha1
|
178
171
|
|
179
172
|
def info_file(*args)
|
180
173
|
return info_files unless args[0]
|
181
|
-
file = args[0]
|
182
174
|
|
183
|
-
param = args[1]
|
175
|
+
param = args[1] || 'basic'
|
184
176
|
|
185
177
|
subcmd = find(InfoFileSubcommands, param)
|
186
178
|
return errmsg "Invalid parameter #{param}\n" unless subcmd
|
187
179
|
|
188
|
-
unless LineCache::cached?(
|
189
|
-
unless LineCache::cached_script?(
|
190
|
-
return print "File #{
|
180
|
+
unless LineCache::cached?(args[0])
|
181
|
+
unless LineCache::cached_script?(args[0])
|
182
|
+
return print "File #{args[0]} is not cached\n"
|
191
183
|
end
|
192
|
-
LineCache::cache(
|
184
|
+
LineCache::cache(args[0], Command.settings[:autoreload])
|
193
185
|
end
|
194
186
|
|
195
|
-
print "File #{
|
196
|
-
info_file_path(
|
187
|
+
print "File #{args[0]}"
|
188
|
+
info_file_path(args[0]) if %w(all basic path).member?(subcmd.name)
|
197
189
|
print "\n"
|
198
190
|
|
199
|
-
info_file_lines(
|
200
|
-
info_file_breakpoints(
|
201
|
-
info_file_mtime(
|
202
|
-
info_file_sha1(
|
191
|
+
info_file_lines(args[0]) if %w(all basic lines).member?(subcmd.name)
|
192
|
+
info_file_breakpoints(args[0]) if %w(all breakpoints).member?(subcmd.name)
|
193
|
+
info_file_mtime(args[0]) if %w(all mtime).member?(subcmd.name)
|
194
|
+
info_file_sha1(args[0]) if %w(all sha1).member?(subcmd.name)
|
203
195
|
end
|
204
196
|
|
205
197
|
def info_files(*args)
|
206
198
|
files = LineCache::cached_files
|
207
199
|
files += SCRIPT_LINES__.keys unless 'stat' == args[0]
|
208
200
|
files.uniq.sort.each do |file|
|
209
|
-
|
210
|
-
|
211
|
-
print "
|
212
|
-
|
213
|
-
print " - %s\n", path
|
214
|
-
else
|
215
|
-
print "\n"
|
216
|
-
end
|
217
|
-
print "\t%s\n", stat.mtime if stat
|
201
|
+
print "File #{file}"
|
202
|
+
info_file_path(file)
|
203
|
+
print "\n"
|
204
|
+
info_file_mtime(file)
|
218
205
|
end
|
219
206
|
end
|
220
207
|
|
221
208
|
def info_instance_variables(*args)
|
222
|
-
unless
|
223
|
-
|
224
|
-
|
225
|
-
end
|
209
|
+
return errmsg "\"info instance_variables\" not available here.\n" unless
|
210
|
+
@state.context
|
211
|
+
|
226
212
|
obj = debug_eval('self')
|
227
213
|
var_list(obj.instance_variables)
|
228
214
|
end
|
229
215
|
|
230
216
|
def info_line(*args)
|
231
|
-
unless @state.context
|
232
|
-
|
233
|
-
return
|
234
|
-
end
|
235
|
-
print "Line %d of \"%s\"\n", @state.line, @state.file
|
217
|
+
return errmsg "\"info line\" not available here.\n" unless @state.context
|
218
|
+
print "Line #{@state.line} of \"#{@state.file}\"\n"
|
236
219
|
end
|
237
220
|
|
238
221
|
def info_locals(*args)
|
239
|
-
unless
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
locals = @state.context.frame_locals(@state.frame_pos)
|
222
|
+
return errmsg "\"info locals\" not available here.\n" unless
|
223
|
+
@state.context
|
224
|
+
|
225
|
+
locals = @state.context.frame_locals
|
244
226
|
locals.keys.sort.each do |name|
|
245
227
|
### FIXME: make a common routine
|
246
228
|
begin
|
@@ -272,8 +254,8 @@ module Byebug
|
|
272
254
|
private :info_stop_reason
|
273
255
|
|
274
256
|
def info_program(*args)
|
275
|
-
return
|
276
|
-
|
257
|
+
return errmsg "The program being debugged is not being run.\n" unless
|
258
|
+
@state.context
|
277
259
|
|
278
260
|
return print "The program crashed.\n" + Byebug.last_exception ?
|
279
261
|
"Exception: #{Byebug.last_exception.inspect}" : "" + "\n" if
|
@@ -284,31 +266,26 @@ module Byebug
|
|
284
266
|
end
|
285
267
|
|
286
268
|
def info_stack(*args)
|
287
|
-
|
288
|
-
|
289
|
-
return
|
290
|
-
end
|
269
|
+
return errmsg "\"info stack\" not available here.\n" unless @state.context
|
270
|
+
|
291
271
|
print_backtrace
|
292
272
|
end
|
293
273
|
|
294
274
|
def info_global_variables(*args)
|
295
|
-
unless
|
296
|
-
|
297
|
-
|
298
|
-
end
|
275
|
+
return errmsg "\"info global_variables\" not available here.\n" unless
|
276
|
+
@state.context
|
277
|
+
|
299
278
|
var_global
|
300
279
|
end
|
301
280
|
|
302
281
|
def info_variables(*args)
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
end
|
282
|
+
return errmsg "\"info variables\" not available here.\n" unless
|
283
|
+
@state.context
|
284
|
+
|
307
285
|
obj = debug_eval('self')
|
308
|
-
locals = @state.context.frame_locals
|
286
|
+
locals = @state.context.frame_locals
|
309
287
|
locals[:self] = @state.context.frame_self(@state.frame_pos)
|
310
288
|
locals.keys.sort.each do |name|
|
311
|
-
next if name =~ /^__dbg_/ # skip byebug pollution
|
312
289
|
### FIXME: make a common routine
|
313
290
|
begin
|
314
291
|
s = "#{name} = #{locals[name].inspect}"
|
@@ -320,37 +297,12 @@ module Byebug
|
|
320
297
|
end
|
321
298
|
end
|
322
299
|
pad_with_dots(s)
|
323
|
-
s.gsub!('%', '%%') # protect against printf format strings
|
324
300
|
print "#{s}\n"
|
325
301
|
end
|
326
302
|
var_list(obj.instance_variables, obj.instance_eval{binding()})
|
327
303
|
var_class_self
|
328
304
|
end
|
329
305
|
|
330
|
-
def help(args)
|
331
|
-
if args[1]
|
332
|
-
subcmd = find(Subcommands, args[1])
|
333
|
-
if subcmd
|
334
|
-
str = subcmd.short_help + '.'
|
335
|
-
if 'file' == subcmd.name and args[2]
|
336
|
-
subsubcmd = find(InfoFileSubcommands, args[2])
|
337
|
-
if subsubcmd
|
338
|
-
str += "\nInvalid \"file\" attribute \"#{args[2]}\"."
|
339
|
-
else
|
340
|
-
str += "\n" + subsubcmd.short_help + '.'
|
341
|
-
end
|
342
|
-
else
|
343
|
-
str += "\n" + subcmd.long_help if subcmd.long_help
|
344
|
-
end
|
345
|
-
else
|
346
|
-
str = "Invalid \"info\" subcommand \"#{args[1]}\"."
|
347
|
-
end
|
348
|
-
else
|
349
|
-
str = InfoCommand.description + format_subcmds(Subcommands)
|
350
|
-
end
|
351
|
-
print str
|
352
|
-
end
|
353
|
-
|
354
306
|
class << self
|
355
307
|
def names
|
356
308
|
%w(info)
|
@@ -360,10 +312,27 @@ module Byebug
|
|
360
312
|
%{
|
361
313
|
info[ subcommand]
|
362
314
|
|
363
|
-
Generic command for showing things about the program being
|
315
|
+
Generic command for showing things about the program being debugged.
|
364
316
|
}
|
365
317
|
end
|
318
|
+
|
319
|
+
def help(args)
|
320
|
+
return description + format_subcmds unless args and args[1]
|
321
|
+
|
322
|
+
return format_subcmd(args[1]) unless 'file' == args[1] and args[2]
|
323
|
+
|
324
|
+
str = subcmd.short_help + '.'
|
325
|
+
subsubcmd = find(InfoFileSubcommands, args[2])
|
326
|
+
if subsubcmd
|
327
|
+
str += "\nInvalid \"file\" attribute \"#{args[2]}\"."
|
328
|
+
else
|
329
|
+
str += "\n" + subsubcmd.short_help + '.'
|
330
|
+
end
|
331
|
+
|
332
|
+
return str
|
333
|
+
end
|
366
334
|
end
|
335
|
+
|
367
336
|
end
|
368
337
|
|
369
338
|
end
|