byebug 0.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.
- data/.gitignore +10 -0
- data/.travis.yml +8 -0
- data/AUTHORS +10 -0
- data/CHANGELOG.md +2 -0
- data/CONTRIBUTING.md +1 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +5 -0
- data/Rakefile +28 -0
- data/bin/byebug +395 -0
- data/byebug.gemspec +29 -0
- data/doc/hanoi.rb +35 -0
- data/doc/primes.rb +28 -0
- data/doc/rdebug-emacs.texi +1030 -0
- data/doc/test-tri2.rb +18 -0
- data/doc/tri3.rb +8 -0
- data/doc/triangle.rb +12 -0
- data/ext/byebug/breakpoint.c +476 -0
- data/ext/byebug/byebug.c +512 -0
- data/ext/byebug/byebug.h +131 -0
- data/ext/byebug/context.c +424 -0
- data/ext/byebug/extconf.rb +21 -0
- data/ext/byebug/locker.c +53 -0
- data/lib/byebug.rb +404 -0
- data/lib/byebug/command.rb +232 -0
- data/lib/byebug/commands/breakpoints.rb +153 -0
- data/lib/byebug/commands/catchpoint.rb +56 -0
- data/lib/byebug/commands/condition.rb +49 -0
- data/lib/byebug/commands/continue.rb +38 -0
- data/lib/byebug/commands/control.rb +110 -0
- data/lib/byebug/commands/display.rb +122 -0
- data/lib/byebug/commands/edit.rb +48 -0
- data/lib/byebug/commands/enable.rb +202 -0
- data/lib/byebug/commands/eval.rb +176 -0
- data/lib/byebug/commands/finish.rb +43 -0
- data/lib/byebug/commands/frame.rb +303 -0
- data/lib/byebug/commands/help.rb +56 -0
- data/lib/byebug/commands/info.rb +462 -0
- data/lib/byebug/commands/irb.rb +123 -0
- data/lib/byebug/commands/jump.rb +66 -0
- data/lib/byebug/commands/kill.rb +51 -0
- data/lib/byebug/commands/list.rb +94 -0
- data/lib/byebug/commands/method.rb +84 -0
- data/lib/byebug/commands/quit.rb +39 -0
- data/lib/byebug/commands/reload.rb +40 -0
- data/lib/byebug/commands/save.rb +90 -0
- data/lib/byebug/commands/set.rb +210 -0
- data/lib/byebug/commands/show.rb +246 -0
- data/lib/byebug/commands/skip.rb +35 -0
- data/lib/byebug/commands/source.rb +36 -0
- data/lib/byebug/commands/stepping.rb +83 -0
- data/lib/byebug/commands/threads.rb +189 -0
- data/lib/byebug/commands/tmate.rb +36 -0
- data/lib/byebug/commands/trace.rb +56 -0
- data/lib/byebug/commands/variables.rb +199 -0
- data/lib/byebug/context.rb +58 -0
- data/lib/byebug/helper.rb +69 -0
- data/lib/byebug/interface.rb +223 -0
- data/lib/byebug/processor.rb +468 -0
- data/lib/byebug/version.rb +3 -0
- data/man/rdebug.1 +241 -0
- data/test/breakpoints_test.rb +357 -0
- data/test/conditions_test.rb +77 -0
- data/test/continue_test.rb +44 -0
- data/test/display_test.rb +141 -0
- data/test/edit_test.rb +56 -0
- data/test/eval_test.rb +92 -0
- data/test/examples/breakpoint1.rb +15 -0
- data/test/examples/breakpoint2.rb +7 -0
- data/test/examples/conditions.rb +4 -0
- data/test/examples/continue.rb +4 -0
- data/test/examples/display.rb +5 -0
- data/test/examples/edit.rb +3 -0
- data/test/examples/edit2.rb +3 -0
- data/test/examples/eval.rb +4 -0
- data/test/examples/finish.rb +20 -0
- data/test/examples/frame.rb +20 -0
- data/test/examples/frame_threads.rb +31 -0
- data/test/examples/help.rb +2 -0
- data/test/examples/info.rb +38 -0
- data/test/examples/info2.rb +3 -0
- data/test/examples/info_threads.rb +48 -0
- data/test/examples/irb.rb +6 -0
- data/test/examples/jump.rb +14 -0
- data/test/examples/kill.rb +2 -0
- data/test/examples/list.rb +12 -0
- data/test/examples/method.rb +15 -0
- data/test/examples/post_mortem.rb +19 -0
- data/test/examples/quit.rb +2 -0
- data/test/examples/reload.rb +6 -0
- data/test/examples/restart.rb +6 -0
- data/test/examples/save.rb +3 -0
- data/test/examples/set.rb +3 -0
- data/test/examples/set_annotate.rb +12 -0
- data/test/examples/settings.rb +1 -0
- data/test/examples/show.rb +2 -0
- data/test/examples/source.rb +3 -0
- data/test/examples/stepping.rb +21 -0
- data/test/examples/thread.rb +32 -0
- data/test/examples/tmate.rb +10 -0
- data/test/examples/trace.rb +7 -0
- data/test/examples/trace_threads.rb +20 -0
- data/test/examples/variables.rb +26 -0
- data/test/finish_test.rb +48 -0
- data/test/frame_test.rb +143 -0
- data/test/help_test.rb +50 -0
- data/test/info_test.rb +313 -0
- data/test/irb_test.rb +81 -0
- data/test/jump_test.rb +70 -0
- data/test/kill_test.rb +48 -0
- data/test/list_test.rb +145 -0
- data/test/method_test.rb +70 -0
- data/test/post_mortem_test.rb +27 -0
- data/test/quit_test.rb +56 -0
- data/test/reload_test.rb +44 -0
- data/test/restart_test.rb +164 -0
- data/test/save_test.rb +92 -0
- data/test/set_test.rb +177 -0
- data/test/show_test.rb +293 -0
- data/test/source_test.rb +45 -0
- data/test/stepping_test.rb +130 -0
- data/test/support/breakpoint.rb +13 -0
- data/test/support/context.rb +14 -0
- data/test/support/matchers.rb +67 -0
- data/test/support/mocha_extensions.rb +72 -0
- data/test/support/processor.rb +7 -0
- data/test/support/test_dsl.rb +206 -0
- data/test/support/test_interface.rb +68 -0
- data/test/test_helper.rb +10 -0
- data/test/tmate_test.rb +44 -0
- data/test/trace_test.rb +159 -0
- data/test/variables_test.rb +119 -0
- metadata +265 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'irb'
|
2
|
+
|
3
|
+
module IRB # :nodoc:
|
4
|
+
module ExtendCommand # :nodoc:
|
5
|
+
class Continue # :nodoc:
|
6
|
+
def self.execute(conf)
|
7
|
+
throw :IRB_EXIT, :cont
|
8
|
+
end
|
9
|
+
end
|
10
|
+
class Next # :nodoc:
|
11
|
+
def self.execute(conf)
|
12
|
+
throw :IRB_EXIT, :next
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class Step # :nodoc:
|
16
|
+
def self.execute(conf)
|
17
|
+
throw :IRB_EXIT, :step
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
ExtendCommandBundle.def_extend_command "cont", :Continue
|
22
|
+
ExtendCommandBundle.def_extend_command "n", :Next
|
23
|
+
ExtendCommandBundle.def_extend_command "step", :Step
|
24
|
+
|
25
|
+
def self.start_session(binding)
|
26
|
+
unless @__initialized
|
27
|
+
args = ARGV.dup
|
28
|
+
ARGV.replace([])
|
29
|
+
IRB.setup(nil)
|
30
|
+
ARGV.replace(args)
|
31
|
+
@__initialized = true
|
32
|
+
end
|
33
|
+
|
34
|
+
workspace = WorkSpace.new(binding)
|
35
|
+
|
36
|
+
irb = Irb.new(workspace)
|
37
|
+
|
38
|
+
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
|
39
|
+
@CONF[:MAIN_CONTEXT] = irb.context
|
40
|
+
|
41
|
+
catch(:IRB_EXIT) do
|
42
|
+
irb.eval_input
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module Byebug
|
48
|
+
|
49
|
+
# Implements byebug "irb" command.
|
50
|
+
class IRBCommand < Command
|
51
|
+
|
52
|
+
register_setting_get(:autoirb) do
|
53
|
+
IRBCommand.always_run
|
54
|
+
end
|
55
|
+
register_setting_set(:autoirb) do |value|
|
56
|
+
IRBCommand.always_run = value
|
57
|
+
end
|
58
|
+
|
59
|
+
def regexp
|
60
|
+
/^\s* irb
|
61
|
+
(?:\s+(-d))?
|
62
|
+
\s*$/x
|
63
|
+
end
|
64
|
+
|
65
|
+
def execute
|
66
|
+
unless @state.interface.kind_of?(LocalInterface)
|
67
|
+
print "Command is available only in local mode.\n"
|
68
|
+
throw :debug_error
|
69
|
+
end
|
70
|
+
|
71
|
+
save_trap = trap("SIGINT") do
|
72
|
+
throw :IRB_EXIT, :cont if $rdebug_in_irb
|
73
|
+
end
|
74
|
+
|
75
|
+
add_debugging = @match.is_a?(MatchData) && '-d' == @match[1]
|
76
|
+
$rdebug_state = @state if add_debugging
|
77
|
+
$rdebug_in_irb = true
|
78
|
+
cont = IRB.start_session(get_binding)
|
79
|
+
case cont
|
80
|
+
when :cont
|
81
|
+
@state.proceed
|
82
|
+
when :step
|
83
|
+
force = Command.settings[:force_stepping]
|
84
|
+
@state.context.step(1, force)
|
85
|
+
@state.proceed
|
86
|
+
when :next
|
87
|
+
force = Command.settings[:force_stepping]
|
88
|
+
@state.context.step_over(1, @state.frame_pos, force)
|
89
|
+
@state.proceed
|
90
|
+
else
|
91
|
+
file = @state.context.frame_file(0)
|
92
|
+
line = @state.context.frame_line(0)
|
93
|
+
CommandProcessor.print_location_and_text(file, line)
|
94
|
+
@state.previous_line = nil
|
95
|
+
end
|
96
|
+
|
97
|
+
ensure
|
98
|
+
$rdebug_in_irb = nil
|
99
|
+
$rdebug_state = nil if add_debugging
|
100
|
+
trap("SIGINT", save_trap) if save_trap
|
101
|
+
end
|
102
|
+
|
103
|
+
class << self
|
104
|
+
def help_command
|
105
|
+
'irb'
|
106
|
+
end
|
107
|
+
|
108
|
+
def help(cmd)
|
109
|
+
%{
|
110
|
+
irb [-d]\tstarts an Interactive Ruby (IRB) session.
|
111
|
+
|
112
|
+
If -d is added you can get access to byebug state via the global variable
|
113
|
+
$RDEBUG_state.
|
114
|
+
|
115
|
+
irb is extended with methods "cont", "n" and "step" which
|
116
|
+
run the corresponding byebug commands. In contrast to the real byebug
|
117
|
+
commands these commands don't allow command arguments.
|
118
|
+
}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Byebug
|
2
|
+
|
3
|
+
# Implements byebug "jump" command
|
4
|
+
class JumpCommand < Command
|
5
|
+
self.allow_in_control = true
|
6
|
+
|
7
|
+
def numeric?(object)
|
8
|
+
true if Float(object) rescue false
|
9
|
+
end
|
10
|
+
|
11
|
+
def regexp
|
12
|
+
/ ^\s*
|
13
|
+
j(?:ump)? \s*
|
14
|
+
(?:\s+(\S+))?\s*
|
15
|
+
(?:\s+(\S+))?\s*
|
16
|
+
$
|
17
|
+
/ix
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute
|
21
|
+
if !@match[1]
|
22
|
+
errmsg "\"jump\" must be followed by a line number\n"
|
23
|
+
return
|
24
|
+
end
|
25
|
+
if !numeric?(@match[1])
|
26
|
+
errmsg "Bad line number: " + @match[1]
|
27
|
+
return
|
28
|
+
end
|
29
|
+
line = @match[1].to_i
|
30
|
+
line = @state.context.frame_line(0) + line if @match[1][0] == '+' or @match[1][0] == '-'
|
31
|
+
if line == @state.context.frame_line(0)
|
32
|
+
CommandProcessor.print_location_and_text(@state.context.frame_file(0), line)
|
33
|
+
return
|
34
|
+
end
|
35
|
+
file = @match[2]
|
36
|
+
file = @state.context.frame_file(file.to_i) if numeric?(file)
|
37
|
+
file = @state.context.frame_file(0) if !file
|
38
|
+
case Byebug.current_context.jump(line, file)
|
39
|
+
when 0
|
40
|
+
@state.proceed
|
41
|
+
when 1
|
42
|
+
errmsg "Not possible to jump from here\n"
|
43
|
+
when 2
|
44
|
+
errmsg "Couldn't find debugged frame\n"
|
45
|
+
when 3
|
46
|
+
errmsg "Couldn't find active code at " + file + ":" + line.to_s + "\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class << self
|
51
|
+
def help_command
|
52
|
+
%w[jump]
|
53
|
+
end
|
54
|
+
|
55
|
+
def help(cmd)
|
56
|
+
%{
|
57
|
+
j[ump] line\tjump to line number (absolute)
|
58
|
+
j[ump] -line\tjump back to line (relative)
|
59
|
+
j[ump] +line\tjump ahead to line (relative)
|
60
|
+
|
61
|
+
Change the next line of code to be executed.
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Byebug
|
2
|
+
|
3
|
+
# Implements byebug "kill" command
|
4
|
+
class KillCommand < Command
|
5
|
+
self.allow_in_control = true
|
6
|
+
|
7
|
+
def regexp
|
8
|
+
/ ^\s*
|
9
|
+
(?:kill) \s*
|
10
|
+
(?:\s+(\S+))?\s*
|
11
|
+
$
|
12
|
+
/ix
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
puts @match[1]
|
17
|
+
if @match[1]
|
18
|
+
signame = @match[1]
|
19
|
+
unless Signal.list.member?(signame)
|
20
|
+
errmsg("signal name #{signame} is not a signal I know about\n")
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
if 'KILL' == signame
|
24
|
+
@state.interface.finalize
|
25
|
+
end
|
26
|
+
else
|
27
|
+
if not confirm("Really kill? (y/n) ")
|
28
|
+
return
|
29
|
+
else
|
30
|
+
signame = 'KILL'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
Process.kill(signame, Process.pid)
|
34
|
+
end
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def help_command
|
38
|
+
%w[kill]
|
39
|
+
end
|
40
|
+
|
41
|
+
def help(cmd)
|
42
|
+
%{
|
43
|
+
kill [SIGNAL]
|
44
|
+
|
45
|
+
Send [signal] to Process.pid
|
46
|
+
Equivalent of Process.kill(Process.pid)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Byebug
|
2
|
+
# Implements byebug "list" command.
|
3
|
+
class ListCommand < Command
|
4
|
+
|
5
|
+
register_setting_get(:autolist) do
|
6
|
+
ListCommand.always_run
|
7
|
+
end
|
8
|
+
register_setting_set(:autolist) do |value|
|
9
|
+
ListCommand.always_run = value
|
10
|
+
end
|
11
|
+
|
12
|
+
def regexp
|
13
|
+
/^\s* l(?:ist)? (?:\s*([-=])|\s+(.+))? $/x
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute
|
17
|
+
listsize = Command.settings[:listsize]
|
18
|
+
if !@match || !(@match[1] || @match[2])
|
19
|
+
b = @state.previous_line ?
|
20
|
+
@state.previous_line + listsize : @state.line - (listsize/2)
|
21
|
+
e = b + listsize - 1
|
22
|
+
elsif @match[1] == '-'
|
23
|
+
b = if @state.previous_line
|
24
|
+
if @state.previous_line > 0
|
25
|
+
@state.previous_line - listsize
|
26
|
+
else
|
27
|
+
@state.previous_line
|
28
|
+
end
|
29
|
+
else
|
30
|
+
@state.line - (listsize/2)
|
31
|
+
end
|
32
|
+
e = b + listsize - 1
|
33
|
+
elsif @match[1] == '='
|
34
|
+
@state.previous_line = nil
|
35
|
+
b = @state.line - (listsize/2)
|
36
|
+
e = b + listsize -1
|
37
|
+
else
|
38
|
+
b, e = @match[2].split(/[-,]/)
|
39
|
+
if e
|
40
|
+
b = b.to_i
|
41
|
+
e = e.to_i
|
42
|
+
else
|
43
|
+
b = b.to_i - (listsize/2)
|
44
|
+
e = b + listsize - 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@state.previous_line = display_list(b, e, @state.file, @state.line)
|
48
|
+
end
|
49
|
+
|
50
|
+
class << self
|
51
|
+
def help_command
|
52
|
+
'list'
|
53
|
+
end
|
54
|
+
|
55
|
+
def help(cmd)
|
56
|
+
%{
|
57
|
+
l[ist]\t\tlist forward
|
58
|
+
l[ist] -\tlist backward
|
59
|
+
l[ist] =\tlist current line
|
60
|
+
l[ist] nn-mm\tlist given lines
|
61
|
+
* NOTE - to turn on autolist, use 'set autolist'
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# Show FILE from line B to E where CURRENT is the current line number.
|
69
|
+
# If we can show from B to E then we return B, otherwise we return the
|
70
|
+
# previous line @state.previous_line.
|
71
|
+
def display_list(b, e, file, current)
|
72
|
+
print "[%d, %d] in %s\n", b, e, file
|
73
|
+
lines = LineCache::getlines(file,
|
74
|
+
Command.settings[:reload_source_on_change])
|
75
|
+
if lines
|
76
|
+
return @state.previous_line if b >= lines.size
|
77
|
+
e = lines.size if lines.size < e
|
78
|
+
[b, 1].max.upto(e) do |n|
|
79
|
+
if n > 0 && lines[n-1]
|
80
|
+
if n == current
|
81
|
+
print "=> %d %s\n", n, lines[n-1].chomp
|
82
|
+
else
|
83
|
+
print " %d %s\n", n, lines[n-1].chomp
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
else
|
88
|
+
errmsg "No sourcefile available for %s\n", file
|
89
|
+
return @state.previous_line
|
90
|
+
end
|
91
|
+
return e == lines.size ? @state.previous_line : b
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Byebug
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'methodsig'
|
5
|
+
have_methodsig = true
|
6
|
+
rescue LoadError
|
7
|
+
have_methodsig = false
|
8
|
+
end
|
9
|
+
|
10
|
+
# Implements the byebug 'method sig' command.
|
11
|
+
class MethodSigCommand < Command
|
12
|
+
def regexp
|
13
|
+
/^\s*m(?:ethod)?\s+sig(?:nature)?\s+(\S+)\s*$/
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute
|
17
|
+
obj = debug_eval('method(:%s)' % @match[1])
|
18
|
+
if obj.is_a?(Method)
|
19
|
+
begin
|
20
|
+
print "%s\n", obj.signature.to_s
|
21
|
+
rescue
|
22
|
+
errmsg("Can't get signature for '#{@match[1]}'\n")
|
23
|
+
end
|
24
|
+
else
|
25
|
+
errmsg("Can't make method out of '#{@match[1]}'\n")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def help_command
|
31
|
+
'method'
|
32
|
+
end
|
33
|
+
|
34
|
+
def help(cmd)
|
35
|
+
%{
|
36
|
+
m[ethod] sig[nature] <obj>\tshow the signature of a method
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end if have_methodsig
|
41
|
+
|
42
|
+
# Implements the byebug 'method' command.
|
43
|
+
class MethodCommand < Command
|
44
|
+
def regexp
|
45
|
+
/^\s*m(?:ethod)?\s+((iv)|(i(:?nstance)?)\s+)?/
|
46
|
+
end
|
47
|
+
|
48
|
+
def execute
|
49
|
+
if @match[1] == "iv"
|
50
|
+
obj = debug_eval(@match.post_match)
|
51
|
+
obj.instance_variables.sort.each do |v|
|
52
|
+
print "%s = %s\n", v, obj.instance_variable_get(v).inspect
|
53
|
+
end
|
54
|
+
elsif @match[1]
|
55
|
+
obj = debug_eval(@match.post_match)
|
56
|
+
print "%s\n", columnize(obj.methods.sort(),
|
57
|
+
self.class.settings[:width])
|
58
|
+
else
|
59
|
+
obj = debug_eval(@match.post_match)
|
60
|
+
unless obj.kind_of? Module
|
61
|
+
print "Should be Class/Module: %s\n", @match.post_match
|
62
|
+
else
|
63
|
+
print "%s\n", columnize(obj.instance_methods(false).sort(),
|
64
|
+
self.class.settings[:width])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
def help_command
|
71
|
+
'method'
|
72
|
+
end
|
73
|
+
|
74
|
+
def help(cmd)
|
75
|
+
%{
|
76
|
+
m[ethod] i[nstance] <obj>\tshow methods of object
|
77
|
+
m[ethod] iv <obj>\t\tshow instance variables of object
|
78
|
+
m[ethod] <class|module>\t\tshow instance methods of class or module
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Byebug
|
2
|
+
|
3
|
+
# Implements byebug "quit" command
|
4
|
+
class QuitCommand < Command
|
5
|
+
self.allow_in_control = true
|
6
|
+
|
7
|
+
def regexp
|
8
|
+
/ ^\s*
|
9
|
+
(?:q(?:uit)?|exit) \s*
|
10
|
+
(!|\s+unconditionally)? \s*
|
11
|
+
$
|
12
|
+
/ix
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
if @match[1] or confirm("Really quit? (y/n) ")
|
17
|
+
@state.interface.finalize
|
18
|
+
exit! # exit -> exit!: No graceful way to stop threads...
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def help_command
|
24
|
+
%w[quit exit]
|
25
|
+
end
|
26
|
+
|
27
|
+
def help(cmd)
|
28
|
+
%{
|
29
|
+
q[uit] [!|unconditionally]\texit from byebug.
|
30
|
+
exit[!]\talias to quit
|
31
|
+
|
32
|
+
Normally we prompt before exiting. However if the parameter
|
33
|
+
"unconditionally" or is given or suffixed with !, we stop
|
34
|
+
without asking further questions.
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|