byebug 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +125 -99
- data/CONTRIBUTING.md +4 -6
- data/GUIDE.md +42 -20
- data/Gemfile +5 -3
- data/README.md +2 -3
- data/Rakefile +11 -7
- data/bin/byebug +2 -252
- data/byebug.gemspec +7 -4
- data/ext/byebug/byebug.c +17 -18
- data/ext/byebug/byebug.h +4 -5
- data/ext/byebug/context.c +37 -39
- data/ext/byebug/threads.c +39 -18
- data/lib/byebug.rb +2 -110
- data/lib/byebug/attacher.rb +23 -0
- data/lib/byebug/breakpoint.rb +60 -0
- data/lib/byebug/command.rb +62 -70
- data/lib/byebug/commands/break.rb +24 -24
- data/lib/byebug/commands/catchpoint.rb +18 -10
- data/lib/byebug/commands/condition.rb +18 -17
- data/lib/byebug/commands/continue.rb +17 -9
- data/lib/byebug/commands/delete.rb +19 -13
- data/lib/byebug/commands/display.rb +19 -53
- data/lib/byebug/commands/edit.rb +7 -4
- data/lib/byebug/commands/enable_disable.rb +130 -0
- data/lib/byebug/commands/eval.rb +40 -22
- data/lib/byebug/commands/finish.rb +13 -4
- data/lib/byebug/commands/frame.rb +65 -45
- data/lib/byebug/commands/help.rb +17 -18
- data/lib/byebug/commands/history.rb +14 -8
- data/lib/byebug/commands/info.rb +160 -182
- data/lib/byebug/commands/interrupt.rb +4 -1
- data/lib/byebug/commands/irb.rb +30 -0
- data/lib/byebug/commands/kill.rb +7 -8
- data/lib/byebug/commands/list.rb +71 -66
- data/lib/byebug/commands/method.rb +14 -6
- data/lib/byebug/commands/pry.rb +35 -0
- data/lib/byebug/commands/quit.rb +9 -6
- data/lib/byebug/commands/reload.rb +5 -2
- data/lib/byebug/commands/restart.rb +13 -9
- data/lib/byebug/commands/save.rb +17 -17
- data/lib/byebug/commands/set.rb +16 -15
- data/lib/byebug/commands/show.rb +10 -11
- data/lib/byebug/commands/source.rb +11 -5
- data/lib/byebug/commands/stepping.rb +38 -24
- data/lib/byebug/commands/threads.rb +45 -31
- data/lib/byebug/commands/trace.rb +22 -9
- data/lib/byebug/commands/undisplay.rb +45 -0
- data/lib/byebug/commands/variables.rb +83 -27
- data/lib/byebug/context.rb +25 -22
- data/lib/byebug/core.rb +82 -0
- data/lib/byebug/helper.rb +37 -28
- data/lib/byebug/history.rb +8 -4
- data/lib/byebug/interface.rb +12 -17
- data/lib/byebug/interfaces/local_interface.rb +11 -8
- data/lib/byebug/interfaces/remote_interface.rb +11 -8
- data/lib/byebug/interfaces/script_interface.rb +9 -6
- data/lib/byebug/options.rb +46 -0
- data/lib/byebug/processor.rb +7 -1
- data/lib/byebug/processors/command_processor.rb +135 -125
- data/lib/byebug/processors/control_command_processor.rb +23 -23
- data/lib/byebug/remote.rb +17 -26
- data/lib/byebug/runner.rb +100 -0
- data/lib/byebug/setting.rb +33 -8
- data/lib/byebug/settings/autoeval.rb +5 -15
- data/lib/byebug/settings/autoirb.rb +4 -1
- data/lib/byebug/settings/autolist.rb +5 -2
- data/lib/byebug/settings/autoreload.rb +5 -2
- data/lib/byebug/settings/autosave.rb +6 -2
- data/lib/byebug/settings/basename.rb +7 -2
- data/lib/byebug/settings/callstyle.rb +4 -1
- data/lib/byebug/settings/forcestep.rb +6 -3
- data/lib/byebug/settings/fullpath.rb +5 -2
- data/lib/byebug/settings/histfile.rb +5 -3
- data/lib/byebug/settings/histsize.rb +5 -3
- data/lib/byebug/settings/linetrace.rb +4 -1
- data/lib/byebug/settings/listsize.rb +5 -1
- data/lib/byebug/settings/post_mortem.rb +21 -13
- data/lib/byebug/settings/stack_on_error.rb +6 -2
- data/lib/byebug/settings/testing.rb +6 -1
- data/lib/byebug/settings/tracing_plus.rb +5 -1
- data/lib/byebug/settings/verbose.rb +13 -2
- data/lib/byebug/settings/width.rb +4 -1
- data/lib/byebug/version.rb +1 -1
- data/test/{break_test.rb → commands/break_test.rb} +41 -53
- data/test/{condition_test.rb → commands/condition_test.rb} +14 -14
- data/test/{continue_test.rb → commands/continue_test.rb} +0 -0
- data/test/{delete_test.rb → commands/delete_test.rb} +2 -2
- data/test/commands/display_test.rb +37 -0
- data/test/{edit_test.rb → commands/edit_test.rb} +0 -0
- data/test/{eval_test.rb → commands/eval_test.rb} +1 -0
- data/test/{finish_test.rb → commands/finish_test.rb} +11 -1
- data/test/{frame_test.rb → commands/frame_test.rb} +12 -16
- data/test/{help_test.rb → commands/help_test.rb} +21 -4
- data/test/{history_test.rb → commands/history_test.rb} +0 -0
- data/test/{info_test.rb → commands/info_test.rb} +5 -55
- data/test/{interrupt_test.rb → commands/interrupt_test.rb} +0 -0
- data/test/commands/irb_test.rb +28 -0
- data/test/{kill_test.rb → commands/kill_test.rb} +1 -1
- data/test/{list_test.rb → commands/list_test.rb} +1 -1
- data/test/{method_test.rb → commands/method_test.rb} +0 -0
- data/test/{post_mortem_test.rb → commands/post_mortem_test.rb} +6 -10
- data/test/{pry_test.rb → commands/pry_test.rb} +4 -13
- data/test/{quit_test.rb → commands/quit_test.rb} +4 -4
- data/test/{reload_test.rb → commands/reload_test.rb} +0 -0
- data/test/{restart_test.rb → commands/restart_test.rb} +6 -0
- data/test/{save_test.rb → commands/save_test.rb} +2 -2
- data/test/{set_test.rb → commands/set_test.rb} +9 -2
- data/test/{show_test.rb → commands/show_test.rb} +1 -1
- data/test/{source_test.rb → commands/source_test.rb} +3 -3
- data/test/{stepping_test.rb → commands/stepping_test.rb} +44 -35
- data/test/{thread_test.rb → commands/thread_test.rb} +0 -0
- data/test/{trace_test.rb → commands/trace_test.rb} +0 -0
- data/test/{display_test.rb → commands/undisplay_test.rb} +7 -45
- data/test/{variables_test.rb → commands/variables_test.rb} +10 -1
- data/test/debugger_alias_test.rb +2 -2
- data/test/runner_test.rb +127 -0
- data/test/support/matchers.rb +27 -25
- data/test/support/test_interface.rb +9 -5
- data/test/support/utils.rb +96 -101
- data/test/test_helper.rb +32 -20
- metadata +93 -68
- data/lib/byebug/commands/enable.rb +0 -154
- data/lib/byebug/commands/repl.rb +0 -126
- data/test/irb_test.rb +0 -47
- data/test/support/breakpoint.rb +0 -13
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Interrupting execution of current thread.
|
4
|
+
#
|
2
5
|
class InterruptCommand < Command
|
3
6
|
self.allow_in_control = true
|
4
7
|
self.allow_in_post_mortem = false
|
@@ -18,7 +21,7 @@ module Byebug
|
|
18
21
|
end
|
19
22
|
|
20
23
|
def description
|
21
|
-
%
|
24
|
+
%(i|nterrupt Interrupts the program.)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'irb'
|
2
|
+
|
3
|
+
module Byebug
|
4
|
+
#
|
5
|
+
# Enter IRB from byebug's prompt
|
6
|
+
#
|
7
|
+
class IrbCommand < Command
|
8
|
+
def regexp
|
9
|
+
/^\s* irb \s*$/x
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
unless @state.interface.is_a?(LocalInterface)
|
14
|
+
return errmsg('Command is available only in local mode.')
|
15
|
+
end
|
16
|
+
|
17
|
+
IRB.start(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def names
|
22
|
+
%w(irb)
|
23
|
+
end
|
24
|
+
|
25
|
+
def description
|
26
|
+
%{irb Starts an Interactive Ruby (IRB) session.}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/byebug/commands/kill.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Send custom signals to the debugged program.
|
4
|
+
#
|
2
5
|
class KillCommand < Command
|
3
6
|
self.allow_in_control = true
|
4
7
|
|
@@ -13,16 +16,12 @@ module Byebug
|
|
13
16
|
errmsg("signal name #{signame} is not a signal I know about\n")
|
14
17
|
return false
|
15
18
|
end
|
16
|
-
if 'KILL' == signame
|
17
|
-
@state.interface.close
|
18
|
-
end
|
19
|
+
@state.interface.close if 'KILL' == signame
|
19
20
|
else
|
20
|
-
|
21
|
-
|
22
|
-
else
|
23
|
-
signame = 'KILL'
|
24
|
-
end
|
21
|
+
return unless confirm('Really kill? (y/n) ')
|
22
|
+
signame = 'KILL'
|
25
23
|
end
|
24
|
+
|
26
25
|
Process.kill(signame, Process.pid)
|
27
26
|
end
|
28
27
|
|
data/lib/byebug/commands/list.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# List parts of the source code.
|
4
|
+
#
|
2
5
|
class ListCommand < Command
|
3
6
|
def regexp
|
4
7
|
/^\s* l(?:ist)? (?:\s*([-=])|\s+(\S+))? \s*$/x
|
@@ -7,7 +10,8 @@ module Byebug
|
|
7
10
|
def execute
|
8
11
|
Byebug.source_reload if Setting[:autoreload]
|
9
12
|
|
10
|
-
|
13
|
+
lines = get_lines(@state.file)
|
14
|
+
unless lines
|
11
15
|
errmsg "No sourcefile available for #{@state.file}\n"
|
12
16
|
return @state.previous_line
|
13
17
|
end
|
@@ -15,7 +19,7 @@ module Byebug
|
|
15
19
|
b, e = set_line_range(Setting[:listsize], lines.size)
|
16
20
|
return @state.previous_line if b < 0
|
17
21
|
|
18
|
-
|
22
|
+
puts "\n[#{b}, #{e}] in #{@state.file}"
|
19
23
|
@state.previous_line = display_list(b, e, lines, @state.line)
|
20
24
|
end
|
21
25
|
|
@@ -25,84 +29,85 @@ module Byebug
|
|
25
29
|
end
|
26
30
|
|
27
31
|
def description
|
28
|
-
%
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
%(l[ist][[-=]][ nn-mm]
|
33
|
+
|
34
|
+
Lists lines of code forward from current line or from the place where
|
35
|
+
code was last listed. If "list-" is specified, lists backwards
|
36
|
+
instead. If "list=" is specified, lists from current line regardless
|
37
|
+
of where code was last listed. A line range can also be specified to
|
38
|
+
list specific sections of code.)
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
42
|
private
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
44
|
+
##
|
45
|
+
# Set line range to be printed by list
|
46
|
+
#
|
47
|
+
# @param listsize - number of lines to be printed
|
48
|
+
# @param maxline - max line number that can be printed
|
49
|
+
#
|
50
|
+
def set_line_range(listsize, maxline)
|
51
|
+
if !@match || !(@match[1] || @match[2])
|
52
|
+
b = if @state.previous_line
|
53
|
+
@state.previous_line + listsize
|
54
|
+
else
|
55
|
+
@state.line - (listsize / 2)
|
56
|
+
end
|
57
|
+
elsif @match[1] == '-'
|
58
|
+
b = if @state.previous_line
|
59
|
+
if @state.previous_line > 0
|
60
|
+
@state.previous_line - listsize
|
55
61
|
else
|
56
|
-
@state.
|
62
|
+
@state.previous_line
|
57
63
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
64
|
+
else
|
65
|
+
@state.line - (listsize / 2)
|
66
|
+
end
|
67
|
+
elsif @match[1] == '='
|
68
|
+
@state.previous_line = nil
|
69
|
+
b = @state.line - (listsize / 2)
|
70
|
+
else
|
71
|
+
b, e = @match[2].split(/[-,]/)
|
72
|
+
if e
|
73
|
+
b = b.to_i
|
74
|
+
e = e.to_i
|
61
75
|
else
|
62
|
-
b
|
63
|
-
if e
|
64
|
-
b = b.to_i
|
65
|
-
e = e.to_i
|
66
|
-
else
|
67
|
-
b = b.to_i - (listsize/2)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
if b > maxline
|
72
|
-
errmsg "Invalid line range"
|
73
|
-
return [ -1, -1 ]
|
76
|
+
b = b.to_i - (listsize / 2)
|
74
77
|
end
|
78
|
+
end
|
75
79
|
|
76
|
-
|
77
|
-
|
80
|
+
if b > maxline
|
81
|
+
errmsg 'Invalid line range'
|
82
|
+
return [-1, -1]
|
83
|
+
end
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
b = e - listsize + 1
|
82
|
-
b = [1, b].max
|
83
|
-
end
|
85
|
+
b = [1, b].max
|
86
|
+
e ||= b + listsize - 1
|
84
87
|
|
85
|
-
|
88
|
+
if e > maxline
|
89
|
+
e = maxline
|
90
|
+
b = e - listsize + 1
|
91
|
+
b = [1, b].max
|
86
92
|
end
|
87
93
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
104
|
-
print "\n"
|
105
|
-
return e == lines.size ? @state.previous_line : b
|
94
|
+
[b, e]
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Show file lines in LINES from line B to line E where CURRENT is the
|
99
|
+
# current line number. If we can show from B to E then we return B,
|
100
|
+
# otherwise we return the previous line @state.previous_line.
|
101
|
+
#
|
102
|
+
def display_list(b, e, lines, current)
|
103
|
+
width = e.to_s.size
|
104
|
+
b.upto(e) do |n|
|
105
|
+
next unless n > 0 && lines[n - 1]
|
106
|
+
line = n == current ? '=>' : ' '
|
107
|
+
line += format(" %#{width}d: %s", n, lines[n - 1].chomp)
|
108
|
+
puts(line)
|
106
109
|
end
|
110
|
+
e == lines.size ? @state.previous_line : b
|
111
|
+
end
|
107
112
|
end
|
108
113
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Show methods of specific classes/modules/objects.
|
4
|
+
#
|
2
5
|
class MethodCommand < Command
|
3
6
|
include Columnize
|
4
7
|
|
@@ -9,11 +12,11 @@ module Byebug
|
|
9
12
|
def execute
|
10
13
|
obj = bb_eval(@match.post_match)
|
11
14
|
if @match[1]
|
12
|
-
|
13
|
-
elsif !obj.
|
14
|
-
|
15
|
+
puts "#{columnize(obj.methods.sort, Setting[:width])}"
|
16
|
+
elsif !obj.is_a?(Module)
|
17
|
+
puts "Should be Class/Module: #{@match.post_match}"
|
15
18
|
else
|
16
|
-
|
19
|
+
puts "#{columnize(obj.instance_methods(false).sort, Setting[:width])}"
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
@@ -23,8 +26,13 @@ module Byebug
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def description
|
26
|
-
%{m[ethod] i[nstance] <obj
|
27
|
-
|
29
|
+
%{m[ethod] (i[nstance][ <obj>]|<class|module>)
|
30
|
+
|
31
|
+
When invoked with "instance", shows instance methods of the object
|
32
|
+
specified as argument or of self no object was specified.
|
33
|
+
|
34
|
+
When invoked only with a class or module, shows class methods of the
|
35
|
+
class or module specified as argument.}
|
28
36
|
end
|
29
37
|
end
|
30
38
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
begin
|
2
|
+
require 'pry'
|
3
|
+
has_pry = true
|
4
|
+
rescue LoadError
|
5
|
+
has_pry = false
|
6
|
+
end
|
7
|
+
|
8
|
+
module Byebug
|
9
|
+
#
|
10
|
+
# Enter Pry from byebug's prompt
|
11
|
+
#
|
12
|
+
class PryCommand < Command
|
13
|
+
def regexp
|
14
|
+
/^\s* pry \s*$/x
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute
|
18
|
+
unless @state.interface.is_a?(LocalInterface)
|
19
|
+
return errmsg('Command is available only in local mode.')
|
20
|
+
end
|
21
|
+
|
22
|
+
get_binding.pry
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def names
|
27
|
+
%w(pry)
|
28
|
+
end
|
29
|
+
|
30
|
+
def description
|
31
|
+
%(pry Starts a Pry session.)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end if has_pry
|
data/lib/byebug/commands/quit.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Exit from byebug.
|
4
|
+
#
|
2
5
|
class QuitCommand < Command
|
3
6
|
self.allow_in_control = true
|
4
7
|
|
@@ -7,10 +10,10 @@ module Byebug
|
|
7
10
|
end
|
8
11
|
|
9
12
|
def execute
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
return unless @match[1] || confirm('Really quit? (y/n) ')
|
14
|
+
|
15
|
+
@state.interface.close
|
16
|
+
exit! # exit -> exit!: No graceful way to stop...
|
14
17
|
end
|
15
18
|
|
16
19
|
class << self
|
@@ -19,11 +22,11 @@ module Byebug
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def description
|
22
|
-
%
|
25
|
+
%(q[uit]|exit [!|unconditionally] Exits from byebug.
|
23
26
|
|
24
27
|
Normally we prompt before exiting. However if the parameter
|
25
28
|
"unconditionally" is given or command is suffixed with !, we exit
|
26
|
-
without asking further questions.
|
29
|
+
without asking further questions.)
|
27
30
|
end
|
28
31
|
end
|
29
32
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Reload source code to pick up latest changes.
|
4
|
+
#
|
2
5
|
class ReloadCommand < Command
|
3
6
|
self.allow_in_control = true
|
4
7
|
self.allow_in_post_mortem = false
|
@@ -10,7 +13,7 @@ module Byebug
|
|
10
13
|
def execute
|
11
14
|
Byebug.source_reload
|
12
15
|
onoff = Setting[:autoreload] ? 'on' : 'off'
|
13
|
-
|
16
|
+
puts "Source code was reloaded. Automatic reloading is #{onoff}"
|
14
17
|
end
|
15
18
|
|
16
19
|
class << self
|
@@ -19,7 +22,7 @@ module Byebug
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def description
|
22
|
-
%
|
25
|
+
%(r[eload] Forces source code reloading.)
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Restart debugged program from within byebug.
|
4
|
+
#
|
2
5
|
class RestartCommand < Command
|
3
6
|
self.allow_in_control = true
|
4
7
|
|
@@ -10,21 +13,22 @@ module Byebug
|
|
10
13
|
prog = PROG_SCRIPT if defined?(PROG_SCRIPT)
|
11
14
|
byebug_script = BYEBUG_SCRIPT if defined?(BYEBUG_SCRIPT)
|
12
15
|
|
13
|
-
return errmsg
|
16
|
+
return errmsg("Don't know name of debugged program") unless prog
|
14
17
|
|
15
18
|
unless File.exist?(File.expand_path(prog))
|
16
|
-
return errmsg
|
19
|
+
return errmsg("Ruby program #{prog} doesn't exist")
|
17
20
|
end
|
18
21
|
|
19
22
|
if byebug_script
|
20
23
|
cmd = "#{byebug_script} #{prog}"
|
21
24
|
else
|
22
|
-
|
25
|
+
puts 'Byebug was not called from the outset...'
|
23
26
|
if File.executable?(prog)
|
24
27
|
cmd = prog
|
25
28
|
else
|
26
|
-
|
27
|
-
|
29
|
+
puts "Ruby program #{prog} not executable... " \
|
30
|
+
"We'll wrap it in a ruby call"
|
31
|
+
cmd = "ruby -rbyebug -I#{$LOAD_PATH.join(' -I')} #{prog}"
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
@@ -36,10 +40,10 @@ module Byebug
|
|
36
40
|
end
|
37
41
|
|
38
42
|
# An execv would be preferable to the "exec" below.
|
39
|
-
|
43
|
+
puts "Re exec'ing:\n\t#{cmd}"
|
40
44
|
exec cmd
|
41
45
|
rescue Errno::EOPNOTSUPP
|
42
|
-
|
46
|
+
puts 'Restart command is not available at this time.'
|
43
47
|
end
|
44
48
|
|
45
49
|
class << self
|
@@ -48,10 +52,10 @@ module Byebug
|
|
48
52
|
end
|
49
53
|
|
50
54
|
def description
|
51
|
-
%
|
55
|
+
%(restart|R [args]
|
52
56
|
|
53
57
|
Restart the program. This is a re-exec - all byebug state
|
54
|
-
is lost. If command arguments are passed those are used.
|
58
|
+
is lost. If command arguments are passed those are used.)
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end
|