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,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../subcommands"
|
4
|
+
|
5
|
+
require_relative "../commands/info/breakpoints"
|
6
|
+
require_relative "../commands/info/display"
|
7
|
+
require_relative "../commands/info/file"
|
8
|
+
require_relative "../commands/info/line"
|
9
|
+
require_relative "../commands/info/program"
|
10
|
+
|
11
|
+
module Byebug
|
12
|
+
#
|
13
|
+
# Shows info about different aspects of the debugger.
|
14
|
+
#
|
15
|
+
class InfoCommand < Command
|
16
|
+
include Subcommands
|
17
|
+
|
18
|
+
self.allow_in_control = true
|
19
|
+
self.allow_in_post_mortem = true
|
20
|
+
|
21
|
+
def self.regexp
|
22
|
+
/^\s* i(?:nfo)? (?:\s+ (.+))? \s*$/x
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.description
|
26
|
+
<<-DESCRIPTION
|
27
|
+
info[ subcommand]
|
28
|
+
|
29
|
+
#{short_description}
|
30
|
+
DESCRIPTION
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.short_description
|
34
|
+
"Shows short description and information about the program being debugged"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Interrupting execution of current thread.
|
8
|
+
#
|
9
|
+
class InterruptCommand < Command
|
10
|
+
self.allow_in_control = true
|
11
|
+
|
12
|
+
def self.regexp
|
13
|
+
/^\s*int(?:errupt)?\s*$/
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.description
|
17
|
+
<<-DESCRIPTION
|
18
|
+
int[errupt]
|
19
|
+
|
20
|
+
#{short_description}
|
21
|
+
DESCRIPTION
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.short_description
|
25
|
+
"Interrupts the program"
|
26
|
+
end
|
27
|
+
|
28
|
+
def execute
|
29
|
+
Byebug.start
|
30
|
+
|
31
|
+
Byebug.thread_context(Thread.main).interrupt
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require "irb"
|
5
|
+
require "English"
|
6
|
+
|
7
|
+
module Byebug
|
8
|
+
#
|
9
|
+
# Enter IRB from byebug's prompt
|
10
|
+
#
|
11
|
+
class IrbCommand < Command
|
12
|
+
self.allow_in_post_mortem = true
|
13
|
+
|
14
|
+
def self.regexp
|
15
|
+
/^\s* irb \s*$/x
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.description
|
19
|
+
<<-DESCRIPTION
|
20
|
+
irb
|
21
|
+
|
22
|
+
#{short_description}
|
23
|
+
DESCRIPTION
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.short_description
|
27
|
+
"Starts an IRB session"
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute
|
31
|
+
return errmsg(pr("base.errors.only_local")) unless processor.interface.instance_of?(LocalInterface)
|
32
|
+
|
33
|
+
# @todo IRB tries to parse $ARGV so we must clear it (see #197). Add a
|
34
|
+
# test case for it so we can remove this comment.
|
35
|
+
with_clean_argv { IRB.start }
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def with_clean_argv
|
41
|
+
saved_argv = $ARGV.dup
|
42
|
+
$ARGV.clear
|
43
|
+
begin
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
$ARGV.concat(saved_argv)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Send custom signals to the debugged program.
|
8
|
+
#
|
9
|
+
class KillCommand < Command
|
10
|
+
self.allow_in_control = true
|
11
|
+
|
12
|
+
def self.regexp
|
13
|
+
/^\s* kill \s* (?:\s+(\S+))? \s*$/x
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.description
|
17
|
+
<<-DESCRIPTION
|
18
|
+
kill[ signal]
|
19
|
+
|
20
|
+
#{short_description}
|
21
|
+
|
22
|
+
Equivalent of Process.kill(Process.pid)
|
23
|
+
DESCRIPTION
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.short_description
|
27
|
+
"Sends a signal to the current process"
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute
|
31
|
+
if @match[1]
|
32
|
+
signame = @match[1]
|
33
|
+
|
34
|
+
return errmsg("signal name #{signame} is not a signal I know about\n") unless Signal.list.member?(signame)
|
35
|
+
else
|
36
|
+
return unless confirm("Really kill? (y/n) ")
|
37
|
+
|
38
|
+
signame = "KILL"
|
39
|
+
end
|
40
|
+
|
41
|
+
processor.interface.close if signame == "KILL"
|
42
|
+
Process.kill(signame, Process.pid)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../source_file_formatter"
|
5
|
+
require_relative "../helpers/file"
|
6
|
+
require_relative "../helpers/parse"
|
7
|
+
|
8
|
+
module Byebug
|
9
|
+
#
|
10
|
+
# List parts of the source code.
|
11
|
+
#
|
12
|
+
class ListCommand < Command
|
13
|
+
include Helpers::FileHelper
|
14
|
+
include Helpers::ParseHelper
|
15
|
+
|
16
|
+
self.allow_in_post_mortem = true
|
17
|
+
|
18
|
+
def self.regexp
|
19
|
+
/^\s* l(?:ist)? (?:\s*([-=])|\s+(\S+))? \s*$/x
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.description
|
23
|
+
<<-DESCRIPTION
|
24
|
+
l[ist][[-=]][ nn-mm]
|
25
|
+
|
26
|
+
#{short_description}
|
27
|
+
|
28
|
+
Lists lines forward from current line or from the place where code was
|
29
|
+
last listed. If "list-" is specified, lists backwards instead. If
|
30
|
+
"list=" is specified, lists from current line regardless of where code
|
31
|
+
was last listed. A line range can also be specified to list specific
|
32
|
+
sections of code.
|
33
|
+
DESCRIPTION
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.short_description
|
37
|
+
"Lists lines of source code"
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute
|
41
|
+
msg = "No sourcefile available for #{frame.file}"
|
42
|
+
raise(msg) unless File.exist?(frame.file)
|
43
|
+
|
44
|
+
b, e = range(@match[2])
|
45
|
+
|
46
|
+
display_lines(b, e)
|
47
|
+
|
48
|
+
processor.prev_line = b
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
#
|
54
|
+
# Line range to be printed by `list`.
|
55
|
+
#
|
56
|
+
# If <input> is set, range is parsed from it.
|
57
|
+
#
|
58
|
+
# Otherwise it's automatically chosen.
|
59
|
+
#
|
60
|
+
def range(input)
|
61
|
+
return auto_range(@match[1] || "+") unless input
|
62
|
+
|
63
|
+
b, e = parse_range(input)
|
64
|
+
raise("Invalid line range") unless valid_range?(b, e)
|
65
|
+
|
66
|
+
[b, e]
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid_range?(first, last)
|
70
|
+
first <= last && (1..max_line).cover?(first) && (1..max_line).cover?(last)
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Set line range to be printed by list
|
75
|
+
#
|
76
|
+
# @return first line number to list
|
77
|
+
# @return last line number to list
|
78
|
+
#
|
79
|
+
def auto_range(direction)
|
80
|
+
prev_line = processor.prev_line
|
81
|
+
|
82
|
+
if direction == "=" || prev_line.nil?
|
83
|
+
source_file_formatter.range_around(frame.line)
|
84
|
+
else
|
85
|
+
source_file_formatter.range_from(move(prev_line, size, direction))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def parse_range(input)
|
90
|
+
first, err = get_int(lower_bound(input), "List", 1, max_line)
|
91
|
+
raise(err) unless first
|
92
|
+
|
93
|
+
if upper_bound(input)
|
94
|
+
last, err = get_int(upper_bound(input), "List", 1, max_line)
|
95
|
+
raise(err) unless last
|
96
|
+
|
97
|
+
last = amend_final(last)
|
98
|
+
else
|
99
|
+
first -= (size / 2)
|
100
|
+
end
|
101
|
+
|
102
|
+
[first, last || move(first, size - 1)]
|
103
|
+
end
|
104
|
+
|
105
|
+
def move(line, size, direction = "+")
|
106
|
+
line.send(direction, size)
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Show a range of lines in the current file.
|
111
|
+
#
|
112
|
+
# @param min [Integer] Lower bound
|
113
|
+
# @param max [Integer] Upper bound
|
114
|
+
#
|
115
|
+
def display_lines(min, max)
|
116
|
+
puts "\n[#{min}, #{max}] in #{frame.file}"
|
117
|
+
|
118
|
+
puts source_file_formatter.lines(min, max).join
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# @param range [String] A string with an integer range format
|
123
|
+
#
|
124
|
+
# @return [String] The lower bound of the given range
|
125
|
+
#
|
126
|
+
def lower_bound(range)
|
127
|
+
split_range(range)[0]
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# @param range [String] A string with an integer range format
|
132
|
+
#
|
133
|
+
# @return [String] The upper bound of the given range
|
134
|
+
#
|
135
|
+
def upper_bound(range)
|
136
|
+
split_range(range)[1]
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# @param str [String] A string with an integer range format
|
141
|
+
#
|
142
|
+
# @return [Array] The upper & lower bounds of the given range
|
143
|
+
#
|
144
|
+
def split_range(str)
|
145
|
+
str.split(/[-,]/)
|
146
|
+
end
|
147
|
+
|
148
|
+
extend Forwardable
|
149
|
+
|
150
|
+
def_delegators :source_file_formatter, :amend_final, :size, :max_line
|
151
|
+
|
152
|
+
def source_file_formatter
|
153
|
+
@source_file_formatter ||= SourceFileFormatter.new(
|
154
|
+
frame.file,
|
155
|
+
->(n) { n == frame.line ? "=>" : " " }
|
156
|
+
)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/eval"
|
5
|
+
|
6
|
+
module Byebug
|
7
|
+
#
|
8
|
+
# Show methods of specific classes/modules/objects.
|
9
|
+
#
|
10
|
+
class MethodCommand < Command
|
11
|
+
include Helpers::EvalHelper
|
12
|
+
|
13
|
+
self.allow_in_post_mortem = true
|
14
|
+
|
15
|
+
def self.regexp
|
16
|
+
/^\s* m(?:ethod)? \s+ (i(:?nstance)?\s+)?/x
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.description
|
20
|
+
<<-DESCRIPTION
|
21
|
+
m[ethod] (i[nstance][ <obj>]|<class|module>)
|
22
|
+
|
23
|
+
#{short_description}
|
24
|
+
|
25
|
+
When invoked with "instance", shows instance methods of the object
|
26
|
+
specified as argument or of self no object was specified.
|
27
|
+
|
28
|
+
When invoked only with a class or module, shows class methods of the
|
29
|
+
class or module specified as argument.
|
30
|
+
DESCRIPTION
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.short_description
|
34
|
+
"Shows methods of an object, class or module"
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute
|
38
|
+
obj = warning_eval(@match.post_match)
|
39
|
+
|
40
|
+
result =
|
41
|
+
if @match[1]
|
42
|
+
prc("method.methods", obj.methods.sort) { |item, _| { name: item } }
|
43
|
+
elsif !obj.is_a?(Module)
|
44
|
+
pr("variable.errors.not_module", object: @match.post_match)
|
45
|
+
else
|
46
|
+
prc("method.methods", obj.instance_methods(false).sort) do |item, _|
|
47
|
+
{ name: item }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
puts result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/parse"
|
5
|
+
|
6
|
+
module Byebug
|
7
|
+
#
|
8
|
+
# Implements the next functionality.
|
9
|
+
#
|
10
|
+
# Allows the user the continue execution until the next instruction in the
|
11
|
+
# current frame.
|
12
|
+
#
|
13
|
+
class NextCommand < Command
|
14
|
+
include Helpers::ParseHelper
|
15
|
+
|
16
|
+
def self.regexp
|
17
|
+
/^\s* n(?:ext)? (?:\s+(\S+))? \s*$/x
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.description
|
21
|
+
<<-DESCRIPTION
|
22
|
+
n[ext][ nnn]
|
23
|
+
|
24
|
+
#{short_description}
|
25
|
+
DESCRIPTION
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.short_description
|
29
|
+
"Runs one or more lines of code"
|
30
|
+
end
|
31
|
+
|
32
|
+
def execute
|
33
|
+
steps, err = parse_steps(@match[1], "Next")
|
34
|
+
return errmsg(err) unless steps
|
35
|
+
|
36
|
+
context.step_over(steps, context.frame.pos)
|
37
|
+
processor.proceed!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/eval"
|
5
|
+
|
6
|
+
module Byebug
|
7
|
+
#
|
8
|
+
# Enter Pry from byebug's prompt
|
9
|
+
#
|
10
|
+
class PryCommand < Command
|
11
|
+
self.allow_in_post_mortem = true
|
12
|
+
|
13
|
+
def self.regexp
|
14
|
+
/^\s* pry \s*$/x
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.description
|
18
|
+
<<-DESCRIPTION
|
19
|
+
pry
|
20
|
+
|
21
|
+
#{short_description}
|
22
|
+
DESCRIPTION
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.short_description
|
26
|
+
"Starts a Pry session"
|
27
|
+
end
|
28
|
+
|
29
|
+
def execute
|
30
|
+
return errmsg(pr("base.errors.only_local")) unless processor.interface.instance_of?(LocalInterface)
|
31
|
+
|
32
|
+
begin
|
33
|
+
require "pry"
|
34
|
+
rescue LoadError
|
35
|
+
return errmsg(pr("pry.errors.not_installed"))
|
36
|
+
end
|
37
|
+
|
38
|
+
Pry.start(context.frame._binding)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Exit from byebug.
|
8
|
+
#
|
9
|
+
class QuitCommand < Command
|
10
|
+
self.allow_in_control = true
|
11
|
+
self.allow_in_post_mortem = true
|
12
|
+
|
13
|
+
def self.regexp
|
14
|
+
/^\s* q(?:uit)? \s* (?:(!|\s+unconditionally))? \s*$/x
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.description
|
18
|
+
<<-DESCRIPTION
|
19
|
+
q[uit][!| unconditionally]
|
20
|
+
|
21
|
+
#{short_description}
|
22
|
+
|
23
|
+
Normally we prompt before exiting. However, if the parameter
|
24
|
+
"unconditionally" is given or command is suffixed with "!", we exit
|
25
|
+
without asking further questions.
|
26
|
+
DESCRIPTION
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.short_description
|
30
|
+
"Exits byebug"
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute
|
34
|
+
return unless @match[1] || confirm(pr("quit.confirmations.really"))
|
35
|
+
|
36
|
+
processor.interface.autosave
|
37
|
+
processor.interface.close
|
38
|
+
|
39
|
+
Process.exit!
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/bin"
|
5
|
+
require_relative "../helpers/path"
|
6
|
+
require "shellwords"
|
7
|
+
require "English"
|
8
|
+
require "rbconfig"
|
9
|
+
|
10
|
+
module Byebug
|
11
|
+
#
|
12
|
+
# Restart debugged program from within byebug.
|
13
|
+
#
|
14
|
+
class RestartCommand < Command
|
15
|
+
include Helpers::BinHelper
|
16
|
+
include Helpers::PathHelper
|
17
|
+
|
18
|
+
self.allow_in_control = true
|
19
|
+
self.allow_in_post_mortem = true
|
20
|
+
|
21
|
+
def self.regexp
|
22
|
+
/^\s* restart (?:\s+(?<args>.+))? \s*$/x
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.description
|
26
|
+
<<-DESCRIPTION
|
27
|
+
restart [args]
|
28
|
+
|
29
|
+
#{short_description}
|
30
|
+
|
31
|
+
This is a re-exec - all byebug state is lost. If command arguments are
|
32
|
+
passed those are used.
|
33
|
+
DESCRIPTION
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.short_description
|
37
|
+
"Restarts the debugged program"
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute
|
41
|
+
cmd = [$PROGRAM_NAME]
|
42
|
+
|
43
|
+
cmd = prepend_byebug_bin(cmd)
|
44
|
+
cmd = prepend_ruby_bin(cmd)
|
45
|
+
|
46
|
+
cmd += (@match[:args] ? @match[:args].shellsplit : $ARGV)
|
47
|
+
|
48
|
+
puts pr("restart.success", cmd: cmd.shelljoin)
|
49
|
+
Kernel.exec(*cmd)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def prepend_byebug_bin(cmd)
|
55
|
+
cmd.unshift(bin_file) if Byebug.mode == :standalone
|
56
|
+
cmd
|
57
|
+
end
|
58
|
+
|
59
|
+
def prepend_ruby_bin(cmd)
|
60
|
+
cmd.unshift(RbConfig.ruby) if which("ruby") != which(cmd.first)
|
61
|
+
cmd
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Save current settings to use them in another debug session.
|
8
|
+
#
|
9
|
+
class SaveCommand < Command
|
10
|
+
self.allow_in_control = true
|
11
|
+
self.allow_in_post_mortem = true
|
12
|
+
|
13
|
+
def self.regexp
|
14
|
+
/^\s* sa(?:ve)? (?:\s+(\S+))? \s*$/x
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.description
|
18
|
+
<<-DESCRIPTION
|
19
|
+
save[ FILE]
|
20
|
+
|
21
|
+
#{short_description}
|
22
|
+
|
23
|
+
Byebug state is saved as a script file. This includes breakpoints,
|
24
|
+
catchpoints, display expressions and some settings. If no filename is
|
25
|
+
given, byebug will fabricate one.
|
26
|
+
|
27
|
+
Use the "source" command in another debug session to restore the saved
|
28
|
+
file.
|
29
|
+
DESCRIPTION
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.short_description
|
33
|
+
"Saves current byebug session to a file"
|
34
|
+
end
|
35
|
+
|
36
|
+
def execute
|
37
|
+
file = File.open(@match[1] || Setting[:savefile], "w")
|
38
|
+
|
39
|
+
save_breakpoints(file)
|
40
|
+
save_catchpoints(file)
|
41
|
+
save_displays(file)
|
42
|
+
save_settings(file)
|
43
|
+
|
44
|
+
print pr("save.messages.done", path: file.path)
|
45
|
+
file.close
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def save_breakpoints(file)
|
51
|
+
Byebug.breakpoints.each do |b|
|
52
|
+
file.puts "break #{b.source}:#{b.pos}#{" if #{b.expr}" if b.expr}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def save_catchpoints(file)
|
57
|
+
Byebug.catchpoints.each_key do |c|
|
58
|
+
file.puts "catch #{c}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def save_displays(file)
|
63
|
+
Byebug.displays.each { |d| file.puts "display #{d[1]}" if d[0] }
|
64
|
+
end
|
65
|
+
|
66
|
+
def save_settings(file)
|
67
|
+
%w[autoirb autolist basename].each do |setting|
|
68
|
+
file.puts "set #{setting} #{Setting[setting.to_sym]}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|