byebug 4.0.5 → 5.0.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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -34
  3. data/CONTRIBUTING.md +26 -31
  4. data/README.md +3 -3
  5. data/lib/byebug/breakpoint.rb +2 -1
  6. data/lib/byebug/command.rb +27 -49
  7. data/lib/byebug/commands/break.rb +21 -15
  8. data/lib/byebug/commands/catch.rb +9 -15
  9. data/lib/byebug/commands/condition.rb +12 -15
  10. data/lib/byebug/commands/continue.rb +8 -11
  11. data/lib/byebug/commands/delete.rb +9 -12
  12. data/lib/byebug/commands/disable.rb +32 -0
  13. data/lib/byebug/commands/disable/breakpoints.rb +38 -0
  14. data/lib/byebug/commands/disable/display.rb +39 -0
  15. data/lib/byebug/commands/display.rb +18 -51
  16. data/lib/byebug/commands/down.rb +39 -0
  17. data/lib/byebug/commands/edit.rb +8 -14
  18. data/lib/byebug/commands/enable.rb +25 -0
  19. data/lib/byebug/commands/enable/breakpoints.rb +38 -0
  20. data/lib/byebug/commands/enable/display.rb +39 -0
  21. data/lib/byebug/commands/eval.rb +10 -192
  22. data/lib/byebug/commands/finish.rb +11 -12
  23. data/lib/byebug/commands/frame.rb +17 -182
  24. data/lib/byebug/commands/help.rb +18 -18
  25. data/lib/byebug/commands/history.rb +9 -10
  26. data/lib/byebug/commands/info.rb +17 -190
  27. data/lib/byebug/commands/info/args.rb +39 -0
  28. data/lib/byebug/commands/info/breakpoints.rb +59 -0
  29. data/lib/byebug/commands/info/catch.rb +39 -0
  30. data/lib/byebug/commands/info/display.rb +42 -0
  31. data/lib/byebug/commands/info/file.rb +81 -0
  32. data/lib/byebug/commands/info/line.rb +31 -0
  33. data/lib/byebug/commands/info/program.rb +51 -0
  34. data/lib/byebug/commands/interrupt.rb +5 -9
  35. data/lib/byebug/commands/irb.rb +5 -9
  36. data/lib/byebug/commands/kill.rb +6 -12
  37. data/lib/byebug/commands/list.rb +47 -19
  38. data/lib/byebug/commands/method.rb +8 -14
  39. data/lib/byebug/commands/next.rb +36 -0
  40. data/lib/byebug/commands/pp.rb +41 -0
  41. data/lib/byebug/commands/pry.rb +5 -9
  42. data/lib/byebug/commands/ps.rb +44 -0
  43. data/lib/byebug/commands/putl.rb +43 -0
  44. data/lib/byebug/commands/quit.rb +8 -12
  45. data/lib/byebug/commands/restart.rb +6 -12
  46. data/lib/byebug/commands/save.rb +30 -39
  47. data/lib/byebug/commands/set.rb +19 -21
  48. data/lib/byebug/commands/show.rb +10 -16
  49. data/lib/byebug/commands/source.rb +6 -12
  50. data/lib/byebug/commands/step.rb +36 -0
  51. data/lib/byebug/commands/thread.rb +13 -130
  52. data/lib/byebug/commands/thread/current.rb +35 -0
  53. data/lib/byebug/commands/thread/list.rb +41 -0
  54. data/lib/byebug/commands/thread/resume.rb +45 -0
  55. data/lib/byebug/commands/thread/stop.rb +41 -0
  56. data/lib/byebug/commands/thread/switch.rb +43 -0
  57. data/lib/byebug/commands/tracevar.rb +8 -14
  58. data/lib/byebug/commands/undisplay.rb +12 -15
  59. data/lib/byebug/commands/untracevar.rb +5 -11
  60. data/lib/byebug/commands/up.rb +39 -0
  61. data/lib/byebug/commands/var.rb +15 -94
  62. data/lib/byebug/commands/var/all.rb +37 -0
  63. data/lib/byebug/commands/var/const.rb +38 -0
  64. data/lib/byebug/commands/var/global.rb +33 -0
  65. data/lib/byebug/commands/var/instance.rb +35 -0
  66. data/lib/byebug/commands/var/local.rb +35 -0
  67. data/lib/byebug/commands/where.rb +47 -0
  68. data/lib/byebug/core.rb +10 -0
  69. data/lib/byebug/helpers/eval.rb +47 -0
  70. data/lib/byebug/helpers/file.rb +46 -0
  71. data/lib/byebug/helpers/frame.rb +76 -0
  72. data/lib/byebug/helpers/parse.rb +74 -0
  73. data/lib/byebug/helpers/string.rb +24 -0
  74. data/lib/byebug/helpers/thread.rb +53 -0
  75. data/lib/byebug/helpers/toggle.rb +56 -0
  76. data/lib/byebug/helpers/var.rb +45 -0
  77. data/lib/byebug/history.rb +2 -4
  78. data/lib/byebug/interface.rb +5 -3
  79. data/lib/byebug/interfaces/local_interface.rb +3 -1
  80. data/lib/byebug/interfaces/remote_interface.rb +3 -1
  81. data/lib/byebug/interfaces/test_interface.rb +6 -2
  82. data/lib/byebug/printers/plain.rb +1 -1
  83. data/lib/byebug/processors/command_processor.rb +9 -11
  84. data/lib/byebug/processors/control_command_processor.rb +1 -1
  85. data/lib/byebug/remote.rb +3 -0
  86. data/lib/byebug/runner.rb +5 -3
  87. data/lib/byebug/setting.rb +2 -18
  88. data/lib/byebug/settings/savefile.rb +21 -0
  89. data/lib/byebug/states/regular_state.rb +15 -6
  90. data/lib/byebug/subcommand_list.rb +33 -0
  91. data/lib/byebug/subcommands.rb +53 -0
  92. data/lib/byebug/version.rb +1 -1
  93. metadata +45 -6
  94. data/lib/byebug/commands/enable_disable.rb +0 -132
  95. data/lib/byebug/commands/stepping.rb +0 -75
  96. data/lib/byebug/helper.rb +0 -131
@@ -8,32 +8,32 @@ module Byebug
8
8
  self.allow_in_control = true
9
9
 
10
10
  def regexp
11
- /^\s* h(?:elp)? (?: \s+(\S+) (?:\s+(\S+))? )? \s*$/x
11
+ /^\s* h(?:elp)? (?:\s+(\S+))? (?:\s+(\S+))? \s*$/x
12
12
  end
13
13
 
14
14
  def execute
15
- return puts(self.class.help) unless @match[1]
15
+ return puts(help) unless @match[1]
16
16
 
17
- cmd = Command.commands.select { |c| c.names.include?(@match[1]) }
18
- return errmsg(pr('help.errors.undefined', cmd: @match[1])) unless cmd.any?
17
+ cmd = Byebug.commands.find { |c| c.to_name == @match[1] }
18
+ return errmsg(pr('help.errors.undefined', cmd: @match[1])) unless cmd
19
19
 
20
- cmd.each { |c| puts c.help(@match[2]) }
21
- end
20
+ cmd = cmd.new(@state)
21
+ return puts(cmd.help) unless @match[2]
22
+
23
+ subcmd = cmd.subcommands.find(@match[2])
24
+ return errmsg(pr('help.errors.undefined', cmd: @match[2])) unless subcmd
22
25
 
23
- class << self
24
- def names
25
- %w(help)
26
- end
26
+ puts(subcmd.help)
27
+ end
27
28
 
28
- def description
29
- prettify <<-EOD
30
- h[elp][ <cmd>[ <subcmd>]]
29
+ def description
30
+ <<-EOD
31
+ h[elp][ <cmd>[ <subcmd>]]
31
32
 
32
- help -- prints this help.
33
- help <cmd> -- prints help on command <cmd>.
34
- help <cmd> <subcmd> -- prints help on <cmd>'s subcommand <subcmd>.
35
- EOD
36
- end
33
+ help -- prints this help.
34
+ help <cmd> -- prints help on command <cmd>.
35
+ help <cmd> <subcmd> -- prints help on <cmd>'s subcommand <subcmd>.
36
+ EOD
37
37
  end
38
38
  end
39
39
  end
@@ -1,10 +1,13 @@
1
1
  require 'byebug/command'
2
+ require 'byebug/helpers/parse'
2
3
 
3
4
  module Byebug
4
5
  #
5
6
  # Show history of byebug commands.
6
7
  #
7
8
  class HistoryCommand < Command
9
+ include Helpers::ParseHelper
10
+
8
11
  def regexp
9
12
  /^\s* hist(?:ory)? (?:\s+(?<num_cmds>.+))? \s*$/x
10
13
  end
@@ -13,23 +16,19 @@ module Byebug
13
16
  history = @state.interface.history
14
17
 
15
18
  if @match[:num_cmds]
16
- size, _ = get_int(@match[:num_cmds], 'history', 1, history.size)
19
+ size, = get_int(@match[:num_cmds], 'history', 1, history.size)
17
20
  return errmsg(err) unless size
18
21
  end
19
22
 
20
23
  puts history.to_s(size)
21
24
  end
22
25
 
23
- class << self
24
- def names
25
- %w(history)
26
- end
26
+ def description
27
+ <<-EOD
28
+ hist[ory] [num_cmds]
27
29
 
28
- def description
29
- prettify <<-EOD
30
- hist[ory] [num_cmds] Show byebug's command history.
31
- EOD
32
- end
30
+ Show byebug's command history.
31
+ EOD
33
32
  end
34
33
  end
35
34
  end
@@ -1,205 +1,32 @@
1
- require 'byebug/command'
1
+ require 'byebug/subcommands'
2
2
 
3
- module Byebug
4
- #
5
- # Utilities for the info command.
6
- #
7
- module InfoFunctions
8
- def info_catch(*_args)
9
- return puts('No frame selected.') unless @state.context
10
-
11
- if Byebug.catchpoints && !Byebug.catchpoints.empty?
12
- Byebug.catchpoints.each do |exception, _hits|
13
- puts("#{exception}: #{exception.is_a?(Class)}")
14
- end
15
- else
16
- puts 'No exceptions set to be caught.'
17
- end
18
- end
19
-
20
- def info_args(*args)
21
- locals = @state.context.frame_locals
22
- args = @state.context.frame_args
23
- return if args == [[:rest]]
24
-
25
- args.map do |_, name|
26
- s = "#{name} = #{locals[name].inspect}"
27
- s[Setting[:width] - 3..-1] = '...' if s.size > Setting[:width]
28
- puts s
29
- end
30
- end
31
-
32
- def info_breakpoint(brkpt)
33
- expr = brkpt.expr.nil? ? '' : " if #{brkpt.expr}"
34
- y_n = brkpt.enabled? ? 'y' : 'n'
35
- interp = format('%-3d %-3s at %s:%s%s',
36
- brkpt.id, y_n, brkpt.source, brkpt.pos, expr)
37
- puts interp
38
- hits = brkpt.hit_count
39
- return unless hits > 0
40
-
41
- s = (hits > 1) ? 's' : ''
42
- puts "\tbreakpoint already hit #{hits} time#{s}"
43
- end
44
-
45
- def info_breakpoints(*args)
46
- return puts('No breakpoints.') if Byebug.breakpoints.empty?
47
-
48
- brkpts = Byebug.breakpoints.sort_by(&:id)
49
- unless args.empty?
50
- indices = args.map(&:to_i)
51
- brkpts = brkpts.select { |b| indices.member?(b.id) }
52
- return errmsg('No breakpoints found among list given') if brkpts.empty?
53
- end
54
-
55
- puts 'Num Enb What'
56
- brkpts.each { |b| info_breakpoint(b) }
57
- end
58
-
59
- def info_display(*_args)
60
- return puts('There are no auto-display expressions now.') unless
61
- @state.display.find { |d| d[0] }
62
-
63
- puts 'Auto-display expressions now in effect:'
64
- puts 'Num Enb Expression'
65
- n = 1
66
- @state.display.each do |d|
67
- puts(format('%3d: %s %s', n, d[0] ? 'y' : 'n', d[1]))
68
- n += 1
69
- end
70
- end
71
-
72
- include FileFunctions
73
-
74
- def info_file_basic(file)
75
- path = File.expand_path(file)
76
- return unless File.exist?(path)
77
-
78
- s = n_lines(path) == 1 ? '' : 's'
79
- "#{path} (#{n_lines(path)} line#{s})"
80
- end
81
-
82
- def info_file_breakpoints(file)
83
- breakpoints = Breakpoint.potential_lines(file)
84
- return unless breakpoints
85
-
86
- breakpoints.to_a.sort.columnize(line_prefix: ' ',
87
- displaywidth: Setting[:width])
88
- end
89
-
90
- def info_file_mtime(file)
91
- File.stat(file).mtime
92
- end
93
-
94
- def info_file_sha1(file)
95
- require 'digest/sha1'
96
- Digest::SHA1.hexdigest(file)
97
- end
98
-
99
- def info_line(*_args)
100
- puts "Line #{@state.line} of \"#{@state.file}\""
101
- end
102
-
103
- def info_stop_reason(stop_reason)
104
- case stop_reason
105
- when :step
106
- puts "It stopped after stepping, next'ing or initial start."
107
- when :breakpoint
108
- puts 'It stopped at a breakpoint.'
109
- when :catchpoint
110
- puts 'It stopped at a catchpoint.'
111
- end
112
- end
113
-
114
- def info_program(*_args)
115
- if @state.context.dead?
116
- puts 'The program crashed.'
117
- excpt = Byebug.last_exception
118
- return puts("Exception: #{excpt.inspect}") if excpt
119
- end
120
-
121
- puts 'Program stopped. '
122
- info_stop_reason @state.context.stop_reason
123
- end
124
- end
3
+ require 'byebug/commands/info/args'
4
+ require 'byebug/commands/info/breakpoints'
5
+ require 'byebug/commands/info/catch'
6
+ require 'byebug/commands/info/display'
7
+ require 'byebug/commands/info/file'
8
+ require 'byebug/commands/info/line'
9
+ require 'byebug/commands/info/program'
125
10
 
11
+ module Byebug
126
12
  #
127
- # Show info about different aspects of the debugger.
13
+ # Shows info about different aspects of the debugger.
128
14
  #
129
15
  class InfoCommand < Command
130
- include Columnize
131
- include InfoFunctions
16
+ include Subcommands
132
17
 
133
18
  self.allow_in_control = true
134
19
 
135
- Subcommands = [
136
- ['args', 1, 'Argument variables of current stack frame'],
137
- ['breakpoints', 1, 'Status of user-settable breakpoints',
138
- 'Without argument, list info about all breakpoints. With an integer ' \
139
- 'argument, list info on that breakpoint.'],
140
- ['catch', 3, 'Exceptions that can be caught in the current stack frame'],
141
- ['display', 2, 'Expressions to display when program stops'],
142
- ['file', 4, 'Info about a particular file read in',
143
- 'File name, number of lines, possible breakpoints in the file, last ' \
144
- 'modification time and sha1 digest are listed.'],
145
- ['line', 2, 'Line number and file name of current position in source ' \
146
- 'file.'],
147
- ['program', 2, 'Execution status of the program']
148
- ].map do |name, min, help|
149
- Subcmd.new(name, min, help)
150
- end
151
-
152
- def info_file(*args)
153
- file = args[0] || @state.file
154
- unless File.exist?(file)
155
- return errmsg(pr('info.errors.undefined_file', file: file))
156
- end
157
-
158
- puts <<-EOC.gsub(/^ {6}/, '')
159
-
160
- File #{info_file_basic(file)}
161
-
162
- Breakpoint line numbers:
163
- #{info_file_breakpoints(file)}
164
-
165
- Modification time: #{info_file_mtime(file)}
166
-
167
- Sha1 Signature: #{info_file_sha1(file)}
168
-
169
- EOC
170
- end
171
-
172
20
  def regexp
173
- /^\s* i(?:nfo)? (?:\s+(.+))? \s*$/x
174
- end
175
-
176
- def execute
177
- return puts(self.class.help) unless @match[1]
178
-
179
- args = @match[1].split(/ +/)
180
- param = args.shift
181
- subcmd = Command.find(Subcommands, param)
182
- return errmsg "Unknown info command #{param}\n" unless subcmd
183
-
184
- if @state.context
185
- send("info_#{subcmd.name}", *args)
186
- else
187
- errmsg "'info #{subcmd.name}' not available without a context.\n"
188
- end
21
+ /^\s* i(?:nfo)? (?:\s+ (.+))? \s*$/x
189
22
  end
190
23
 
191
- class << self
192
- def names
193
- %w(info)
194
- end
195
-
196
- def description
197
- prettify <<-EOD
198
- info[ subcommand]
24
+ def description
25
+ <<-EOD
26
+ info[ subcommand]
199
27
 
200
- Generic command for showing things about the program being debugged.
201
- EOD
202
- end
28
+ Generic command for showing things about the program being debugged.
29
+ EOD
203
30
  end
204
31
  end
205
32
  end
@@ -0,0 +1,39 @@
1
+ module Byebug
2
+ #
3
+ # Reopens the +info+ command to define the +args+ subcommand
4
+ #
5
+ class InfoCommand < Command
6
+ #
7
+ # Information about arguments of the current method/block
8
+ #
9
+ class ArgsSubcommand < Command
10
+ def regexp
11
+ /^\s* a(?:rgs)? \s*$/x
12
+ end
13
+
14
+ def execute
15
+ locals = @state.context.frame_locals
16
+ args = @state.context.frame_args
17
+ return if args == [[:rest]]
18
+
19
+ args.map do |_, name|
20
+ s = "#{name} = #{locals[name].inspect}"
21
+ s[Setting[:width] - 3..-1] = '...' if s.size > Setting[:width]
22
+ puts s
23
+ end
24
+ end
25
+
26
+ def short_description
27
+ 'Information about arguments of the current method/block'
28
+ end
29
+
30
+ def description
31
+ <<-EOD
32
+ inf[o] a[args]
33
+
34
+ #{short_description}
35
+ EOD
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,59 @@
1
+ module Byebug
2
+ #
3
+ # Reopens the +info+ command to define the +breakpoints+ subcommand
4
+ #
5
+ class InfoCommand < Command
6
+ #
7
+ # Information about current breakpoints
8
+ #
9
+ class BreakpointsSubcommand < Command
10
+ def regexp
11
+ /^\s* b(?:reakpoints)? (?:\s+ (.+))? \s*$/x
12
+ end
13
+
14
+ def execute
15
+ return puts('No breakpoints.') if Byebug.breakpoints.empty?
16
+
17
+ breakpoints = Byebug.breakpoints.sort_by(&:id)
18
+
19
+ if @match[1]
20
+ indices = @match[1].split(/ +/).map(&:to_i)
21
+ breakpoints = breakpoints.select { |b| indices.member?(b.id) }
22
+ if breakpoints.empty?
23
+ return errmsg('No breakpoints found among list given')
24
+ end
25
+ end
26
+
27
+ puts 'Num Enb What'
28
+ breakpoints.each { |b| info_breakpoint(b) }
29
+ end
30
+
31
+ def short_description
32
+ 'Status of user settable breakpoints.'
33
+ end
34
+
35
+ def description
36
+ <<-EOD
37
+ inf[o] b[reakpoints]
38
+
39
+ #{short_description}
40
+ EOD
41
+ end
42
+
43
+ private
44
+
45
+ def info_breakpoint(brkpt)
46
+ expr = brkpt.expr.nil? ? '' : " if #{brkpt.expr}"
47
+ y_n = brkpt.enabled? ? 'y' : 'n'
48
+ interp = format('%-3d %-3s at %s:%s%s',
49
+ brkpt.id, y_n, brkpt.source, brkpt.pos, expr)
50
+ puts interp
51
+ hits = brkpt.hit_count
52
+ return unless hits > 0
53
+
54
+ s = (hits > 1) ? 's' : ''
55
+ puts "\tbreakpoint already hit #{hits} time#{s}"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,39 @@
1
+ module Byebug
2
+ #
3
+ # Reopens the +info+ command to define the +catch+ subcommand
4
+ #
5
+ class InfoCommand < Command
6
+ #
7
+ # Information on exceptions that can be caught by the debugger
8
+ #
9
+ class CatchSubcommand < Command
10
+ def regexp
11
+ /^\s* c(?:atch)? (?:\s+ (.+))? \s*$/x
12
+ end
13
+
14
+ def execute
15
+ return puts('No frame selected.') unless @state.context
16
+
17
+ if Byebug.catchpoints && !Byebug.catchpoints.empty?
18
+ Byebug.catchpoints.each do |exception, _hits|
19
+ puts("#{exception}: #{exception.is_a?(Class)}")
20
+ end
21
+ else
22
+ puts 'No exceptions set to be caught.'
23
+ end
24
+ end
25
+
26
+ def short_description
27
+ 'Exceptions that can be caught in the current stack frame'
28
+ end
29
+
30
+ def description
31
+ <<-EOD
32
+ inf[o] c[atch]
33
+
34
+ #{short_description}
35
+ EOD
36
+ end
37
+ end
38
+ end
39
+ end