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
@@ -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)