runger_byebug 11.2.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 +7 -0
- data/CHANGELOG.md +954 -0
- data/CONTRIBUTING.md +58 -0
- data/GUIDE.md +1806 -0
- data/LICENSE +23 -0
- data/README.md +199 -0
- data/exe/byebug +6 -0
- data/ext/byebug/breakpoint.c +521 -0
- data/ext/byebug/byebug.c +900 -0
- data/ext/byebug/byebug.h +145 -0
- data/ext/byebug/context.c +687 -0
- data/ext/byebug/extconf.rb +12 -0
- data/ext/byebug/locker.c +96 -0
- data/ext/byebug/threads.c +241 -0
- data/lib/byebug/attacher.rb +48 -0
- data/lib/byebug/breakpoint.rb +94 -0
- data/lib/byebug/command.rb +111 -0
- data/lib/byebug/command_list.rb +34 -0
- data/lib/byebug/commands/break.rb +114 -0
- data/lib/byebug/commands/catch.rb +78 -0
- data/lib/byebug/commands/condition.rb +55 -0
- data/lib/byebug/commands/continue.rb +68 -0
- data/lib/byebug/commands/debug.rb +38 -0
- data/lib/byebug/commands/delete.rb +55 -0
- data/lib/byebug/commands/disable/breakpoints.rb +42 -0
- data/lib/byebug/commands/disable/display.rb +43 -0
- data/lib/byebug/commands/disable.rb +33 -0
- data/lib/byebug/commands/display.rb +66 -0
- data/lib/byebug/commands/down.rb +45 -0
- data/lib/byebug/commands/edit.rb +69 -0
- data/lib/byebug/commands/enable/breakpoints.rb +42 -0
- data/lib/byebug/commands/enable/display.rb +43 -0
- data/lib/byebug/commands/enable.rb +33 -0
- data/lib/byebug/commands/finish.rb +57 -0
- data/lib/byebug/commands/frame.rb +57 -0
- data/lib/byebug/commands/help.rb +64 -0
- data/lib/byebug/commands/history.rb +39 -0
- data/lib/byebug/commands/info/breakpoints.rb +65 -0
- data/lib/byebug/commands/info/display.rb +49 -0
- data/lib/byebug/commands/info/file.rb +80 -0
- data/lib/byebug/commands/info/line.rb +35 -0
- data/lib/byebug/commands/info/program.rb +49 -0
- data/lib/byebug/commands/info.rb +37 -0
- data/lib/byebug/commands/interrupt.rb +34 -0
- data/lib/byebug/commands/irb.rb +50 -0
- data/lib/byebug/commands/kill.rb +45 -0
- data/lib/byebug/commands/list.rb +159 -0
- data/lib/byebug/commands/method.rb +53 -0
- data/lib/byebug/commands/next.rb +40 -0
- data/lib/byebug/commands/pry.rb +41 -0
- data/lib/byebug/commands/quit.rb +42 -0
- data/lib/byebug/commands/restart.rb +64 -0
- data/lib/byebug/commands/save.rb +72 -0
- data/lib/byebug/commands/set.rb +79 -0
- data/lib/byebug/commands/show.rb +45 -0
- data/lib/byebug/commands/skip.rb +85 -0
- data/lib/byebug/commands/source.rb +40 -0
- data/lib/byebug/commands/step.rb +40 -0
- data/lib/byebug/commands/thread/current.rb +37 -0
- data/lib/byebug/commands/thread/list.rb +43 -0
- data/lib/byebug/commands/thread/resume.rb +45 -0
- data/lib/byebug/commands/thread/stop.rb +43 -0
- data/lib/byebug/commands/thread/switch.rb +46 -0
- data/lib/byebug/commands/thread.rb +34 -0
- data/lib/byebug/commands/tracevar.rb +54 -0
- data/lib/byebug/commands/undisplay.rb +51 -0
- data/lib/byebug/commands/untracevar.rb +36 -0
- data/lib/byebug/commands/up.rb +45 -0
- data/lib/byebug/commands/var/all.rb +41 -0
- data/lib/byebug/commands/var/args.rb +39 -0
- data/lib/byebug/commands/var/const.rb +49 -0
- data/lib/byebug/commands/var/global.rb +37 -0
- data/lib/byebug/commands/var/instance.rb +39 -0
- data/lib/byebug/commands/var/local.rb +39 -0
- data/lib/byebug/commands/var.rb +37 -0
- data/lib/byebug/commands/where.rb +64 -0
- data/lib/byebug/commands.rb +40 -0
- data/lib/byebug/context.rb +157 -0
- data/lib/byebug/core.rb +115 -0
- data/lib/byebug/errors.rb +29 -0
- data/lib/byebug/frame.rb +185 -0
- data/lib/byebug/helpers/bin.rb +47 -0
- data/lib/byebug/helpers/eval.rb +134 -0
- data/lib/byebug/helpers/file.rb +63 -0
- data/lib/byebug/helpers/frame.rb +75 -0
- data/lib/byebug/helpers/parse.rb +80 -0
- data/lib/byebug/helpers/path.rb +40 -0
- data/lib/byebug/helpers/reflection.rb +19 -0
- data/lib/byebug/helpers/string.rb +33 -0
- data/lib/byebug/helpers/thread.rb +67 -0
- data/lib/byebug/helpers/toggle.rb +62 -0
- data/lib/byebug/helpers/var.rb +70 -0
- data/lib/byebug/history.rb +130 -0
- data/lib/byebug/interface.rb +146 -0
- data/lib/byebug/interfaces/local_interface.rb +63 -0
- data/lib/byebug/interfaces/remote_interface.rb +50 -0
- data/lib/byebug/interfaces/script_interface.rb +33 -0
- data/lib/byebug/interfaces/test_interface.rb +67 -0
- data/lib/byebug/option_setter.rb +95 -0
- data/lib/byebug/printers/base.rb +68 -0
- data/lib/byebug/printers/plain.rb +44 -0
- data/lib/byebug/printers/texts/base.yml +115 -0
- data/lib/byebug/printers/texts/plain.yml +33 -0
- data/lib/byebug/processors/command_processor.rb +173 -0
- data/lib/byebug/processors/control_processor.rb +24 -0
- data/lib/byebug/processors/post_mortem_processor.rb +18 -0
- data/lib/byebug/processors/script_processor.rb +49 -0
- data/lib/byebug/remote/client.rb +57 -0
- data/lib/byebug/remote/server.rb +47 -0
- data/lib/byebug/remote.rb +85 -0
- data/lib/byebug/runner.rb +198 -0
- data/lib/byebug/setting.rb +79 -0
- data/lib/byebug/settings/autoirb.rb +29 -0
- data/lib/byebug/settings/autolist.rb +29 -0
- data/lib/byebug/settings/autopry.rb +29 -0
- data/lib/byebug/settings/autosave.rb +17 -0
- data/lib/byebug/settings/basename.rb +16 -0
- data/lib/byebug/settings/callstyle.rb +20 -0
- data/lib/byebug/settings/fullpath.rb +16 -0
- data/lib/byebug/settings/histfile.rb +20 -0
- data/lib/byebug/settings/histsize.rb +20 -0
- data/lib/byebug/settings/linetrace.rb +22 -0
- data/lib/byebug/settings/listsize.rb +21 -0
- data/lib/byebug/settings/post_mortem.rb +27 -0
- data/lib/byebug/settings/savefile.rb +20 -0
- data/lib/byebug/settings/stack_on_error.rb +15 -0
- data/lib/byebug/settings/width.rb +20 -0
- data/lib/byebug/source_file_formatter.rb +71 -0
- data/lib/byebug/subcommands.rb +54 -0
- data/lib/byebug/version.rb +8 -0
- data/lib/byebug.rb +3 -0
- metadata +194 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Byebug
|
4
|
+
#
|
5
|
+
# Handles byebug's command line options
|
6
|
+
#
|
7
|
+
class OptionSetter
|
8
|
+
def initialize(runner, opts)
|
9
|
+
@runner = runner
|
10
|
+
@opts = opts
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup
|
14
|
+
debug
|
15
|
+
include_flag
|
16
|
+
post_mortem
|
17
|
+
quit
|
18
|
+
rc
|
19
|
+
stop
|
20
|
+
require_flag
|
21
|
+
remote
|
22
|
+
trace
|
23
|
+
version
|
24
|
+
help
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def debug
|
30
|
+
@opts.on "-d", "--debug", "Set $DEBUG=true" do
|
31
|
+
$DEBUG = true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def include_flag
|
36
|
+
@opts.on "-I", "--include list", "Add paths to $LOAD_PATH" do |list|
|
37
|
+
$LOAD_PATH.push(list.split(":")).flatten!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def post_mortem
|
42
|
+
@opts.on "-m", "--[no-]post-mortem", "Use post-mortem mode" do |v|
|
43
|
+
Setting[:post_mortem] = v
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def quit
|
48
|
+
@opts.on "-q", "--[no-]quit", "Quit when script finishes" do |v|
|
49
|
+
@runner.quit = v
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def rc
|
54
|
+
@opts.on "-x", "--[no-]rc", "Run byebug initialization file" do |v|
|
55
|
+
@runner.init_script = v
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def stop
|
60
|
+
@opts.on "-s", "--[no-]stop", "Stop when script is loaded" do |v|
|
61
|
+
@runner.stop = v
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def require_flag
|
66
|
+
@opts.on "-r", "--require file", "Require library before script" do |lib|
|
67
|
+
require lib
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def remote
|
72
|
+
@opts.on "-R", "--remote [host:]port", "Remote debug [host:]port" do |p|
|
73
|
+
@runner.remote = p
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def trace
|
78
|
+
@opts.on "-t", "--[no-]trace", "Turn on line tracing" do |v|
|
79
|
+
Setting[:linetrace] = v
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def version
|
84
|
+
@opts.on "-v", "--version", "Print program version" do
|
85
|
+
@runner.version = Byebug::VERSION
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def help
|
90
|
+
@opts.on "-h", "--help", "Display this message" do
|
91
|
+
@runner.help = @opts.help
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
module Printers
|
7
|
+
#
|
8
|
+
# Base printer
|
9
|
+
#
|
10
|
+
class Base
|
11
|
+
class MissedPath < StandardError; end
|
12
|
+
class MissedArgument < StandardError; end
|
13
|
+
|
14
|
+
SEPARATOR = "."
|
15
|
+
|
16
|
+
def type
|
17
|
+
self.class.name.split("::").last.downcase
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def locate(path)
|
23
|
+
result = nil
|
24
|
+
contents.each_value do |contents|
|
25
|
+
result = parts(path).reduce(contents) do |r, part|
|
26
|
+
r&.key?(part) ? r[part] : nil
|
27
|
+
end
|
28
|
+
break if result
|
29
|
+
end
|
30
|
+
raise MissedPath, "Can't find part path '#{path}'" unless result
|
31
|
+
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
def translate(string, args = {})
|
36
|
+
# they may contain #{} string interpolation
|
37
|
+
string.gsub(/\|\w+$/, "").gsub(/([^#]?){([^}]*)}/) do
|
38
|
+
key = Regexp.last_match[2].to_s
|
39
|
+
raise MissedArgument, "Missed argument #{key} for '#{string}'" unless args.key?(key.to_sym)
|
40
|
+
|
41
|
+
"#{Regexp.last_match[1]}#{args[key.to_sym]}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def parts(path)
|
46
|
+
path.split(SEPARATOR)
|
47
|
+
end
|
48
|
+
|
49
|
+
def contents
|
50
|
+
@contents ||= contents_files.each_with_object({}) do |filename, hash|
|
51
|
+
hash[filename] = YAML.load_file(filename) || {}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def array_of_args(collection, &_block)
|
56
|
+
collection_with_index = collection.each.with_index
|
57
|
+
collection_with_index.each_with_object([]) do |(item, index), array|
|
58
|
+
args = yield item, index
|
59
|
+
array << args if args
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def contents_files
|
64
|
+
[File.join(__dir__, "texts", "base.yml")]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
module Printers
|
7
|
+
#
|
8
|
+
# Plain text printer
|
9
|
+
#
|
10
|
+
class Plain < Base
|
11
|
+
def print(path, args = {})
|
12
|
+
message = translate(locate(path), args)
|
13
|
+
tail = parts(path).include?("confirmations") ? " (y/n) " : "\n"
|
14
|
+
message << tail
|
15
|
+
end
|
16
|
+
|
17
|
+
def print_collection(path, collection, &block)
|
18
|
+
lines = array_of_args(collection, &block).map do |args|
|
19
|
+
print(path, args)
|
20
|
+
end
|
21
|
+
|
22
|
+
lines.join
|
23
|
+
end
|
24
|
+
|
25
|
+
def print_variables(variables, *_unused)
|
26
|
+
print_collection("variable.variable", variables) do |(key, value), _|
|
27
|
+
value = value.nil? ? "nil" : value.to_s
|
28
|
+
if "#{key} = #{value}".size > Setting[:width]
|
29
|
+
key_size = "#{key} = ".size
|
30
|
+
value = value[0..Setting[:width] - key_size - 4] + "..."
|
31
|
+
end
|
32
|
+
|
33
|
+
{ key: key, value: value }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def contents_files
|
40
|
+
[File.join(__dir__, "texts", "plain.yml")] + super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
base:
|
2
|
+
errors:
|
3
|
+
only_local: "Command is available only in local mode."
|
4
|
+
|
5
|
+
break:
|
6
|
+
errors:
|
7
|
+
line: "Line {line} is not a valid breakpoint in file {file}.\n\nValid break points are:\n{valid_breakpoints}"
|
8
|
+
location: "Invalid breakpoint location"
|
9
|
+
state: "We are not in a state that has an associated file"
|
10
|
+
class: "Unknown class {klass}"
|
11
|
+
far_line: "There are only {lines} lines in file {file}"
|
12
|
+
source: "No file named {file}"
|
13
|
+
expression: "Incorrect expression \"{expr}\"; breakpoint disabled"
|
14
|
+
no_breakpoint: "Invalid breakpoint id. Use \"info breakpoint\" to find out the correct id"
|
15
|
+
no_breakpoint_delete: "No breakpoint number {pos}"
|
16
|
+
not_changed: "Incorrect expression \"{expr}\", breakpoint not changed"
|
17
|
+
confirmations:
|
18
|
+
delete_all: "Delete all breakpoints?"
|
19
|
+
messages:
|
20
|
+
breakpoint_deleted: "Deleted breakpoint {pos}"
|
21
|
+
|
22
|
+
catch:
|
23
|
+
added: "Catching exception {exception}."
|
24
|
+
removed: "Catch for exception {exception} removed"
|
25
|
+
errors:
|
26
|
+
off: "Off expected. Got {off}"
|
27
|
+
not_class: "Warning {class} is not known to be a Class"
|
28
|
+
not_found: "Catch for exception {exception} not found"
|
29
|
+
confirmations:
|
30
|
+
delete_all: "Delete all catchpoints? (y or n) "
|
31
|
+
|
32
|
+
condition:
|
33
|
+
errors:
|
34
|
+
no_breakpoints: "No breakpoints have been set"
|
35
|
+
|
36
|
+
continue:
|
37
|
+
errors:
|
38
|
+
unstopped_line: "Line {line} is not a valid stopping point in file"
|
39
|
+
|
40
|
+
display:
|
41
|
+
confirmations:
|
42
|
+
clear_all: "Clear all expressions?"
|
43
|
+
errors:
|
44
|
+
undefined: "Display expression {expr} is not defined"
|
45
|
+
|
46
|
+
edit:
|
47
|
+
errors:
|
48
|
+
state: "We are not in a state that has an associated file"
|
49
|
+
file_line: "Invalid file[:line] number specification: {file_line}"
|
50
|
+
not_readable: "File {file} is not readable."
|
51
|
+
not_exist: "File {file} does not exist."
|
52
|
+
|
53
|
+
frame:
|
54
|
+
errors:
|
55
|
+
too_low: "Can't navigate beyond the oldest frame"
|
56
|
+
too_high: "Can't navigate beyond the newest frame"
|
57
|
+
c_frame: "Can't navigate to c-frame"
|
58
|
+
|
59
|
+
info:
|
60
|
+
errors:
|
61
|
+
undefined_file: "{file} is not a valid source file"
|
62
|
+
|
63
|
+
pry:
|
64
|
+
errors:
|
65
|
+
not_installed: "You need to install pry in order to run this command"
|
66
|
+
|
67
|
+
quit:
|
68
|
+
confirmations:
|
69
|
+
really: "Really quit?"
|
70
|
+
|
71
|
+
save:
|
72
|
+
messages:
|
73
|
+
done: "Saved to '{path}'"
|
74
|
+
|
75
|
+
set:
|
76
|
+
errors:
|
77
|
+
unknown_setting: "Unknown setting :{key}"
|
78
|
+
must_specify_value: "You must specify a value for setting :{key}"
|
79
|
+
on_off: "Expecting 'on', 1, true, 'off', 0, false. Got: {arg}."
|
80
|
+
|
81
|
+
show:
|
82
|
+
errors:
|
83
|
+
unknown_setting: "Unknown setting :{key}"
|
84
|
+
|
85
|
+
source:
|
86
|
+
errors:
|
87
|
+
not_found: "File \"{file}\" not found"
|
88
|
+
|
89
|
+
thread:
|
90
|
+
errors:
|
91
|
+
no_thread: "No such thread"
|
92
|
+
current_thread: "It's the current thread"
|
93
|
+
wrong_action: "Can't {subcmd} thread {arg}"
|
94
|
+
already_running: "Already running"
|
95
|
+
|
96
|
+
toggle:
|
97
|
+
errors:
|
98
|
+
no_breakpoints: "No breakpoints have been set"
|
99
|
+
no_display: "No display expressions have been set"
|
100
|
+
syntax: "\"{toggle}\" must be followed by \"display\", \"breakpoints\" or breakpoint ids"
|
101
|
+
expression: "Expression \"{expr}\" syntactically incorrect; breakpoint remains disabled."
|
102
|
+
messages:
|
103
|
+
toggled: "Breakpoint {bpnum} {endis}abled"
|
104
|
+
|
105
|
+
parse:
|
106
|
+
errors:
|
107
|
+
int:
|
108
|
+
too_low: "\"{cmd}\" argument \"{str}\" needs to be at least {min}"
|
109
|
+
too_high: "\"{cmd}\" argument \"{str}\" needs to be at most {max}"
|
110
|
+
not_number: "\"{cmd}\" argument \"{str}\" needs to be a number"
|
111
|
+
|
112
|
+
variable:
|
113
|
+
errors:
|
114
|
+
not_module: "Should be Class/Module: {object}"
|
115
|
+
cant_get_class_vars: "can't get class variables here.\n"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
break:
|
2
|
+
created: "Created breakpoint {id} at {file}:{line}"
|
3
|
+
|
4
|
+
display:
|
5
|
+
result: "{n}: {exp} = {result}"
|
6
|
+
|
7
|
+
eval:
|
8
|
+
exception: "{text_message}"
|
9
|
+
result: "{result}"
|
10
|
+
|
11
|
+
frame:
|
12
|
+
line: "{mark} #{pos} {call} at {file}:{line}"
|
13
|
+
|
14
|
+
method:
|
15
|
+
methods: "{name}|c"
|
16
|
+
|
17
|
+
restart:
|
18
|
+
success: "Re exec'ing:\n {cmd}"
|
19
|
+
|
20
|
+
thread:
|
21
|
+
context: "{status_flag}{debug_flag}{id} {thread} {file_line}"
|
22
|
+
|
23
|
+
trace:
|
24
|
+
messages:
|
25
|
+
success: "Tracing global variable \"{var}\"."
|
26
|
+
on_change: "traced global variable '{name}' has value '{value}'"
|
27
|
+
undo: "Not tracing global variable \"{var}\" anymore."
|
28
|
+
errors:
|
29
|
+
var_is_not_global: "'{name}' is not a global variable."
|
30
|
+
needs_global_variable: "tracevar needs a global variable name"
|
31
|
+
|
32
|
+
variable:
|
33
|
+
variable: "{key} = {value}"
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
require_relative "../helpers/eval"
|
6
|
+
require_relative "../errors"
|
7
|
+
|
8
|
+
module Byebug
|
9
|
+
#
|
10
|
+
# Processes commands in regular mode.
|
11
|
+
#
|
12
|
+
# You can override this class to create your own command processor that, for
|
13
|
+
# example, whitelists only certain commands to be executed.
|
14
|
+
#
|
15
|
+
# @see PostMortemProcessor for a example
|
16
|
+
#
|
17
|
+
class CommandProcessor
|
18
|
+
include Helpers::EvalHelper
|
19
|
+
|
20
|
+
attr_accessor :prev_line
|
21
|
+
attr_reader :context, :interface
|
22
|
+
|
23
|
+
def initialize(context, interface = LocalInterface.new)
|
24
|
+
@context = context
|
25
|
+
@interface = interface
|
26
|
+
|
27
|
+
@proceed = false
|
28
|
+
@prev_line = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def printer
|
32
|
+
@printer ||= Printers::Plain.new
|
33
|
+
end
|
34
|
+
|
35
|
+
extend Forwardable
|
36
|
+
|
37
|
+
def_delegators :@context, :frame
|
38
|
+
|
39
|
+
def_delegator :printer, :print, :pr
|
40
|
+
def_delegator :printer, :print_collection, :prc
|
41
|
+
def_delegator :printer, :print_variables, :prv
|
42
|
+
|
43
|
+
def_delegators :interface, :errmsg, :puts, :confirm
|
44
|
+
|
45
|
+
def_delegators :Byebug, :commands
|
46
|
+
|
47
|
+
#
|
48
|
+
# Available commands
|
49
|
+
#
|
50
|
+
def command_list
|
51
|
+
@command_list ||= CommandList.new(commands)
|
52
|
+
end
|
53
|
+
|
54
|
+
def at_line
|
55
|
+
process_commands
|
56
|
+
end
|
57
|
+
|
58
|
+
def at_tracing
|
59
|
+
puts "Tracing: #{context.full_location}"
|
60
|
+
|
61
|
+
run_auto_cmds(2)
|
62
|
+
end
|
63
|
+
|
64
|
+
def at_breakpoint(brkpt)
|
65
|
+
number = Byebug.breakpoints.index(brkpt) + 1
|
66
|
+
|
67
|
+
puts "Stopped by breakpoint #{number} at #{frame.file}:#{frame.line}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def at_catchpoint(exception)
|
71
|
+
puts "Catchpoint at #{context.location}: `#{exception}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
def at_return(return_value)
|
75
|
+
puts "Return value is: #{safe_inspect(return_value)}"
|
76
|
+
|
77
|
+
process_commands
|
78
|
+
end
|
79
|
+
|
80
|
+
def at_end
|
81
|
+
process_commands
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Let the execution continue
|
86
|
+
#
|
87
|
+
def proceed!
|
88
|
+
@proceed = true
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Handle byebug commands.
|
93
|
+
#
|
94
|
+
def process_commands
|
95
|
+
before_repl
|
96
|
+
|
97
|
+
repl
|
98
|
+
ensure
|
99
|
+
after_repl
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
|
104
|
+
#
|
105
|
+
# Prompt shown before reading a command.
|
106
|
+
#
|
107
|
+
def prompt
|
108
|
+
"(byebug) "
|
109
|
+
end
|
110
|
+
|
111
|
+
def before_repl
|
112
|
+
@proceed = false
|
113
|
+
@prev_line = nil
|
114
|
+
|
115
|
+
run_auto_cmds(1)
|
116
|
+
interface.autorestore
|
117
|
+
end
|
118
|
+
|
119
|
+
def after_repl
|
120
|
+
interface.autosave
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# Main byebug's REPL
|
125
|
+
#
|
126
|
+
def repl
|
127
|
+
until @proceed
|
128
|
+
cmd = interface.read_command(prompt)
|
129
|
+
return if cmd.nil?
|
130
|
+
|
131
|
+
next if cmd == ""
|
132
|
+
|
133
|
+
run_cmd(cmd)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def auto_cmds_for(run_level)
|
140
|
+
command_list.select { |cmd| cmd.always_run >= run_level }
|
141
|
+
end
|
142
|
+
|
143
|
+
#
|
144
|
+
# Run permanent commands.
|
145
|
+
#
|
146
|
+
def run_auto_cmds(run_level)
|
147
|
+
safely do
|
148
|
+
auto_cmds_for(run_level).each { |cmd| cmd.new(self).execute }
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Executes the received input
|
154
|
+
#
|
155
|
+
# Instantiates a command matching the input and runs it. If a matching
|
156
|
+
# command is not found, it evaluates the unknown input.
|
157
|
+
#
|
158
|
+
def run_cmd(input)
|
159
|
+
safely do
|
160
|
+
command = command_list.match(input)
|
161
|
+
return command.new(self, input).execute if command
|
162
|
+
|
163
|
+
puts safe_inspect(multiple_thread_eval(input))
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def safely
|
168
|
+
yield
|
169
|
+
rescue StandardError => e
|
170
|
+
errmsg(e.message)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "command_processor"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Processes commands when there's not program running
|
8
|
+
#
|
9
|
+
class ControlProcessor < CommandProcessor
|
10
|
+
#
|
11
|
+
# Available commands
|
12
|
+
#
|
13
|
+
def commands
|
14
|
+
super.select(&:allow_in_control)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Prompt shown before reading a command.
|
19
|
+
#
|
20
|
+
def prompt
|
21
|
+
"(byebug:ctrl) "
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "command_processor"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Processes commands in post_mortem mode
|
8
|
+
#
|
9
|
+
class PostMortemProcessor < CommandProcessor
|
10
|
+
def commands
|
11
|
+
super.select(&:allow_in_post_mortem)
|
12
|
+
end
|
13
|
+
|
14
|
+
def prompt
|
15
|
+
"(byebug:post_mortem) "
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "command_processor"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Processes commands from a file
|
8
|
+
#
|
9
|
+
class ScriptProcessor < CommandProcessor
|
10
|
+
#
|
11
|
+
# Available commands
|
12
|
+
#
|
13
|
+
def commands
|
14
|
+
super.select(&:allow_in_control)
|
15
|
+
end
|
16
|
+
|
17
|
+
def repl
|
18
|
+
while (input = interface.read_command(prompt))
|
19
|
+
safely do
|
20
|
+
command = command_list.match(input)
|
21
|
+
raise CommandNotFound.new(input) unless command
|
22
|
+
|
23
|
+
command.new(self, input).execute
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def after_repl
|
29
|
+
super
|
30
|
+
|
31
|
+
interface.close
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Prompt shown before reading a command.
|
36
|
+
#
|
37
|
+
def prompt
|
38
|
+
"(byebug:ctrl) "
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def without_exceptions
|
44
|
+
yield
|
45
|
+
rescue StandardError
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
module Remote
|
7
|
+
#
|
8
|
+
# Client for remote debugging
|
9
|
+
#
|
10
|
+
class Client
|
11
|
+
attr_reader :interface, :socket
|
12
|
+
|
13
|
+
def initialize(interface)
|
14
|
+
@interface = interface
|
15
|
+
@socket = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Connects to the remote byebug
|
20
|
+
#
|
21
|
+
def start(host = "localhost", port = PORT)
|
22
|
+
connect_at(host, port)
|
23
|
+
|
24
|
+
while (line = socket.gets)
|
25
|
+
case line
|
26
|
+
when /^PROMPT (.*)$/
|
27
|
+
input = interface.read_command(Regexp.last_match[1])
|
28
|
+
break unless input
|
29
|
+
|
30
|
+
socket.puts input
|
31
|
+
when /^CONFIRM (.*)$/
|
32
|
+
input = interface.readline(Regexp.last_match[1])
|
33
|
+
break unless input
|
34
|
+
|
35
|
+
socket.puts input
|
36
|
+
else
|
37
|
+
interface.puts line
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
socket.close
|
42
|
+
end
|
43
|
+
|
44
|
+
def started?
|
45
|
+
!socket.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def connect_at(host, port)
|
51
|
+
interface.puts "Connecting to byebug server at #{host}:#{port}..."
|
52
|
+
@socket = TCPSocket.new(host, port)
|
53
|
+
interface.puts "Connected."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|