byebug 3.5.1 → 4.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.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.rubocop.yml +18 -1
- data/.travis.yml +21 -1
- data/CHANGELOG.md +356 -308
- data/CONTRIBUTING.md +31 -15
- data/GUIDE.md +859 -475
- data/Gemfile +8 -10
- data/LICENSE +1 -1
- data/README.md +41 -45
- data/Rakefile +30 -28
- data/byebug.gemspec +18 -18
- data/ext/byebug/breakpoint.c +88 -75
- data/ext/byebug/byebug.c +253 -252
- data/ext/byebug/byebug.h +53 -53
- data/ext/byebug/context.c +188 -159
- data/ext/byebug/extconf.rb +9 -6
- data/ext/byebug/locker.c +53 -11
- data/ext/byebug/threads.c +137 -39
- data/lib/byebug/attacher.rb +7 -2
- data/lib/byebug/breakpoint.rb +30 -0
- data/lib/byebug/command.rb +36 -32
- data/lib/byebug/commands/break.rb +49 -48
- data/lib/byebug/commands/catch.rb +64 -0
- data/lib/byebug/commands/condition.rb +13 -9
- data/lib/byebug/commands/continue.rb +8 -4
- data/lib/byebug/commands/delete.rb +10 -4
- data/lib/byebug/commands/display.rb +33 -25
- data/lib/byebug/commands/edit.rb +18 -13
- data/lib/byebug/commands/enable_disable.rb +26 -24
- data/lib/byebug/commands/eval.rb +77 -35
- data/lib/byebug/commands/finish.rb +9 -5
- data/lib/byebug/commands/frame.rb +66 -125
- data/lib/byebug/commands/help.rb +14 -21
- data/lib/byebug/commands/history.rb +5 -1
- data/lib/byebug/commands/info.rb +41 -106
- data/lib/byebug/commands/interrupt.rb +6 -2
- data/lib/byebug/commands/irb.rb +5 -2
- data/lib/byebug/commands/kill.rb +6 -2
- data/lib/byebug/commands/list.rb +21 -14
- data/lib/byebug/commands/method.rb +17 -9
- data/lib/byebug/commands/pry.rb +13 -3
- data/lib/byebug/commands/quit.rb +10 -5
- data/lib/byebug/commands/restart.rb +12 -19
- data/lib/byebug/commands/save.rb +10 -6
- data/lib/byebug/commands/set.rb +15 -14
- data/lib/byebug/commands/show.rb +8 -8
- data/lib/byebug/commands/source.rb +14 -8
- data/lib/byebug/commands/stepping.rb +15 -29
- data/lib/byebug/commands/threads.rb +73 -49
- data/lib/byebug/commands/tracevar.rb +56 -0
- data/lib/byebug/commands/undisplay.rb +8 -4
- data/lib/byebug/commands/untracevar.rb +38 -0
- data/lib/byebug/commands/var.rb +107 -0
- data/lib/byebug/context.rb +78 -42
- data/lib/byebug/core.rb +78 -40
- data/lib/byebug/helper.rb +58 -42
- data/lib/byebug/history.rb +12 -1
- data/lib/byebug/interface.rb +91 -11
- data/lib/byebug/interfaces/local_interface.rb +12 -19
- data/lib/byebug/interfaces/remote_interface.rb +12 -15
- data/lib/byebug/interfaces/script_interface.rb +14 -18
- data/lib/byebug/interfaces/test_interface.rb +54 -0
- data/lib/byebug/printers/base.rb +64 -0
- data/lib/byebug/printers/plain.rb +53 -0
- data/lib/byebug/processor.rb +20 -1
- data/lib/byebug/processors/command_processor.rb +57 -172
- data/lib/byebug/processors/control_command_processor.rb +16 -43
- data/lib/byebug/remote.rb +13 -7
- data/lib/byebug/runner.rb +102 -54
- data/lib/byebug/setting.rb +45 -68
- data/lib/byebug/settings/autoeval.rb +2 -0
- data/lib/byebug/settings/autoirb.rb +3 -0
- data/lib/byebug/settings/autolist.rb +3 -0
- data/lib/byebug/settings/autosave.rb +2 -0
- data/lib/byebug/settings/basename.rb +2 -0
- data/lib/byebug/settings/callstyle.rb +2 -0
- data/lib/byebug/settings/fullpath.rb +2 -0
- data/lib/byebug/settings/histfile.rb +2 -0
- data/lib/byebug/settings/histsize.rb +2 -0
- data/lib/byebug/settings/linetrace.rb +2 -0
- data/lib/byebug/settings/listsize.rb +2 -0
- data/lib/byebug/settings/post_mortem.rb +7 -2
- data/lib/byebug/settings/stack_on_error.rb +2 -0
- data/lib/byebug/settings/verbose.rb +2 -0
- data/lib/byebug/settings/width.rb +2 -0
- data/lib/byebug/state.rb +12 -0
- data/lib/byebug/states/control_state.rb +26 -0
- data/lib/byebug/states/regular_state.rb +178 -0
- data/lib/byebug/version.rb +1 -1
- metadata +24 -109
- data/lib/byebug/commands/catchpoint.rb +0 -53
- data/lib/byebug/commands/reload.rb +0 -29
- data/lib/byebug/commands/trace.rb +0 -50
- data/lib/byebug/commands/variables.rb +0 -206
- data/lib/byebug/options.rb +0 -46
- data/lib/byebug/settings/autoreload.rb +0 -12
- data/lib/byebug/settings/forcestep.rb +0 -14
- data/lib/byebug/settings/testing.rb +0 -12
- data/lib/byebug/settings/tracing_plus.rb +0 -11
- data/test/commands/break_test.rb +0 -364
- data/test/commands/condition_test.rb +0 -85
- data/test/commands/continue_test.rb +0 -47
- data/test/commands/delete_test.rb +0 -26
- data/test/commands/display_test.rb +0 -37
- data/test/commands/edit_test.rb +0 -52
- data/test/commands/eval_test.rb +0 -89
- data/test/commands/finish_test.rb +0 -74
- data/test/commands/frame_test.rb +0 -223
- data/test/commands/help_test.rb +0 -66
- data/test/commands/history_test.rb +0 -61
- data/test/commands/info_test.rb +0 -238
- data/test/commands/interrupt_test.rb +0 -45
- data/test/commands/irb_test.rb +0 -28
- data/test/commands/kill_test.rb +0 -50
- data/test/commands/list_test.rb +0 -174
- data/test/commands/method_test.rb +0 -52
- data/test/commands/post_mortem_test.rb +0 -71
- data/test/commands/pry_test.rb +0 -26
- data/test/commands/quit_test.rb +0 -53
- data/test/commands/reload_test.rb +0 -39
- data/test/commands/restart_test.rb +0 -46
- data/test/commands/save_test.rb +0 -67
- data/test/commands/set_test.rb +0 -140
- data/test/commands/show_test.rb +0 -76
- data/test/commands/source_test.rb +0 -46
- data/test/commands/stepping_test.rb +0 -192
- data/test/commands/thread_test.rb +0 -164
- data/test/commands/trace_test.rb +0 -71
- data/test/commands/undisplay_test.rb +0 -75
- data/test/commands/variables_test.rb +0 -105
- data/test/debugger_alias_test.rb +0 -7
- data/test/runner_test.rb +0 -150
- data/test/support/matchers.rb +0 -65
- data/test/support/test_interface.rb +0 -59
- data/test/support/utils.rb +0 -122
- data/test/test_helper.rb +0 -58
data/lib/byebug/interface.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'byebug/history'
|
2
|
+
require 'byebug/helper'
|
2
3
|
|
3
4
|
#
|
4
5
|
# Namespace for all of byebug's code
|
@@ -11,30 +12,109 @@ module Byebug
|
|
11
12
|
#
|
12
13
|
class Interface
|
13
14
|
attr_accessor :command_queue, :history
|
15
|
+
attr_reader :input, :output, :error
|
14
16
|
|
15
17
|
def initialize
|
16
18
|
@command_queue, @history = [], History.new
|
17
19
|
end
|
18
20
|
|
19
21
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
+
# Pops a command from the input stream.
|
23
|
+
#
|
24
|
+
def read_command(prompt)
|
25
|
+
return command_queue.shift unless command_queue.empty?
|
26
|
+
|
27
|
+
cmds = read_input(prompt)
|
28
|
+
return unless cmds
|
29
|
+
|
30
|
+
command_queue.concat(cmds)
|
31
|
+
command_queue.shift
|
32
|
+
end
|
33
|
+
|
34
|
+
include FileFunctions
|
35
|
+
#
|
36
|
+
# Pushes lines in +filename+ to the command queue.
|
37
|
+
#
|
38
|
+
def read_file(filename)
|
39
|
+
command_queue.concat(get_lines(filename))
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Reads a new line from the interface's input stream.
|
44
|
+
#
|
45
|
+
def read_input(prompt, save_hist = true)
|
46
|
+
line = readline(prompt)
|
47
|
+
return unless line
|
48
|
+
|
49
|
+
history.push(line) if save_hist
|
50
|
+
|
51
|
+
split_commands(line)
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Prints an error message to the error stream.
|
22
56
|
#
|
23
57
|
def errmsg(message)
|
24
|
-
print("*** #{message}\n")
|
58
|
+
error.print("*** #{message}\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Prints an output message to the output stream.
|
63
|
+
#
|
64
|
+
def puts(message)
|
65
|
+
output.puts(message)
|
25
66
|
end
|
26
67
|
|
27
|
-
|
68
|
+
def print(message)
|
69
|
+
output.print(message)
|
70
|
+
end
|
28
71
|
|
29
72
|
#
|
30
|
-
#
|
73
|
+
# Confirms user introduced an affirmative response to the input stream.
|
31
74
|
#
|
32
|
-
def
|
33
|
-
|
75
|
+
def confirm(prompt)
|
76
|
+
readline(prompt) == 'y'
|
34
77
|
end
|
35
|
-
end
|
36
78
|
|
37
|
-
|
38
|
-
|
39
|
-
|
79
|
+
def close
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Saves or clears history according to +autosave+ setting.
|
84
|
+
#
|
85
|
+
def autosave
|
86
|
+
Setting[:autosave] ? history.save : history.clear
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Restores history according to +autosave+ setting.
|
91
|
+
#
|
92
|
+
def autorestore
|
93
|
+
history.restore if Setting[:autosave]
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
#
|
99
|
+
# Splits a command line of the form "cmd1 ; cmd2 ; ... ; cmdN" into an
|
100
|
+
# array of commands: [cmd1, cmd2, ..., cmdN]
|
101
|
+
#
|
102
|
+
def split_commands(cmd_line)
|
103
|
+
return [''] if cmd_line.empty?
|
104
|
+
|
105
|
+
cmd_line.split(/;/).each_with_object([]) do |v, m|
|
106
|
+
if m.empty? || m.last[-1] != '\\'
|
107
|
+
m << v
|
108
|
+
next
|
109
|
+
end
|
110
|
+
|
111
|
+
m.last[-1, 1] = ''
|
112
|
+
m.last << ';' << v
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
40
116
|
end
|
117
|
+
|
118
|
+
require 'byebug/interfaces/local_interface'
|
119
|
+
require 'byebug/interfaces/script_interface'
|
120
|
+
require 'byebug/interfaces/remote_interface'
|
@@ -3,30 +3,23 @@ module Byebug
|
|
3
3
|
# Interface class for standard byebug use.
|
4
4
|
#
|
5
5
|
class LocalInterface < Interface
|
6
|
-
def
|
7
|
-
|
6
|
+
def initialize
|
7
|
+
super()
|
8
|
+
@input, @output, @error = STDIN, STDOUT, STDERR
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def readline(prompt, hist)
|
24
|
-
line = Readline.readline(prompt, false)
|
11
|
+
#
|
12
|
+
# Reads a single line of input using Readline. If Ctrl-C is pressed in the
|
13
|
+
# middle of input, the line is reset to only the prompt and we ask for input
|
14
|
+
# again.
|
15
|
+
#
|
16
|
+
# @param prompt Prompt to be displayed.
|
17
|
+
#
|
18
|
+
def readline(prompt)
|
19
|
+
Readline.readline(prompt, false)
|
25
20
|
rescue Interrupt
|
26
21
|
puts('^C')
|
27
22
|
retry
|
28
|
-
ensure
|
29
|
-
save_history(line) if hist
|
30
23
|
end
|
31
24
|
end
|
32
25
|
end
|
@@ -7,32 +7,29 @@ module Byebug
|
|
7
7
|
class RemoteInterface < Interface
|
8
8
|
def initialize(socket)
|
9
9
|
super()
|
10
|
-
@
|
10
|
+
@input, @output, @error = socket, socket, socket
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
rescue IOError
|
13
|
+
def read_command(prompt)
|
14
|
+
super("PROMPT #{prompt}")
|
16
15
|
end
|
17
16
|
|
18
17
|
def confirm(prompt)
|
19
|
-
|
18
|
+
super("CONFIRM #{prompt}")
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def puts(message)
|
27
|
-
@socket.puts(message)
|
21
|
+
def close
|
22
|
+
output.close
|
23
|
+
rescue IOError
|
24
|
+
errmsg('Error closing the interface...')
|
28
25
|
end
|
29
26
|
|
30
|
-
|
27
|
+
def readline(prompt)
|
28
|
+
output.puts(prompt)
|
31
29
|
|
32
|
-
|
33
|
-
@socket.puts msg
|
34
|
-
result = @socket.gets
|
30
|
+
result = input.gets
|
35
31
|
fail IOError unless result
|
32
|
+
|
36
33
|
result.chomp
|
37
34
|
end
|
38
35
|
end
|
@@ -3,31 +3,27 @@ module Byebug
|
|
3
3
|
# Interface class for command execution from script files.
|
4
4
|
#
|
5
5
|
class ScriptInterface < Interface
|
6
|
-
def initialize(file,
|
6
|
+
def initialize(file, verbose = false)
|
7
7
|
super()
|
8
|
-
@
|
9
|
-
@
|
8
|
+
@input = File.open(file)
|
9
|
+
@output = verbose ? STDOUT : StringIO.new
|
10
|
+
@error = verbose ? STDERR : StringIO.new
|
10
11
|
end
|
11
12
|
|
12
|
-
def read_command(
|
13
|
-
|
14
|
-
puts "# #{result}" if @verbose
|
15
|
-
next if result =~ /^\s*#/
|
16
|
-
next if result.strip.empty?
|
17
|
-
return result.chomp
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def confirm(_prompt)
|
22
|
-
'y'
|
13
|
+
def read_command(prompt)
|
14
|
+
readline(prompt, false)
|
23
15
|
end
|
24
16
|
|
25
|
-
def
|
26
|
-
|
17
|
+
def close
|
18
|
+
input.close
|
27
19
|
end
|
28
20
|
|
29
|
-
def
|
30
|
-
|
21
|
+
def readline(*)
|
22
|
+
while (result = input.gets)
|
23
|
+
output.puts "+ #{result}"
|
24
|
+
next if result =~ /^\s*#/
|
25
|
+
return result.chomp
|
26
|
+
end
|
31
27
|
end
|
32
28
|
end
|
33
29
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Byebug
|
2
|
+
#
|
3
|
+
# Custom interface for easier assertions
|
4
|
+
#
|
5
|
+
class TestInterface < Interface
|
6
|
+
attr_accessor :test_block
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super()
|
10
|
+
@input, @output, @error = [], [], []
|
11
|
+
end
|
12
|
+
|
13
|
+
def errmsg(message)
|
14
|
+
error.concat(message.to_s.split("\n"))
|
15
|
+
end
|
16
|
+
|
17
|
+
def print(message)
|
18
|
+
output.concat(message.to_s.split("\n"))
|
19
|
+
end
|
20
|
+
|
21
|
+
def puts(message)
|
22
|
+
output.concat(message.to_s.split("\n"))
|
23
|
+
end
|
24
|
+
|
25
|
+
def read_command(prompt)
|
26
|
+
cmd = super(prompt)
|
27
|
+
|
28
|
+
return cmd unless cmd.nil? && test_block
|
29
|
+
|
30
|
+
test_block.call
|
31
|
+
self.test_block = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear
|
35
|
+
@input, @output, @error = [], [], []
|
36
|
+
history.clear
|
37
|
+
end
|
38
|
+
|
39
|
+
def inspect
|
40
|
+
[
|
41
|
+
'Input:', input.join("\n"),
|
42
|
+
'Output:', output.join("\n"),
|
43
|
+
'Error:', error.join("\n")
|
44
|
+
].join("\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
def readline(prompt)
|
48
|
+
puts(prompt)
|
49
|
+
|
50
|
+
cmd = input.shift
|
51
|
+
cmd.is_a?(Proc) ? cmd.call : cmd
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Byebug
|
4
|
+
module Printers
|
5
|
+
class Base
|
6
|
+
class MissedPath < StandardError; end
|
7
|
+
class MissedArgument < StandardError; end
|
8
|
+
|
9
|
+
SEPARATOR = '.'
|
10
|
+
|
11
|
+
def type
|
12
|
+
self.class.name.split('::').last.downcase
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def locate(path)
|
18
|
+
result = nil
|
19
|
+
contents.each do |_, contents|
|
20
|
+
result = parts(path).reduce(contents) do |r, part|
|
21
|
+
r && r.key?(part) ? r[part] : nil
|
22
|
+
end
|
23
|
+
break if result
|
24
|
+
end
|
25
|
+
fail MissedPath, "Can't find part path '#{path}'" unless result
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
def translate(string, args = {})
|
30
|
+
# they may contain #{} string interpolation
|
31
|
+
string.gsub(/\|\w+$/, '').gsub(/([^#]?){([^}]*)}/) do
|
32
|
+
key = Regexp.last_match[2].to_s
|
33
|
+
unless args.key?(key.to_sym)
|
34
|
+
fail MissedArgument, "Missed argument #{key} for '#{string}'"
|
35
|
+
end
|
36
|
+
|
37
|
+
"#{Regexp.last_match[1]}#{args[key.to_sym]}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def parts(path)
|
42
|
+
path.split(SEPARATOR)
|
43
|
+
end
|
44
|
+
|
45
|
+
def contents
|
46
|
+
@contents ||= contents_files.each_with_object({}) do |filename, hash|
|
47
|
+
hash[filename] = YAML.load_file(filename) || {}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def array_of_args(collection, &block)
|
52
|
+
collection_with_index = collection.each.with_index
|
53
|
+
collection_with_index.each_with_object([]) do |(item, index), array|
|
54
|
+
args = block.call(item, index)
|
55
|
+
array << args if args
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def contents_files
|
60
|
+
[File.expand_path(File.join('..', 'texts', 'base.yml'), __FILE__)]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'byebug/printers/base'
|
2
|
+
|
3
|
+
module Byebug
|
4
|
+
module Printers
|
5
|
+
class Plain < Base
|
6
|
+
include Columnize
|
7
|
+
|
8
|
+
def print(path, args = {})
|
9
|
+
message = translate(locate(path), args)
|
10
|
+
tail = parts(path).include?('confirmations') ? ' (y/n) ' : "\n"
|
11
|
+
message << tail
|
12
|
+
end
|
13
|
+
|
14
|
+
def print_collection(path, collection, &block)
|
15
|
+
modifier = get_modifier(path)
|
16
|
+
lines = array_of_args(collection, &block).map do |args|
|
17
|
+
print(path, args)
|
18
|
+
end
|
19
|
+
|
20
|
+
if modifier == 'c'
|
21
|
+
columnize(lines.map { |l| l.gsub(/\n$/, '') }, Setting[:width])
|
22
|
+
else
|
23
|
+
lines.join('')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def print_variables(variables)
|
28
|
+
print_collection('variable.variable', variables) do |(key, value), _|
|
29
|
+
value = value.nil? ? 'nil' : value.to_s
|
30
|
+
if "#{key} = #{value}".size > Setting[:width]
|
31
|
+
key_size = "#{key} = ".size
|
32
|
+
value = value[0..Setting[:width] - key_size - 4] + '...'
|
33
|
+
end
|
34
|
+
|
35
|
+
{ key: key, value: value }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def get_modifier(path)
|
42
|
+
modifier_regexp = /\|(\w+)$/
|
43
|
+
modifier_match = locate(path).match(modifier_regexp)
|
44
|
+
modifier_match && modifier_match[1]
|
45
|
+
end
|
46
|
+
|
47
|
+
def contents_files
|
48
|
+
[File.expand_path(File.join('..', 'texts', 'plain.yml'), __FILE__)] +
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/byebug/processor.rb
CHANGED
@@ -16,9 +16,28 @@ module Byebug
|
|
16
16
|
rescue
|
17
17
|
nil
|
18
18
|
end
|
19
|
+
|
20
|
+
def self.load_commands
|
21
|
+
Dir.glob(File.expand_path('../commands/*.rb', __FILE__)).each do |file|
|
22
|
+
require file
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.load_settings
|
27
|
+
Dir.glob(File.expand_path('../settings/*.rb', __FILE__)).each do |file|
|
28
|
+
require file
|
29
|
+
end
|
30
|
+
|
31
|
+
Byebug.constants.grep(/[a-z]Setting/).map do |name|
|
32
|
+
setting = Byebug.const_get(name).new
|
33
|
+
Byebug::Setting.settings[setting.to_sym] = setting
|
34
|
+
end
|
35
|
+
end
|
19
36
|
end
|
37
|
+
|
38
|
+
Processor.load_commands
|
39
|
+
Processor.load_settings
|
20
40
|
end
|
21
41
|
|
22
|
-
require 'byebug/command'
|
23
42
|
require 'byebug/processors/command_processor'
|
24
43
|
require 'byebug/processors/control_command_processor'
|