byebug 9.0.5 → 11.1.3
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 +5 -5
- data/CHANGELOG.md +399 -264
- data/CONTRIBUTING.md +12 -19
- data/GUIDE.md +40 -26
- data/LICENSE +18 -18
- data/README.md +103 -74
- data/exe/byebug +6 -0
- data/ext/byebug/breakpoint.c +2 -2
- data/ext/byebug/byebug.c +26 -31
- data/ext/byebug/byebug.h +44 -28
- data/ext/byebug/context.c +45 -32
- data/ext/byebug/extconf.rb +7 -5
- data/ext/byebug/locker.c +4 -4
- data/ext/byebug/threads.c +12 -12
- data/lib/byebug/attacher.rb +18 -4
- data/lib/byebug/breakpoint.rb +26 -6
- data/lib/byebug/command.rb +20 -14
- data/lib/byebug/command_list.rb +3 -1
- data/lib/byebug/commands/break.rb +36 -22
- data/lib/byebug/commands/catch.rb +16 -18
- data/lib/byebug/commands/condition.rb +11 -11
- data/lib/byebug/commands/continue.rb +32 -12
- data/lib/byebug/commands/debug.rb +7 -5
- data/lib/byebug/commands/delete.rb +13 -11
- data/lib/byebug/commands/disable/breakpoints.rb +7 -5
- data/lib/byebug/commands/disable/display.rb +7 -5
- data/lib/byebug/commands/disable.rb +8 -6
- data/lib/byebug/commands/display.rb +11 -9
- data/lib/byebug/commands/down.rb +10 -8
- data/lib/byebug/commands/edit.rb +11 -8
- data/lib/byebug/commands/enable/breakpoints.rb +7 -5
- data/lib/byebug/commands/enable/display.rb +7 -5
- data/lib/byebug/commands/enable.rb +8 -6
- data/lib/byebug/commands/finish.rb +9 -7
- data/lib/byebug/commands/frame.rb +11 -9
- data/lib/byebug/commands/help.rb +7 -5
- data/lib/byebug/commands/history.rb +7 -5
- data/lib/byebug/commands/info/breakpoints.rb +18 -14
- data/lib/byebug/commands/info/display.rb +16 -9
- data/lib/byebug/commands/info/file.rb +13 -14
- data/lib/byebug/commands/info/line.rb +5 -3
- data/lib/byebug/commands/info/program.rb +8 -6
- data/lib/byebug/commands/info.rb +11 -9
- data/lib/byebug/commands/interrupt.rb +8 -4
- data/lib/byebug/commands/irb.rb +13 -12
- data/lib/byebug/commands/kill.rb +11 -11
- data/lib/byebug/commands/list.rb +41 -46
- data/lib/byebug/commands/method.rb +10 -8
- data/lib/byebug/commands/next.rb +8 -6
- data/lib/byebug/commands/pry.rb +10 -10
- data/lib/byebug/commands/quit.rb +10 -8
- data/lib/byebug/commands/restart.rb +30 -11
- data/lib/byebug/commands/save.rb +10 -8
- data/lib/byebug/commands/set.rb +13 -11
- data/lib/byebug/commands/show.rb +7 -5
- data/lib/byebug/commands/skip.rb +85 -0
- data/lib/byebug/commands/source.rb +7 -7
- data/lib/byebug/commands/step.rb +8 -6
- data/lib/byebug/commands/thread/current.rb +6 -4
- data/lib/byebug/commands/thread/list.rb +7 -5
- data/lib/byebug/commands/thread/resume.rb +7 -7
- data/lib/byebug/commands/thread/stop.rb +6 -4
- data/lib/byebug/commands/thread/switch.rb +6 -4
- data/lib/byebug/commands/thread.rb +11 -9
- data/lib/byebug/commands/tracevar.rb +10 -11
- data/lib/byebug/commands/undisplay.rb +12 -11
- data/lib/byebug/commands/untracevar.rb +8 -6
- data/lib/byebug/commands/up.rb +10 -8
- data/lib/byebug/commands/var/all.rb +7 -5
- data/lib/byebug/commands/var/args.rb +6 -4
- data/lib/byebug/commands/var/const.rb +9 -9
- data/lib/byebug/commands/var/global.rb +5 -3
- data/lib/byebug/commands/var/instance.rb +6 -4
- data/lib/byebug/commands/var/local.rb +6 -4
- data/lib/byebug/commands/var.rb +12 -10
- data/lib/byebug/commands/where.rb +9 -7
- data/lib/byebug/commands.rb +40 -37
- data/lib/byebug/context.rb +7 -5
- data/lib/byebug/core.rb +26 -25
- data/lib/byebug/errors.rb +4 -2
- data/lib/byebug/frame.rb +19 -22
- data/lib/byebug/helpers/bin.rb +47 -0
- data/lib/byebug/helpers/eval.rb +15 -13
- data/lib/byebug/helpers/file.rb +6 -4
- data/lib/byebug/helpers/frame.rb +7 -5
- data/lib/byebug/helpers/parse.rb +5 -5
- data/lib/byebug/helpers/path.rb +9 -11
- data/lib/byebug/helpers/reflection.rb +2 -0
- data/lib/byebug/helpers/string.rb +11 -2
- data/lib/byebug/helpers/thread.rb +10 -8
- data/lib/byebug/helpers/toggle.rb +28 -27
- data/lib/byebug/helpers/var.rb +9 -7
- data/lib/byebug/history.rb +20 -11
- data/lib/byebug/interface.rb +13 -11
- data/lib/byebug/interfaces/local_interface.rb +25 -7
- data/lib/byebug/interfaces/remote_interface.rb +21 -9
- data/lib/byebug/interfaces/script_interface.rb +4 -1
- data/lib/byebug/interfaces/test_interface.rb +5 -3
- data/lib/byebug/option_setter.rb +14 -12
- data/lib/byebug/printers/base.rb +10 -10
- data/lib/byebug/printers/plain.rb +9 -8
- data/lib/byebug/printers/texts/base.yml +7 -3
- data/lib/byebug/printers/texts/plain.yml +1 -1
- data/lib/byebug/processors/command_processor.rb +11 -12
- data/lib/byebug/processors/control_processor.rb +4 -6
- data/lib/byebug/processors/post_mortem_processor.rb +4 -2
- data/lib/byebug/processors/script_processor.rb +7 -3
- data/lib/byebug/remote/client.rb +57 -0
- data/lib/byebug/remote/server.rb +47 -0
- data/lib/byebug/remote.rb +46 -66
- data/lib/byebug/runner.rb +43 -49
- data/lib/byebug/setting.rb +11 -5
- data/lib/byebug/settings/autoirb.rb +7 -5
- data/lib/byebug/settings/autolist.rb +7 -5
- data/lib/byebug/settings/autopry.rb +7 -5
- data/lib/byebug/settings/autosave.rb +4 -2
- data/lib/byebug/settings/basename.rb +4 -2
- data/lib/byebug/settings/callstyle.rb +4 -3
- data/lib/byebug/settings/fullpath.rb +4 -2
- data/lib/byebug/settings/histfile.rb +5 -3
- data/lib/byebug/settings/histsize.rb +4 -2
- data/lib/byebug/settings/linetrace.rb +6 -4
- data/lib/byebug/settings/listsize.rb +4 -2
- data/lib/byebug/settings/post_mortem.rb +6 -4
- data/lib/byebug/settings/savefile.rb +4 -2
- data/lib/byebug/settings/stack_on_error.rb +4 -2
- data/lib/byebug/settings/width.rb +3 -1
- data/lib/byebug/source_file_formatter.rb +71 -0
- data/lib/byebug/subcommands.rb +6 -4
- data/lib/byebug/version.rb +2 -1
- data/lib/byebug.rb +3 -1
- metadata +22 -20
- data/bin/byebug +0 -7
data/ext/byebug/threads.c
CHANGED
@@ -14,12 +14,12 @@ t_tbl_mark_keyvalue(st_data_t key, st_data_t value, st_data_t tbl)
|
|
14
14
|
{
|
15
15
|
UNUSED(tbl);
|
16
16
|
|
17
|
-
rb_gc_mark((VALUE)
|
17
|
+
rb_gc_mark((VALUE)key);
|
18
18
|
|
19
19
|
if (!value)
|
20
20
|
return ST_CONTINUE;
|
21
21
|
|
22
|
-
rb_gc_mark((VALUE)
|
22
|
+
rb_gc_mark((VALUE)value);
|
23
23
|
|
24
24
|
return ST_CONTINUE;
|
25
25
|
}
|
@@ -27,16 +27,16 @@ t_tbl_mark_keyvalue(st_data_t key, st_data_t value, st_data_t tbl)
|
|
27
27
|
static void
|
28
28
|
t_tbl_mark(void *data)
|
29
29
|
{
|
30
|
-
threads_table_t *t_tbl = (threads_table_t *)
|
30
|
+
threads_table_t *t_tbl = (threads_table_t *)data;
|
31
31
|
st_table *tbl = t_tbl->tbl;
|
32
32
|
|
33
|
-
st_foreach(tbl, t_tbl_mark_keyvalue, (st_data_t)
|
33
|
+
st_foreach(tbl, t_tbl_mark_keyvalue, (st_data_t)tbl);
|
34
34
|
}
|
35
35
|
|
36
36
|
static void
|
37
37
|
t_tbl_free(void *data)
|
38
38
|
{
|
39
|
-
threads_table_t *t_tbl = (threads_table_t *)
|
39
|
+
threads_table_t *t_tbl = (threads_table_t *)data;
|
40
40
|
|
41
41
|
st_free_table(t_tbl->tbl);
|
42
42
|
xfree(t_tbl);
|
@@ -70,7 +70,7 @@ check_thread_i(st_data_t key, st_data_t value, st_data_t data)
|
|
70
70
|
if (!value)
|
71
71
|
return ST_DELETE;
|
72
72
|
|
73
|
-
if (!is_living_thread((VALUE)
|
73
|
+
if (!is_living_thread((VALUE)key))
|
74
74
|
return ST_DELETE;
|
75
75
|
|
76
76
|
return ST_CONTINUE;
|
@@ -110,7 +110,7 @@ cleanup_dead_threads(void)
|
|
110
110
|
* Looks up a context in the threads table. If not present, it creates it.
|
111
111
|
*/
|
112
112
|
void
|
113
|
-
thread_context_lookup(VALUE thread, VALUE *
|
113
|
+
thread_context_lookup(VALUE thread, VALUE *context)
|
114
114
|
{
|
115
115
|
threads_table_t *t_tbl;
|
116
116
|
|
@@ -118,7 +118,7 @@ thread_context_lookup(VALUE thread, VALUE * context)
|
|
118
118
|
|
119
119
|
if (!st_lookup(t_tbl->tbl, thread, context) || !*context)
|
120
120
|
{
|
121
|
-
*context =
|
121
|
+
*context = byebug_context_create(thread);
|
122
122
|
st_insert(t_tbl->tbl, thread, *context);
|
123
123
|
}
|
124
124
|
}
|
@@ -129,12 +129,12 @@ thread_context_lookup(VALUE thread, VALUE * context)
|
|
129
129
|
* Thanks to this, all threads are "frozen" while the user is typing commands.
|
130
130
|
*/
|
131
131
|
void
|
132
|
-
acquire_lock(debug_context_t *
|
132
|
+
acquire_lock(debug_context_t *dc)
|
133
133
|
{
|
134
134
|
while ((!NIL_P(locker) && locker != rb_thread_current())
|
135
135
|
|| CTX_FL_TEST(dc, CTX_FL_SUSPEND))
|
136
136
|
{
|
137
|
-
|
137
|
+
byebug_add_to_locked(rb_thread_current());
|
138
138
|
rb_thread_stop();
|
139
139
|
|
140
140
|
if (CTX_FL_TEST(dc, CTX_FL_SUSPEND))
|
@@ -159,10 +159,10 @@ release_lock(void)
|
|
159
159
|
locker = Qnil;
|
160
160
|
|
161
161
|
if (NIL_P(next_thread))
|
162
|
-
thread =
|
162
|
+
thread = byebug_pop_from_locked();
|
163
163
|
else
|
164
164
|
{
|
165
|
-
|
165
|
+
byebug_remove_from_locked(next_thread);
|
166
166
|
thread = next_thread;
|
167
167
|
next_thread = Qnil;
|
168
168
|
}
|
data/lib/byebug/attacher.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#
|
2
4
|
# Main Container for all of Byebug's code
|
3
5
|
#
|
4
6
|
module Byebug
|
5
7
|
#
|
6
|
-
#
|
7
|
-
# events occur. Before entering byebug the init script is read.
|
8
|
+
# Starts byebug, and stops at the first line of user's code.
|
8
9
|
#
|
9
10
|
def self.attach
|
10
|
-
require 'byebug/core'
|
11
|
-
|
12
11
|
unless started?
|
13
12
|
self.mode = :attached
|
14
13
|
|
@@ -18,6 +17,13 @@ module Byebug
|
|
18
17
|
|
19
18
|
current_context.step_out(3, true)
|
20
19
|
end
|
20
|
+
|
21
|
+
def self.spawn(host = "localhost", port = nil)
|
22
|
+
require_relative "core"
|
23
|
+
|
24
|
+
self.wait_connection = true
|
25
|
+
start_server(host, port || PORT)
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
23
29
|
#
|
@@ -27,6 +33,14 @@ end
|
|
27
33
|
#
|
28
34
|
module Kernel
|
29
35
|
def byebug
|
36
|
+
require_relative "core"
|
37
|
+
|
38
|
+
Byebug.attach unless Byebug.mode == :off
|
39
|
+
end
|
40
|
+
|
41
|
+
def remote_byebug(host = "localhost", port = nil)
|
42
|
+
Byebug.spawn(host, port)
|
43
|
+
|
30
44
|
Byebug.attach
|
31
45
|
end
|
32
46
|
|
data/lib/byebug/breakpoint.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Byebug
|
2
4
|
#
|
3
5
|
# Implements breakpoints
|
@@ -49,12 +51,30 @@ module Byebug
|
|
49
51
|
#
|
50
52
|
def self.potential_lines(filename)
|
51
53
|
name = "#{Time.new.to_i}_#{rand(2**31)}"
|
52
|
-
lines = {}
|
53
54
|
iseq = RubyVM::InstructionSequence.compile(File.read(filename), name)
|
54
55
|
|
56
|
+
if iseq.respond_to?(:each_child)
|
57
|
+
potential_lines_with_trace_points(iseq, {})
|
58
|
+
else
|
59
|
+
potential_lines_without_trace_points(iseq, {})
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.potential_lines_with_trace_points(iseq, lines)
|
64
|
+
iseq.trace_points.each { |(line, _)| lines[line] = true }
|
65
|
+
iseq.each_child do |child|
|
66
|
+
potential_lines_with_trace_points(child, lines)
|
67
|
+
end
|
68
|
+
|
69
|
+
lines.keys.sort
|
70
|
+
end
|
71
|
+
|
72
|
+
private_class_method :potential_lines_with_trace_points
|
73
|
+
|
74
|
+
def self.potential_lines_without_trace_points(iseq, lines)
|
55
75
|
iseq.disasm.each_line do |line|
|
56
76
|
res = /^\d+ (?<insn>\w+)\s+.+\(\s*(?<lineno>\d+)\)$/.match(line)
|
57
|
-
next unless res && res[:insn] ==
|
77
|
+
next unless res && res[:insn] == "trace"
|
58
78
|
|
59
79
|
lines[res[:lineno].to_i] = true
|
60
80
|
end
|
@@ -62,6 +82,8 @@ module Byebug
|
|
62
82
|
lines.keys
|
63
83
|
end
|
64
84
|
|
85
|
+
private_class_method :potential_lines_without_trace_points
|
86
|
+
|
65
87
|
#
|
66
88
|
# Returns true if a breakpoint could be set in line number +lineno+ in file
|
67
89
|
# name +filename.
|
@@ -81,10 +103,8 @@ module Byebug
|
|
81
103
|
# Prints all information associated to the breakpoint
|
82
104
|
#
|
83
105
|
def inspect
|
84
|
-
meths = %w
|
85
|
-
values = meths.map
|
86
|
-
"#{field}: #{send(field)}"
|
87
|
-
end.join(', ')
|
106
|
+
meths = %w[id pos source expr hit_condition hit_count hit_value enabled?]
|
107
|
+
values = meths.map { |field| "#{field}: #{send(field)}" }.join(", ")
|
88
108
|
"#<Byebug::Breakpoint #{values}>"
|
89
109
|
end
|
90
110
|
end
|
data/lib/byebug/command.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require_relative "helpers/string"
|
3
5
|
|
4
6
|
module Byebug
|
5
7
|
#
|
@@ -16,11 +18,11 @@ module Byebug
|
|
16
18
|
# end
|
17
19
|
#
|
18
20
|
# def self.description
|
19
|
-
#
|
21
|
+
# "Custom long desc"
|
20
22
|
# end
|
21
23
|
#
|
22
24
|
# def.short_description
|
23
|
-
#
|
25
|
+
# "Custom short desc"
|
24
26
|
# end
|
25
27
|
#
|
26
28
|
# def execute
|
@@ -47,16 +49,16 @@ module Byebug
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def arguments
|
50
|
-
@match[0].split(
|
52
|
+
@match[0].split(" ").drop(1).join(" ")
|
51
53
|
end
|
52
54
|
|
53
|
-
def_delegators
|
55
|
+
def_delegators "self.class", :help, :match
|
54
56
|
|
55
|
-
def_delegator
|
56
|
-
def_delegator
|
57
|
-
def_delegator
|
57
|
+
def_delegator "processor.printer", :print, :pr
|
58
|
+
def_delegator "processor.printer", :print_collection, :prc
|
59
|
+
def_delegator "processor.printer", :print_variables, :prv
|
58
60
|
|
59
|
-
def_delegators
|
61
|
+
def_delegators "processor.interface", :errmsg, :puts, :print, :confirm
|
60
62
|
|
61
63
|
class << self
|
62
64
|
include Helpers::StringHelper
|
@@ -77,14 +79,18 @@ module Byebug
|
|
77
79
|
#
|
78
80
|
def to_s
|
79
81
|
name
|
80
|
-
.split(
|
81
|
-
.map { |n| n.gsub(/Command$/,
|
82
|
+
.split("::")
|
83
|
+
.map { |n| n.gsub(/Command$/, "").downcase if /Command$/.match?(n) }
|
82
84
|
.compact
|
83
|
-
.join(
|
85
|
+
.join(" ")
|
84
86
|
end
|
85
87
|
|
86
88
|
def columnize(width)
|
87
|
-
format(
|
89
|
+
format(
|
90
|
+
" %-<name>#{width}s -- %<description>s\n",
|
91
|
+
name: to_s,
|
92
|
+
description: short_description
|
93
|
+
)
|
88
94
|
end
|
89
95
|
|
90
96
|
#
|
data/lib/byebug/command_list.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/eval"
|
5
|
+
require_relative "../helpers/file"
|
6
|
+
require_relative "../helpers/parse"
|
7
|
+
require_relative "../source_file_formatter"
|
5
8
|
|
6
9
|
module Byebug
|
7
10
|
#
|
@@ -19,32 +22,30 @@ module Byebug
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def self.description
|
22
|
-
<<-
|
23
|
-
b[reak] [file
|
24
|
-
b[reak] [module
|
25
|
+
<<-DESCRIPTION
|
26
|
+
b[reak] [<file>:]<line> [if <expr>]
|
27
|
+
b[reak] [<module>::...]<class>(.|#)<method> [if <expr>]
|
25
28
|
|
26
29
|
They can be specified by line or method and an expression can be added
|
27
30
|
for conditionally enabled breakpoints.
|
28
31
|
|
29
32
|
#{short_description}
|
30
|
-
|
33
|
+
DESCRIPTION
|
31
34
|
end
|
32
35
|
|
33
36
|
def self.short_description
|
34
|
-
|
37
|
+
"Sets breakpoints in the source code"
|
35
38
|
end
|
36
39
|
|
37
40
|
def execute
|
38
41
|
return puts(help) unless @match[1]
|
39
42
|
|
40
43
|
b = line_breakpoint(@match[1]) || method_breakpoint(@match[1])
|
41
|
-
return errmsg(pr(
|
44
|
+
return errmsg(pr("break.errors.location")) unless b
|
42
45
|
|
43
|
-
if syntax_valid?(@match[2])
|
44
|
-
return puts(pr('break.created', id: b.id, file: b.source, line: b.pos))
|
45
|
-
end
|
46
|
+
return puts(pr("break.created", id: b.id, file: b.source, line: b.pos)) if syntax_valid?(@match[2])
|
46
47
|
|
47
|
-
errmsg(pr(
|
48
|
+
errmsg(pr("break.errors.expression", expr: @match[2]))
|
48
49
|
b.enabled = false
|
49
50
|
end
|
50
51
|
|
@@ -73,26 +74,39 @@ module Byebug
|
|
73
74
|
def target_object(str)
|
74
75
|
k = error_eval(str)
|
75
76
|
|
76
|
-
k
|
77
|
-
rescue
|
78
|
-
errmsg(
|
77
|
+
k&.is_a?(Module) ? k.name : str
|
78
|
+
rescue StandardError
|
79
|
+
errmsg("Warning: breakpoint source is not yet defined")
|
79
80
|
str
|
80
81
|
end
|
81
82
|
|
82
83
|
def add_line_breakpoint(file, line)
|
83
|
-
raise(pr(
|
84
|
+
raise(pr("break.errors.source", file: file)) unless File.exist?(file)
|
84
85
|
|
85
86
|
fullpath = File.realpath(file)
|
86
87
|
|
87
|
-
if line > n_lines(file)
|
88
|
-
raise(pr('break.errors.far_line', lines: n_lines(file), file: fullpath))
|
89
|
-
end
|
88
|
+
raise(pr("break.errors.far_line", lines: n_lines(file), file: fullpath)) if line > n_lines(file)
|
90
89
|
|
91
90
|
unless Breakpoint.potential_line?(fullpath, line)
|
92
|
-
|
91
|
+
msg = pr(
|
92
|
+
"break.errors.line",
|
93
|
+
file: fullpath,
|
94
|
+
line: line,
|
95
|
+
valid_breakpoints: valid_breakpoints_for(fullpath, line)
|
96
|
+
)
|
97
|
+
|
98
|
+
raise(msg)
|
93
99
|
end
|
94
100
|
|
95
101
|
Breakpoint.add(fullpath, line, @match[2])
|
96
102
|
end
|
103
|
+
|
104
|
+
def valid_breakpoints_for(path, line)
|
105
|
+
potential_lines = Breakpoint.potential_lines(path)
|
106
|
+
annotator = ->(n) { potential_lines.include?(n) ? "[B]" : " " }
|
107
|
+
source_file_formatter = SourceFileFormatter.new(path, annotator)
|
108
|
+
|
109
|
+
source_file_formatter.lines_around(line).join.chomp
|
110
|
+
end
|
97
111
|
end
|
98
112
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/eval"
|
3
5
|
|
4
6
|
module Byebug
|
5
7
|
#
|
@@ -17,7 +19,7 @@ module Byebug
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def self.description
|
20
|
-
<<-
|
22
|
+
<<-DESCRIPTION
|
21
23
|
cat[ch][ (off|<exception>[ off])]
|
22
24
|
|
23
25
|
#{short_description}
|
@@ -26,19 +28,19 @@ module Byebug
|
|
26
28
|
catch off -- deletes all catchpoints
|
27
29
|
catch <exception> -- enables handling <exception>
|
28
30
|
catch <exception> off -- disables handling <exception>
|
29
|
-
|
31
|
+
DESCRIPTION
|
30
32
|
end
|
31
33
|
|
32
34
|
def self.short_description
|
33
|
-
|
35
|
+
"Handles exception catchpoints"
|
34
36
|
end
|
35
37
|
|
36
38
|
def execute
|
37
39
|
return info unless @match[1]
|
38
40
|
|
39
|
-
return
|
41
|
+
return @match[1] == "off" ? clear : add(@match[1]) unless @match[2]
|
40
42
|
|
41
|
-
return errmsg pr(
|
43
|
+
return errmsg pr("catch.errors.off", off: cmd) unless @match[2] == "off"
|
42
44
|
|
43
45
|
remove(@match[1])
|
44
46
|
end
|
@@ -46,34 +48,30 @@ module Byebug
|
|
46
48
|
private
|
47
49
|
|
48
50
|
def remove(exception)
|
49
|
-
unless Byebug.catchpoints.member?(exception)
|
50
|
-
return errmsg pr('catch.errors.not_found', exception: exception)
|
51
|
-
end
|
51
|
+
return errmsg pr("catch.errors.not_found", exception: exception) unless Byebug.catchpoints.member?(exception)
|
52
52
|
|
53
|
-
puts pr(
|
53
|
+
puts pr("catch.removed", exception: exception)
|
54
54
|
Byebug.catchpoints.delete(exception)
|
55
55
|
end
|
56
56
|
|
57
57
|
def add(exception)
|
58
|
-
if warning_eval(exception.is_a?(Class).to_s)
|
59
|
-
errmsg pr('catch.errors.not_class', class: exception)
|
60
|
-
end
|
58
|
+
errmsg pr("catch.errors.not_class", class: exception) if warning_eval(exception.is_a?(Class).to_s)
|
61
59
|
|
62
|
-
puts pr(
|
60
|
+
puts pr("catch.added", exception: exception)
|
63
61
|
Byebug.add_catchpoint(exception)
|
64
62
|
end
|
65
63
|
|
66
64
|
def clear
|
67
|
-
Byebug.catchpoints.clear if confirm(pr(
|
65
|
+
Byebug.catchpoints.clear if confirm(pr("catch.confirmations.delete_all"))
|
68
66
|
end
|
69
67
|
|
70
68
|
def info
|
71
69
|
if Byebug.catchpoints && !Byebug.catchpoints.empty?
|
72
|
-
Byebug.catchpoints.
|
70
|
+
Byebug.catchpoints.each_key do |exception|
|
73
71
|
puts("#{exception}: #{exception.is_a?(Class)}")
|
74
72
|
end
|
75
73
|
else
|
76
|
-
puts
|
74
|
+
puts "No exceptions set to be caught."
|
77
75
|
end
|
78
76
|
end
|
79
77
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/parse"
|
3
5
|
|
4
6
|
module Byebug
|
5
7
|
#
|
@@ -17,7 +19,7 @@ module Byebug
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def self.description
|
20
|
-
<<-
|
22
|
+
<<-DESCRIPTION
|
21
23
|
cond[ition] <n>[ expr]
|
22
24
|
|
23
25
|
#{short_description}
|
@@ -26,28 +28,26 @@ module Byebug
|
|
26
28
|
an integer and <expr> is an expression to be evaluated whenever
|
27
29
|
breakpoint <n> is reached. If no expression is specified, the condition
|
28
30
|
is removed.
|
29
|
-
|
31
|
+
DESCRIPTION
|
30
32
|
end
|
31
33
|
|
32
34
|
def self.short_description
|
33
|
-
|
35
|
+
"Sets conditions on breakpoints"
|
34
36
|
end
|
35
37
|
|
36
38
|
def execute
|
37
39
|
return puts(help) unless @match[1]
|
38
40
|
|
39
41
|
breakpoints = Byebug.breakpoints.sort_by(&:id)
|
40
|
-
return errmsg(pr(
|
42
|
+
return errmsg(pr("condition.errors.no_breakpoints")) if breakpoints.empty?
|
41
43
|
|
42
|
-
pos, err = get_int(@match[1],
|
44
|
+
pos, err = get_int(@match[1], "Condition", 1)
|
43
45
|
return errmsg(err) if err
|
44
46
|
|
45
47
|
breakpoint = breakpoints.find { |b| b.id == pos }
|
46
|
-
return errmsg(pr(
|
48
|
+
return errmsg(pr("break.errors.no_breakpoint")) unless breakpoint
|
47
49
|
|
48
|
-
unless syntax_valid?(@match[2])
|
49
|
-
return errmsg(pr('break.errors.not_changed', expr: @match[2]))
|
50
|
-
end
|
50
|
+
return errmsg(pr("break.errors.not_changed", expr: @match[2])) unless syntax_valid?(@match[2])
|
51
51
|
|
52
52
|
breakpoint.expr = @match[2]
|
53
53
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/parse"
|
3
5
|
|
4
6
|
module Byebug
|
5
7
|
#
|
@@ -12,37 +14,55 @@ module Byebug
|
|
12
14
|
include Helpers::ParseHelper
|
13
15
|
|
14
16
|
def self.regexp
|
15
|
-
/^\s* c(?:ont(?:inue)?)? (
|
17
|
+
/^\s* c(?:ont(?:inue)?)? (?:(!|\s+unconditionally|\s+\S+))? \s*$/x
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.description
|
19
|
-
<<-
|
21
|
+
<<-DESCRIPTION
|
20
22
|
c[ont[inue]][ <line_number>]
|
21
23
|
|
22
24
|
#{short_description}
|
23
|
-
|
25
|
+
|
26
|
+
Normally the program stops at the next breakpoint. However, if the
|
27
|
+
parameter "unconditionally" is given or the command is suffixed with
|
28
|
+
"!", the program will run until the end regardless of any enabled
|
29
|
+
breakpoints.
|
30
|
+
DESCRIPTION
|
24
31
|
end
|
25
32
|
|
26
33
|
def self.short_description
|
27
|
-
|
34
|
+
"Runs until program ends, hits a breakpoint or reaches a line"
|
28
35
|
end
|
29
36
|
|
30
37
|
def execute
|
31
|
-
if
|
32
|
-
num, err = get_int(
|
38
|
+
if until_line?
|
39
|
+
num, err = get_int(modifier, "Continue", 0, nil)
|
33
40
|
return errmsg(err) unless num
|
34
41
|
|
35
42
|
filename = File.expand_path(frame.file)
|
36
|
-
unless Breakpoint.potential_line?(filename, num)
|
37
|
-
return errmsg(pr('continue.errors.unstopped_line', line: num))
|
38
|
-
end
|
43
|
+
return errmsg(pr("continue.errors.unstopped_line", line: num)) unless Breakpoint.potential_line?(filename, num)
|
39
44
|
|
40
45
|
Breakpoint.add(filename, num)
|
41
46
|
end
|
42
47
|
|
43
48
|
processor.proceed!
|
44
49
|
|
45
|
-
Byebug.
|
50
|
+
Byebug.mode = :off if unconditionally?
|
51
|
+
Byebug.stop if unconditionally? || Byebug.stoppable?
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def until_line?
|
57
|
+
@match[1] && !["!", "unconditionally"].include?(modifier)
|
58
|
+
end
|
59
|
+
|
60
|
+
def unconditionally?
|
61
|
+
@match[1] && ["!", "unconditionally"].include?(modifier)
|
62
|
+
end
|
63
|
+
|
64
|
+
def modifier
|
65
|
+
@match[1].lstrip
|
46
66
|
end
|
47
67
|
end
|
48
68
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/eval"
|
3
5
|
|
4
6
|
module Byebug
|
5
7
|
#
|
@@ -13,18 +15,18 @@ module Byebug
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def self.description
|
16
|
-
<<-
|
18
|
+
<<-DESCRIPTION
|
17
19
|
debug <expression>
|
18
20
|
|
19
21
|
#{short_description}
|
20
22
|
|
21
23
|
Allows, for example, setting breakpoints on expressions evaluated from
|
22
24
|
the debugger's prompt.
|
23
|
-
|
25
|
+
DESCRIPTION
|
24
26
|
end
|
25
27
|
|
26
28
|
def self.short_description
|
27
|
-
|
29
|
+
"Spawns a subdebugger"
|
28
30
|
end
|
29
31
|
|
30
32
|
def execute
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../command"
|
4
|
+
require_relative "../helpers/parse"
|
3
5
|
|
4
6
|
module Byebug
|
5
7
|
#
|
@@ -16,36 +18,36 @@ module Byebug
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.description
|
19
|
-
<<-
|
21
|
+
<<-DESCRIPTION
|
20
22
|
del[ete][ nnn...]
|
21
23
|
|
22
24
|
#{short_description}
|
23
25
|
|
24
26
|
Without and argument, deletes all breakpoints. With integer arguments,
|
25
27
|
it deletes specific breakpoints.
|
26
|
-
|
28
|
+
DESCRIPTION
|
27
29
|
end
|
28
30
|
|
29
31
|
def self.short_description
|
30
|
-
|
32
|
+
"Deletes breakpoints"
|
31
33
|
end
|
32
34
|
|
33
35
|
def execute
|
34
36
|
unless @match[1]
|
35
|
-
if confirm(pr(
|
36
|
-
Byebug.breakpoints.clear
|
37
|
-
end
|
37
|
+
Byebug.breakpoints.clear if confirm(pr("break.confirmations.delete_all"))
|
38
38
|
|
39
39
|
return
|
40
40
|
end
|
41
41
|
|
42
42
|
@match[1].split(/ +/).each do |number|
|
43
|
-
pos, err = get_int(number,
|
43
|
+
pos, err = get_int(number, "Delete", 1)
|
44
44
|
|
45
45
|
return errmsg(err) unless pos
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
if Breakpoint.remove(pos)
|
48
|
+
puts(pr("break.messages.breakpoint_deleted", pos: pos))
|
49
|
+
else
|
50
|
+
errmsg(pr("break.errors.no_breakpoint_delete", pos: pos))
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|