byebug 3.2.0 → 3.3.0

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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +125 -99
  4. data/CONTRIBUTING.md +4 -6
  5. data/GUIDE.md +42 -20
  6. data/Gemfile +5 -3
  7. data/README.md +2 -3
  8. data/Rakefile +11 -7
  9. data/bin/byebug +2 -252
  10. data/byebug.gemspec +7 -4
  11. data/ext/byebug/byebug.c +17 -18
  12. data/ext/byebug/byebug.h +4 -5
  13. data/ext/byebug/context.c +37 -39
  14. data/ext/byebug/threads.c +39 -18
  15. data/lib/byebug.rb +2 -110
  16. data/lib/byebug/attacher.rb +23 -0
  17. data/lib/byebug/breakpoint.rb +60 -0
  18. data/lib/byebug/command.rb +62 -70
  19. data/lib/byebug/commands/break.rb +24 -24
  20. data/lib/byebug/commands/catchpoint.rb +18 -10
  21. data/lib/byebug/commands/condition.rb +18 -17
  22. data/lib/byebug/commands/continue.rb +17 -9
  23. data/lib/byebug/commands/delete.rb +19 -13
  24. data/lib/byebug/commands/display.rb +19 -53
  25. data/lib/byebug/commands/edit.rb +7 -4
  26. data/lib/byebug/commands/enable_disable.rb +130 -0
  27. data/lib/byebug/commands/eval.rb +40 -22
  28. data/lib/byebug/commands/finish.rb +13 -4
  29. data/lib/byebug/commands/frame.rb +65 -45
  30. data/lib/byebug/commands/help.rb +17 -18
  31. data/lib/byebug/commands/history.rb +14 -8
  32. data/lib/byebug/commands/info.rb +160 -182
  33. data/lib/byebug/commands/interrupt.rb +4 -1
  34. data/lib/byebug/commands/irb.rb +30 -0
  35. data/lib/byebug/commands/kill.rb +7 -8
  36. data/lib/byebug/commands/list.rb +71 -66
  37. data/lib/byebug/commands/method.rb +14 -6
  38. data/lib/byebug/commands/pry.rb +35 -0
  39. data/lib/byebug/commands/quit.rb +9 -6
  40. data/lib/byebug/commands/reload.rb +5 -2
  41. data/lib/byebug/commands/restart.rb +13 -9
  42. data/lib/byebug/commands/save.rb +17 -17
  43. data/lib/byebug/commands/set.rb +16 -15
  44. data/lib/byebug/commands/show.rb +10 -11
  45. data/lib/byebug/commands/source.rb +11 -5
  46. data/lib/byebug/commands/stepping.rb +38 -24
  47. data/lib/byebug/commands/threads.rb +45 -31
  48. data/lib/byebug/commands/trace.rb +22 -9
  49. data/lib/byebug/commands/undisplay.rb +45 -0
  50. data/lib/byebug/commands/variables.rb +83 -27
  51. data/lib/byebug/context.rb +25 -22
  52. data/lib/byebug/core.rb +82 -0
  53. data/lib/byebug/helper.rb +37 -28
  54. data/lib/byebug/history.rb +8 -4
  55. data/lib/byebug/interface.rb +12 -17
  56. data/lib/byebug/interfaces/local_interface.rb +11 -8
  57. data/lib/byebug/interfaces/remote_interface.rb +11 -8
  58. data/lib/byebug/interfaces/script_interface.rb +9 -6
  59. data/lib/byebug/options.rb +46 -0
  60. data/lib/byebug/processor.rb +7 -1
  61. data/lib/byebug/processors/command_processor.rb +135 -125
  62. data/lib/byebug/processors/control_command_processor.rb +23 -23
  63. data/lib/byebug/remote.rb +17 -26
  64. data/lib/byebug/runner.rb +100 -0
  65. data/lib/byebug/setting.rb +33 -8
  66. data/lib/byebug/settings/autoeval.rb +5 -15
  67. data/lib/byebug/settings/autoirb.rb +4 -1
  68. data/lib/byebug/settings/autolist.rb +5 -2
  69. data/lib/byebug/settings/autoreload.rb +5 -2
  70. data/lib/byebug/settings/autosave.rb +6 -2
  71. data/lib/byebug/settings/basename.rb +7 -2
  72. data/lib/byebug/settings/callstyle.rb +4 -1
  73. data/lib/byebug/settings/forcestep.rb +6 -3
  74. data/lib/byebug/settings/fullpath.rb +5 -2
  75. data/lib/byebug/settings/histfile.rb +5 -3
  76. data/lib/byebug/settings/histsize.rb +5 -3
  77. data/lib/byebug/settings/linetrace.rb +4 -1
  78. data/lib/byebug/settings/listsize.rb +5 -1
  79. data/lib/byebug/settings/post_mortem.rb +21 -13
  80. data/lib/byebug/settings/stack_on_error.rb +6 -2
  81. data/lib/byebug/settings/testing.rb +6 -1
  82. data/lib/byebug/settings/tracing_plus.rb +5 -1
  83. data/lib/byebug/settings/verbose.rb +13 -2
  84. data/lib/byebug/settings/width.rb +4 -1
  85. data/lib/byebug/version.rb +1 -1
  86. data/test/{break_test.rb → commands/break_test.rb} +41 -53
  87. data/test/{condition_test.rb → commands/condition_test.rb} +14 -14
  88. data/test/{continue_test.rb → commands/continue_test.rb} +0 -0
  89. data/test/{delete_test.rb → commands/delete_test.rb} +2 -2
  90. data/test/commands/display_test.rb +37 -0
  91. data/test/{edit_test.rb → commands/edit_test.rb} +0 -0
  92. data/test/{eval_test.rb → commands/eval_test.rb} +1 -0
  93. data/test/{finish_test.rb → commands/finish_test.rb} +11 -1
  94. data/test/{frame_test.rb → commands/frame_test.rb} +12 -16
  95. data/test/{help_test.rb → commands/help_test.rb} +21 -4
  96. data/test/{history_test.rb → commands/history_test.rb} +0 -0
  97. data/test/{info_test.rb → commands/info_test.rb} +5 -55
  98. data/test/{interrupt_test.rb → commands/interrupt_test.rb} +0 -0
  99. data/test/commands/irb_test.rb +28 -0
  100. data/test/{kill_test.rb → commands/kill_test.rb} +1 -1
  101. data/test/{list_test.rb → commands/list_test.rb} +1 -1
  102. data/test/{method_test.rb → commands/method_test.rb} +0 -0
  103. data/test/{post_mortem_test.rb → commands/post_mortem_test.rb} +6 -10
  104. data/test/{pry_test.rb → commands/pry_test.rb} +4 -13
  105. data/test/{quit_test.rb → commands/quit_test.rb} +4 -4
  106. data/test/{reload_test.rb → commands/reload_test.rb} +0 -0
  107. data/test/{restart_test.rb → commands/restart_test.rb} +6 -0
  108. data/test/{save_test.rb → commands/save_test.rb} +2 -2
  109. data/test/{set_test.rb → commands/set_test.rb} +9 -2
  110. data/test/{show_test.rb → commands/show_test.rb} +1 -1
  111. data/test/{source_test.rb → commands/source_test.rb} +3 -3
  112. data/test/{stepping_test.rb → commands/stepping_test.rb} +44 -35
  113. data/test/{thread_test.rb → commands/thread_test.rb} +0 -0
  114. data/test/{trace_test.rb → commands/trace_test.rb} +0 -0
  115. data/test/{display_test.rb → commands/undisplay_test.rb} +7 -45
  116. data/test/{variables_test.rb → commands/variables_test.rb} +10 -1
  117. data/test/debugger_alias_test.rb +2 -2
  118. data/test/runner_test.rb +127 -0
  119. data/test/support/matchers.rb +27 -25
  120. data/test/support/test_interface.rb +9 -5
  121. data/test/support/utils.rb +96 -101
  122. data/test/test_helper.rb +32 -20
  123. metadata +93 -68
  124. data/lib/byebug/commands/enable.rb +0 -154
  125. data/lib/byebug/commands/repl.rb +0 -126
  126. data/test/irb_test.rb +0 -47
  127. data/test/support/breakpoint.rb +0 -13
@@ -1,25 +1,29 @@
1
1
  module Byebug
2
+ #
3
+ # Custom display utilities.
4
+ #
2
5
  module DisplayFunctions
3
6
  def display_expression(exp)
4
- print "#{exp} = #{bb_warning_eval(exp).inspect}\n"
7
+ "#{exp} = #{bb_warning_eval(exp).inspect}"
5
8
  end
6
9
 
7
10
  def active_display_expressions?
8
- @state.display.select{|d| d[0]}.size > 0
11
+ @state.display.select { |d| d[0] }.size > 0
9
12
  end
10
13
 
11
14
  def print_display_expressions
12
15
  n = 1
13
- for d in @state.display
14
- if d[0]
15
- print "#{n}: "
16
- display_expression(d[1])
17
- end
16
+ @state.display.each do |d|
17
+ puts "#{n}: #{display_expression(d[1])}" if d[0]
18
18
  n += 1
19
19
  end
20
20
  end
21
21
  end
22
22
 
23
+ #
24
+ # Implements the functionality of adding custom expressions to be displayed
25
+ # every time the debugger stops.
26
+ #
23
27
  class AddDisplayCommand < Command
24
28
  self.allow_in_post_mortem = false
25
29
 
@@ -30,8 +34,7 @@ module Byebug
30
34
  def execute
31
35
  exp = @match[1]
32
36
  @state.display.push [true, exp]
33
- print "#{@state.display.size}: "
34
- display_expression(exp)
37
+ puts "#{@state.display.size}: #{display_expression(exp)}"
35
38
  end
36
39
 
37
40
  class << self
@@ -40,11 +43,16 @@ module Byebug
40
43
  end
41
44
 
42
45
  def description
43
- %{disp[lay] <expression>\tadd expression into display expression list}
46
+ %(disp[lay] <expression>
47
+
48
+ Add <expression> into display expression list.)
44
49
  end
45
50
  end
46
51
  end
47
52
 
53
+ #
54
+ # Displays the value of enabled expressions.
55
+ #
48
56
  class DisplayCommand < Command
49
57
  self.allow_in_post_mortem = false
50
58
 
@@ -66,49 +74,7 @@ module Byebug
66
74
  end
67
75
 
68
76
  def description
69
- %{disp[lay]\t\tdisplay expression list}
70
- end
71
- end
72
- end
73
-
74
- class DeleteDisplayCommand < Command
75
- self.allow_in_post_mortem = false
76
-
77
- def regexp
78
- /^\s* undisp(?:lay)? (?:\s+(\S+))? \s*$/x
79
- end
80
-
81
- def execute
82
- unless pos = @match[1]
83
- if confirm('Clear all expressions? (y/n) ')
84
- for d in @state.display
85
- d[0] = false
86
- end
87
- end
88
- else
89
- pos = get_int(pos, 'Undisplay')
90
- return unless pos
91
- if @state.display[pos-1]
92
- @state.display[pos-1][0] = nil
93
- else
94
- errmsg "Display expression %d is not defined.\n", pos
95
- end
96
- end
97
- end
98
-
99
- class << self
100
- def names
101
- %w(undisplay)
102
- end
103
-
104
- def description
105
- %{undisp[lay][ nnn]
106
-
107
- Cancel some expressions to be displayed when program stops. Arguments
108
- are the code numbers of the expressions to stop displaying. No
109
- argument means cancel all automatic-display expressions. "delete
110
- display" has the same effect as this command. Do "info display" to see
111
- the current list of code numbers.}
77
+ %(disp[lay] Display expression list.)
112
78
  end
113
79
  end
114
80
  end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Edit a file from byebug's prompt.
4
+ #
2
5
  class EditCommand < Command
3
6
  self.allow_in_control = true
4
7
 
@@ -7,13 +10,13 @@ module Byebug
7
10
  end
8
11
 
9
12
  def execute
10
- if not @match[1]
13
+ if !@match[1]
11
14
  unless @state.file
12
15
  return errmsg "We are not in a state that has an associated file.\n"
13
16
  end
14
17
  file = @state.file
15
18
  line = @state.line if @state.line
16
- elsif @pos_match = /([^:]+)[:]([0-9]+)/.match(@match[1])
19
+ elsif (@pos_match = /([^:]+)[:]([0-9]+)/.match(@match[1]))
17
20
  file, line = @pos_match.captures
18
21
  elsif File.exist?(@match[1])
19
22
  file = @match[1]
@@ -37,11 +40,11 @@ module Byebug
37
40
  end
38
41
 
39
42
  def description
40
- %{edit[ file:lineno]\tEdit specified file.
43
+ %(edit[ file:lineno] Edit specified files.
41
44
 
42
45
  With no argument, edits file containing most recent line listed.
43
46
  Editing targets can also be specified to start editing at a specific
44
- line in a specific file.}
47
+ line in a specific file.)
45
48
  end
46
49
  end
47
50
  end
@@ -0,0 +1,130 @@
1
+ module Byebug
2
+ #
3
+ # Mixin to assist command parsing
4
+ #
5
+ module EnableDisableFunctions
6
+ def enable_disable_breakpoints(is_enable, args)
7
+ return errmsg('No breakpoints have been set') if Breakpoint.none?
8
+
9
+ all_breakpoints = Byebug.breakpoints.sort_by { |b| b.id }
10
+ if args.empty?
11
+ selected_breakpoints = all_breakpoints
12
+ else
13
+ selected_ids = []
14
+ args.each do |pos|
15
+ last_id = all_breakpoints.last.id
16
+ pos, err = get_int(pos, "#{is_enable} breakpoints", 1, last_id)
17
+ return errmsg(err) unless pos
18
+
19
+ selected_ids << pos
20
+ end
21
+ selected_breakpoints = all_breakpoints.select do
22
+ |b| selected_ids.include?(b.id)
23
+ end
24
+ end
25
+
26
+ selected_breakpoints.each do |b|
27
+ enabled = ('enable' == is_enable)
28
+ if enabled && !syntax_valid?(b.expr)
29
+ return errmsg("Expression \"#{b.expr}\" syntactically incorrect; " \
30
+ 'breakpoint remains disabled.')
31
+ end
32
+
33
+ b.enabled = enabled
34
+ end
35
+ end
36
+
37
+ def enable_disable_display(is_enable, args)
38
+ if 0 == @state.display.size
39
+ return errmsg('No display expressions have been set')
40
+ end
41
+
42
+ args.each do |pos|
43
+ pos, err = get_int(pos, "#{is_enable} display", 1, @state.display.size)
44
+ return errmsg(err) unless pos
45
+
46
+ @state.display[pos - 1][0] = ('enable' == is_enable)
47
+ end
48
+ end
49
+ end
50
+
51
+ #
52
+ # Enabling or disabling custom display expressions or breakpoints.
53
+ #
54
+ class EnableDisableCommand < Command
55
+ Subcommands = [
56
+ ['breakpoints', 2, 'Enable/disable breakpoints. Give breakpoint ' \
57
+ 'numbers (separated by spaces) as arguments or no ' \
58
+ 'argument at all if you want to enable/disable ' \
59
+ 'every breakpoint'],
60
+ ['display', 2, 'Enable/disable some expressions to be displayed when ' \
61
+ ' when program stops. Arguments are the code numbers ' \
62
+ 'of the expressions to resume/stop displaying. Do ' \
63
+ '"info display" to see the current list of code ' \
64
+ 'numbers']
65
+ ].map do |name, min, help|
66
+ Subcmd.new(name, min, help)
67
+ end unless defined?(Subcommands)
68
+
69
+ def regexp
70
+ /^\s* (dis|en)(?:able)? (?:\s+(.+))? \s*$/x
71
+ end
72
+
73
+ def execute
74
+ cmd = @match[1] == 'dis' ? 'disable' : 'enable'
75
+
76
+ return errmsg("\"#{cmd}\" must be followed by \"display\", " \
77
+ "\"breakpoints\" or breakpoint ids") unless @match[2]
78
+
79
+ args = @match[2].split(/[ \t]+/)
80
+ param = args.shift
81
+ subcmd = Command.find(Subcommands, param)
82
+ if subcmd
83
+ send("#{cmd}_#{subcmd.name}", args)
84
+ else
85
+ send("#{cmd}_breakpoints", args.unshift(param))
86
+ end
87
+ end
88
+
89
+ def enable_breakpoints(args)
90
+ enable_disable_breakpoints('enable', args)
91
+ end
92
+
93
+ def enable_display(args)
94
+ enable_disable_display('enable', args)
95
+ end
96
+
97
+ def disable_breakpoints(args)
98
+ enable_disable_breakpoints('disable', args)
99
+ end
100
+
101
+ def disable_display(args)
102
+ enable_disable_display('disable', args)
103
+ end
104
+
105
+ class << self
106
+ def names
107
+ %w((en|dis)able)
108
+ end
109
+
110
+ def description
111
+ %{(en|dis)[able][[ (breakpoints|display)][ n1[ n2[ ...[ nn]]]]]
112
+
113
+ Enables or disables breakpoints or displays.
114
+
115
+ "enable" by itself enables all breakpoints, just like
116
+ "enable breakpoints". On the other side, "disable" or
117
+ "disable breakpoints" disable all breakpoints.
118
+
119
+ You can also specify a space separated list of breakpoint numbers to
120
+ enable or disable specific breakpoints. You can use either
121
+ "enable <id1> ... <idn>" or "enable breakpoints <id1> ... <idn>" and
122
+ the same with "disable".
123
+
124
+ If instead of "breakpoints" you specify "display", the command will
125
+ work exactly the same way, but displays will get enabled/disabled
126
+ instead of breakpoints.}
127
+ end
128
+ end
129
+ end
130
+ end
@@ -1,6 +1,10 @@
1
+ require 'English'
1
2
  require 'pp'
2
3
 
3
4
  module Byebug
5
+ #
6
+ # Utilities used by the eval command
7
+ #
4
8
  module EvalFunctions
5
9
  def run_with_binding
6
10
  binding = get_binding
@@ -8,6 +12,9 @@ module Byebug
8
12
  end
9
13
  end
10
14
 
15
+ #
16
+ # Evaluation of expressions from byebug's prompt.
17
+ #
11
18
  class EvalCommand < Command
12
19
  self.allow_in_control = true
13
20
 
@@ -24,13 +31,13 @@ module Byebug
24
31
  expr = @match ? @match.post_match : @input
25
32
  run_with_binding do |b|
26
33
  if Setting[:stack_on_error]
27
- print "#{bb_eval(expr, b).inspect}\n"
34
+ puts "#{bb_eval(expr, b).inspect}"
28
35
  else
29
- print "#{bb_warning_eval(expr, b).inspect}\n"
36
+ puts "#{bb_warning_eval(expr, b).inspect}"
30
37
  end
31
38
  end
32
39
  rescue
33
- print "#{$!.class} Exception: #{$!.message}\n"
40
+ puts "#{$ERROR_INFO.class} Exception: #{$ERROR_INFO.message}"
34
41
  end
35
42
 
36
43
  class << self
@@ -39,15 +46,19 @@ module Byebug
39
46
  end
40
47
 
41
48
  def description
42
- %{(p|e[val]) expression
49
+ %{(p|e[val]) <expression>
50
+
51
+ Evaluates <expression> and prints its value.
43
52
 
44
- Evaluate expression and print its value
45
53
  * NOTE - unknown input is automatically evaluated, to turn this off
46
- use 'set noautoeval'}
54
+ use 'set noautoeval'.}
47
55
  end
48
56
  end
49
57
  end
50
58
 
59
+ #
60
+ # Evaluation and pretty printing from byebug's prompt.
61
+ #
51
62
  class PPCommand < Command
52
63
  self.allow_in_control = true
53
64
 
@@ -64,9 +75,9 @@ module Byebug
64
75
  PP.pp(bb_warning_eval(@match.post_match, b), out)
65
76
  end
66
77
  end
67
- print out.string
78
+ puts out.string
68
79
  rescue
69
- out.puts $!.message
80
+ out.puts $ERROR_INFO.message
70
81
  end
71
82
 
72
83
  class << self
@@ -75,11 +86,16 @@ module Byebug
75
86
  end
76
87
 
77
88
  def description
78
- %{pp expression\tevaluate expression and pretty-print its value}
89
+ %(pp <expression>
90
+
91
+ Evaluates <expression> and pretty-prints its value.)
79
92
  end
80
93
  end
81
94
  end
82
95
 
96
+ #
97
+ # Evaluation, pretty printing and columnizing from byebug's prompt.
98
+ #
83
99
  class PutLCommand < Command
84
100
  include Columnize
85
101
  self.allow_in_control = true
@@ -97,15 +113,15 @@ module Byebug
97
113
  vals = bb_warning_eval(@match.post_match, b)
98
114
  end
99
115
  if vals.is_a?(Array)
100
- vals = vals.map{|item| item.to_s}
101
- print "#{columnize(vals, Setting[:width])}\n"
116
+ vals = vals.map { |item| item.to_s }
117
+ puts "#{columnize(vals, Setting[:width])}"
102
118
  else
103
119
  PP.pp(vals, out)
104
- print out.string
120
+ puts out.string
105
121
  end
106
122
  end
107
123
  rescue
108
- out.puts $!.message
124
+ out.puts $ERROR_INFO.message
109
125
  end
110
126
 
111
127
  class << self
@@ -114,13 +130,16 @@ module Byebug
114
130
  end
115
131
 
116
132
  def description
117
- %{putl expression
133
+ %(putl <expression>
118
134
 
119
- Evaluate expression, an array, and columnize its value}
135
+ Evaluates <expression>, an array, and columnize its value.)
120
136
  end
121
137
  end
122
138
  end
123
139
 
140
+ #
141
+ # Evaluation, pretty printing, columnizing and sorting from byebug's prompt
142
+ #
124
143
  class PSCommand < Command
125
144
  include Columnize
126
145
  self.allow_in_control = true
@@ -138,15 +157,15 @@ module Byebug
138
157
  vals = bb_warning_eval(@match.post_match, b)
139
158
  end
140
159
  if vals.is_a?(Array)
141
- vals = vals.map{|item| item.to_s}
142
- print "#{columnize(vals.sort!, Setting[:width])}\n"
160
+ vals = vals.map { |item| item.to_s }
161
+ puts "#{columnize(vals.sort!, Setting[:width])}"
143
162
  else
144
163
  PP.pp(vals, out)
145
- print out.string
164
+ puts out.string
146
165
  end
147
166
  end
148
167
  rescue
149
- out.puts $!.message
168
+ out.puts $ERROR_INFO.message
150
169
  end
151
170
 
152
171
  class << self
@@ -155,11 +174,10 @@ module Byebug
155
174
  end
156
175
 
157
176
  def description
158
- %{ps expression
177
+ %(ps <expression>
159
178
 
160
- Evaluate expression, an array, sort and columnize its value}
179
+ Evaluates <expression>, an array, sort and columnize its value.)
161
180
  end
162
181
  end
163
182
  end
164
-
165
183
  end
@@ -1,4 +1,9 @@
1
1
  module Byebug
2
+ #
3
+ # Implements the finish functionality.
4
+ #
5
+ # Allows the user to continue execution until certain frames are finished.
6
+ #
2
7
  class FinishCommand < Command
3
8
  self.allow_in_post_mortem = false
4
9
 
@@ -8,8 +13,12 @@ module Byebug
8
13
 
9
14
  def execute
10
15
  max_frames = Context.stack_size - @state.frame_pos
11
- n_frames = get_int(@match[1], 'finish', 0, max_frames - 1, 1)
12
- return nil unless n_frames
16
+ if @match[1]
17
+ n_frames, err = get_int(@match[1], 'finish', 0, max_frames - 1)
18
+ return errmsg(err) unless n_frames
19
+ else
20
+ n_frames = 1
21
+ end
13
22
 
14
23
  force = n_frames == 0 ? true : false
15
24
  @state.context.step_out(@state.frame_pos + n_frames, force)
@@ -23,11 +32,11 @@ module Byebug
23
32
  end
24
33
 
25
34
  def description
26
- %{fin[ish][ n_frames]\tExecute until frame returns.
35
+ %(fin[ish][ n_frames] Execute until frame returns.
27
36
 
28
37
  If no number is given, we run until the current frame returns. If a
29
38
  number of frames `n_frames` is given, then we run until `n_frames`
30
- return from the current position.}
39
+ return from the current position.)
31
40
  end
32
41
  end
33
42
  end