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.
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
@@ -247,7 +247,6 @@ class Module
247
247
  end
248
248
 
249
249
  module Kernel
250
-
251
250
  ##
252
251
  # Enters byebug after _steps_ line events occur.
253
252
  #
@@ -267,13 +266,30 @@ module Kernel
267
266
  end
268
267
  end
269
268
  alias breakpoint byebug unless respond_to?(:breakpoint)
269
+ end
270
270
 
271
- ##
272
- # Returns a binding of n-th call frame
273
- #
274
- def binding_n(n = 0)
275
- Byebug.skip do
276
- Byebug.context.frame_binding(n+1)
271
+ module Rails
272
+ module Rack
273
+ class Debugger
274
+ def initialize(app)
275
+ @app = app
276
+
277
+ # clear ARGV so that rails server options aren't passed to IRB
278
+ ARGV.clear
279
+
280
+ require 'byebug'
281
+
282
+ ::Byebug.start
283
+ puts "=> Byebug enabled"
284
+ rescue LoadError
285
+ puts "You're missing the 'byebug' gem. Add it to your Gemfile, bundle " \
286
+ "it and try again."
287
+ exit(1)
288
+ end
289
+
290
+ def call(env)
291
+ @app.call(env)
292
+ end
277
293
  end
278
294
  end
279
295
  end
@@ -30,24 +30,6 @@ module Byebug
30
30
  end
31
31
  return nil
32
32
  end
33
-
34
- ##
35
- # Build formatted list of subcmds
36
- #
37
- def format_subcmds(subcmds)
38
- cmd_name = self.class.names.join("|")
39
- s = "\n" \
40
- "--\n" \
41
- "List of \"#{cmd_name}\" subcommands:\n" \
42
- "--\n"
43
- width = subcmds.map(&:name).max_by(&:size).size
44
- for subcmd in subcmds do
45
- s += sprintf \
46
- "%s %-#{width}s -- %s\n", cmd_name, subcmd.name, subcmd.short_help
47
- end
48
- return s
49
- end
50
-
51
33
  end
52
34
 
53
35
  # Root dir for byebug
@@ -74,7 +56,37 @@ module Byebug
74
56
  output = description.split("\n").map{|l| l.gsub(/^ +/, '')}
75
57
  output.shift if output.first && output.first.empty?
76
58
  output.pop if output.last && output.last.empty?
77
- output.join("\n") + "\n"
59
+ output = output.join("\n") + "\n"
60
+
61
+ if defined? self::Subcommands
62
+ return output += format_subcmds unless args and args[1]
63
+ output += format_subcmd(args[1])
64
+ end
65
+
66
+ return output
67
+ end
68
+
69
+ def format_subcmd(subcmd_name)
70
+ subcmd = find(self::Subcommands, subcmd_name)
71
+ return "Invalid \"#{names.join("|")}\" " \
72
+ "subcommand \"#{args[1]}\"." unless subcmd
73
+
74
+ return "#{subcmd.short_help}.\n" \
75
+ "#{subcmd.long_help || '' }"
76
+ end
77
+
78
+ def format_subcmds
79
+ cmd_name = names.join("|")
80
+ s = "\n" \
81
+ "--\n" \
82
+ "List of \"#{cmd_name}\" subcommands:\n" \
83
+ "--\n"
84
+ width = self::Subcommands.map(&:name).max_by(&:size).size
85
+ for subcmd in self::Subcommands do
86
+ s += sprintf \
87
+ "%s %-#{width}s -- %s\n", cmd_name, subcmd.name, subcmd.short_help
88
+ end
89
+ return s
78
90
  end
79
91
 
80
92
  def inherited(klass)
@@ -185,9 +197,9 @@ module Byebug
185
197
  rescue StandardError, ScriptError => e
186
198
  if Command.settings[:stack_trace_on_error]
187
199
  at = eval("caller(1)", b)
188
- print "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
200
+ print "#{at.shift}:#{e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')}"
189
201
  for i in at
190
- print "\tfrom %s\n", i
202
+ print "\tfrom #{i}\n"
191
203
  end
192
204
  else
193
205
  print "#{e.class} Exception: #{e.message}\n"
@@ -212,9 +224,8 @@ module Byebug
212
224
  end
213
225
  end
214
226
 
215
- def get_binding
216
- @state.context ? @state.context.frame_binding(@state.frame_pos) :
217
- TOPLEVEL_BINDING
227
+ def get_binding pos = @state.frame_pos
228
+ @state.context ? @state.context.frame_binding(pos) : TOPLEVEL_BINDING
218
229
  end
219
230
  end
220
231
 
@@ -1,7 +1,7 @@
1
1
  module Byebug
2
2
 
3
3
  # Implements byebug "break" command.
4
- class AddBreakpoint < Command
4
+ class BreakCommand < Command
5
5
  self.allow_in_control = true
6
6
 
7
7
  def regexp
@@ -14,8 +14,7 @@ module Byebug
14
14
  end
15
15
 
16
16
  def execute
17
- return print AddBreakpoint.help(nil) if
18
- AddBreakpoint.names.include?(@match[0])
17
+ return print self.class.help(nil) if self.class.names.include?(@match[0])
19
18
 
20
19
  if @match[1]
21
20
  line, _, _, expr = @match.captures
@@ -61,27 +60,20 @@ module Byebug
61
60
  line = line.to_i
62
61
  if LineCache.cache(brkpt_filename, Command.settings[:autoreload])
63
62
  last_line = LineCache.size(brkpt_filename)
64
- if line > last_line
65
- errmsg \
66
- "There are only %d lines in file %s\n",
67
- last_line, brkpt_filename
68
- return
69
- end
70
- unless LineCache.trace_line_numbers(brkpt_filename).member?(line)
71
- errmsg \
72
- "Line %d is not a stopping point in file %s\n",
73
- line, brkpt_filename
74
- return
75
- end
63
+ return errmsg "There are only #{last_line} lines in file " \
64
+ "#{brkpt_filename}\n" if line > last_line
65
+
66
+ return errmsg "Line #{line} is not a stopping point in file " \
67
+ "#{brkpt_filename}\n" unless
68
+ LineCache.trace_line_numbers(brkpt_filename).member?(line)
76
69
  else
77
- errmsg("No source file named %s\n", brkpt_filename)
70
+ errmsg "No source file named #{brkpt_filename}\n"
78
71
  return unless confirm("Set breakpoint anyway? (y/n) ")
79
72
  end
80
73
 
81
- unless @state.context
82
- errmsg "We are not in a state we can add breakpoints.\n"
83
- return
84
- end
74
+ return errmsg "We are not in a state we can add breakpoints.\n" unless
75
+ @state.context
76
+
85
77
  b = Byebug.add_breakpoint brkpt_filename, line, expr
86
78
  print "Created breakpoint #{b.id} at " \
87
79
  "#{CommandProcessor.canonic_file(brkpt_filename)}:#{line.to_s}\n"
@@ -114,7 +106,7 @@ module Byebug
114
106
  end
115
107
 
116
108
  # Implements byebug "delete" command.
117
- class DeleteBreakpointCommand < Command
109
+ class DeleteCommand < Command
118
110
  self.allow_in_control = true
119
111
 
120
112
  def regexp
@@ -122,19 +114,16 @@ module Byebug
122
114
  end
123
115
 
124
116
  def execute
125
- return errmsg "We are not in a state we can delete breakpoints.\n" unless @state.context
126
- brkpts = @match[1]
127
- unless brkpts
128
- if confirm("Delete all breakpoints? (y or n) ")
129
- Byebug.breakpoints.clear
130
- end
117
+ return errmsg "We are not in a state we can delete breakpoints.\n" unless
118
+ @state.context
119
+
120
+ if not @match[1]
121
+ Byebug.breakpoints.clear if confirm("Delete all breakpoints? (y or n) ")
131
122
  else
132
- brkpts.split(/[ \t]+/).each do |pos|
133
- pos = get_int(pos, "Delete", 1)
134
- return unless pos
135
- unless Byebug.remove_breakpoint(pos)
136
- errmsg "No breakpoint number %d\n", pos
137
- end
123
+ @match[1].split(/[ \t]+/).each do |pos|
124
+ return unless pos = get_int(pos, "Delete", 1)
125
+ errmsg "No breakpoint number %d\n", pos unless
126
+ Byebug.remove_breakpoint(pos)
138
127
  end
139
128
  end
140
129
  end
@@ -148,8 +137,8 @@ module Byebug
148
137
  %{
149
138
  del[ete][ nnn...]
150
139
 
151
- Without argumen, deletes all breakpoints. With integer numbers,
152
- deletes specific breakpoints.
140
+ Without and argument, deletes all breakpoints. With integer arguments,
141
+ it deletes specific breakpoints.
153
142
  }
154
143
  end
155
144
  end
@@ -11,29 +11,25 @@ module Byebug
11
11
 
12
12
  def execute
13
13
  excn = @match[1]
14
- if not excn
15
- # No args given.
16
- info_catch
17
- elsif not @match[2]
18
- # One arg given.
19
- if 'off' == excn
14
+ return info_catch unless excn
15
+
16
+ if not @match[2]
17
+ if 'off' == @match[1]
20
18
  Byebug.catchpoints.clear if
21
19
  confirm("Delete all catchpoints? (y or n) ")
22
20
  else
23
- binding = @state.context ? get_binding : TOPLEVEL_BINDING
24
- unless debug_eval("#{excn}.is_a?(Class)", binding)
25
- print "Warning #{excn} is not known to be a Class\n"
26
- end
27
- Byebug.add_catchpoint(excn)
28
- print "Catch exception %s.\n", excn
21
+ print "Warning #{@match[1]} is not known to be a Class\n" unless
22
+ debug_eval "#{@match[1]}.is_a?(Class)", get_binding
23
+ Byebug.add_catchpoint @match[1]
24
+ print "Catch exception #{@match[1]}.\n"
29
25
  end
30
26
  elsif @match[2] != 'off'
31
- errmsg "Off expected. Got %s\n", @match[2]
32
- elsif Byebug.catchpoints.member?(excn)
33
- Byebug.catchpoints.delete(excn)
34
- print "Catch for exception %s removed.\n", excn
27
+ errmsg "Off expected. Got #{@match[2]}\n"
28
+ elsif Byebug.catchpoints.member?(@match[1])
29
+ Byebug.catchpoints.delete @match[1]
30
+ print "Catch for exception #{match[1]} removed.\n"
35
31
  else
36
- errmsg "Catch for exception %s not found.\n", excn
32
+ return errmsg "Catch for exception #{@match[1]} not found\n"
37
33
  end
38
34
  end
39
35
 
@@ -7,26 +7,21 @@ module Byebug
7
7
  end
8
8
 
9
9
  def execute
10
- if not @match[1]
11
- errmsg "\"condition\" must be followed by breakpoint number and expression\n"
12
- else
13
- breakpoints = Byebug.breakpoints.sort_by{|b| b.id }
14
- largest = breakpoints.inject(0) do |tally, b|
15
- tally = b.id if b.id > tally
16
- end
17
- if 0 == largest
18
- print "No breakpoints have been set.\n"
19
- return
20
- end
21
- pos = get_int(@match[1], "Condition", 1, largest)
22
- return unless pos
23
- breakpoints.each do |b|
24
- if b.id == pos
25
- b.expr = @match[2].empty? ? nil : @match[2]
26
- break
27
- end
28
- end
10
+ return errmsg "\"condition\" must be followed by " \
11
+ "breakpoint number and expression\n" unless @match[1]
29
12
 
13
+ breakpoints = Byebug.breakpoints.sort_by{|b| b.id }
14
+ largest = breakpoints.inject(0) do |tally, b|
15
+ tally = b.id if b.id > tally
16
+ end
17
+
18
+ return print "No breakpoints have been set.\n" if 0 == largest
19
+ return unless pos = get_int(@match[1], "Condition", 1, largest)
20
+ breakpoints.each do |b|
21
+ if b.id == pos
22
+ b.expr = @match[2].empty? ? nil : @match[2]
23
+ break
24
+ end
30
25
  end
31
26
  end
32
27
 
@@ -12,13 +12,11 @@ module Byebug
12
12
  def execute
13
13
  if @match[1] && !@state.context.dead?
14
14
  filename = File.expand_path(@state.file)
15
- line_number = get_int(@match[1], "Continue", 0, nil, 0)
16
- return unless line_number
17
- unless LineCache.trace_line_numbers(filename).member?(line_number)
18
- errmsg("Line %d is not a stopping point in file \"%s\".\n",
19
- line_number, filename)
20
- return
21
- end
15
+ return unless line_number = get_int(@match[1], "Continue", 0, nil, 0)
16
+ return errmsg "Line #{line_number} is not a stopping point in file " \
17
+ "\"#{filename}\"\n" unless
18
+ LineCache.trace_line_numbers(filename).member?(line_number)
19
+
22
20
  Byebug.add_breakpoint filename, line_number
23
21
  end
24
22
  @state.proceed
@@ -2,7 +2,7 @@ module Byebug
2
2
 
3
3
  module DisplayFunctions
4
4
  def display_expression(exp)
5
- print "%s = %s\n", exp, debug_silent_eval(exp).to_s
5
+ print "#{exp} = #{debug_silent_eval(exp).to_s}\n"
6
6
  end
7
7
 
8
8
  def active_display_expressions?
@@ -13,7 +13,7 @@ module Byebug
13
13
  n = 1
14
14
  for d in @state.display
15
15
  if d[0]
16
- print "%d: ", n
16
+ print "#{n}: "
17
17
  display_expression(d[1])
18
18
  end
19
19
  n += 1
@@ -29,7 +29,7 @@ module Byebug
29
29
  def execute
30
30
  exp = @match[1]
31
31
  @state.display.push [true, exp]
32
- print "%d: ", @state.display.size
32
+ print "#{@state.display.size}: "
33
33
  display_expression(exp)
34
34
  end
35
35
 
@@ -8,7 +8,7 @@ module Byebug
8
8
  end
9
9
 
10
10
  def execute
11
- if not @match[1] or @match[1].strip.empty?
11
+ if not @match[1]
12
12
  unless @state.context
13
13
  errmsg "We are not in a state that has an associated file.\n"
14
14
  return
@@ -64,18 +64,16 @@ module Byebug
64
64
  end
65
65
 
66
66
  def execute
67
- if not @match[1]
68
- errmsg "\"enable\" must be followed by \"display\", \"breakpoints\" " \
69
- "or breakpoint numbers.\n"
67
+ return errmsg "\"enable\" must be followed by \"display\", " \
68
+ "\"breakpoints\" or breakpoint numbers.\n" unless @match[1]
69
+
70
+ args = @match[1].split(/[ \t]+/)
71
+ param = args.shift
72
+ subcmd = find(Subcommands, param)
73
+ if subcmd
74
+ send("enable_#{subcmd.name}", args)
70
75
  else
71
- args = @match[1].split(/[ \t]+/)
72
- param = args.shift
73
- subcmd = find(Subcommands, param)
74
- if subcmd
75
- send("enable_#{subcmd.name}", args)
76
- else
77
- send('enable_breakpoints', args.unshift(param))
78
- end
76
+ send('enable_breakpoints', args.unshift(param))
79
77
  end
80
78
  end
81
79
 
@@ -87,17 +85,6 @@ module Byebug
87
85
  enable_disable_display('Enable', args)
88
86
  end
89
87
 
90
- def help
91
- if args[1]
92
- subcmd = find(Subcommands, args[1])
93
- return "Invalid \"enable\" subcommand \"#{args[1]}\"." unless subcmd
94
- str = subcmd.short_help + '.'
95
- str += '\n' + subcmd.long_help if subcmd.long_help
96
- return str
97
- end
98
- EnableCommand.description + format_subcmds(Subcommands)
99
- end
100
-
101
88
  class << self
102
89
  def names
103
90
  %w(enable)
@@ -131,18 +118,16 @@ module Byebug
131
118
  end
132
119
 
133
120
  def execute
134
- if not @match[1]
135
- errmsg "\"disable\" must be followed by \"display\", \"breakpoints\" " \
136
- "or breakpoint numbers.\n"
121
+ return errmsg "\"disable\" must be followed by \"display\", " \
122
+ "\"breakpoints\" or breakpoint numbers.\n" unless @match[1]
123
+
124
+ args = @match[1].split(/[ \t]+/)
125
+ param = args.shift
126
+ subcmd = find(Subcommands, param)
127
+ if subcmd
128
+ send("disable_#{subcmd.name}", args)
137
129
  else
138
- args = @match[1].split(/[ \t]+/)
139
- param = args.shift
140
- subcmd = find(Subcommands, param)
141
- if subcmd
142
- send("disable_#{subcmd.name}", args)
143
- else
144
- send('disable_breakpoints', args.unshift(param))
145
- end
130
+ send('disable_breakpoints', args.unshift(param))
146
131
  end
147
132
  end
148
133
 
@@ -154,18 +139,6 @@ module Byebug
154
139
  enable_disable_display('Disable', args)
155
140
  end
156
141
 
157
- def help(args)
158
- if args[1]
159
- subcmd = find(Subcommands, args[1])
160
- return "Invalid \"disable\" subcommand \"#{args[1]}\"." unless subcmd
161
-
162
- str = subcmd.short_help + '.'
163
- str += '\n' + subcmd.long_help if subcmd.long_help
164
- return str
165
- end
166
- DisableCommand.description + format_subcmds(Subcommads)
167
- end
168
-
169
142
  class << self
170
143
  def names
171
144
  %w(disable)