byebug 1.0.2 → 1.0.3

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +1 -1
  4. data/bin/byebug +1 -2
  5. data/byebug.gemspec +1 -1
  6. data/ext/byebug/byebug.c +50 -35
  7. data/ext/byebug/context.c +99 -45
  8. data/lib/byebug.rb +5 -10
  9. data/lib/byebug/command.rb +20 -12
  10. data/lib/byebug/commands/breakpoints.rb +1 -1
  11. data/lib/byebug/commands/control.rb +14 -21
  12. data/lib/byebug/commands/display.rb +4 -4
  13. data/lib/byebug/commands/enable.rb +20 -19
  14. data/lib/byebug/commands/eval.rb +1 -1
  15. data/lib/byebug/commands/finish.rb +4 -5
  16. data/lib/byebug/commands/info.rb +118 -116
  17. data/lib/byebug/commands/list.rb +72 -48
  18. data/lib/byebug/commands/reload.rb +4 -3
  19. data/lib/byebug/commands/set.rb +7 -16
  20. data/lib/byebug/commands/show.rb +2 -2
  21. data/lib/byebug/commands/threads.rb +7 -6
  22. data/lib/byebug/context.rb +10 -2
  23. data/lib/byebug/helper.rb +3 -3
  24. data/lib/byebug/processor.rb +1 -1
  25. data/lib/byebug/version.rb +1 -1
  26. data/old_doc/byebug.texi +45 -51
  27. data/test/breakpoints_test.rb +180 -195
  28. data/test/display_test.rb +59 -53
  29. data/test/eval_test.rb +0 -2
  30. data/test/examples/info.rb +5 -5
  31. data/test/examples/info_threads.rb +1 -1
  32. data/test/finish_test.rb +16 -15
  33. data/test/info_test.rb +9 -10
  34. data/test/irb_test.rb +64 -65
  35. data/test/list_test.rb +76 -50
  36. data/test/method_test.rb +10 -5
  37. data/test/post_mortem_test.rb +27 -25
  38. data/test/reload_test.rb +31 -31
  39. data/test/restart_test.rb +106 -110
  40. data/test/show_test.rb +8 -16
  41. data/test/stepping_test.rb +4 -2
  42. data/test/support/test_dsl.rb +37 -76
  43. data/test/test_helper.rb +0 -1
  44. data/test/variables_test.rb +9 -12
  45. metadata +4 -4
@@ -22,7 +22,7 @@ module Byebug
22
22
  if expr
23
23
  if expr !~ /^\s*if\s+(.+)/
24
24
  if file or line
25
- errmsg "Expecting 'if' in breakpoint condition; got: #{expr}.\n"
25
+ errmsg "Expecting \"if\" in breakpoint condition; got: #{expr}.\n"
26
26
  else
27
27
  errmsg "Invalid breakpoint location: #{expr}.\n"
28
28
  end
@@ -1,6 +1,6 @@
1
1
  module Byebug
2
2
 
3
- class RestartCommand < Command # :nodoc:
3
+ class RestartCommand < Command
4
4
  self.allow_in_control = true
5
5
 
6
6
  def regexp
@@ -12,28 +12,24 @@ module Byebug
12
12
  end
13
13
 
14
14
  def execute
15
- if not defined? Byebug::PROG_SCRIPT
16
- errmsg "Don't know name of debugged program\n"
17
- return
18
- end
15
+ return errmsg "Don't know name of debugged program\n" unless
16
+ defined? Byebug::PROG_SCRIPT
19
17
 
20
- if not File.exist?(File.expand_path(Byebug::PROG_SCRIPT))
21
- errmsg "Ruby program #{Byebug::PROG_SCRIPT} doesn't exist\n"
22
- return
23
- end
18
+ return errmsg "Ruby program #{Byebug::PROG_SCRIPT} doesn't exist\n" unless
19
+ File.exist?(File.expand_path(Byebug::PROG_SCRIPT))
24
20
 
25
- if not defined? Byebug::RDEBUG_SCRIPT
21
+ if not defined? Byebug::BYEBUG_SCRIPT
26
22
  print "Byebug was not called from the outset...\n"
27
23
  if not File.executable?(Byebug::PROG_SCRIPT)
28
24
  print "Ruby program #{Byebug::PROG_SCRIPT} not executable... " \
29
25
  "We'll add a call to Ruby.\n"
30
26
  ruby = begin defined?(Gem) ? Gem.ruby : "ruby" rescue "ruby" end
31
- byebug_script = "#{ruby} -I#{$:.join(' -I')} #{Byebug::PROG_SCRIPT}"
27
+ cmd = "#{ruby} -I#{$:.join(' -I')} #{Byebug::PROG_SCRIPT}"
32
28
  else
33
- byebug_script = Byebug::PROG_SCRIPT
29
+ cmd = Byebug::PROG_SCRIPT
34
30
  end
35
31
  else
36
- byebug_script = Byebug::RDEBUG_SCRIPT
32
+ cmd = Byebug::BYEBUG_SCRIPT
37
33
  end
38
34
 
39
35
  begin
@@ -43,16 +39,13 @@ module Byebug
43
39
  end
44
40
 
45
41
  if @match[1]
46
- argv = [Byebug::PROG_SCRIPT] + @match[1].split(/[ \t]+/)
42
+ cmd += " #{@match[1]}"
43
+ elsif not defined? Command.settings[:argv]
44
+ return errmsg "Arguments not set. Use 'set args' to set them.\n"
47
45
  else
48
- if not defined? Command.settings[:argv]
49
- errmsg "Arguments have not been set. Use 'set args' to set them.\n"
50
- return
51
- else
52
- argv = Command.settings[:argv]
53
- end
46
+ require 'shellwords'
47
+ cmd += " #{Command.settings[:argv].compact.shelljoin}"
54
48
  end
55
- cmd = "#{byebug_script} #{argv.compact.join(' ')}"
56
49
 
57
50
  # An execv would be preferable to the "exec" below.
58
51
  print "Re exec'ing:\n\t#{cmd}\n"
@@ -1,6 +1,6 @@
1
1
  module Byebug
2
2
 
3
- module DisplayFunctions # :nodoc:
3
+ module DisplayFunctions
4
4
 
5
5
  def display_expression(exp)
6
6
  print "%s = %s\n", exp, debug_silent_eval(exp).to_s
@@ -22,7 +22,7 @@ module Byebug
22
22
  end
23
23
  end
24
24
 
25
- class AddDisplayCommand < Command # :nodoc:
25
+ class AddDisplayCommand < Command
26
26
  def regexp
27
27
  /^\s*disp(?:lay)?\s+(.+)$/
28
28
  end
@@ -47,7 +47,7 @@ module Byebug
47
47
  end
48
48
  end
49
49
 
50
- class DisplayCommand < Command # :nodoc:
50
+ class DisplayCommand < Command
51
51
  def self.always_run
52
52
  Byebug.annotate = 0 unless Byebug.annotate
53
53
  if Byebug.annotate > 1
@@ -78,7 +78,7 @@ module Byebug
78
78
  end
79
79
  end
80
80
 
81
- class DeleteDisplayCommand < Command # :nodoc:
81
+ class DeleteDisplayCommand < Command
82
82
 
83
83
  def regexp
84
84
  /^\s* undisp(?:lay)? \s* (?:(\S+))?$/x
@@ -16,14 +16,15 @@ module Byebug
16
16
  return nil unless pos
17
17
  breakpoints.each do |b|
18
18
  if b.id == pos
19
- enabled = ("Enable" == is_enable)
19
+ enabled = ('Enable' == is_enable)
20
20
  if enabled
21
21
  unless syntax_valid?(b.expr)
22
- errmsg("Expression \"#{b.expr}\" syntactically incorrect; breakpoint remains disabled.\n")
22
+ errmsg "Expression \"#{b.expr}\" syntactically incorrect; " \
23
+ "breakpoint remains disabled.\n"
23
24
  break
24
25
  end
25
26
  end
26
- b.enabled = ("Enable" == is_enable)
27
+ b.enabled = ('Enable' == is_enable)
27
28
  break
28
29
  end
29
30
  end
@@ -38,7 +39,7 @@ module Byebug
38
39
  args.each do |pos|
39
40
  pos = get_int(pos, "#{is_enable} display", 1, @state.display.size)
40
41
  return nil unless pos
41
- @state.display[pos-1][0] = ("Enable" == is_enable)
42
+ @state.display[pos-1][0] = ('Enable' == is_enable)
42
43
  end
43
44
  end
44
45
 
@@ -49,11 +50,11 @@ module Byebug
49
50
  [
50
51
  ['breakpoints', 2, 'Enable specified breakpoints',
51
52
  'Give breakpoint numbers (separated by spaces) as arguments. This is ' \
52
- 'used to cancel the effect of the \"disable\" command.'],
53
+ 'used to cancel the effect of the "disable" command.'],
53
54
  ['display', 2,
54
55
  'Enable some expressions to be displayed when program stops',
55
56
  'Arguments are the code numbers of the expressions to resume ' \
56
- 'displaying. Do \"info display\" to see the current list of code ' \
57
+ 'displaying. Do "info display" to see the current list of code ' \
57
58
  'numbers.'],
58
59
  ].map do |name, min, short_help, long_help|
59
60
  SubcmdStruct.new(name, min, short_help, long_help)
@@ -65,8 +66,8 @@ module Byebug
65
66
 
66
67
  def execute
67
68
  if not @match[1]
68
- errmsg "\"enable\" must be followed \"display\", \"breakpoints\"" +
69
- " or breakpoint numbers.\n"
69
+ errmsg "\"enable\" must be followed by \"display\", \"breakpoints\" " \
70
+ "or breakpoint numbers.\n"
70
71
  else
71
72
  args = @match[1].split(/[ \t]+/)
72
73
  param = args.shift
@@ -74,17 +75,17 @@ module Byebug
74
75
  if subcmd
75
76
  send("enable_#{subcmd.name}", args)
76
77
  else
77
- send("enable_breakpoints", args.unshift(param))
78
+ send('enable_breakpoints', args.unshift(param))
78
79
  end
79
80
  end
80
81
  end
81
82
 
82
83
  def enable_breakpoints(args)
83
- enable_disable_breakpoints("Enable", args)
84
+ enable_disable_breakpoints('Enable', args)
84
85
  end
85
86
 
86
87
  def enable_display(args)
87
- enable_disable_display("Enable", args)
88
+ enable_disable_display('Enable', args)
88
89
  end
89
90
 
90
91
  class << self
@@ -99,7 +100,7 @@ module Byebug
99
100
  return "Invalid \"enable\" subcommand \"#{args[1]}\"." unless subcmd
100
101
 
101
102
  str = subcmd.short_help + '.'
102
- str += "\n" + subcmd.long_help if subcmd.long_help
103
+ str += '\n' + subcmd.long_help if subcmd.long_help
103
104
  return str
104
105
  end
105
106
 
@@ -127,7 +128,7 @@ module Byebug
127
128
  'breakpoint is not forgotten, but has no effect until reenabled.'],
128
129
  ['display', 1, 'Disable some display expressions when program stops',
129
130
  'Arguments are the code numbers of the expressions to stop ' \
130
- 'displaying. Do \"info display\" to see the current list of code ' \
131
+ 'displaying. Do "info display" to see the current list of code ' \
131
132
  'numbers.'],
132
133
  ].map do |name, min, short_help, long_help|
133
134
  SubcmdStruct.new(name, min, short_help, long_help)
@@ -139,8 +140,8 @@ module Byebug
139
140
 
140
141
  def execute
141
142
  if not @match[1]
142
- errmsg "\"disable\" must be followed \"display\", \"breakpoints\"" +
143
- " or breakpoint numbers.\n"
143
+ errmsg "\"disable\" must be followed by \"display\", \"breakpoints\" " \
144
+ "or breakpoint numbers.\n"
144
145
  else
145
146
  args = @match[1].split(/[ \t]+/)
146
147
  param = args.shift
@@ -148,17 +149,17 @@ module Byebug
148
149
  if subcmd
149
150
  send("disable_#{subcmd.name}", args)
150
151
  else
151
- send("disable_breakpoints", args.unshift(param))
152
+ send('disable_breakpoints', args.unshift(param))
152
153
  end
153
154
  end
154
155
  end
155
156
 
156
157
  def disable_breakpoints(args)
157
- enable_disable_breakpoints("Disable", args)
158
+ enable_disable_breakpoints('Disable', args)
158
159
  end
159
160
 
160
161
  def disable_display(args)
161
- enable_disable_display("Disable", args)
162
+ enable_disable_display('Disable', args)
162
163
  end
163
164
 
164
165
  class << self
@@ -173,7 +174,7 @@ module Byebug
173
174
  return "Invalid \"disable\" subcommand \"#{args[1]}\"." unless subcmd
174
175
 
175
176
  str = subcmd.short_help + '.'
176
- str += "\n" + subcmd.long_help if subcmd.long_help
177
+ str += '\n' + subcmd.long_help if subcmd.long_help
177
178
  return str
178
179
  end
179
180
 
@@ -23,7 +23,7 @@ module Byebug
23
23
  end
24
24
  end
25
25
 
26
- class EvalCommand < Command # :nodoc:
26
+ class EvalCommand < Command
27
27
  self.allow_in_control = true
28
28
 
29
29
  register_setting_get(:autoeval) do
@@ -31,11 +31,10 @@ module Byebug
31
31
  %{
32
32
  fin[ish] [frame-number]\tExecute until selected stack frame returns.
33
33
 
34
- If no frame number is given, we run until the currently selected frame
35
- returns. The currently selected frame starts out the most-recent
36
- frame or 0 if no frame positioning (e.g "up", "down" or "frame") has
37
- been performed. If a frame number is given we run until that frame
38
- returns.
34
+ If no frame number is given, we run until the currently selected frame returns.
35
+ The currently selected frame starts out the most-recent frame or 0 if no frame
36
+ positioning (e.g "up", "down" or "frame") has been performed. If a frame number
37
+ is given we run until that frame returns.
39
38
  }
40
39
  end
41
40
  end
@@ -41,18 +41,18 @@ module Byebug
41
41
  ['locals', 2, 'Local variables of the current stack frame'],
42
42
  ['program', 2, 'Execution status of the program'],
43
43
  ['stack', 2, 'Backtrace of the stack'],
44
- # ['thread', 6, 'List info about thread NUM',
45
- # 'If no thread number is given, we list info for all threads. "terse"' \
46
- # ' and "verbose" options are possible. If "terse", just give summary ' \
47
- # 'thread name information. See "help info threads" for more detail ' \
48
- # 'about this summary information. If "verbose" is appended to the end' \
49
- # ' of the command, then the entire stack trace is given for each ' \
50
- # 'thread.'],
51
- # ['threads', 7, 'information of currently-known threads',
52
- # 'This information includes whether the thread is the current thread ' \
53
- # '(+), it\'s suspended ($) or it\'s ignored (!), plus the thread ' \
54
- # 'number and the top stack item. If "verbose" is given then the ' \
55
- # 'entire stack frame is shown.'],
44
+ ['thread', 6, 'List info about thread NUM',
45
+ 'If no thread number is given, we list info for all threads. "terse"' \
46
+ ' and "verbose" options are possible. If "terse", just give summary ' \
47
+ 'thread name information. See "help info threads" for more detail ' \
48
+ 'about this summary information. If "verbose" is appended to the end' \
49
+ ' of the command, then the entire stack trace is given for each ' \
50
+ 'thread.'],
51
+ ['threads', 7, 'information of currently-known threads',
52
+ 'This information includes whether the thread is the current thread ' \
53
+ '(+), it\'s suspended ($) or it\'s ignored (!), plus the thread ' \
54
+ 'number and the top stack item. If "verbose" is given then the ' \
55
+ 'entire stack frame is shown.'],
56
56
  ['variables', 1,
57
57
  'Local and instance variables of the current stack frame']
58
58
  ].map do |name, min, short_help, long_help|
@@ -114,37 +114,30 @@ module Byebug
114
114
  end
115
115
 
116
116
  def info_breakpoints(*args)
117
- unless @state.context
118
- print "info breakpoints not available here.\n"
119
- return
117
+ return print "\"info breakpoints\" not available here.\n" unless
118
+ @state.context
119
+
120
+ return print "No breakpoints.\n" if Byebug.breakpoints.empty?
121
+
122
+ brkpts = Byebug.breakpoints.sort_by{|b| b.id}
123
+ unless args.empty?
124
+ indices = args.map{|a| a.to_i}
125
+ brkpts = brkpts.select{|b| indices.member?(b.id)}
126
+ return errmsg "No breakpoints found among list given.\n" if
127
+ brkpts.empty?
120
128
  end
121
- unless Byebug.breakpoints.empty?
122
- brkpts = Byebug.breakpoints.sort_by{|b| b.id}
123
- unless args.empty?
124
- indices = args.map{|a| a.to_i}
125
- brkpts = brkpts.select{|b| indices.member?(b.id)}
126
- if brkpts.empty?
127
- errmsg "No breakpoints found among list given.\n"
128
- return
129
- end
129
+ print "Num Enb What\n"
130
+ brkpts.each do |b|
131
+ print "%-3d %-3s at %s:%s%s\n", b.id,
132
+ b.enabled? ? 'y' : 'n',
133
+ b.source,
134
+ b.pos,
135
+ b.expr.nil? ? '' : " if #{b.expr}"
136
+ hits = b.hit_count
137
+ if hits > 0
138
+ s = (hits > 1) ? 's' : ''
139
+ print "\tbreakpoint already hit #{hits} time#{s}\n"
130
140
  end
131
- print "Num Enb What\n"
132
- brkpts.each do |b|
133
- if b.expr.nil?
134
- print "%3d %s at %s:%s\n",
135
- b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos
136
- else
137
- print "%3d %s at %s:%s if %s\n",
138
- b.id, (b.enabled? ? 'y' : 'n'), b.source, b.pos, b.expr
139
- end
140
- hits = b.hit_count
141
- if hits > 0
142
- s = (hits > 1) ? 's' : ''
143
- print "\tbreakpoint already hit #{hits} time#{s}\n"
144
- end
145
- end
146
- else
147
- print "No breakpoints.\n"
148
141
  end
149
142
  end
150
143
 
@@ -167,6 +160,35 @@ module Byebug
167
160
  end
168
161
  end
169
162
 
163
+ def info_file_path(file)
164
+ path = LineCache.path(file)
165
+ if path != file
166
+ print " - #{path}"
167
+ end
168
+ end
169
+
170
+ def info_file_lines(file)
171
+ lines = LineCache.size(file)
172
+ print "\t %d lines\n", lines if lines
173
+ end
174
+
175
+ def info_file_breakpoints(file)
176
+ breakpoints = LineCache.trace_line_numbers(file)
177
+ if breakpoints
178
+ print "\tbreakpoint line numbers:\n"
179
+ print columnize(breakpoints.to_a.sort, self.class.settings[:width])
180
+ end
181
+ end
182
+
183
+ def info_file_mtime(file)
184
+ stat = LineCache.stat(file)
185
+ print "\t%s\n", stat.mtime if stat
186
+ end
187
+
188
+ def info_file_sha1(file)
189
+ print "\t%s\n", LineCache.sha1(file)
190
+ end
191
+
170
192
  def info_file(*args)
171
193
  return info_files unless args[0]
172
194
  file = args[0]
@@ -184,33 +206,13 @@ module Byebug
184
206
  end
185
207
 
186
208
  print "File #{file}"
187
- path = LineCache.path(file)
188
- if %w(all basic path).member?(subcmd.name) and path != file
189
- print " - #{path}"
190
- end
209
+ info_file_path(file) if %w(all basic path).member?(subcmd.name)
191
210
  print "\n"
192
211
 
193
- if %w(all basic lines).member?(subcmd.name)
194
- lines = LineCache.size(file)
195
- print "\t %d lines\n", lines if lines
196
- end
197
-
198
- if %w(all breakpoints).member?(subcmd.name)
199
- breakpoints = LineCache.trace_line_numbers(file)
200
- if breakpoints
201
- print "\tbreakpoint line numbers:\n"
202
- print columnize(breakpoints.to_a.sort, self.class.settings[:width])
203
- end
204
- end
205
-
206
- if %w(all mtime).member?(subcmd.name)
207
- stat = LineCache.stat(file)
208
- print "\t%s\n", stat.mtime if stat
209
- end
210
-
211
- if %w(all sha1).member?(subcmd.name)
212
- print "\t%s\n", LineCache.sha1(file)
213
- end
212
+ info_file_lines(file) if %w(all basic lines).member?(subcmd.name)
213
+ info_file_breakpoints(file) if %w(all breakpoints).member?(subcmd.name)
214
+ info_file_mtime(file) if %w(all mtime).member?(subcmd.name)
215
+ info_file_sha1(file) if %w(all sha1).member?(subcmd.name)
214
216
  end
215
217
 
216
218
  def info_files(*args)
@@ -301,56 +303,56 @@ module Byebug
301
303
  print_backtrace
302
304
  end
303
305
 
304
- # def info_thread_preamble(arg)
305
- # if not @state.context
306
- # errmsg "info threads not available here.\n"
307
- # return false, false
308
- # end
309
- # verbose = if arg
310
- # subcmd = find(InfoThreadSubcommands, arg)
311
- # unless subcmd
312
- # errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
313
- # return false, false
314
- # end
315
- # 'verbose' == subcmd.name
316
- # else
317
- # false
318
- # end
319
- # return true, verbose
320
- # end
321
- # private :info_thread_preamble
322
-
323
- # def info_threads(*args)
324
- # ok, verbose = info_thread_preamble(args[0])
325
- # return unless ok
326
- # threads = Byebug.contexts.sort_by{|c| c.thnum}.each do |c|
327
- # display_context(c, !verbose)
328
- # if verbose and not c.ignored?
329
- # (0...c.stack_size).each do |idx|
330
- # print "\t"
331
- # print_frame(idx, false, c)
332
- # end
333
- # end
334
- # end
335
- # end
336
-
337
- # def info_thread(*args)
338
- # unless args[0]
339
- # info_threads(args[0])
340
- # return
341
- # end
342
- # ok, verbose = info_thread_preamble(args[1])
343
- # return unless ok
344
- # c = parse_thread_num("info thread" , args[0])
345
- # return unless c
346
- # display_context(c, !verbose)
347
- # if verbose and not c.ignored?
348
- # (0...c.stack_size).each do |idx|
349
- # print "\t"
350
- # print_frame(idx, false, c)
351
- # end
352
- # end
353
- # end
306
+ def info_thread_preamble(arg)
307
+ if not @state.context
308
+ errmsg "info threads not available here.\n"
309
+ return false, false
310
+ end
311
+ verbose = if arg
312
+ subcmd = find(InfoThreadSubcommands, arg)
313
+ unless subcmd
314
+ errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
315
+ return false, false
316
+ end
317
+ 'verbose' == subcmd.name
318
+ else
319
+ false
320
+ end
321
+ return true, verbose
322
+ end
323
+ private :info_thread_preamble
324
+
325
+ def info_threads(*args)
326
+ ok, verbose = info_thread_preamble(args[0])
327
+ return unless ok
328
+ threads = Byebug.contexts.sort_by{|c| c.thnum}.each do |c|
329
+ display_context(c, !verbose)
330
+ if verbose and not c.ignored?
331
+ (0...c.stack_size).each do |idx|
332
+ print "\t"
333
+ print_frame(idx, false, c)
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ def info_thread(*args)
340
+ unless args[0]
341
+ info_threads(args[0])
342
+ return
343
+ end
344
+ ok, verbose = info_thread_preamble(args[1])
345
+ return unless ok
346
+ c = parse_thread_num("info thread" , args[0])
347
+ return unless c
348
+ display_context(c, !verbose)
349
+ if verbose and not c.ignored?
350
+ (0...c.stack_size).each do |idx|
351
+ print "\t"
352
+ print_frame(idx, false, c)
353
+ end
354
+ end
355
+ end
354
356
 
355
357
  def info_global_variables(*args)
356
358
  unless @state.context