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,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Interrupting execution of current thread.
4
+ #
2
5
  class InterruptCommand < Command
3
6
  self.allow_in_control = true
4
7
  self.allow_in_post_mortem = false
@@ -18,7 +21,7 @@ module Byebug
18
21
  end
19
22
 
20
23
  def description
21
- %{i|nterrupt\t interrupt the program}
24
+ %(i|nterrupt Interrupts the program.)
22
25
  end
23
26
  end
24
27
  end
@@ -0,0 +1,30 @@
1
+ require 'irb'
2
+
3
+ module Byebug
4
+ #
5
+ # Enter IRB from byebug's prompt
6
+ #
7
+ class IrbCommand < Command
8
+ def regexp
9
+ /^\s* irb \s*$/x
10
+ end
11
+
12
+ def execute
13
+ unless @state.interface.is_a?(LocalInterface)
14
+ return errmsg('Command is available only in local mode.')
15
+ end
16
+
17
+ IRB.start(__FILE__)
18
+ end
19
+
20
+ class << self
21
+ def names
22
+ %w(irb)
23
+ end
24
+
25
+ def description
26
+ %{irb Starts an Interactive Ruby (IRB) session.}
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Send custom signals to the debugged program.
4
+ #
2
5
  class KillCommand < Command
3
6
  self.allow_in_control = true
4
7
 
@@ -13,16 +16,12 @@ module Byebug
13
16
  errmsg("signal name #{signame} is not a signal I know about\n")
14
17
  return false
15
18
  end
16
- if 'KILL' == signame
17
- @state.interface.close
18
- end
19
+ @state.interface.close if 'KILL' == signame
19
20
  else
20
- if not confirm("Really kill? (y/n) ")
21
- return
22
- else
23
- signame = 'KILL'
24
- end
21
+ return unless confirm('Really kill? (y/n) ')
22
+ signame = 'KILL'
25
23
  end
24
+
26
25
  Process.kill(signame, Process.pid)
27
26
  end
28
27
 
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # List parts of the source code.
4
+ #
2
5
  class ListCommand < Command
3
6
  def regexp
4
7
  /^\s* l(?:ist)? (?:\s*([-=])|\s+(\S+))? \s*$/x
@@ -7,7 +10,8 @@ module Byebug
7
10
  def execute
8
11
  Byebug.source_reload if Setting[:autoreload]
9
12
 
10
- unless lines = get_lines(@state.file)
13
+ lines = get_lines(@state.file)
14
+ unless lines
11
15
  errmsg "No sourcefile available for #{@state.file}\n"
12
16
  return @state.previous_line
13
17
  end
@@ -15,7 +19,7 @@ module Byebug
15
19
  b, e = set_line_range(Setting[:listsize], lines.size)
16
20
  return @state.previous_line if b < 0
17
21
 
18
- print "\n[#{b}, #{e}] in #{@state.file}\n"
22
+ puts "\n[#{b}, #{e}] in #{@state.file}"
19
23
  @state.previous_line = display_list(b, e, lines, @state.line)
20
24
  end
21
25
 
@@ -25,84 +29,85 @@ module Byebug
25
29
  end
26
30
 
27
31
  def description
28
- %{l[ist]\t\tlist forward
29
- l[ist] -\tlist backward
30
- l[ist] =\tlist current line
31
- l[ist] nn-mm\tlist given lines
32
- * NOTE - to turn on autolist, use 'set autolist'}
32
+ %(l[ist][[-=]][ nn-mm]
33
+
34
+ Lists lines of code forward from current line or from the place where
35
+ code was last listed. If "list-" is specified, lists backwards
36
+ instead. If "list=" is specified, lists from current line regardless
37
+ of where code was last listed. A line range can also be specified to
38
+ list specific sections of code.)
33
39
  end
34
40
  end
35
41
 
36
42
  private
37
43
 
38
- ##
39
- # Set line range to be printed by list
40
- #
41
- # @param listsize - number of lines to be printed
42
- # @param maxline - max line number that can be printed
43
- #
44
- def set_line_range(listsize, maxline)
45
- if !@match || !(@match[1] || @match[2])
46
- b = @state.previous_line ?
47
- @state.previous_line + listsize : @state.line - (listsize/2)
48
- elsif @match[1] == '-'
49
- b = if @state.previous_line
50
- if @state.previous_line > 0
51
- @state.previous_line - listsize
52
- else
53
- @state.previous_line
54
- end
44
+ ##
45
+ # Set line range to be printed by list
46
+ #
47
+ # @param listsize - number of lines to be printed
48
+ # @param maxline - max line number that can be printed
49
+ #
50
+ def set_line_range(listsize, maxline)
51
+ if !@match || !(@match[1] || @match[2])
52
+ b = if @state.previous_line
53
+ @state.previous_line + listsize
54
+ else
55
+ @state.line - (listsize / 2)
56
+ end
57
+ elsif @match[1] == '-'
58
+ b = if @state.previous_line
59
+ if @state.previous_line > 0
60
+ @state.previous_line - listsize
55
61
  else
56
- @state.line - (listsize/2)
62
+ @state.previous_line
57
63
  end
58
- elsif @match[1] == '='
59
- @state.previous_line = nil
60
- b = @state.line - (listsize/2)
64
+ else
65
+ @state.line - (listsize / 2)
66
+ end
67
+ elsif @match[1] == '='
68
+ @state.previous_line = nil
69
+ b = @state.line - (listsize / 2)
70
+ else
71
+ b, e = @match[2].split(/[-,]/)
72
+ if e
73
+ b = b.to_i
74
+ e = e.to_i
61
75
  else
62
- b, e = @match[2].split(/[-,]/)
63
- if e
64
- b = b.to_i
65
- e = e.to_i
66
- else
67
- b = b.to_i - (listsize/2)
68
- end
69
- end
70
-
71
- if b > maxline
72
- errmsg "Invalid line range"
73
- return [ -1, -1 ]
76
+ b = b.to_i - (listsize / 2)
74
77
  end
78
+ end
75
79
 
76
- b = [1, b].max
77
- e ||= b + listsize - 1
80
+ if b > maxline
81
+ errmsg 'Invalid line range'
82
+ return [-1, -1]
83
+ end
78
84
 
79
- if e > maxline
80
- e = maxline
81
- b = e - listsize + 1
82
- b = [1, b].max
83
- end
85
+ b = [1, b].max
86
+ e ||= b + listsize - 1
84
87
 
85
- return [ b, e ]
88
+ if e > maxline
89
+ e = maxline
90
+ b = e - listsize + 1
91
+ b = [1, b].max
86
92
  end
87
93
 
88
- ##
89
- # Show file lines in LINES from line B to line E where CURRENT is the
90
- # current line number. If we can show from B to E then we return B,
91
- # otherwise we return the previous line @state.previous_line.
92
- #
93
- def display_list(b, e, lines, current)
94
- width = e.to_s.size
95
- b.upto(e) do |n|
96
- if n > 0 && lines[n-1]
97
- if n == current
98
- print "=> %#{width}d: %s\n", n, lines[n-1].chomp
99
- else
100
- print " %#{width}d: %s\n", n, lines[n-1].chomp
101
- end
102
- end
103
- end
104
- print "\n"
105
- return e == lines.size ? @state.previous_line : b
94
+ [b, e]
95
+ end
96
+
97
+ ##
98
+ # Show file lines in LINES from line B to line E where CURRENT is the
99
+ # current line number. If we can show from B to E then we return B,
100
+ # otherwise we return the previous line @state.previous_line.
101
+ #
102
+ def display_list(b, e, lines, current)
103
+ width = e.to_s.size
104
+ b.upto(e) do |n|
105
+ next unless n > 0 && lines[n - 1]
106
+ line = n == current ? '=>' : ' '
107
+ line += format(" %#{width}d: %s", n, lines[n - 1].chomp)
108
+ puts(line)
106
109
  end
110
+ e == lines.size ? @state.previous_line : b
111
+ end
107
112
  end
108
113
  end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Show methods of specific classes/modules/objects.
4
+ #
2
5
  class MethodCommand < Command
3
6
  include Columnize
4
7
 
@@ -9,11 +12,11 @@ module Byebug
9
12
  def execute
10
13
  obj = bb_eval(@match.post_match)
11
14
  if @match[1]
12
- print "#{columnize(obj.methods.sort(), Setting[:width])}\n"
13
- elsif !obj.kind_of?(Module)
14
- print "Should be Class/Module: #{@match.post_match}\n"
15
+ puts "#{columnize(obj.methods.sort, Setting[:width])}"
16
+ elsif !obj.is_a?(Module)
17
+ puts "Should be Class/Module: #{@match.post_match}"
15
18
  else
16
- print "#{columnize(obj.instance_methods(false).sort(), Setting[:width])}\n"
19
+ puts "#{columnize(obj.instance_methods(false).sort, Setting[:width])}"
17
20
  end
18
21
  end
19
22
 
@@ -23,8 +26,13 @@ module Byebug
23
26
  end
24
27
 
25
28
  def description
26
- %{m[ethod] i[nstance] <obj>\tshow methods of object
27
- m[ethod] <class|module>\t\tshow instance methods of class or module}
29
+ %{m[ethod] (i[nstance][ <obj>]|<class|module>)
30
+
31
+ When invoked with "instance", shows instance methods of the object
32
+ specified as argument or of self no object was specified.
33
+
34
+ When invoked only with a class or module, shows class methods of the
35
+ class or module specified as argument.}
28
36
  end
29
37
  end
30
38
  end
@@ -0,0 +1,35 @@
1
+ begin
2
+ require 'pry'
3
+ has_pry = true
4
+ rescue LoadError
5
+ has_pry = false
6
+ end
7
+
8
+ module Byebug
9
+ #
10
+ # Enter Pry from byebug's prompt
11
+ #
12
+ class PryCommand < Command
13
+ def regexp
14
+ /^\s* pry \s*$/x
15
+ end
16
+
17
+ def execute
18
+ unless @state.interface.is_a?(LocalInterface)
19
+ return errmsg('Command is available only in local mode.')
20
+ end
21
+
22
+ get_binding.pry
23
+ end
24
+
25
+ class << self
26
+ def names
27
+ %w(pry)
28
+ end
29
+
30
+ def description
31
+ %(pry Starts a Pry session.)
32
+ end
33
+ end
34
+ end
35
+ end if has_pry
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Exit from byebug.
4
+ #
2
5
  class QuitCommand < Command
3
6
  self.allow_in_control = true
4
7
 
@@ -7,10 +10,10 @@ module Byebug
7
10
  end
8
11
 
9
12
  def execute
10
- if @match[1] or confirm("Really quit? (y/n) ")
11
- @state.interface.close
12
- exit! # exit -> exit!: No graceful way to stop...
13
- end
13
+ return unless @match[1] || confirm('Really quit? (y/n) ')
14
+
15
+ @state.interface.close
16
+ exit! # exit -> exit!: No graceful way to stop...
14
17
  end
15
18
 
16
19
  class << self
@@ -19,11 +22,11 @@ module Byebug
19
22
  end
20
23
 
21
24
  def description
22
- %{q[uit]|exit [!|unconditionally]\tExits from byebug.
25
+ %(q[uit]|exit [!|unconditionally] Exits from byebug.
23
26
 
24
27
  Normally we prompt before exiting. However if the parameter
25
28
  "unconditionally" is given or command is suffixed with !, we exit
26
- without asking further questions.}
29
+ without asking further questions.)
27
30
  end
28
31
  end
29
32
  end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Reload source code to pick up latest changes.
4
+ #
2
5
  class ReloadCommand < Command
3
6
  self.allow_in_control = true
4
7
  self.allow_in_post_mortem = false
@@ -10,7 +13,7 @@ module Byebug
10
13
  def execute
11
14
  Byebug.source_reload
12
15
  onoff = Setting[:autoreload] ? 'on' : 'off'
13
- print "Source code was reloaded. Automatic reloading is #{onoff}\n"
16
+ puts "Source code was reloaded. Automatic reloading is #{onoff}"
14
17
  end
15
18
 
16
19
  class << self
@@ -19,7 +22,7 @@ module Byebug
19
22
  end
20
23
 
21
24
  def description
22
- %{r[eload]\tforces source code reloading}
25
+ %(r[eload] Forces source code reloading.)
23
26
  end
24
27
  end
25
28
  end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Restart debugged program from within byebug.
4
+ #
2
5
  class RestartCommand < Command
3
6
  self.allow_in_control = true
4
7
 
@@ -10,21 +13,22 @@ module Byebug
10
13
  prog = PROG_SCRIPT if defined?(PROG_SCRIPT)
11
14
  byebug_script = BYEBUG_SCRIPT if defined?(BYEBUG_SCRIPT)
12
15
 
13
- return errmsg "Don't know name of debugged program\n" unless prog
16
+ return errmsg("Don't know name of debugged program") unless prog
14
17
 
15
18
  unless File.exist?(File.expand_path(prog))
16
- return errmsg "Ruby program #{prog} doesn't exist\n"
19
+ return errmsg("Ruby program #{prog} doesn't exist")
17
20
  end
18
21
 
19
22
  if byebug_script
20
23
  cmd = "#{byebug_script} #{prog}"
21
24
  else
22
- print "Byebug was not called from the outset...\n"
25
+ puts 'Byebug was not called from the outset...'
23
26
  if File.executable?(prog)
24
27
  cmd = prog
25
28
  else
26
- print "Ruby program #{prog} not executable... We'll wrap it in a ruby call\n"
27
- cmd = "ruby -rbyebug -I#{$:.join(' -I')} #{prog}"
29
+ puts "Ruby program #{prog} not executable... " \
30
+ "We'll wrap it in a ruby call"
31
+ cmd = "ruby -rbyebug -I#{$LOAD_PATH.join(' -I')} #{prog}"
28
32
  end
29
33
  end
30
34
 
@@ -36,10 +40,10 @@ module Byebug
36
40
  end
37
41
 
38
42
  # An execv would be preferable to the "exec" below.
39
- print "Re exec'ing:\n\t#{cmd}\n"
43
+ puts "Re exec'ing:\n\t#{cmd}"
40
44
  exec cmd
41
45
  rescue Errno::EOPNOTSUPP
42
- print "Restart command is not available at this time.\n"
46
+ puts 'Restart command is not available at this time.'
43
47
  end
44
48
 
45
49
  class << self
@@ -48,10 +52,10 @@ module Byebug
48
52
  end
49
53
 
50
54
  def description
51
- %{restart|R [args]
55
+ %(restart|R [args]
52
56
 
53
57
  Restart the program. This is a re-exec - all byebug state
54
- is lost. If command arguments are passed those are used.}
58
+ is lost. If command arguments are passed those are used.)
55
59
  end
56
60
  end
57
61
  end