byebug 5.0.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -1
  3. data/CONTRIBUTING.md +35 -13
  4. data/GUIDE.md +256 -198
  5. data/README.md +5 -11
  6. data/ext/byebug/byebug.c +5 -43
  7. data/ext/byebug/byebug.h +6 -1
  8. data/ext/byebug/context.c +4 -5
  9. data/lib/byebug/command.rb +64 -64
  10. data/lib/byebug/command_list.rb +32 -0
  11. data/lib/byebug/commands.rb +37 -0
  12. data/lib/byebug/commands/break.rb +45 -37
  13. data/lib/byebug/commands/catch.rb +52 -28
  14. data/lib/byebug/commands/condition.rb +19 -13
  15. data/lib/byebug/commands/continue.rb +15 -11
  16. data/lib/byebug/commands/delete.rb +18 -12
  17. data/lib/byebug/commands/disable.rb +9 -10
  18. data/lib/byebug/commands/disable/breakpoints.rb +13 -11
  19. data/lib/byebug/commands/disable/display.rb +13 -11
  20. data/lib/byebug/commands/display.rb +32 -24
  21. data/lib/byebug/commands/down.rb +18 -14
  22. data/lib/byebug/commands/edit.rb +42 -26
  23. data/lib/byebug/commands/enable.rb +9 -3
  24. data/lib/byebug/commands/enable/breakpoints.rb +13 -11
  25. data/lib/byebug/commands/enable/display.rb +13 -11
  26. data/lib/byebug/commands/finish.rb +23 -14
  27. data/lib/byebug/commands/frame.rb +21 -18
  28. data/lib/byebug/commands/help.rb +39 -16
  29. data/lib/byebug/commands/history.rb +16 -10
  30. data/lib/byebug/commands/info.rb +8 -5
  31. data/lib/byebug/commands/info/breakpoints.rb +16 -14
  32. data/lib/byebug/commands/info/display.rb +18 -18
  33. data/lib/byebug/commands/info/file.rb +22 -22
  34. data/lib/byebug/commands/info/line.rb +13 -11
  35. data/lib/byebug/commands/info/program.rb +13 -17
  36. data/lib/byebug/commands/interrupt.rb +13 -11
  37. data/lib/byebug/commands/irb.rb +16 -10
  38. data/lib/byebug/commands/kill.rb +19 -13
  39. data/lib/byebug/commands/list.rb +35 -24
  40. data/lib/byebug/commands/method.rb +25 -15
  41. data/lib/byebug/commands/next.rb +15 -13
  42. data/lib/byebug/commands/pry.rb +18 -11
  43. data/lib/byebug/commands/ps.rb +21 -23
  44. data/lib/byebug/commands/quit.rb +17 -11
  45. data/lib/byebug/commands/restart.rb +28 -24
  46. data/lib/byebug/commands/save.rb +23 -15
  47. data/lib/byebug/commands/set.rb +26 -19
  48. data/lib/byebug/commands/show.rb +20 -14
  49. data/lib/byebug/commands/source.rb +15 -14
  50. data/lib/byebug/commands/step.rb +15 -13
  51. data/lib/byebug/commands/thread.rb +8 -4
  52. data/lib/byebug/commands/thread/current.rb +11 -11
  53. data/lib/byebug/commands/thread/list.rb +14 -14
  54. data/lib/byebug/commands/thread/resume.rb +14 -14
  55. data/lib/byebug/commands/thread/stop.rb +14 -14
  56. data/lib/byebug/commands/thread/switch.rb +15 -14
  57. data/lib/byebug/commands/tracevar.rb +20 -16
  58. data/lib/byebug/commands/undisplay.rb +22 -18
  59. data/lib/byebug/commands/untracevar.rb +13 -11
  60. data/lib/byebug/commands/up.rb +18 -14
  61. data/lib/byebug/commands/var.rb +10 -3
  62. data/lib/byebug/commands/var/all.rb +15 -13
  63. data/lib/byebug/commands/var/args.rb +37 -0
  64. data/lib/byebug/commands/var/const.rb +25 -14
  65. data/lib/byebug/commands/var/global.rb +13 -11
  66. data/lib/byebug/commands/var/instance.rb +13 -11
  67. data/lib/byebug/commands/var/local.rb +13 -11
  68. data/lib/byebug/commands/where.rb +15 -11
  69. data/lib/byebug/context.rb +71 -73
  70. data/lib/byebug/core.rb +45 -26
  71. data/lib/byebug/errors.rb +27 -0
  72. data/lib/byebug/frame.rb +181 -0
  73. data/lib/byebug/helpers/eval.rb +67 -26
  74. data/lib/byebug/helpers/file.rb +18 -3
  75. data/lib/byebug/helpers/frame.rb +36 -39
  76. data/lib/byebug/helpers/parse.rb +15 -13
  77. data/lib/byebug/helpers/path.rb +21 -0
  78. data/lib/byebug/helpers/reflection.rb +17 -0
  79. data/lib/byebug/helpers/thread.rb +20 -14
  80. data/lib/byebug/helpers/toggle.rb +10 -5
  81. data/lib/byebug/helpers/var.rb +36 -15
  82. data/lib/byebug/interface.rb +27 -9
  83. data/lib/byebug/option_setter.rb +93 -0
  84. data/lib/byebug/printers/base.rb +3 -0
  85. data/lib/byebug/printers/plain.rb +4 -14
  86. data/lib/byebug/printers/texts/base.yml +2 -7
  87. data/lib/byebug/processors/command_processor.rb +101 -102
  88. data/lib/byebug/processors/control_processor.rb +20 -0
  89. data/lib/byebug/processors/post_mortem_processor.rb +16 -0
  90. data/lib/byebug/processors/script_processor.rb +49 -0
  91. data/lib/byebug/remote.rb +13 -7
  92. data/lib/byebug/runner.rb +39 -65
  93. data/lib/byebug/setting.rb +4 -1
  94. data/lib/byebug/settings/post_mortem.rb +0 -16
  95. data/lib/byebug/settings/savefile.rb +1 -4
  96. data/lib/byebug/subcommands.rb +27 -29
  97. data/lib/byebug/version.rb +4 -1
  98. metadata +14 -29
  99. data/lib/byebug/commands/eval.rb +0 -43
  100. data/lib/byebug/commands/info/args.rb +0 -39
  101. data/lib/byebug/commands/info/catch.rb +0 -39
  102. data/lib/byebug/commands/pp.rb +0 -41
  103. data/lib/byebug/commands/putl.rb +0 -43
  104. data/lib/byebug/processor.rb +0 -43
  105. data/lib/byebug/processors/control_command_processor.rb +0 -48
  106. data/lib/byebug/settings/verbose.rb +0 -20
  107. data/lib/byebug/state.rb +0 -12
  108. data/lib/byebug/states/control_state.rb +0 -26
  109. data/lib/byebug/states/regular_state.rb +0 -187
  110. data/lib/byebug/subcommand_list.rb +0 -33
@@ -10,34 +10,41 @@ module Byebug
10
10
  include Helpers::FileHelper
11
11
  include Helpers::ParseHelper
12
12
 
13
- def regexp
13
+ self.allow_in_post_mortem = true
14
+
15
+ def self.regexp
14
16
  /^\s* l(?:ist)? (?:\s*([-=])|\s+(\S+))? \s*$/x
15
17
  end
16
18
 
19
+ def self.description
20
+ <<-EOD
21
+ l[ist][[-=]][ nn-mm]
22
+
23
+ #{short_description}
24
+
25
+ Lists lines forward from current line or from the place where code was
26
+ last listed. If "list-" is specified, lists backwards instead. If
27
+ "list=" is specified, lists from current line regardless of where code
28
+ was last listed. A line range can also be specified to list specific
29
+ sections of code.
30
+ EOD
31
+ end
32
+
33
+ def self.short_description
34
+ 'Lists lines of source code'
35
+ end
36
+
17
37
  def execute
18
- exist = File.exist?(@state.file)
19
- return errmsg "No sourcefile available for #{@state.file}\n" unless exist
38
+ msg = "No sourcefile available for #{frame.file}"
39
+ return errmsg(msg) unless File.exist?(frame.file)
20
40
 
21
- @match ||= match('list')
22
- max_lines = n_lines(@state.file)
41
+ max_lines = n_lines(frame.file)
23
42
  b, e = range(@match[2], max_lines)
24
43
  return errmsg('Invalid line range') unless valid_range?(b, e, max_lines)
25
44
 
26
45
  display_lines(b, e)
27
46
 
28
- @state.prev_line = b
29
- end
30
-
31
- def description
32
- <<-EOD
33
- l[ist][[-=]][ nn-mm]
34
-
35
- Lists lines of code forward from current line or from the place where
36
- code was last listed. If "list-" is specified, lists backwards instead.
37
- If "list=" is specified, lists from current line regardless of where
38
- code was last listed. A line range can also be specified to list
39
- specific sections of code.
40
- EOD
47
+ processor.prev_line = b
41
48
  end
42
49
 
43
50
  private
@@ -99,9 +106,10 @@ module Byebug
99
106
  end
100
107
 
101
108
  def lower(size, direction = '+')
102
- return @state.line - size / 2 if direction == '=' || !@state.prev_line
109
+ prev_line = processor.prev_line
110
+ return frame.line - size / 2 if direction == '=' || prev_line.nil?
103
111
 
104
- move(@state.prev_line, size, direction)
112
+ move(prev_line, size, direction)
105
113
  end
106
114
 
107
115
  def move(line, size, direction = '+')
@@ -109,16 +117,19 @@ module Byebug
109
117
  end
110
118
 
111
119
  #
112
- # Show lines in @state.file from line number <min> to line number <max>.
120
+ # Show a range of lines in the current file.
121
+ #
122
+ # @param min [Integer] Lower bound
123
+ # @param max [Integer] Upper bound
113
124
  #
114
125
  def display_lines(min, max)
115
- puts "\n[#{min}, #{max}] in #{@state.file}"
126
+ puts "\n[#{min}, #{max}] in #{frame.file}"
116
127
 
117
- File.foreach(@state.file).with_index do |line, lineno|
128
+ File.foreach(frame.file).with_index do |line, lineno|
118
129
  break if lineno + 1 > max
119
130
  next unless (min..max).include?(lineno + 1)
120
131
 
121
- mark = lineno + 1 == @state.line ? '=> ' : ' '
132
+ mark = lineno + 1 == frame.line ? '=> ' : ' '
122
133
  puts format("#{mark}%#{max.to_s.size}d: %s", lineno + 1, line)
123
134
  end
124
135
  end
@@ -1,18 +1,40 @@
1
1
  require 'byebug/command'
2
+ require 'byebug/helpers/eval'
2
3
 
3
4
  module Byebug
4
5
  #
5
6
  # Show methods of specific classes/modules/objects.
6
7
  #
7
8
  class MethodCommand < Command
8
- include Columnize
9
+ include Helpers::EvalHelper
9
10
 
10
- def regexp
11
+ self.allow_in_post_mortem = true
12
+
13
+ def self.regexp
11
14
  /^\s* m(?:ethod)? \s+ (i(:?nstance)?\s+)?/x
12
15
  end
13
16
 
17
+ def self.description
18
+ <<-EOD
19
+ m[ethod] (i[nstance][ <obj>]|<class|module>)
20
+
21
+ #{short_description}
22
+
23
+ When invoked with "instance", shows instance methods of the object
24
+ specified as argument or of self no object was specified.
25
+
26
+ When invoked only with a class or module, shows class methods of the
27
+ class or module specified as argument.
28
+ EOD
29
+ end
30
+
31
+ def self.short_description
32
+ 'Shows methods of an object, class or module'
33
+ end
34
+
14
35
  def execute
15
- obj = bb_eval(@match.post_match)
36
+ obj = single_thread_eval(@match.post_match)
37
+
16
38
  result =
17
39
  if @match[1]
18
40
  prc('method.methods', obj.methods.sort) { |item, _| { name: item } }
@@ -25,17 +47,5 @@ module Byebug
25
47
  end
26
48
  puts result
27
49
  end
28
-
29
- def description
30
- <<-EOD
31
- m[ethod] (i[nstance][ <obj>]|<class|module>)
32
-
33
- When invoked with "instance", shows instance methods of the object
34
- specified as argument or of self no object was specified.
35
-
36
- When invoked only with a class or module, shows class methods of the
37
- class or module specified as argument.
38
- EOD
39
- end
40
50
  end
41
51
  end
@@ -11,26 +11,28 @@ module Byebug
11
11
  class NextCommand < Command
12
12
  include Helpers::ParseHelper
13
13
 
14
- self.allow_in_post_mortem = false
15
-
16
- def regexp
14
+ def self.regexp
17
15
  /^\s* n(?:ext)? (?:\s+(\S+))? \s*$/x
18
16
  end
19
17
 
20
- def execute
21
- steps, err = parse_steps(@match[1], 'Next')
22
- return errmsg(err) unless steps
23
-
24
- @state.context.step_over(steps, @state.frame)
25
- @state.proceed
26
- end
27
-
28
- def description
18
+ def self.description
29
19
  <<-EOD
30
20
  n[ext][ nnn]
31
21
 
32
- Steps over once or nnn times.
22
+ #{short_description}
33
23
  EOD
34
24
  end
25
+
26
+ def self.short_description
27
+ 'Runs one or more lines of code'
28
+ end
29
+
30
+ def execute
31
+ steps, err = parse_steps(@match[1], 'Next')
32
+ return errmsg(err) unless steps
33
+
34
+ context.step_over(steps, context.frame.pos)
35
+ processor.proceed!
36
+ end
35
37
  end
36
38
  end
@@ -1,16 +1,31 @@
1
1
  require 'byebug/command'
2
+ require 'byebug/helpers/eval'
2
3
 
3
4
  module Byebug
4
5
  #
5
6
  # Enter Pry from byebug's prompt
6
7
  #
7
8
  class PryCommand < Command
8
- def regexp
9
+ self.allow_in_post_mortem = true
10
+
11
+ def self.regexp
9
12
  /^\s* pry \s*$/x
10
13
  end
11
14
 
15
+ def self.description
16
+ <<-EOD
17
+ pry
18
+
19
+ #{short_description}
20
+ EOD
21
+ end
22
+
23
+ def self.short_description
24
+ 'Starts a Pry session'
25
+ end
26
+
12
27
  def execute
13
- unless @state.interface.is_a?(LocalInterface)
28
+ unless processor.interface.is_a?(LocalInterface)
14
29
  return errmsg(pr('base.errors.only_local'))
15
30
  end
16
31
 
@@ -20,15 +35,7 @@ module Byebug
20
35
  errmsg(pr('pry.errors.not_installed'))
21
36
  end
22
37
 
23
- get_binding.pry
24
- end
25
-
26
- def description
27
- <<-EOD
28
- pry
29
-
30
- Starts a Pry session.
31
- EOD
38
+ context.binding.pry
32
39
  end
33
40
  end
34
41
  end
@@ -5,40 +5,38 @@ require 'byebug/helpers/eval'
5
5
 
6
6
  module Byebug
7
7
  #
8
- # Evaluation, pretty printing, columnizing and sorting from byebug's prompt
8
+ # Enhanced evaluation of expressions from byebug's prompt. Besides
9
+ # evaluating, it sorts and pretty prints arrays.
9
10
  #
10
11
  class PsCommand < Command
11
12
  include Helpers::EvalHelper
12
- include Columnize
13
13
 
14
- self.allow_in_control = true
14
+ self.allow_in_post_mortem = true
15
15
 
16
- def regexp
17
- /^\s* ps \s+/x
16
+ def self.regexp
17
+ /^\s* ps (\s+ (.+)) \s*$/x
18
18
  end
19
19
 
20
- def execute
21
- out = StringIO.new
22
- run_with_binding do |b|
23
- res = eval_with_setting(b, @match.post_match, Setting[:stack_on_error])
24
-
25
- if res.is_a?(Array)
26
- puts "#{columnize(res.map(&:to_s).sort!, Setting[:width])}"
27
- else
28
- PP.pp(res, out)
29
- puts out.string
30
- end
31
- end
32
- rescue
33
- out.puts $ERROR_INFO.message
34
- end
35
-
36
- def description
20
+ def self.description
37
21
  <<-EOD
38
22
  ps <expression>
39
23
 
40
- Evaluates <expression>, an array, sort and columnize its value.
24
+ #{short_description}
41
25
  EOD
42
26
  end
27
+
28
+ def self.short_description
29
+ 'Evaluates an expression and prettyprints & sort the result'
30
+ end
31
+
32
+ def execute
33
+ return puts(help) unless @match[1]
34
+
35
+ res = thread_safe_eval(@match[1])
36
+ res = res.sort if res.respond_to?(:sort)
37
+
38
+ out = PP.pp(res, StringIO.new, Setting[:width])
39
+ print pr('eval.result', expr: @match[1], result: out.string)
40
+ end
43
41
  end
44
42
  end
@@ -6,29 +6,35 @@ module Byebug
6
6
  #
7
7
  class QuitCommand < Command
8
8
  self.allow_in_control = true
9
+ self.allow_in_post_mortem = true
9
10
 
10
- def regexp
11
+ def self.regexp
11
12
  /^\s* q(?:uit)? \s* (?:(!|\s+unconditionally))? \s*$/x
12
13
  end
13
14
 
14
- def execute
15
- return unless @match[1] || confirm(pr('quit.confirmations.really'))
16
-
17
- @state.interface.autosave
18
- @state.interface.close
19
- exit! # exit -> exit!: No graceful way to stop...
20
- end
21
-
22
- def description
15
+ def self.description
23
16
  <<-EOD
24
17
  q[uit] [!|unconditionally]
25
18
 
26
- Exits from byebug.
19
+ #{short_description}
27
20
 
28
21
  Normally we prompt before exiting. However if the parameter
29
22
  "unconditionally" is given or command is suffixed with !, we exit
30
23
  without asking further questions.
31
24
  EOD
32
25
  end
26
+
27
+ def self.short_description
28
+ 'Exits byebug'
29
+ end
30
+
31
+ def execute
32
+ return unless @match[1] || confirm(pr('quit.confirmations.really'))
33
+
34
+ processor.interface.autosave
35
+ processor.interface.close
36
+
37
+ Process.exit!
38
+ end
33
39
  end
34
40
  end
@@ -1,41 +1,45 @@
1
1
  require 'byebug/command'
2
+ require 'byebug/helpers/path'
3
+ require 'shellwords'
2
4
 
3
5
  module Byebug
4
6
  #
5
7
  # Restart debugged program from within byebug.
6
8
  #
7
9
  class RestartCommand < Command
8
- self.allow_in_control = true
10
+ include Helpers::PathHelper
9
11
 
10
- def regexp
11
- /^\s* (?:restart|R) (?:\s+(?<args>.+))? \s*$/x
12
- end
12
+ self.allow_in_control = true
13
+ self.allow_in_post_mortem = true
13
14
 
14
- def execute
15
- if Byebug.mode == :standalone
16
- cmd = "#{Gem.bin_path('byebug', 'byebug')} #{$PROGRAM_NAME}"
17
- else
18
- cmd = $PROGRAM_NAME
19
- end
20
-
21
- if @match[:args]
22
- cmd += " #{@match[:args]}"
23
- else
24
- require 'shellwords'
25
- cmd += " #{$ARGV.compact.shelljoin}"
26
- end
27
-
28
- puts pr('restart.success', cmd: cmd)
29
- exec(cmd)
15
+ def self.regexp
16
+ /^\s* restart (?:\s+(?<args>.+))? \s*$/x
30
17
  end
31
18
 
32
- def description
19
+ def self.description
33
20
  <<-EOD
34
- restart|R [args]
21
+ restart [args]
35
22
 
36
- Restart the program. This is a re-exec - all byebug state
37
- is lost. If command arguments are passed those are used.
23
+ #{short_description}
24
+
25
+ This is a re-exec - all byebug state is lost. If command arguments are
26
+ passed those are used.
38
27
  EOD
39
28
  end
29
+
30
+ def self.short_description
31
+ 'Restarts the debugged program'
32
+ end
33
+
34
+ def execute
35
+ argv = [$PROGRAM_NAME]
36
+
37
+ argv.unshift(bin_file) if Byebug.mode == :standalone
38
+
39
+ argv += (@match[:args] ? @match[:args].shellsplit : $ARGV.compact)
40
+
41
+ puts pr('restart.success', cmd: argv.shelljoin)
42
+ exec(*argv)
43
+ end
40
44
  end
41
45
  end
@@ -6,11 +6,31 @@ module Byebug
6
6
  #
7
7
  class SaveCommand < Command
8
8
  self.allow_in_control = true
9
+ self.allow_in_post_mortem = true
9
10
 
10
- def regexp
11
+ def self.regexp
11
12
  /^\s* sa(?:ve)? (?:\s+(\S+))? \s*$/x
12
13
  end
13
14
 
15
+ def self.description
16
+ <<-EOD
17
+ save[ FILE]
18
+
19
+ #{short_description}
20
+
21
+ Byebug state is saved as a script file. This includes breakpoints,
22
+ catchpoints, display expressions and some settings. If no filename is
23
+ given, byebug will fabricate one.
24
+
25
+ Use the "source" command in another debug session to restore the saved
26
+ file.
27
+ EOD
28
+ end
29
+
30
+ def self.short_description
31
+ 'Saves current byebug session to a file'
32
+ end
33
+
14
34
  def execute
15
35
  file = File.open(@match[1] || Setting[:savefile], 'w')
16
36
 
@@ -23,18 +43,6 @@ module Byebug
23
43
  file.close
24
44
  end
25
45
 
26
- def description
27
- <<-EOD
28
- save[ FILE]
29
-
30
- Saves current byebug state to FILE as a script file. This includes
31
- breakpoints, catchpoints, display expressions and some settings. If no
32
- filename is given, we will fabricate one.
33
-
34
- Use the "source" command in another debug session to restore them.
35
- EOD
36
- end
37
-
38
46
  private
39
47
 
40
48
  def save_breakpoints(file)
@@ -50,11 +58,11 @@ module Byebug
50
58
  end
51
59
 
52
60
  def save_displays(file)
53
- @state.display.each { |d| file.puts "display #{d[1]}" if d[0] }
61
+ Byebug.displays.each { |d| file.puts "display #{d[1]}" if d[0] }
54
62
  end
55
63
 
56
64
  def save_settings(file)
57
- %w(autoeval autoirb autolist basename).each do |setting|
65
+ %w(autoirb autolist basename).each do |setting|
58
66
  file.puts "set #{setting} #{Setting[setting.to_sym]}"
59
67
  end
60
68
  end