byebug 11.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +897 -0
  3. data/CONTRIBUTING.md +58 -0
  4. data/GUIDE.md +1806 -0
  5. data/LICENSE +23 -0
  6. data/README.md +199 -0
  7. data/exe/byebug +6 -0
  8. data/ext/byebug/breakpoint.c +517 -0
  9. data/ext/byebug/byebug.c +905 -0
  10. data/ext/byebug/byebug.h +143 -0
  11. data/ext/byebug/context.c +673 -0
  12. data/ext/byebug/extconf.rb +12 -0
  13. data/ext/byebug/locker.c +96 -0
  14. data/ext/byebug/threads.c +230 -0
  15. data/lib/byebug.rb +3 -0
  16. data/lib/byebug/attacher.rb +48 -0
  17. data/lib/byebug/breakpoint.rb +111 -0
  18. data/lib/byebug/command.rb +111 -0
  19. data/lib/byebug/command_list.rb +34 -0
  20. data/lib/byebug/commands.rb +40 -0
  21. data/lib/byebug/commands/break.rb +112 -0
  22. data/lib/byebug/commands/catch.rb +78 -0
  23. data/lib/byebug/commands/condition.rb +55 -0
  24. data/lib/byebug/commands/continue.rb +68 -0
  25. data/lib/byebug/commands/debug.rb +38 -0
  26. data/lib/byebug/commands/delete.rb +55 -0
  27. data/lib/byebug/commands/disable.rb +33 -0
  28. data/lib/byebug/commands/disable/breakpoints.rb +42 -0
  29. data/lib/byebug/commands/disable/display.rb +43 -0
  30. data/lib/byebug/commands/display.rb +66 -0
  31. data/lib/byebug/commands/down.rb +45 -0
  32. data/lib/byebug/commands/edit.rb +69 -0
  33. data/lib/byebug/commands/enable.rb +33 -0
  34. data/lib/byebug/commands/enable/breakpoints.rb +42 -0
  35. data/lib/byebug/commands/enable/display.rb +43 -0
  36. data/lib/byebug/commands/finish.rb +57 -0
  37. data/lib/byebug/commands/frame.rb +57 -0
  38. data/lib/byebug/commands/help.rb +64 -0
  39. data/lib/byebug/commands/history.rb +39 -0
  40. data/lib/byebug/commands/info.rb +37 -0
  41. data/lib/byebug/commands/info/breakpoints.rb +65 -0
  42. data/lib/byebug/commands/info/display.rb +49 -0
  43. data/lib/byebug/commands/info/file.rb +80 -0
  44. data/lib/byebug/commands/info/line.rb +35 -0
  45. data/lib/byebug/commands/info/program.rb +49 -0
  46. data/lib/byebug/commands/interrupt.rb +34 -0
  47. data/lib/byebug/commands/irb.rb +50 -0
  48. data/lib/byebug/commands/kill.rb +45 -0
  49. data/lib/byebug/commands/list.rb +159 -0
  50. data/lib/byebug/commands/method.rb +53 -0
  51. data/lib/byebug/commands/next.rb +40 -0
  52. data/lib/byebug/commands/pry.rb +41 -0
  53. data/lib/byebug/commands/quit.rb +42 -0
  54. data/lib/byebug/commands/restart.rb +64 -0
  55. data/lib/byebug/commands/save.rb +72 -0
  56. data/lib/byebug/commands/set.rb +79 -0
  57. data/lib/byebug/commands/show.rb +45 -0
  58. data/lib/byebug/commands/skip.rb +85 -0
  59. data/lib/byebug/commands/source.rb +40 -0
  60. data/lib/byebug/commands/step.rb +40 -0
  61. data/lib/byebug/commands/thread.rb +34 -0
  62. data/lib/byebug/commands/thread/current.rb +37 -0
  63. data/lib/byebug/commands/thread/list.rb +43 -0
  64. data/lib/byebug/commands/thread/resume.rb +45 -0
  65. data/lib/byebug/commands/thread/stop.rb +43 -0
  66. data/lib/byebug/commands/thread/switch.rb +46 -0
  67. data/lib/byebug/commands/tracevar.rb +54 -0
  68. data/lib/byebug/commands/undisplay.rb +51 -0
  69. data/lib/byebug/commands/untracevar.rb +36 -0
  70. data/lib/byebug/commands/up.rb +45 -0
  71. data/lib/byebug/commands/var.rb +37 -0
  72. data/lib/byebug/commands/var/all.rb +41 -0
  73. data/lib/byebug/commands/var/args.rb +39 -0
  74. data/lib/byebug/commands/var/const.rb +49 -0
  75. data/lib/byebug/commands/var/global.rb +37 -0
  76. data/lib/byebug/commands/var/instance.rb +39 -0
  77. data/lib/byebug/commands/var/local.rb +39 -0
  78. data/lib/byebug/commands/where.rb +53 -0
  79. data/lib/byebug/context.rb +157 -0
  80. data/lib/byebug/core.rb +115 -0
  81. data/lib/byebug/errors.rb +29 -0
  82. data/lib/byebug/frame.rb +185 -0
  83. data/lib/byebug/helpers/bin.rb +47 -0
  84. data/lib/byebug/helpers/eval.rb +126 -0
  85. data/lib/byebug/helpers/file.rb +63 -0
  86. data/lib/byebug/helpers/frame.rb +75 -0
  87. data/lib/byebug/helpers/parse.rb +75 -0
  88. data/lib/byebug/helpers/path.rb +40 -0
  89. data/lib/byebug/helpers/reflection.rb +19 -0
  90. data/lib/byebug/helpers/string.rb +33 -0
  91. data/lib/byebug/helpers/thread.rb +67 -0
  92. data/lib/byebug/helpers/toggle.rb +62 -0
  93. data/lib/byebug/helpers/var.rb +54 -0
  94. data/lib/byebug/history.rb +130 -0
  95. data/lib/byebug/interface.rb +146 -0
  96. data/lib/byebug/interfaces/local_interface.rb +44 -0
  97. data/lib/byebug/interfaces/remote_interface.rb +50 -0
  98. data/lib/byebug/interfaces/script_interface.rb +33 -0
  99. data/lib/byebug/interfaces/test_interface.rb +67 -0
  100. data/lib/byebug/option_setter.rb +95 -0
  101. data/lib/byebug/printers/base.rb +68 -0
  102. data/lib/byebug/printers/plain.rb +44 -0
  103. data/lib/byebug/printers/texts/base.yml +115 -0
  104. data/lib/byebug/printers/texts/plain.yml +33 -0
  105. data/lib/byebug/processors/command_processor.rb +173 -0
  106. data/lib/byebug/processors/control_processor.rb +24 -0
  107. data/lib/byebug/processors/post_mortem_processor.rb +18 -0
  108. data/lib/byebug/processors/script_processor.rb +49 -0
  109. data/lib/byebug/remote.rb +85 -0
  110. data/lib/byebug/remote/client.rb +57 -0
  111. data/lib/byebug/remote/server.rb +47 -0
  112. data/lib/byebug/runner.rb +198 -0
  113. data/lib/byebug/setting.rb +79 -0
  114. data/lib/byebug/settings/autoirb.rb +29 -0
  115. data/lib/byebug/settings/autolist.rb +29 -0
  116. data/lib/byebug/settings/autopry.rb +29 -0
  117. data/lib/byebug/settings/autosave.rb +17 -0
  118. data/lib/byebug/settings/basename.rb +16 -0
  119. data/lib/byebug/settings/callstyle.rb +20 -0
  120. data/lib/byebug/settings/fullpath.rb +16 -0
  121. data/lib/byebug/settings/histfile.rb +20 -0
  122. data/lib/byebug/settings/histsize.rb +20 -0
  123. data/lib/byebug/settings/linetrace.rb +22 -0
  124. data/lib/byebug/settings/listsize.rb +21 -0
  125. data/lib/byebug/settings/post_mortem.rb +27 -0
  126. data/lib/byebug/settings/savefile.rb +20 -0
  127. data/lib/byebug/settings/stack_on_error.rb +15 -0
  128. data/lib/byebug/settings/width.rb +20 -0
  129. data/lib/byebug/source_file_formatter.rb +71 -0
  130. data/lib/byebug/subcommands.rb +54 -0
  131. data/lib/byebug/version.rb +8 -0
  132. metadata +199 -0
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "readline"
5
+ rescue LoadError
6
+ warn <<-MESSAGE
7
+ Sorry, you can't use byebug without Readline. To solve this, you need to
8
+ rebuild Ruby with Readline support. If using Ubuntu, try `sudo apt-get
9
+ install libreadline-dev` and then reinstall your Ruby.
10
+ MESSAGE
11
+
12
+ raise
13
+ end
14
+
15
+ module Byebug
16
+ #
17
+ # Handles byebug's history of commands.
18
+ #
19
+ class History
20
+ attr_accessor :size
21
+
22
+ def initialize
23
+ self.size = 0
24
+ end
25
+
26
+ #
27
+ # Array holding the list of commands in history
28
+ #
29
+ def buffer
30
+ Readline::HISTORY.to_a
31
+ end
32
+
33
+ #
34
+ # Restores history from disk.
35
+ #
36
+ def restore
37
+ return unless File.exist?(Setting[:histfile])
38
+
39
+ File.readlines(Setting[:histfile]).reverse_each { |l| push(l.chomp) }
40
+ end
41
+
42
+ #
43
+ # Saves history to disk.
44
+ #
45
+ def save
46
+ n_cmds = Setting[:histsize] > size ? size : Setting[:histsize]
47
+
48
+ File.open(Setting[:histfile], "w") do |file|
49
+ n_cmds.times { file.puts(pop) }
50
+ end
51
+
52
+ clear
53
+ end
54
+
55
+ #
56
+ # Discards history.
57
+ #
58
+ def clear
59
+ size.times { pop }
60
+ end
61
+
62
+ #
63
+ # Adds a new command to Readline's history.
64
+ #
65
+ def push(cmd)
66
+ return if ignore?(cmd)
67
+
68
+ self.size += 1
69
+ Readline::HISTORY.push(cmd)
70
+ end
71
+
72
+ #
73
+ # Removes a command from Readline's history.
74
+ #
75
+ def pop
76
+ self.size -= 1
77
+ Readline::HISTORY.pop
78
+ end
79
+
80
+ #
81
+ # Prints the requested numbers of history entries.
82
+ #
83
+ def to_s(n_cmds)
84
+ show_size = n_cmds ? specific_max_size(n_cmds) : default_max_size
85
+
86
+ commands = buffer.last(show_size)
87
+
88
+ last_ids(show_size).zip(commands).map do |l|
89
+ format("%<position>5d %<command>s", position: l[0], command: l[1])
90
+ end.join("\n") + "\n"
91
+ end
92
+
93
+ #
94
+ # Array of ids of the last +number+ commands.
95
+ #
96
+ def last_ids(number)
97
+ (1 + size - number..size).to_a
98
+ end
99
+
100
+ #
101
+ # Max number of commands to be displayed when no size has been specified.
102
+ #
103
+ # Never more than Setting[:histsize].
104
+ #
105
+ def default_max_size
106
+ [Setting[:histsize], self.size].min
107
+ end
108
+
109
+ #
110
+ # Max number of commands to be displayed when a size has been specified.
111
+ #
112
+ # The only bound here is not showing more items than available.
113
+ #
114
+ def specific_max_size(number)
115
+ [self.size, number].min
116
+ end
117
+
118
+ #
119
+ # Whether a specific command should not be stored in history.
120
+ #
121
+ # For now, empty lines and consecutive duplicates.
122
+ #
123
+ def ignore?(buf)
124
+ return true if /^\s*$/ =~ buf
125
+ return false if Readline::HISTORY.empty?
126
+
127
+ buffer[Readline::HISTORY.length - 1] == buf
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/setting"
4
+ require "byebug/history"
5
+ require "byebug/helpers/file"
6
+
7
+ #
8
+ # Namespace for all of byebug's code
9
+ #
10
+ module Byebug
11
+ #
12
+ # Main Interface class
13
+ #
14
+ # Contains common functionality to all implemented interfaces.
15
+ #
16
+ class Interface
17
+ include Helpers::FileHelper
18
+
19
+ attr_accessor :command_queue, :history
20
+ attr_reader :input, :output, :error
21
+
22
+ def initialize
23
+ @command_queue = []
24
+ @history = History.new
25
+ @last_line = ""
26
+ end
27
+
28
+ def last_if_empty(input)
29
+ @last_line = input.empty? ? @last_line : input
30
+ end
31
+
32
+ #
33
+ # Pops a command from the input stream.
34
+ #
35
+ def read_command(prompt)
36
+ return command_queue.shift unless command_queue.empty?
37
+
38
+ read_input(prompt)
39
+ end
40
+
41
+ #
42
+ # Pushes lines in +filename+ to the command queue.
43
+ #
44
+ def read_file(filename)
45
+ command_queue.concat(get_lines(filename))
46
+ end
47
+
48
+ #
49
+ # Reads a new line from the interface's input stream, parses it into
50
+ # commands and saves it to history.
51
+ #
52
+ # @return [String] Representing something to be run by the debugger.
53
+ #
54
+ def read_input(prompt, save_hist = true)
55
+ line = prepare_input(prompt)
56
+ return unless line
57
+
58
+ history.push(line) if save_hist
59
+
60
+ command_queue.concat(split_commands(line))
61
+ command_queue.shift
62
+ end
63
+
64
+ #
65
+ # Reads a new line from the interface's input stream.
66
+ #
67
+ # @return [String] New string read or the previous string if the string
68
+ # read now was empty.
69
+ #
70
+ def prepare_input(prompt)
71
+ line = readline(prompt)
72
+ return unless line
73
+
74
+ last_if_empty(line)
75
+ end
76
+
77
+ #
78
+ # Prints an error message to the error stream.
79
+ #
80
+ def errmsg(message)
81
+ error.print("*** #{message}\n")
82
+ end
83
+
84
+ #
85
+ # Prints an output message to the output stream.
86
+ #
87
+ def puts(message)
88
+ output.puts(message)
89
+ end
90
+
91
+ #
92
+ # Prints an output message to the output stream without a final "\n".
93
+ #
94
+ def print(message)
95
+ output.print(message)
96
+ end
97
+
98
+ #
99
+ # Confirms user introduced an affirmative response to the input stream.
100
+ #
101
+ def confirm(prompt)
102
+ readline(prompt) == "y"
103
+ end
104
+
105
+ def close
106
+ end
107
+
108
+ #
109
+ # Saves or clears history according to +autosave+ setting.
110
+ #
111
+ def autosave
112
+ Setting[:autosave] ? history.save : history.clear
113
+ end
114
+
115
+ #
116
+ # Restores history according to +autosave+ setting.
117
+ #
118
+ def autorestore
119
+ history.restore if Setting[:autosave]
120
+ end
121
+
122
+ private
123
+
124
+ #
125
+ # Splits a command line of the form "cmd1 ; cmd2 ; ... ; cmdN" into an
126
+ # array of commands: [cmd1, cmd2, ..., cmdN]
127
+ #
128
+ def split_commands(cmd_line)
129
+ return [""] if cmd_line.empty?
130
+
131
+ cmd_line.split(/;/).each_with_object([]) do |v, m|
132
+ if m.empty? || m.last[-1] != '\\'
133
+ m << v.strip
134
+ next
135
+ end
136
+
137
+ m.last[-1, 1] = ""
138
+ m.last << ";" << v
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ require "byebug/interfaces/local_interface"
145
+ require "byebug/interfaces/script_interface"
146
+ require "byebug/interfaces/remote_interface"
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Interface class for standard byebug use.
6
+ #
7
+ class LocalInterface < Interface
8
+ EOF_ALIAS = "continue"
9
+
10
+ def initialize
11
+ super()
12
+ @input = $stdin
13
+ @output = $stdout
14
+ @error = $stderr
15
+ end
16
+
17
+ #
18
+ # Reads a single line of input using Readline. If Ctrl-D is pressed, it
19
+ # returns "continue", meaning that program's execution will go on.
20
+ #
21
+ # @param prompt Prompt to be displayed.
22
+ #
23
+ def readline(prompt)
24
+ with_repl_like_sigint { Readline.readline(prompt) || EOF_ALIAS }
25
+ end
26
+
27
+ #
28
+ # Yields the block handling Ctrl-C the following way: if pressed while
29
+ # waiting for input, the line is reset to only the prompt and we ask for
30
+ # input again.
31
+ #
32
+ # @note Any external 'INT' traps are overriden during this method.
33
+ #
34
+ def with_repl_like_sigint
35
+ orig_handler = trap("INT") { raise Interrupt }
36
+ yield
37
+ rescue Interrupt
38
+ puts("^C")
39
+ retry
40
+ ensure
41
+ trap("INT", orig_handler)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/history"
4
+
5
+ module Byebug
6
+ #
7
+ # Interface class for remote use of byebug.
8
+ #
9
+ class RemoteInterface < Interface
10
+ def initialize(socket)
11
+ super()
12
+ @input = socket
13
+ @output = socket
14
+ @error = socket
15
+ end
16
+
17
+ def read_command(prompt)
18
+ super("PROMPT #{prompt}")
19
+ rescue Errno::EPIPE, Errno::ECONNABORTED
20
+ "continue"
21
+ end
22
+
23
+ def confirm(prompt)
24
+ super("CONFIRM #{prompt}")
25
+ rescue Errno::EPIPE, Errno::ECONNABORTED
26
+ false
27
+ end
28
+
29
+ def print(message)
30
+ super(message)
31
+ rescue Errno::EPIPE, Errno::ECONNABORTED
32
+ nil
33
+ end
34
+
35
+ def puts(message)
36
+ super(message)
37
+ rescue Errno::EPIPE, Errno::ECONNABORTED
38
+ nil
39
+ end
40
+
41
+ def close
42
+ output.close
43
+ end
44
+
45
+ def readline(prompt)
46
+ puts(prompt)
47
+ (input.gets || "continue").chomp
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Interface class for command execution from script files.
6
+ #
7
+ class ScriptInterface < Interface
8
+ def initialize(file, verbose = false)
9
+ super()
10
+ @verbose = verbose
11
+ @input = File.open(file)
12
+ @output = verbose ? $stdout : StringIO.new
13
+ @error = $stderr
14
+ end
15
+
16
+ def read_command(prompt)
17
+ readline(prompt, false)
18
+ end
19
+
20
+ def close
21
+ input.close
22
+ end
23
+
24
+ def readline(*)
25
+ while (result = input.gets)
26
+ output.puts "+ #{result}" if @verbose
27
+ next if result =~ /^\s*#/
28
+
29
+ return result.chomp
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Custom interface for easier assertions
6
+ #
7
+ class TestInterface < Interface
8
+ attr_accessor :test_block
9
+
10
+ def initialize
11
+ super()
12
+
13
+ clear
14
+ end
15
+
16
+ def errmsg(message)
17
+ error.concat(prepare(message))
18
+ end
19
+
20
+ def print(message)
21
+ output.concat(prepare(message))
22
+ end
23
+
24
+ def puts(message)
25
+ output.concat(prepare(message))
26
+ end
27
+
28
+ def read_command(prompt)
29
+ cmd = super(prompt)
30
+
31
+ return cmd unless cmd.nil? && test_block
32
+
33
+ test_block.call
34
+ self.test_block = nil
35
+ end
36
+
37
+ def clear
38
+ @input = []
39
+ @output = []
40
+ @error = []
41
+ history.clear
42
+ end
43
+
44
+ def inspect
45
+ [
46
+ "Input:", input.join("\n"),
47
+ "Output:", output.join("\n"),
48
+ "Error:", error.join("\n")
49
+ ].join("\n")
50
+ end
51
+
52
+ def readline(prompt)
53
+ puts(prompt)
54
+
55
+ cmd = input.shift
56
+ cmd.is_a?(Proc) ? cmd.call : cmd
57
+ end
58
+
59
+ private
60
+
61
+ def prepare(message)
62
+ return message.map(&:to_s) if message.respond_to?(:map)
63
+
64
+ message.to_s.split("\n")
65
+ end
66
+ end
67
+ end