byebug 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
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