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,17 +1,23 @@
1
1
  module Byebug
2
+ #
3
+ # Utilities for the save command.
4
+ #
2
5
  module SaveFunctions
3
6
  # Create a temporary file to write in if file is nil
4
7
  def open_save
5
- require "tempfile"
6
- file = Tempfile.new("byebug-save")
8
+ require 'tempfile'
9
+ file = Tempfile.new('byebug-save')
7
10
  # We want close to not unlink, so redefine.
8
11
  def file.close
9
12
  @tmpfile.close if @tmpfile
10
13
  end
11
- return file
14
+ file
12
15
  end
13
16
  end
14
17
 
18
+ #
19
+ # Save current settings to use them in another debug session.
20
+ #
15
21
  class SaveCommand < Command
16
22
  self.allow_in_control = true
17
23
 
@@ -28,15 +34,10 @@ module Byebug
28
34
  end
29
35
 
30
36
  def save_displays(file)
31
- for d in @state.display
32
- if d[0]
33
- file.puts "display #{d[1]}"
34
- end
35
- end
37
+ @state.display.each { |d| file.puts "display #{d[1]}" if d[0] }
36
38
  end
37
39
 
38
40
  def save_settings(file)
39
- # FIXME put routine in set
40
41
  %w(autoeval autoirb autolist basename testing).each do |setting|
41
42
  file.puts "set #{setting} #{Setting[setting.to_sym]}"
42
43
  end
@@ -47,8 +48,8 @@ module Byebug
47
48
  end
48
49
 
49
50
  def execute
50
- if not @match[1]
51
- file = open_save()
51
+ if !@match[1]
52
+ file = open_save
52
53
  else
53
54
  file = open(@match[1], 'w')
54
55
  end
@@ -56,10 +57,8 @@ module Byebug
56
57
  save_catchpoints(file)
57
58
  save_displays(file)
58
59
  save_settings(file)
59
- print "Saved to '#{file.path}'\n"
60
- if @state and @state.interface
61
- @state.interface.restart_file = file.path
62
- end
60
+ puts "Saved to '#{file.path}'"
61
+ @state.interface.restart_file = file.path if @state && @state.interface
63
62
  file.close
64
63
  end
65
64
 
@@ -69,12 +68,13 @@ module Byebug
69
68
  end
70
69
 
71
70
  def description
72
- %{save[ FILE]
71
+ %(save[ FILE]
73
72
 
74
73
  Saves current byebug state to FILE as a script file. This includes
75
74
  breakpoints, catchpoints, display expressions and some settings. If
76
75
  no filename is given, we will fabricate one.
77
- Use the "source" command in another debug session to restore them.}
76
+
77
+ Use the "source" command in another debug session to restore them.)
78
78
  end
79
79
  end
80
80
  end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Change byebug settings.
4
+ #
2
5
  class SetCommand < Command
3
6
  self.allow_in_control = true
4
7
 
@@ -8,34 +11,35 @@ module Byebug
8
11
 
9
12
  def execute
10
13
  key, value = @match[:setting], @match[:value]
11
- return print SetCommand.help if key.nil? && value.nil?
14
+ return puts(SetCommand.help) if key.nil? && value.nil?
12
15
 
13
16
  full_key = Setting.find(key)
14
- return print "Unknown setting :#{key}\n" unless full_key
17
+ return errmsg("Unknown setting :#{key}") unless full_key
15
18
 
16
19
  if !Setting.boolean?(full_key) && value.nil?
17
- return print "You must specify a value for setting :#{key}\n"
20
+ value, err = nil, "You must specify a value for setting :#{key}"
18
21
  elsif Setting.boolean?(full_key)
19
- value = get_onoff(value, key =~ /^no/ ? false : true)
22
+ value, err = get_onoff(value, key =~ /^no/ ? false : true)
20
23
  elsif Setting.integer?(full_key)
21
- return unless value = get_int(value, full_key, 1)
24
+ value, err = get_int(value, full_key, 1)
22
25
  end
26
+ return errmsg(err) if value.nil?
23
27
 
24
28
  Setting[full_key.to_sym] = value
25
29
 
26
- return print Setting.settings[full_key.to_sym].to_s
30
+ puts Setting.settings[full_key.to_sym].to_s
27
31
  end
28
32
 
29
33
  def get_onoff(arg, default)
30
34
  return default if arg.nil?
35
+
31
36
  case arg
32
37
  when '1', 'on', 'true'
33
- return true
38
+ true
34
39
  when '0', 'off', 'false'
35
- return false
40
+ false
36
41
  else
37
- print "Expecting 'on', 1, true, 'off', 0, false. Got: #{arg}.\n"
38
- raise RuntimeError
42
+ [nil, "Expecting 'on', 1, true, 'off', 0, false. Got: #{arg}.\n"]
39
43
  end
40
44
  end
41
45
 
@@ -56,14 +60,11 @@ module Byebug
56
60
  Conversely, you can use "set no<setting> to disable them.
57
61
 
58
62
  You can see these environment settings with the "show" command.
59
-
60
63
  EOD
61
64
  end
62
65
 
63
- def help(setting = nil)
64
- return "set #{setting.to_sym} <value>\n\n#{setting.help}" if setting
65
-
66
- description + Setting.format()
66
+ def help(subcmds = [])
67
+ Setting.help('set', subcmds.first)
67
68
  end
68
69
  end
69
70
  end
@@ -1,4 +1,7 @@
1
1
  module Byebug
2
+ #
3
+ # Show byebug settings.
4
+ #
2
5
  class ShowCommand < Command
3
6
  self.allow_in_control = true
4
7
 
@@ -8,14 +11,12 @@ module Byebug
8
11
 
9
12
  def execute
10
13
  key = @match[:setting]
11
- return print ShowCommand.help if key.nil?
14
+ return puts(self.class.help) if key.nil?
12
15
 
13
16
  full_key = Setting.find(key)
14
- if full_key
15
- print Setting.settings[full_key.to_sym].to_s
16
- else
17
- print "Unknown setting :#{key}\n"
18
- end
17
+ return errmsg("Unknown setting :#{key}") unless full_key
18
+
19
+ puts Setting.settings[full_key.to_sym].to_s
19
20
  end
20
21
 
21
22
  class << self
@@ -24,7 +25,7 @@ module Byebug
24
25
  end
25
26
 
26
27
  def description
27
- <<-EOD.gsub(/^ /, '')
28
+ <<-EOD.gsub(/^ {8}/, '')
28
29
 
29
30
  show <setting> <value>
30
31
 
@@ -34,10 +35,8 @@ module Byebug
34
35
  EOD
35
36
  end
36
37
 
37
- def help(setting = nil)
38
- return "show #{setting.to_sym} <value>\n\n#{setting.help}" if setting
39
-
40
- description + Setting.format()
38
+ def help(subcmds = [])
39
+ Setting.help('show', subcmds.first)
41
40
  end
42
41
  end
43
42
  end
@@ -1,4 +1,9 @@
1
1
  module Byebug
2
+ #
3
+ # Execute a file containing byebug commands.
4
+ #
5
+ # It can be used to restore a previously saved debugging session.
6
+ #
2
7
  class SourceCommand < Command
3
8
  self.allow_in_control = true
4
9
 
@@ -7,13 +12,12 @@ module Byebug
7
12
  end
8
13
 
9
14
  def execute
10
- return print SourceCommand.help(nil) if
11
- SourceCommand.names.include?(@match[0])
15
+ return puts(self.class.help) if self.class.names.include?(@match[0])
12
16
 
13
17
  file = File.expand_path(@match[1]).strip
14
- return errmsg "File \"#{file}\" not found\n" unless File.exist?(file)
18
+ return errmsg("File \"#{file}\" not found") unless File.exist?(file)
15
19
 
16
- if @state and @state.interface
20
+ if @state && @state.interface
17
21
  @state.interface.command_queue += File.open(file).readlines
18
22
  else
19
23
  Byebug.run_script(file, @state)
@@ -26,7 +30,9 @@ module Byebug
26
30
  end
27
31
 
28
32
  def description
29
- %{source FILE\texecutes a file containing byebug commands}
33
+ %(source <file>
34
+
35
+ Executes file <file> containing byebug commands.)
30
36
  end
31
37
  end
32
38
  end
@@ -3,19 +3,24 @@ module Byebug
3
3
  # Mixin to assist command parsing
4
4
  #
5
5
  module SteppingFunctions
6
- def parse_stepping_args(command_name, match)
7
- if match[1].nil?
8
- force = Setting[:forcestep]
9
- elsif match[1] == '+'
10
- force = true
11
- elsif match[1] == '-'
12
- force = false
6
+ def parse_force(str)
7
+ return Setting[:forcestep] unless str
8
+
9
+ case str
10
+ when '+' then
11
+ true
12
+ when '-' then
13
+ false
13
14
  end
14
- steps = get_int(match[2], command_name, 1)
15
- return [steps, force]
16
15
  end
17
16
  end
18
17
 
18
+ #
19
+ # Implements the next functionality.
20
+ #
21
+ # Allows the user the continue execution until the next instruction in the
22
+ # current frame.
23
+ #
19
24
  class NextCommand < Command
20
25
  self.allow_in_post_mortem = false
21
26
 
@@ -24,9 +29,10 @@ module Byebug
24
29
  end
25
30
 
26
31
  def execute
27
- steps, force = parse_stepping_args("Next", @match)
28
- return unless steps
29
- @state.context.step_over steps, @state.frame_pos, force
32
+ steps, err = parse_steps(@match[2], 'Next')
33
+ return errmsg(err) unless steps
34
+
35
+ @state.context.step_over(steps, @state.frame_pos, parse_force(@match[1]))
30
36
  @state.proceed
31
37
  end
32
38
 
@@ -36,14 +42,21 @@ module Byebug
36
42
  end
37
43
 
38
44
  def description
39
- %{n[ext][+-]?[ nnn]\tstep over once or nnn times,
40
- \t\t'+' forces to move to another line.
41
- \t\t'-' is the opposite of '+' and disables the :forcestep setting.
42
- }
45
+ %(n[ext][+-]?[ nnn]
46
+
47
+ Steps over once or nnn times.
48
+ '+' forces to move to another line.
49
+ '-' is the opposite of '+' and disables the :forcestep setting.)
43
50
  end
44
51
  end
45
52
  end
46
53
 
54
+ #
55
+ # Implements the step functionality.
56
+ #
57
+ # Allows the user the continue execution until the next instruction, possibily
58
+ # in a different frame. Use step to step into method calls or blocks.
59
+ #
47
60
  class StepCommand < Command
48
61
  self.allow_in_post_mortem = false
49
62
 
@@ -52,9 +65,10 @@ module Byebug
52
65
  end
53
66
 
54
67
  def execute
55
- steps, force = parse_stepping_args("Step", @match)
56
- return unless steps
57
- @state.context.step_into steps, force
68
+ steps, err = parse_steps(@match[2], 'Steps')
69
+ return errmsg(err) unless steps
70
+
71
+ @state.context.step_into(steps, parse_force(@match[1]))
58
72
  @state.proceed
59
73
  end
60
74
 
@@ -64,11 +78,11 @@ module Byebug
64
78
  end
65
79
 
66
80
  def description
67
- %{
68
- s[tep][+-]?[ nnn]\tstep (into methods) once or nnn times
69
- \t\t'+' forces to move to another line.
70
- \t\t'-' is the opposite of '+' and disables the :forcestep setting.
71
- }
81
+ %{s[tep][+-]?[ nnn]
82
+
83
+ Steps (into methods) once or nnn times.
84
+ '+' forces to move to another line.
85
+ '-' is the opposite of '+' and disables the :forcestep setting.}
72
86
  end
73
87
  end
74
88
  end
@@ -1,17 +1,22 @@
1
1
  module Byebug
2
+ #
3
+ # Utilities to assist commands related to threads.
4
+ #
2
5
  module ThreadFunctions
3
6
  def display_context(context, should_show_top_frame = true)
4
7
  args = thread_arguments(context, should_show_top_frame)
5
- print "%s%s%d %s\t%s\n", args[:status_flag], args[:debug_flag], args[:id],
6
- args[:thread], args[:file_line]
8
+ interp = format("%s%s%d %s\t%s",
9
+ args[:status_flag], args[:debug_flag], args[:id],
10
+ args[:thread], args[:file_line])
11
+ puts interp
7
12
  end
8
13
 
9
14
  def thread_arguments(context, should_show_top_frame = true)
10
15
  status_flag = if context.suspended?
11
- "$"
12
- else
13
- context.thread == Thread.current ? '+' : ' '
14
- end
16
+ '$'
17
+ else
18
+ context.thread == Thread.current ? '+' : ' '
19
+ end
15
20
  debug_flag = context.ignored? ? '!' : ' '
16
21
  if should_show_top_frame
17
22
  if context.thread == Thread.current && !context.dead?
@@ -36,19 +41,18 @@ module Byebug
36
41
  end
37
42
 
38
43
  def parse_thread_num(subcmd, arg)
39
- if '' == arg
40
- errmsg "\"#{subcmd}\" needs a thread number"
41
- nil
42
- else
43
- thread_num = get_int(arg, subcmd, 1)
44
- return nil unless thread_num
45
- get_context(thread_num)
46
- end
44
+ return errmsg("\"#{subcmd}\" needs a thread number") if '' == arg
45
+
46
+ thread_num, err = get_int(arg, subcmd, 1)
47
+ return errmsg(err) unless thread_num
48
+
49
+ Byebug.contexts.find { |c| c.thnum == thnum }
47
50
  end
48
51
 
49
52
  def parse_thread_num_for_cmd(subcmd, arg)
50
53
  c = parse_thread_num(subcmd, arg)
51
- return nil unless c
54
+ return unless c
55
+
52
56
  case
53
57
  when nil == c
54
58
  errmsg 'No such thread'
@@ -57,13 +61,14 @@ module Byebug
57
61
  when c.ignored?
58
62
  errmsg "Can't #{subcmd} thread #{arg}"
59
63
  else
60
- return c
64
+ c
61
65
  end
62
- return nil
63
66
  end
64
-
65
67
  end
66
68
 
69
+ #
70
+ # List current threads.
71
+ #
67
72
  class ThreadListCommand < Command
68
73
  self.allow_in_control = true
69
74
 
@@ -82,13 +87,14 @@ module Byebug
82
87
  end
83
88
 
84
89
  def description
85
- %{
86
- th[read] l[ist]\t\t\tlist all threads
87
- }
90
+ %(th[read] l[ist] Lists all threads.)
88
91
  end
89
92
  end
90
93
  end
91
94
 
95
+ #
96
+ # Show current thread.
97
+ #
92
98
  class ThreadCurrentCommand < Command
93
99
  def regexp
94
100
  /^\s* th(?:read)? \s+ (?:cur(?:rent)?)? \s*$/x
@@ -104,11 +110,14 @@ module Byebug
104
110
  end
105
111
 
106
112
  def description
107
- %{th[read] [cur[rent]]\t\tshow current thread}
113
+ %(th[read] [cur[rent]] Shows current thread.)
108
114
  end
109
115
  end
110
116
  end
111
117
 
118
+ #
119
+ # Stop execution of a thread.
120
+ #
112
121
  class ThreadStopCommand < Command
113
122
  self.allow_in_control = true
114
123
  self.allow_in_post_mortem = false
@@ -120,6 +129,7 @@ module Byebug
120
129
  def execute
121
130
  c = parse_thread_num_for_cmd('thread stop', @match[1])
122
131
  return unless c
132
+
123
133
  c.suspend
124
134
  display_context(c)
125
135
  end
@@ -130,11 +140,14 @@ module Byebug
130
140
  end
131
141
 
132
142
  def description
133
- %{th[read] stop <nnn>\t\tstop thread nnn}
143
+ %(th[read] stop <n> Stops thread <n>.)
134
144
  end
135
145
  end
136
146
  end
137
147
 
148
+ #
149
+ # Resume execution of a thread.
150
+ #
138
151
  class ThreadResumeCommand < Command
139
152
  self.allow_in_control = true
140
153
  self.allow_in_post_mortem = false
@@ -146,10 +159,7 @@ module Byebug
146
159
  def execute
147
160
  c = parse_thread_num_for_cmd('thread resume', @match[1])
148
161
  return unless c
149
- if !c.suspended?
150
- errmsg 'Already running'
151
- return
152
- end
162
+ return errmsg('Already running') unless c.suspended?
153
163
  c.resume
154
164
  display_context(c)
155
165
  end
@@ -160,11 +170,14 @@ module Byebug
160
170
  end
161
171
 
162
172
  def description
163
- %{th[read] resume <nnn>\t\tresume thread nnn}
173
+ %(th[read] resume <n> Resumes thread <n>.)
164
174
  end
165
175
  end
166
176
  end
167
177
 
178
+ #
179
+ # Switch execution to a different thread.
180
+ #
168
181
  class ThreadSwitchCommand < Command
169
182
  self.allow_in_control = true
170
183
  self.allow_in_post_mortem = false
@@ -175,11 +188,12 @@ module Byebug
175
188
 
176
189
  def execute
177
190
  if @match[1] =~ /switch/
178
- errmsg '"thread switch" needs a thread number'
179
- return
191
+ return errmsg('"thread switch" needs a thread number')
180
192
  end
193
+
181
194
  c = parse_thread_num_for_cmd('thread switch', @match[1])
182
195
  return unless c
196
+
183
197
  display_context(c)
184
198
  c.step_into 1
185
199
  c.thread.run
@@ -192,7 +206,7 @@ module Byebug
192
206
  end
193
207
 
194
208
  def description
195
- %{th[read] [sw[itch]] <nnn>\tswitch thread context to nnn}
209
+ %(th[read] [sw[itch]] <nnn> Switches thread context to <n>.)
196
210
  end
197
211
  end
198
212
  end