byebug 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/GUIDE.md +209 -0
  4. data/README.md +11 -2
  5. data/Rakefile +12 -0
  6. data/ext/byebug/byebug.c +50 -53
  7. data/ext/byebug/context.c +0 -24
  8. data/lib/byebug.rb +23 -7
  9. data/lib/byebug/command.rb +35 -24
  10. data/lib/byebug/commands/breakpoints.rb +24 -35
  11. data/lib/byebug/commands/catchpoint.rb +13 -17
  12. data/lib/byebug/commands/condition.rb +14 -19
  13. data/lib/byebug/commands/continue.rb +5 -7
  14. data/lib/byebug/commands/display.rb +3 -3
  15. data/lib/byebug/commands/edit.rb +1 -1
  16. data/lib/byebug/commands/enable.rb +18 -45
  17. data/lib/byebug/commands/eval.rb +1 -1
  18. data/lib/byebug/commands/finish.rb +1 -1
  19. data/lib/byebug/commands/frame.rb +24 -22
  20. data/lib/byebug/commands/info.rb +91 -122
  21. data/lib/byebug/commands/jump.rb +3 -8
  22. data/lib/byebug/commands/list.rb +2 -2
  23. data/lib/byebug/commands/method.rb +6 -8
  24. data/lib/byebug/commands/save.rb +1 -1
  25. data/lib/byebug/commands/set.rb +0 -12
  26. data/lib/byebug/commands/show.rb +9 -21
  27. data/lib/byebug/commands/variables.rb +3 -3
  28. data/lib/byebug/context.rb +13 -2
  29. data/lib/byebug/interface.rb +13 -7
  30. data/lib/byebug/processor.rb +23 -25
  31. data/lib/byebug/version.rb +1 -1
  32. data/old_doc/primes.rb +1 -4
  33. data/test/continue_test.rb +2 -9
  34. data/test/examples/list.rb +1 -1
  35. data/test/examples/trace.rb +1 -0
  36. data/test/help_test.rb +1 -1
  37. data/test/info_test.rb +3 -3
  38. data/test/list_test.rb +7 -1
  39. data/test/method_test.rb +0 -1
  40. data/test/show_test.rb +8 -0
  41. data/test/support/matchers.rb +4 -2
  42. data/test/trace_test.rb +18 -1
  43. metadata +2 -2
@@ -2,7 +2,7 @@ module Byebug
2
2
 
3
3
  module EvalFunctions
4
4
  def run_with_binding
5
- binding = @state.context ? get_binding : TOPLEVEL_BINDING
5
+ binding = get_binding
6
6
  $__dbg_interface = @state.interface
7
7
  eval(<<-EOC, binding)
8
8
  __dbg_verbose_save=$VERBOSE; $VERBOSE=false
@@ -11,7 +11,7 @@ module Byebug
11
11
 
12
12
  def execute
13
13
  max_frame = @state.context.stack_size - @state.frame_pos
14
- if !@match[1] or @match[1].empty?
14
+ if not @match[1]
15
15
  frame_pos = @state.frame_pos
16
16
  else
17
17
  frame_pos = get_int(@match[1], "Finish", 0, max_frame-1, 0)
@@ -16,10 +16,11 @@ module Byebug
16
16
  end
17
17
 
18
18
  if abs_frame_pos >= context.stack_size then
19
- errmsg "Adjusting would put us beyond the oldest (initial) frame.\n"
20
- return
19
+ return \
20
+ errmsg "Adjusting would put us beyond the oldest (initial) frame.\n"
21
21
  elsif abs_frame_pos < 0 then
22
- errmsg "Adjusting would put us beyond the newest (innermost) frame.\n"
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(@state.frame_pos)
32
- @state.line = context.frame_line(@state.frame_pos)
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(@state.frame_pos, false)
35
+ print_frame @state.frame_pos, false
35
36
  end
36
37
 
37
- def get_frame_call(prefix, pos, context)
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(pos)
49
- locals = context.frame_locals(pos)
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(pos)
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, context = @state.context)
88
- file = context.frame_file(pos)
89
- line = context.frame_line(pos)
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(frame_str, pos, context)
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?(context, sentinal=nil, cs=caller)
133
- recorded_size = context.stack_size
134
- to_find_fl = "#{context.frame_file(0)}:#{context.frame_line(0)}"
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?(@state.context, Byebug.start_sentinal)
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 help(cmd)
266
+ def description
265
267
  %{
266
268
  f[rame][ frame-number]
267
269
 
@@ -2,10 +2,8 @@ module Byebug
2
2
 
3
3
  module InfoFunctions
4
4
  def info_catch(*args)
5
- unless @state.context
6
- print "No frame selected.\n"
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(@match) unless @match[1]
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
- print "No frame selected.\n"
87
- return
88
- end
89
- locals = @state.context.frame_locals(@state.frame_pos)
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 print "\"info breakpoints\" not available here.\n" unless
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 do |b|
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 @state.context
128
- print "info display not available here.\n"
129
- return
130
- end
131
- if @state.display.find{|d| d[0]}
132
- print "Auto-display expressions now in effect:\n"
133
- print "Num Enb Expression\n"
134
- n = 1
135
- for d in @state.display
136
- print "%3d: %s %s\n", n, (d[0] ? 'y' : 'n'), d[1] if
137
- d[0] != nil
138
- n += 1
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 %d lines\n", lines if lines
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%s\n", stat.mtime if stat
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%s\n", LineCache.sha1(file)
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] ? args[1] : 'basic'
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?(file)
189
- unless LineCache::cached_script?(file)
190
- return print "File #{file} is not cached\n"
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(file, Command.settings[:autoreload])
184
+ LineCache::cache(args[0], Command.settings[:autoreload])
193
185
  end
194
186
 
195
- print "File #{file}"
196
- info_file_path(file) if %w(all basic path).member?(subcmd.name)
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(file) if %w(all basic lines).member?(subcmd.name)
200
- info_file_breakpoints(file) if %w(all breakpoints).member?(subcmd.name)
201
- info_file_mtime(file) if %w(all mtime).member?(subcmd.name)
202
- info_file_sha1(file) if %w(all sha1).member?(subcmd.name)
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
- stat = LineCache::stat(file)
210
- path = LineCache::path(file)
211
- print "File %s", file
212
- if path and path != file
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 @state.context
223
- print "info instance_variables not available here.\n"
224
- return
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
- errmsg "info line not available here.\n"
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 @state.context
240
- errmsg "info line not available here.\n"
241
- return
242
- end
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 print "The program being debugged is not being run.\n" if
276
- not @state.context
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
- if not @state.context
288
- errmsg "info stack not available here.\n"
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 @state.context
296
- errmsg "info global_variables not available here.\n"
297
- return
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
- if not @state.context
304
- errmsg "info variables not available here.\n"
305
- return
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(@state.frame_pos)
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