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
@@ -9,17 +9,13 @@ module Byebug
9
9
  end
10
10
 
11
11
  def switch_to_frame(frame_no)
12
- if frame_no < 0
13
- abs_frame_no = Context.stack_size + frame_no
14
- else
15
- abs_frame_no = frame_no
16
- end
12
+ frame_no >= 0 ? frame_no : Context.stack_size + frame_no
17
13
  end
18
14
 
19
15
  def navigate_to_frame(jump_no)
20
16
  return if jump_no == 0
21
17
  total_jumps, current_jumps, new_pos = jump_no.abs, 0, @state.frame_pos
22
- step = jump_no/total_jumps
18
+ step = jump_no / total_jumps
23
19
  loop do
24
20
  new_pos += step
25
21
  return new_pos if new_pos < 0 || new_pos >= Context.stack_size
@@ -29,21 +25,22 @@ module Byebug
29
25
  current_jumps += 1
30
26
  break if current_jumps == total_jumps
31
27
  end
32
- return new_pos
28
+ new_pos
33
29
  end
34
30
 
35
31
  def adjust_frame(frame_pos, absolute)
36
32
  if absolute
37
33
  abs_frame_pos = switch_to_frame(frame_pos)
38
- return errmsg "Can't navigate to c-frame\n" if c_frame?(abs_frame_pos)
34
+ return errmsg("Can't navigate to c-frame") if c_frame?(abs_frame_pos)
39
35
  else
40
36
  abs_frame_pos = navigate_to_frame(frame_pos)
41
37
  end
42
38
 
43
- return errmsg "Can't navigate beyond the oldest frame\n" if
44
- abs_frame_pos >= Context.stack_size
45
- return errmsg "Can't navigate beyond the newest frame\n" if
46
- abs_frame_pos < 0
39
+ if abs_frame_pos >= Context.stack_size
40
+ return errmsg("Can't navigate beyond the oldest frame")
41
+ elsif abs_frame_pos < 0
42
+ return errmsg("Can't navigate beyond the newest frame")
43
+ end
47
44
 
48
45
  @state.frame_pos = abs_frame_pos
49
46
  @state.file = @state.context.frame_file @state.frame_pos
@@ -54,14 +51,14 @@ module Byebug
54
51
 
55
52
  def get_frame_class(style, pos)
56
53
  frame_class = style == 'short' ? '' : "#{@state.context.frame_class pos}"
57
- return frame_class == '' ? '' : "#{frame_class}."
54
+ frame_class == '' ? '' : "#{frame_class}."
58
55
  end
59
56
 
60
57
  def get_frame_block_and_method(pos)
61
58
  frame_deco_regexp = /((?:block(?: \(\d+ levels\))?|rescue) in )?(.+)/
62
59
  frame_deco_method = "#{@state.context.frame_method pos}"
63
60
  frame_block_and_method = frame_deco_regexp.match(frame_deco_method)[1..2]
64
- return frame_block_and_method.map{ |x| x.nil? ? '' : x }
61
+ frame_block_and_method.map { |x| x.nil? ? '' : x }
65
62
  end
66
63
 
67
64
  def get_frame_args(style, pos)
@@ -71,18 +68,19 @@ module Byebug
71
68
  locals = @state.context.frame_locals pos if style == 'long'
72
69
  my_args = args.map do |arg|
73
70
  case arg[0]
74
- when :block
75
- prefix, default = '&', 'block'
76
- when :rest
77
- prefix, default = '*', 'args'
78
- else
79
- prefix, default = '', nil
71
+ when :block
72
+ prefix, default = '&', 'block'
73
+ when :rest
74
+ prefix, default = '*', 'args'
75
+ else
76
+ prefix, default = '', nil
80
77
  end
78
+
81
79
  klass = style == 'long' && arg[1] ? "##{locals[arg[1]].class}" : ''
82
80
  "#{prefix}#{arg[1] || default}#{klass}"
83
81
  end
84
82
 
85
- return "(#{my_args.join(', ')})"
83
+ "(#{my_args.join(', ')})"
86
84
  end
87
85
 
88
86
  def get_frame_call(prefix, pos)
@@ -94,10 +92,10 @@ module Byebug
94
92
 
95
93
  max_call_str_size = Setting[:width] - prefix.size
96
94
  if call_str.size > max_call_str_size
97
- call_str = call_str[0..max_call_str_size - 5] + "...)"
95
+ call_str = call_str[0..max_call_str_size - 5] + '...)'
98
96
  end
99
97
 
100
- return call_str
98
+ call_str
101
99
  end
102
100
 
103
101
  def print_backtrace
@@ -119,36 +117,43 @@ module Byebug
119
117
  end
120
118
  end
121
119
 
120
+ require 'pathname'
121
+
122
122
  def shortpath(fullpath)
123
- separator = File::ALT_SEPARATOR || File::SEPARATOR
124
- "...#{separator}" + fullpath.split(separator)[-3..-1].join(separator)
123
+ components = Pathname(fullpath).each_filename.to_a
124
+ return File.join(components) if components.size <= 2
125
+
126
+ File.join('...', components[-3..-1])
125
127
  end
126
128
 
127
129
  def print_frame(pos, mark_current = true)
128
- fullpath = @state.context.frame_file pos
130
+ fullpath = @state.context.frame_file(pos)
129
131
  file = Setting[:fullpath] ? fullpath : shortpath(fullpath)
130
- line = @state.context.frame_line pos
132
+ line = @state.context.frame_line(pos)
131
133
 
132
134
  if mark_current
133
135
  frame_str = (pos == @state.frame_pos) ? '--> ' : ' '
134
136
  else
135
- frame_str = ""
137
+ frame_str = ''
136
138
  end
137
139
  frame_str += c_frame?(pos) ? ' ͱ-- ' : ''
138
140
 
139
- frame_str += sprintf "#%-2d ", pos
141
+ frame_str += format('#%-2d ', pos)
140
142
  frame_str += get_frame_call frame_str, pos
141
143
  file_line = "at #{CommandProcessor.canonic_file(file)}:#{line}"
142
144
  if frame_str.size + file_line.size + 1 > Setting[:width]
143
- frame_str += "\n #{file_line}\n"
145
+ frame_str += "\n #{file_line}"
144
146
  else
145
- frame_str += " #{file_line}\n"
147
+ frame_str += " #{file_line}"
146
148
  end
147
149
 
148
- print frame_str
150
+ puts frame_str
149
151
  end
150
152
  end
151
153
 
154
+ #
155
+ # Show current backtrace.
156
+ #
152
157
  class WhereCommand < Command
153
158
  def regexp
154
159
  /^\s* (?:w(?:here)?|bt|backtrace) \s*$/x
@@ -164,26 +169,30 @@ module Byebug
164
169
  end
165
170
 
166
171
  def description
167
- %{w[here]|bt|backtrace\tdisplay stack frames
172
+ %(w[here]|bt|backtrace Display stack frames.
168
173
 
169
174
  Print the entire stack frame. Each frame is numbered; the most recent
170
175
  frame is 0. A frame number can be referred to in the "frame" command;
171
176
  "up" and "down" add or subtract respectively to frame numbers shown.
172
177
  The position of the current frame is marked with -->. C-frames hang
173
178
  from their most immediate Ruby frame to indicate that they are not
174
- navigable}
179
+ navigable.)
175
180
  end
176
181
  end
177
182
  end
178
183
 
184
+ #
185
+ # Move the current frame up in the backtrace.
186
+ #
179
187
  class UpCommand < Command
180
188
  def regexp
181
189
  /^\s* u(?:p)? (?:\s+(\S+))? \s*$/x
182
190
  end
183
191
 
184
192
  def execute
185
- pos = get_int(@match[1], 'Up')
186
- return unless pos
193
+ pos, err = parse_steps(@match[1], 'Up')
194
+ return errmsg(err) unless pos
195
+
187
196
  adjust_frame(pos, false)
188
197
  end
189
198
 
@@ -193,19 +202,23 @@ module Byebug
193
202
  end
194
203
 
195
204
  def description
196
- %{up[ count]\tmove to higher frame}
205
+ %(up[ count] Move to higher frame.)
197
206
  end
198
207
  end
199
208
  end
200
209
 
210
+ #
211
+ # Move the current frame down in the backtrace.
212
+ #
201
213
  class DownCommand < Command
202
214
  def regexp
203
215
  /^\s* down (?:\s+(\S+))? \s*$/x
204
216
  end
205
217
 
206
218
  def execute
207
- pos = get_int(@match[1], 'Down')
208
- return unless pos
219
+ pos, err = parse_steps(@match[1], 'Down')
220
+ return errmsg(err) unless pos
221
+
209
222
  adjust_frame(-pos, false)
210
223
  end
211
224
 
@@ -215,11 +228,14 @@ module Byebug
215
228
  end
216
229
 
217
230
  def description
218
- %{down[ count]\tmove to lower frame}
231
+ %(down[ count] Move to lower frame.)
219
232
  end
220
233
  end
221
234
  end
222
235
 
236
+ #
237
+ # Move to specific frames in the backtrace.
238
+ #
223
239
  class FrameCommand < Command
224
240
  def regexp
225
241
  /^\s* f(?:rame)? (?:\s+(\S+))? \s*$/x
@@ -227,7 +243,10 @@ module Byebug
227
243
 
228
244
  def execute
229
245
  return print_frame @state.frame_pos unless @match[1]
230
- return unless pos = get_int(@match[1], 'Frame')
246
+
247
+ pos, err = get_int(@match[1], 'Frame')
248
+ return errmsg(err) unless pos
249
+
231
250
  adjust_frame(pos, true)
232
251
  end
233
252
 
@@ -237,17 +256,18 @@ module Byebug
237
256
  end
238
257
 
239
258
  def description
240
- %{f[rame][ frame-number]
259
+ %(f[rame][ frame-number]
241
260
 
242
261
  Move the current frame to the specified frame number, or the 0 if no
243
262
  frame-number has been given.
244
263
 
245
- A negative number indicates position from the other end, so "frame -1"
246
- moves to the oldest frame, and "frame 0" moves to the newest frame.
264
+ A negative number indicates position from the other end, so
265
+ "frame -1" moves to the oldest frame, and "frame 0" moves to the
266
+ newest frame.
247
267
 
248
268
  Without an argument, the command prints the current stack frame. Since
249
269
  the current position is redisplayed, it may trigger a resyncronization
250
- if there is a front end also watching over things.}
270
+ if there is a front end also watching over things.)
251
271
  end
252
272
  end
253
273
  end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Ask for help from byebug's prompt.
4
+ #
2
5
  class HelpCommand < Command
3
6
  include Columnize
4
7
 
@@ -12,24 +15,18 @@ module Byebug
12
15
  if @match[1]
13
16
  args = @match[1].split
14
17
  cmds = @state.commands.select { |cmd| cmd.names.include?(args[0]) }
15
- unless cmds.empty?
16
- help = cmds.map{ |cmd| cmd.help(args) }.join("\n")
17
- help = help.split("\n").map{|l| l.gsub(/^ +/, '')}
18
- help.shift if help.first && help.first.empty?
19
- help.pop if help.last && help.last.empty?
20
- return print help.join("\n") + "\n"
21
- else
22
- return errmsg "Undefined command: \"#{args[0]}\". Try \"help\".\n" if
23
- args[0]
18
+ if cmds.empty?
19
+ return errmsg("Undefined command: \"#{args[0]}\". Try \"help\"")
24
20
  end
25
- end
26
21
 
27
- print "byebug help v#{VERSION}\n" unless Setting[:testing]
22
+ return puts(cmds.map { |cmd| cmd.help(args[1..-1]) }.join("\n"))
23
+ end
28
24
 
29
- print "Type \"help <command-name>\" for help on a specific command\n\n"
30
- print "Available commands:\n"
31
- cmds = @state.commands.map{ |cmd| cmd.names }.flatten.uniq.sort
32
- print columnize(cmds, Setting[:width])
25
+ puts "byebug help v#{VERSION}" unless Setting[:testing]
26
+ puts "Type \"help <command-name>\" for help on a specific command\n"
27
+ puts 'Available commands:'
28
+ cmds = @state.commands.map { |cmd| cmd.names }.flatten.uniq.sort
29
+ puts columnize(cmds, Setting[:width])
33
30
  end
34
31
 
35
32
  class << self
@@ -38,9 +35,11 @@ module Byebug
38
35
  end
39
36
 
40
37
  def description
41
- %{h[elp]\t\tprint this help
42
- h[elp] command\tprint help on command
43
- h[elp] command subcommand\tprint help on subcommand}
38
+ %(h[elp][ <command>[ <subcommand>]]
39
+
40
+ "help" alone prints this help.
41
+ "help <command>" prints help on <command>.
42
+ "help <command> <subcommand> prints help on <subcommand>.)
44
43
  end
45
44
  end
46
45
  end
@@ -1,18 +1,24 @@
1
1
  module Byebug
2
+ #
3
+ # Show history of byebug commands.
4
+ #
2
5
  class HistoryCommand < Command
3
6
  def regexp
4
7
  /^\s* hist(?:ory)? (?:\s+(?<num_cmds>.+))? \s*$/x
5
8
  end
6
9
 
7
10
  def execute
8
- if Setting[:autosave]
9
- if arg = @match[:num_cmds]
10
- size = get_int(arg, 'history', 1, Setting[:histsize])
11
- end
12
- print History.to_s(size || Setting[:histsize])
13
- else
14
- errmsg "Not currently saving history. Enable it with \"set autosave\"\n"
11
+ unless Setting[:autosave]
12
+ return errmsg('Not currently saving history. ' \
13
+ "Enable it with \"set autosave\"")
15
14
  end
15
+
16
+ if @match[:num_cmds]
17
+ size, err = get_int(@match[:num_cmds], 'history', 1, Setting[:histsize])
18
+ return errmsg(err) unless size
19
+ end
20
+
21
+ puts History.to_s(size || Setting[:histsize])
16
22
  end
17
23
 
18
24
  class << self
@@ -21,7 +27,7 @@ module Byebug
21
27
  end
22
28
 
23
29
  def description
24
- %{hist[ory] [num_cmds]\t\tShow byebug's command history}
30
+ %(hist[ory] [num_cmds] Show byebug's command history.)
25
31
  end
26
32
  end
27
33
  end
@@ -1,81 +1,17 @@
1
1
  module Byebug
2
+ #
3
+ # Utility methods to assist the info command
4
+ #
2
5
  module InfoFunctions
3
- def info_catch(*args)
4
- return print "No frame selected.\n" unless @state.context
6
+ def info_catch(*_args)
7
+ return puts('No frame selected.') unless @state.context
5
8
 
6
- if Byebug.catchpoints and not Byebug.catchpoints.empty?
7
- Byebug.catchpoints.each do |exception, hits|
8
- print "#{exception}: #{exception.is_a?(Class)}\n"
9
+ if Byebug.catchpoints && !Byebug.catchpoints.empty?
10
+ Byebug.catchpoints.each do |exception, _hits|
11
+ puts("#{exception}: #{exception.is_a?(Class)}")
9
12
  end
10
13
  else
11
- print "No exceptions set to be caught.\n"
12
- end
13
- end
14
- end
15
-
16
- class InfoCommand < Command
17
- include Columnize
18
- self.allow_in_control = true
19
-
20
- Subcommands = [
21
- ['args' , 1, 'Argument variables of current stack frame' ],
22
- ['breakpoints' , 1, 'Status of user-settable breakpoints',
23
- 'Without argument, list info about all ' \
24
- 'breakpoints. With an integer argument, ' \
25
- 'list info on that breakpoint.' ],
26
- ['catch' , 3, 'Exceptions that can be caught in the ' \
27
- 'current stack frame' ],
28
- ['display' , 2, 'Expressions to display when program stops' ],
29
- ['file' , 4, 'Info about a particular file read in',
30
- 'After the file name is supplied, you can' \
31
- 'list file attributes that you wish to ' \
32
- 'see. Attributes include: "all", "basic",' \
33
- ' "breakpoint", "lines", "mtime", "path" ' \
34
- 'and "sha1".' ],
35
- ['files' , 5, 'File names and timestamps of files read in' ],
36
- ['global_variables' , 2, 'Global variables' ],
37
- ['instance_variables', 2, 'Instance variables in current stack frame' ],
38
- ['line' , 2, 'Line number and file name of current ' \
39
- 'position in source file' ],
40
- ['locals' , 2, 'Local variables of the current stack frame' ],
41
- ['program' , 2, 'Execution status of the program' ],
42
- ['variables' , 1, 'Local and instance variables of the ' \
43
- 'current stack frame' ]
44
- ].map do |name, min, help|
45
- Subcmd.new(name, min, help)
46
- end unless defined?(Subcommands)
47
-
48
- InfoFileSubcommands = [
49
- ['all' , 1, 'All file information available - breakpoints, ' \
50
- 'lines, mtime, path and sha1' ],
51
- ['basic' , 2, 'basic information - path, number of lines' ],
52
- ['breakpoints', 2, 'Show trace line numbers',
53
- 'These are the line number where a breakpoint ' \
54
- 'can be set.' ],
55
- ['lines' , 1, 'Show number of lines in the file' ],
56
- ['mtime' , 1, 'Show modification time of file' ],
57
- ['path' , 4, 'Show full file path name for file' ],
58
- ['sha1' , 1, 'Show SHA1 hash of contents of the file' ]
59
- ].map do |name, min, help|
60
- Subcmd.new(name, min, help)
61
- end unless defined?(InfoFileSubcommands)
62
-
63
- def regexp
64
- /^\s* i(?:nfo)? (?:\s+(.+))? \s*$/x
65
- end
66
-
67
- def execute
68
- return print InfoCommand.help(nil) unless @match[1]
69
-
70
- args = @match[1].split(/[ \t]+/)
71
- param = args.shift
72
- subcmd = Command.find(Subcommands, param)
73
- return errmsg "Unknown info command #{param}\n" unless subcmd
74
-
75
- if @state.context
76
- send("info_#{subcmd.name}", *args)
77
- else
78
- errmsg "info_#{subcmd.name} not available without a context.\n"
14
+ puts 'No exceptions set to be caught.'
79
15
  end
80
16
  end
81
17
 
@@ -86,104 +22,81 @@ module Byebug
86
22
 
87
23
  args.map do |_, name|
88
24
  s = "#{name} = #{locals[name].inspect}"
89
- s[Setting[:width]-3..-1] = "..." if s.size > Setting[:width]
90
- print "#{s}\n"
25
+ s[Setting[:width] - 3..-1] = '...' if s.size > Setting[:width]
26
+ puts s
91
27
  end
92
28
  end
93
29
 
94
30
  def info_breakpoint(brkpt)
95
31
  expr = brkpt.expr.nil? ? '' : " if #{brkpt.expr}"
96
- print "%-3d %-3s at %s:%s%s\n" %
97
- [brkpt.id, brkpt.enabled? ? 'y' : 'n', brkpt.source, brkpt.pos, expr]
32
+ y_n = brkpt.enabled? ? 'y' : 'n'
33
+ interp = format('%-3d %-3s at %s:%s%s',
34
+ brkpt.id, y_n, brkpt.source, brkpt.pos, expr)
35
+ puts interp
98
36
  hits = brkpt.hit_count
99
- if hits > 0
100
- s = (hits > 1) ? 's' : ''
101
- print "\tbreakpoint already hit #{hits} time#{s}\n"
102
- end
37
+ return unless hits > 0
38
+
39
+ s = (hits > 1) ? 's' : ''
40
+ puts "\tbreakpoint already hit #{hits} time#{s}"
103
41
  end
104
- private :info_breakpoint
105
42
 
106
43
  def info_breakpoints(*args)
107
- return print "No breakpoints.\n" if Byebug.breakpoints.empty?
44
+ return puts('No breakpoints.') if Byebug.breakpoints.empty?
108
45
 
109
- brkpts = Byebug.breakpoints.sort_by{|b| b.id}
46
+ brkpts = Byebug.breakpoints.sort_by { |b| b.id }
110
47
  unless args.empty?
111
- indices = args.map{|a| a.to_i}
112
- brkpts = brkpts.select{|b| indices.member?(b.id)}
113
- return errmsg "No breakpoints found among list given.\n" if
114
- brkpts.empty?
48
+ indices = args.map { |a| a.to_i }
49
+ brkpts = brkpts.select { |b| indices.member?(b.id) }
50
+ return errmsg('No breakpoints found among list given') if brkpts.empty?
115
51
  end
116
- print "Num Enb What\n"
52
+
53
+ puts 'Num Enb What'
117
54
  brkpts.each { |b| info_breakpoint(b) }
118
55
  end
119
56
 
120
- def info_display(*args)
121
- return print "There are no auto-display expressions now.\n" unless
122
- @state.display.find{|d| d[0]}
57
+ def info_display(*_args)
58
+ return puts('There are no auto-display expressions now.') unless
59
+ @state.display.find { |d| d[0] }
123
60
 
124
- print "Auto-display expressions now in effect:\n" \
125
- "Num Enb Expression\n"
61
+ puts 'Auto-display expressions now in effect:'
62
+ puts 'Num Enb Expression'
126
63
  n = 1
127
- for d in @state.display
128
- print "%3d: %s %s\n" % [n, (d[0] ? 'y' : 'n'), d[1]]
64
+ @state.display.each do |d|
65
+ puts(format('%3d: %s %s', n, d[0] ? 'y' : 'n', d[1]))
129
66
  n += 1
130
67
  end
131
68
  end
132
69
 
133
70
  def info_file_path(file)
134
- print "File #{file}"
71
+ s = "File #{file}"
135
72
  path = File.expand_path(file)
136
- print " - #{path}\n" if path and path != file
73
+ s = "#{s} - #{path}" if path && path != file
74
+ puts s
137
75
  end
138
- private :info_file_path
139
76
 
140
77
  def info_file_lines(file)
141
78
  lines = File.foreach(file)
142
- print "\t#{lines.count} lines\n" if lines
79
+ puts "\t#{lines.count} lines" if lines
143
80
  end
144
- private :info_file_lines
145
81
 
146
82
  def info_file_breakpoints(file)
147
83
  breakpoints = LineCache.trace_line_numbers(file)
148
- if breakpoints
149
- print "\tbreakpoint line numbers:\n"
150
- print columnize(breakpoints.to_a.sort, Setting[:width])
151
- end
84
+ return unless breakpoints
85
+
86
+ puts "\tbreakpoint line numbers:"
87
+ puts columnize(breakpoints.to_a.sort, Setting[:width])
152
88
  end
153
- private :info_file_breakpoints
154
89
 
155
90
  def info_file_mtime(file)
156
91
  stat = File.stat(file)
157
- print "\t#{stat.mtime}\n" if stat
92
+ puts "\t#{stat.mtime}" if stat
158
93
  end
159
- private :info_file_mtime
160
94
 
161
95
  def info_file_sha1(file)
162
- print "\t#{Digest::SHA1.hexdigest(file)}\n"
163
- end
164
- private :info_file_sha1
165
-
166
- def info_file(*args)
167
- return info_files unless args[0]
168
-
169
- subcmd = Command.find(InfoFileSubcommands, args[1] || 'basic')
170
- return errmsg "Invalid parameter #{args[1]}\n" unless subcmd
171
-
172
- if %w(all basic).member?(subcmd.name)
173
- info_file_path(args[0])
174
- info_file_lines(args[0])
175
- if subcmd.name == 'all'
176
- info_file_breakpoints(args[0])
177
- info_file_mtime(args[0])
178
- info_file_sha1(args[0])
179
- end
180
- else
181
- print "File #{args[0]}\n" if subcmd.name != 'path'
182
- send("info_file_#{subcmd.name}", args[0])
183
- end
96
+ puts "\t#{Digest::SHA1.hexdigest(file)}"
184
97
  end
185
98
 
186
- def info_files(*args)
99
+ def info_files(*_args)
187
100
  files = SCRIPT_LINES__.keys
188
101
  files.uniq.sort.each do |file|
189
102
  info_file_path(file)
@@ -191,18 +104,8 @@ module Byebug
191
104
  end
192
105
  end
193
106
 
194
- def info_instance_variables(*args)
195
- obj = bb_eval('self')
196
- var_list(obj.instance_variables)
197
- end
198
-
199
- def info_line(*args)
200
- print "Line #{@state.line} of \"#{@state.file}\"\n"
201
- end
202
-
203
- def info_locals(*args)
204
- locals = @state.context.frame_locals
205
- print_hash(locals)
107
+ def info_line(*_args)
108
+ puts "Line #{@state.line} of \"#{@state.file}\""
206
109
  end
207
110
 
208
111
  def print_hash(vars)
@@ -211,55 +114,130 @@ module Byebug
211
114
  s = "#{name} = #{vars[name].inspect}"
212
115
  rescue
213
116
  begin
214
- s = "#{name} = #{vars[name].to_s}"
215
- rescue
216
- s = "#{name} = *Error in evaluation*"
117
+ s = "#{name} = #{vars[name]}"
118
+ rescue
119
+ s = "#{name} = *Error in evaluation*"
217
120
  end
218
121
  end
219
- s[Setting[:width]-3..-1] = "..." if s.size > Setting[:width]
220
- print "#{s}\n"
122
+ s[Setting[:width] - 3..-1] = '...' if s.size > Setting[:width]
123
+ puts s
221
124
  end
222
125
  end
223
- private :print_hash
224
126
 
225
127
  def info_stop_reason(stop_reason)
226
128
  case stop_reason
227
- when :step
228
- print "It stopped after stepping, next'ing or initial start.\n"
229
- when :breakpoint
230
- print("It stopped at a breakpoint.\n")
231
- when :catchpoint
232
- print("It stopped at a catchpoint.\n")
233
- else
234
- print "unknown reason: %s\n" % @state.context.stop_reason.to_s
129
+ when :step
130
+ puts "It stopped after stepping, next'ing or initial start."
131
+ when :breakpoint
132
+ puts 'It stopped at a breakpoint.'
133
+ when :catchpoint
134
+ puts 'It stopped at a catchpoint.'
135
+ else
136
+ puts "Unknown reason: #{@state.context.stop_reason}"
235
137
  end
236
138
  end
237
- private :info_stop_reason
238
139
 
239
- def info_program(*args)
140
+ def info_program(*_args)
240
141
  if @state.context.dead?
241
- print "The program crashed.\n"
242
- print "Exception: #{Byebug.last_exception.inspect}\n" if Byebug.last_exception
243
- return
142
+ puts 'The program crashed.'
143
+ excpt = Byebug.last_exception
144
+ return puts("Exception: #{excpt.inspect}") if excpt
244
145
  end
245
146
 
246
- print "Program stopped. "
147
+ puts 'Program stopped. '
247
148
  info_stop_reason @state.context.stop_reason
248
149
  end
249
150
 
250
- def info_global_variables(*args)
251
- var_global
252
- end
253
-
254
- def info_variables(*args)
151
+ def info_variables(*_args)
255
152
  locals = @state.context.frame_locals
256
153
  locals[:self] = @state.context.frame_self(@state.frame_pos)
257
154
  print_hash(locals)
258
155
 
259
156
  obj = bb_eval('self')
260
- var_list(obj.instance_variables, obj.instance_eval{binding()})
157
+ var_list(obj.instance_variables, obj.instance_eval { binding })
261
158
  var_class_self
262
159
  end
160
+ end
161
+
162
+ #
163
+ # Show info about different aspects of the debugger.
164
+ #
165
+ class InfoCommand < Command
166
+ include Columnize
167
+ self.allow_in_control = true
168
+
169
+ Subcommands = [
170
+ ['args', 1, 'Argument variables of current stack frame'],
171
+ ['breakpoints', 1, 'Status of user-settable breakpoints',
172
+ 'Without argument, list info about all breakpoints. With an integer ' \
173
+ 'argument, list info on that breakpoint.'],
174
+ ['catch', 3, 'Exceptions that can be caught in the current stack frame'],
175
+ ['display', 2, 'Expressions to display when program stops'],
176
+ ['file', 4, 'Info about a particular file read in',
177
+ 'After the file name is supplied, you can list file attributes that ' \
178
+ 'you wish to see. Attributes include: "all", "basic", "breakpoint", ' \
179
+ '"lines", "mtime", "path" and "sha1".'],
180
+ ['files', 5, 'File names and timestamps of files read in'],
181
+ ['line', 2, 'Line number and file name of current position in source ' \
182
+ 'file.'],
183
+ ['program', 2, 'Execution status of the program']
184
+ ].map do |name, min, help|
185
+ Subcmd.new(name, min, help)
186
+ end unless defined?(Subcommands)
187
+
188
+ InfoFileSubcommands = [
189
+ ['all', 1, 'All file information available - breakpoints, lines, ' \
190
+ 'mtime, path and sha1'],
191
+ ['basic', 2, 'basic information - path, number of lines'],
192
+ ['breakpoints', 2, 'Show trace line numbers',
193
+ 'These are the line number where a breakpoint can be set.'],
194
+ ['lines', 1, 'Show number of lines in the file'],
195
+ ['mtime', 1, 'Show modification time of file'],
196
+ ['path', 4, 'Show full file path name for file'],
197
+ ['sha1', 1, 'Show SHA1 hash of contents of the file']
198
+ ].map do |name, min, help|
199
+ Subcmd.new(name, min, help)
200
+ end unless defined?(InfoFileSubcommands)
201
+
202
+ def info_file(*args)
203
+ return info_files unless args[0]
204
+
205
+ mode = args[1] || 'basic'
206
+ subcmd = Command.find(InfoFileSubcommands, mode)
207
+ return errmsg "Invalid parameter #{args[1]}\n" unless subcmd
208
+
209
+ if %w(all basic).member?(subcmd.name)
210
+ info_file_path(args[0])
211
+ info_file_lines(args[0])
212
+ if subcmd.name == 'all'
213
+ info_file_breakpoints(args[0])
214
+ info_file_mtime(args[0])
215
+ info_file_sha1(args[0])
216
+ end
217
+ else
218
+ puts("File #{args[0]}") if subcmd.name != 'path'
219
+ send("info_file_#{subcmd.name}", args[0])
220
+ end
221
+ end
222
+
223
+ def regexp
224
+ /^\s* i(?:nfo)? (?:\s+(.+))? \s*$/x
225
+ end
226
+
227
+ def execute
228
+ return puts(InfoCommand.help) unless @match[1]
229
+
230
+ args = @match[1].split(/[ \t]+/)
231
+ param = args.shift
232
+ subcmd = Command.find(Subcommands, param)
233
+ return errmsg "Unknown info command #{param}\n" unless subcmd
234
+
235
+ if @state.context
236
+ send("info_#{subcmd.name}", *args)
237
+ else
238
+ errmsg "info_#{subcmd.name} not available without a context.\n"
239
+ end
240
+ end
263
241
 
264
242
  class << self
265
243
  def names
@@ -267,25 +245,25 @@ module Byebug
267
245
  end
268
246
 
269
247
  def description
270
- %{info[ subcommand]
248
+ <<-EOD.gsub(/^ {8}/, '')
271
249
 
272
- Generic command for showing things about the program being debugged.}
250
+ info[ subcommand]
251
+
252
+ Generic command for showing things about the program being debugged.
253
+
254
+ EOD
273
255
  end
274
256
 
275
- def help(args)
276
- return description + format_subcmds unless args and args[1]
257
+ def help(subcmds = [])
258
+ return description + format_subcmds if subcmds.empty?
277
259
 
278
- return format_subcmd(args[1]) unless 'file' == args[1] and args[2]
260
+ subcmd = subcmds.first
261
+ return format_subcmd(subcmd) unless 'file' == subcmd && subcmds[2]
279
262
 
280
- str = subcmd.short_help + '.'
281
- subsubcmd = Command.find(InfoFileSubcommands, args[2])
282
- if subsubcmd
283
- str += "\nInvalid \"file\" attribute \"#{args[2]}\"."
284
- else
285
- str += "\n" + subsubcmd.short_help + '.'
286
- end
263
+ subsubcmd = Command.find(InfoFileSubcommands, subcmds[2])
264
+ return "\nInvalid \"file\" attribute \"#{args[2]}\"." unless subsubcmd
287
265
 
288
- return str
266
+ subsubcmd.short_help
289
267
  end
290
268
  end
291
269
  end