byebug 11.0.1
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 +897 -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 +517 -0
- data/ext/byebug/byebug.c +905 -0
- data/ext/byebug/byebug.h +143 -0
- data/ext/byebug/context.c +673 -0
- data/ext/byebug/extconf.rb +12 -0
- data/ext/byebug/locker.c +96 -0
- data/ext/byebug/threads.c +230 -0
- data/lib/byebug.rb +3 -0
- data/lib/byebug/attacher.rb +48 -0
- data/lib/byebug/breakpoint.rb +111 -0
- data/lib/byebug/command.rb +111 -0
- data/lib/byebug/command_list.rb +34 -0
- data/lib/byebug/commands.rb +40 -0
- data/lib/byebug/commands/break.rb +112 -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.rb +33 -0
- data/lib/byebug/commands/disable/breakpoints.rb +42 -0
- data/lib/byebug/commands/disable/display.rb +43 -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.rb +33 -0
- data/lib/byebug/commands/enable/breakpoints.rb +42 -0
- data/lib/byebug/commands/enable/display.rb +43 -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.rb +37 -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/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.rb +34 -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/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.rb +37 -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/where.rb +53 -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 +126 -0
- data/lib/byebug/helpers/file.rb +63 -0
- data/lib/byebug/helpers/frame.rb +75 -0
- data/lib/byebug/helpers/parse.rb +75 -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 +54 -0
- data/lib/byebug/history.rb +130 -0
- data/lib/byebug/interface.rb +146 -0
- data/lib/byebug/interfaces/local_interface.rb +44 -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.rb +85 -0
- data/lib/byebug/remote/client.rb +57 -0
- data/lib/byebug/remote/server.rb +47 -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
- metadata +199 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require "byebug/helpers/string"
|
5
|
+
|
6
|
+
module Byebug
|
7
|
+
#
|
8
|
+
# Parent class of all byebug commands.
|
9
|
+
#
|
10
|
+
# Subclass it and name the subclass ending with the word Command to implement
|
11
|
+
# your own custom command.
|
12
|
+
#
|
13
|
+
# @example Define a custom command
|
14
|
+
#
|
15
|
+
# class MyCustomCommand < Command
|
16
|
+
# def self.regexp
|
17
|
+
# /custom_regexp/
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def self.description
|
21
|
+
# "Custom long desc"
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def.short_description
|
25
|
+
# "Custom short desc"
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# def execute
|
29
|
+
# # My command's implementation
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
class Command
|
34
|
+
extend Forwardable
|
35
|
+
|
36
|
+
attr_reader :processor
|
37
|
+
|
38
|
+
def initialize(processor, input = self.class.to_s)
|
39
|
+
@processor = processor
|
40
|
+
@match = match(input)
|
41
|
+
end
|
42
|
+
|
43
|
+
def context
|
44
|
+
@context ||= processor.context
|
45
|
+
end
|
46
|
+
|
47
|
+
def frame
|
48
|
+
@frame ||= context.frame
|
49
|
+
end
|
50
|
+
|
51
|
+
def arguments
|
52
|
+
@match[0].split(" ").drop(1).join(" ")
|
53
|
+
end
|
54
|
+
|
55
|
+
def_delegators "self.class", :help, :match
|
56
|
+
|
57
|
+
def_delegator "processor.printer", :print, :pr
|
58
|
+
def_delegator "processor.printer", :print_collection, :prc
|
59
|
+
def_delegator "processor.printer", :print_variables, :prv
|
60
|
+
|
61
|
+
def_delegators "processor.interface", :errmsg, :puts, :print, :confirm
|
62
|
+
|
63
|
+
class << self
|
64
|
+
include Helpers::StringHelper
|
65
|
+
|
66
|
+
#
|
67
|
+
# Special methods to allow command filtering in processors
|
68
|
+
#
|
69
|
+
attr_accessor :allow_in_control, :allow_in_post_mortem
|
70
|
+
|
71
|
+
attr_writer :always_run
|
72
|
+
|
73
|
+
def always_run
|
74
|
+
@always_run ||= 0
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Name of the command, as executed by the user.
|
79
|
+
#
|
80
|
+
def to_s
|
81
|
+
name
|
82
|
+
.split("::")
|
83
|
+
.map { |n| n.gsub(/Command$/, "").downcase if n =~ /Command$/ }
|
84
|
+
.compact
|
85
|
+
.join(" ")
|
86
|
+
end
|
87
|
+
|
88
|
+
def columnize(width)
|
89
|
+
format(
|
90
|
+
" %-<name>#{width}s -- %<description>s\n",
|
91
|
+
name: to_s,
|
92
|
+
description: short_description
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Default help text for a command.
|
98
|
+
#
|
99
|
+
def help
|
100
|
+
prettify(description)
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Command's regexp match against an input
|
105
|
+
#
|
106
|
+
def match(input)
|
107
|
+
regexp.match(input)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "byebug/errors"
|
4
|
+
|
5
|
+
module Byebug
|
6
|
+
#
|
7
|
+
# Holds an array of subcommands for a command
|
8
|
+
#
|
9
|
+
class CommandList
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
def initialize(commands)
|
13
|
+
@commands = commands.sort_by(&:to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def match(input)
|
17
|
+
find { |cmd| cmd.match(input) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def each
|
21
|
+
@commands.each { |cmd| yield(cmd) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"\n" + map { |cmd| cmd.columnize(width) }.join + "\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def width
|
31
|
+
@width ||= map(&:to_s).max_by(&:size).size
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "byebug/commands/break"
|
4
|
+
require "byebug/commands/catch"
|
5
|
+
require "byebug/commands/condition"
|
6
|
+
require "byebug/commands/continue"
|
7
|
+
require "byebug/commands/debug"
|
8
|
+
require "byebug/commands/delete"
|
9
|
+
require "byebug/commands/disable"
|
10
|
+
require "byebug/commands/display"
|
11
|
+
require "byebug/commands/down"
|
12
|
+
require "byebug/commands/edit"
|
13
|
+
require "byebug/commands/enable"
|
14
|
+
require "byebug/commands/finish"
|
15
|
+
require "byebug/commands/frame"
|
16
|
+
require "byebug/commands/help"
|
17
|
+
require "byebug/commands/history"
|
18
|
+
require "byebug/commands/info"
|
19
|
+
require "byebug/commands/interrupt"
|
20
|
+
require "byebug/commands/irb"
|
21
|
+
require "byebug/commands/kill"
|
22
|
+
require "byebug/commands/list"
|
23
|
+
require "byebug/commands/method"
|
24
|
+
require "byebug/commands/next"
|
25
|
+
require "byebug/commands/pry"
|
26
|
+
require "byebug/commands/quit"
|
27
|
+
require "byebug/commands/restart"
|
28
|
+
require "byebug/commands/save"
|
29
|
+
require "byebug/commands/set"
|
30
|
+
require "byebug/commands/show"
|
31
|
+
require "byebug/commands/skip"
|
32
|
+
require "byebug/commands/source"
|
33
|
+
require "byebug/commands/step"
|
34
|
+
require "byebug/commands/thread"
|
35
|
+
require "byebug/commands/tracevar"
|
36
|
+
require "byebug/commands/undisplay"
|
37
|
+
require "byebug/commands/untracevar"
|
38
|
+
require "byebug/commands/up"
|
39
|
+
require "byebug/commands/var"
|
40
|
+
require "byebug/commands/where"
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "byebug/command"
|
4
|
+
require "byebug/helpers/eval"
|
5
|
+
require "byebug/helpers/file"
|
6
|
+
require "byebug/helpers/parse"
|
7
|
+
require "byebug/source_file_formatter"
|
8
|
+
|
9
|
+
module Byebug
|
10
|
+
#
|
11
|
+
# Implements breakpoint functionality
|
12
|
+
#
|
13
|
+
class BreakCommand < Command
|
14
|
+
include Helpers::EvalHelper
|
15
|
+
include Helpers::FileHelper
|
16
|
+
include Helpers::ParseHelper
|
17
|
+
|
18
|
+
self.allow_in_control = true
|
19
|
+
|
20
|
+
def self.regexp
|
21
|
+
/^\s* b(?:reak)? (?:\s+ (.+?))? (?:\s+ if \s+(.+))? \s*$/x
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.description
|
25
|
+
<<-DESCRIPTION
|
26
|
+
b[reak] [<file>:]<line> [if <expr>]
|
27
|
+
b[reak] [<module>::...]<class>(.|#)<method> [if <expr>]
|
28
|
+
|
29
|
+
They can be specified by line or method and an expression can be added
|
30
|
+
for conditionally enabled breakpoints.
|
31
|
+
|
32
|
+
#{short_description}
|
33
|
+
DESCRIPTION
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.short_description
|
37
|
+
"Sets breakpoints in the source code"
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute
|
41
|
+
return puts(help) unless @match[1]
|
42
|
+
|
43
|
+
b = line_breakpoint(@match[1]) || method_breakpoint(@match[1])
|
44
|
+
return errmsg(pr("break.errors.location")) unless b
|
45
|
+
|
46
|
+
return puts(pr("break.created", id: b.id, file: b.source, line: b.pos)) if syntax_valid?(@match[2])
|
47
|
+
|
48
|
+
errmsg(pr("break.errors.expression", expr: @match[2]))
|
49
|
+
b.enabled = false
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def line_breakpoint(location)
|
55
|
+
line_match = location.match(/^(\d+)$/)
|
56
|
+
file_line_match = location.match(/^(.+):(\d+)$/)
|
57
|
+
return unless line_match || file_line_match
|
58
|
+
|
59
|
+
file = line_match ? frame.file : file_line_match[1]
|
60
|
+
line = line_match ? line_match[1].to_i : file_line_match[2].to_i
|
61
|
+
|
62
|
+
add_line_breakpoint(file, line)
|
63
|
+
end
|
64
|
+
|
65
|
+
def method_breakpoint(location)
|
66
|
+
location.match(/([^.#]+)[.#](.+)/) do |match|
|
67
|
+
klass = target_object(match[1])
|
68
|
+
method = match[2].intern
|
69
|
+
|
70
|
+
Breakpoint.add(klass, method, @match[2])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def target_object(str)
|
75
|
+
k = error_eval(str)
|
76
|
+
|
77
|
+
k&.is_a?(Module) ? k.name : str
|
78
|
+
rescue StandardError
|
79
|
+
errmsg("Warning: breakpoint source is not yet defined")
|
80
|
+
str
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_line_breakpoint(file, line)
|
84
|
+
raise(pr("break.errors.source", file: file)) unless File.exist?(file)
|
85
|
+
|
86
|
+
fullpath = File.realpath(file)
|
87
|
+
|
88
|
+
raise(pr("break.errors.far_line", lines: n_lines(file), file: fullpath)) if line > n_lines(file)
|
89
|
+
|
90
|
+
unless Breakpoint.potential_line?(fullpath, line)
|
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)
|
99
|
+
end
|
100
|
+
|
101
|
+
Breakpoint.add(fullpath, line, @match[2])
|
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
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "byebug/command"
|
4
|
+
require "byebug/helpers/eval"
|
5
|
+
|
6
|
+
module Byebug
|
7
|
+
#
|
8
|
+
# Implements exception catching.
|
9
|
+
#
|
10
|
+
# Enables the user to catch unhandled assertion when they happen.
|
11
|
+
#
|
12
|
+
class CatchCommand < Command
|
13
|
+
include Helpers::EvalHelper
|
14
|
+
|
15
|
+
self.allow_in_post_mortem = true
|
16
|
+
|
17
|
+
def self.regexp
|
18
|
+
/^\s* cat(?:ch)? (?:\s+(\S+))? (?:\s+(off))? \s*$/x
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.description
|
22
|
+
<<-DESCRIPTION
|
23
|
+
cat[ch][ (off|<exception>[ off])]
|
24
|
+
|
25
|
+
#{short_description}
|
26
|
+
|
27
|
+
catch -- lists catchpoints
|
28
|
+
catch off -- deletes all catchpoints
|
29
|
+
catch <exception> -- enables handling <exception>
|
30
|
+
catch <exception> off -- disables handling <exception>
|
31
|
+
DESCRIPTION
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.short_description
|
35
|
+
"Handles exception catchpoints"
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute
|
39
|
+
return info unless @match[1]
|
40
|
+
|
41
|
+
return @match[1] == "off" ? clear : add(@match[1]) unless @match[2]
|
42
|
+
|
43
|
+
return errmsg pr("catch.errors.off", off: cmd) unless @match[2] == "off"
|
44
|
+
|
45
|
+
remove(@match[1])
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def remove(exception)
|
51
|
+
return errmsg pr("catch.errors.not_found", exception: exception) unless Byebug.catchpoints.member?(exception)
|
52
|
+
|
53
|
+
puts pr("catch.removed", exception: exception)
|
54
|
+
Byebug.catchpoints.delete(exception)
|
55
|
+
end
|
56
|
+
|
57
|
+
def add(exception)
|
58
|
+
errmsg pr("catch.errors.not_class", class: exception) if warning_eval(exception.is_a?(Class).to_s)
|
59
|
+
|
60
|
+
puts pr("catch.added", exception: exception)
|
61
|
+
Byebug.add_catchpoint(exception)
|
62
|
+
end
|
63
|
+
|
64
|
+
def clear
|
65
|
+
Byebug.catchpoints.clear if confirm(pr("catch.confirmations.delete_all"))
|
66
|
+
end
|
67
|
+
|
68
|
+
def info
|
69
|
+
if Byebug.catchpoints && !Byebug.catchpoints.empty?
|
70
|
+
Byebug.catchpoints.each_key do |exception|
|
71
|
+
puts("#{exception}: #{exception.is_a?(Class)}")
|
72
|
+
end
|
73
|
+
else
|
74
|
+
puts "No exceptions set to be caught."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "byebug/command"
|
4
|
+
require "byebug/helpers/parse"
|
5
|
+
|
6
|
+
module Byebug
|
7
|
+
#
|
8
|
+
# Implements conditions on breakpoints.
|
9
|
+
#
|
10
|
+
# Adds the ability to stop on breakpoints only under certain conditions.
|
11
|
+
#
|
12
|
+
class ConditionCommand < Command
|
13
|
+
include Helpers::ParseHelper
|
14
|
+
|
15
|
+
self.allow_in_post_mortem = true
|
16
|
+
|
17
|
+
def self.regexp
|
18
|
+
/^\s* cond(?:ition)? (?:\s+(\d+)(?:\s+(.*))?)? \s*$/x
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.description
|
22
|
+
<<-DESCRIPTION
|
23
|
+
cond[ition] <n>[ expr]
|
24
|
+
|
25
|
+
#{short_description}
|
26
|
+
|
27
|
+
Specify breakpoint number <n> to break only if <expr> is true. <n> is
|
28
|
+
an integer and <expr> is an expression to be evaluated whenever
|
29
|
+
breakpoint <n> is reached. If no expression is specified, the condition
|
30
|
+
is removed.
|
31
|
+
DESCRIPTION
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.short_description
|
35
|
+
"Sets conditions on breakpoints"
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute
|
39
|
+
return puts(help) unless @match[1]
|
40
|
+
|
41
|
+
breakpoints = Byebug.breakpoints.sort_by(&:id)
|
42
|
+
return errmsg(pr("condition.errors.no_breakpoints")) if breakpoints.empty?
|
43
|
+
|
44
|
+
pos, err = get_int(@match[1], "Condition", 1)
|
45
|
+
return errmsg(err) if err
|
46
|
+
|
47
|
+
breakpoint = breakpoints.find { |b| b.id == pos }
|
48
|
+
return errmsg(pr("break.errors.no_breakpoint")) unless breakpoint
|
49
|
+
|
50
|
+
return errmsg(pr("break.errors.not_changed", expr: @match[2])) unless syntax_valid?(@match[2])
|
51
|
+
|
52
|
+
breakpoint.expr = @match[2]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "byebug/command"
|
4
|
+
require "byebug/helpers/parse"
|
5
|
+
|
6
|
+
module Byebug
|
7
|
+
#
|
8
|
+
# Implements the continue command.
|
9
|
+
#
|
10
|
+
# Allows the user to continue execution until the next stopping point, a
|
11
|
+
# specific line number or until program termination.
|
12
|
+
#
|
13
|
+
class ContinueCommand < Command
|
14
|
+
include Helpers::ParseHelper
|
15
|
+
|
16
|
+
def self.regexp
|
17
|
+
/^\s* c(?:ont(?:inue)?)? (?:(!|\s+unconditionally|\s+\S+))? \s*$/x
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.description
|
21
|
+
<<-DESCRIPTION
|
22
|
+
c[ont[inue]][ <line_number>]
|
23
|
+
|
24
|
+
#{short_description}
|
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
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.short_description
|
34
|
+
"Runs until program ends, hits a breakpoint or reaches a line"
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute
|
38
|
+
if until_line?
|
39
|
+
num, err = get_int(modifier, "Continue", 0, nil)
|
40
|
+
return errmsg(err) unless num
|
41
|
+
|
42
|
+
filename = File.expand_path(frame.file)
|
43
|
+
return errmsg(pr("continue.errors.unstopped_line", line: num)) unless Breakpoint.potential_line?(filename, num)
|
44
|
+
|
45
|
+
Breakpoint.add(filename, num)
|
46
|
+
end
|
47
|
+
|
48
|
+
processor.proceed!
|
49
|
+
|
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
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|