byebug 1.8.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -1
- data/GUIDE.md +14 -22
- data/README.md +69 -6
- data/bin/byebug +3 -20
- data/ext/byebug/breakpoint.c +185 -101
- data/ext/byebug/byebug.c +393 -214
- data/ext/byebug/byebug.h +34 -15
- data/ext/byebug/context.c +327 -102
- data/ext/byebug/extconf.rb +1 -1
- data/ext/byebug/locker.c +54 -0
- data/ext/byebug/threads.c +113 -0
- data/lib/byebug.rb +19 -58
- data/lib/byebug/command.rb +18 -19
- data/lib/byebug/commands/breakpoints.rb +1 -4
- data/lib/byebug/commands/catchpoint.rb +1 -1
- data/lib/byebug/commands/condition.rb +1 -1
- data/lib/byebug/commands/control.rb +2 -3
- data/lib/byebug/commands/display.rb +2 -7
- data/lib/byebug/commands/edit.rb +1 -1
- data/lib/byebug/commands/enable.rb +12 -12
- data/lib/byebug/commands/eval.rb +4 -4
- data/lib/byebug/commands/finish.rb +1 -1
- data/lib/byebug/commands/frame.rb +12 -8
- data/lib/byebug/commands/info.rb +20 -52
- data/lib/byebug/commands/kill.rb +1 -5
- data/lib/byebug/commands/list.rb +2 -1
- data/lib/byebug/commands/quit.rb +1 -1
- data/lib/byebug/commands/repl.rb +2 -2
- data/lib/byebug/commands/save.rb +1 -1
- data/lib/byebug/commands/set.rb +84 -90
- data/lib/byebug/commands/show.rb +44 -53
- data/lib/byebug/commands/skip.rb +1 -1
- data/lib/byebug/commands/stepping.rb +5 -4
- data/lib/byebug/commands/threads.rb +202 -0
- data/lib/byebug/commands/trace.rb +1 -1
- data/lib/byebug/helper.rb +3 -3
- data/lib/byebug/interface.rb +2 -20
- data/lib/byebug/processor.rb +21 -100
- data/lib/byebug/remote.rb +3 -3
- data/lib/byebug/version.rb +1 -1
- data/old_doc/byebug.1 +0 -6
- data/old_doc/byebug.texi +29 -46
- data/test/breakpoints_test.rb +44 -65
- data/test/conditions_test.rb +0 -9
- data/test/continue_test.rb +2 -2
- data/test/display_test.rb +4 -23
- data/test/edit_test.rb +2 -16
- data/test/eval_test.rb +4 -13
- data/test/examples/thread.rb +32 -0
- data/test/finish_test.rb +1 -13
- data/test/frame_test.rb +5 -12
- data/test/help_test.rb +2 -12
- data/test/info_test.rb +8 -18
- data/test/kill_test.rb +1 -10
- data/test/list_test.rb +5 -14
- data/test/method_test.rb +1 -10
- data/test/post_mortem_test.rb +247 -14
- data/test/quit_test.rb +0 -9
- data/test/reload_test.rb +1 -15
- data/test/repl_test.rb +1 -9
- data/test/restart_test.rb +3 -18
- data/test/save_test.rb +1 -13
- data/test/set_test.rb +35 -32
- data/test/show_test.rb +8 -27
- data/test/source_test.rb +1 -8
- data/test/stepping_test.rb +65 -96
- data/test/support/test_dsl.rb +12 -17
- data/test/test_helper.rb +1 -1
- data/test/thread_test.rb +106 -0
- data/test/trace_test.rb +5 -17
- data/test/variables_test.rb +1 -10
- metadata +9 -7
- data/lib/byebug/commands/jump.rb +0 -52
- data/test/jump_test.rb +0 -77
- data/test/support/context.rb +0 -15
data/lib/byebug/commands/show.rb
CHANGED
@@ -5,9 +5,6 @@ module Byebug
|
|
5
5
|
|
6
6
|
def show_setting(setting_name)
|
7
7
|
case setting_name
|
8
|
-
when /^annotate$/
|
9
|
-
Byebug.annotate ||= 0
|
10
|
-
return ("Annotation level is #{Byebug.annotate}")
|
11
8
|
when /^args$/
|
12
9
|
if Command.settings[:argv] and Command.settings[:argv].size > 0
|
13
10
|
if defined?(Byebug::BYEBUG_SCRIPT)
|
@@ -77,10 +74,10 @@ module Byebug
|
|
77
74
|
on_off = Command.settings[:testing]
|
78
75
|
return "Currently testing byebug is #{show_onoff(on_off)}."
|
79
76
|
when /^forcestep$/
|
80
|
-
on_off = Command.settings[:
|
77
|
+
on_off = Command.settings[:forcestep]
|
81
78
|
return "force-stepping is #{show_onoff(on_off)}."
|
82
79
|
when /^fullpath$/
|
83
|
-
on_off = Command.settings[:
|
80
|
+
on_off = Command.settings[:fullpath]
|
84
81
|
return "Displaying frame's full file names is #{show_onoff(on_off)}."
|
85
82
|
when /^history(:?\s+(filename|save|size))?$/
|
86
83
|
args = @match[1].split
|
@@ -119,21 +116,23 @@ module Byebug
|
|
119
116
|
when /^linetrace$/
|
120
117
|
on_off = Byebug.tracing?
|
121
118
|
return "line tracing is #{show_onoff(on_off)}."
|
122
|
-
when /^
|
123
|
-
|
124
|
-
if on_off
|
125
|
-
return "line tracing style is different consecutive lines."
|
126
|
-
else
|
119
|
+
when /^linetrace_plus$/
|
120
|
+
if Command.settings[:linetrace_plus]
|
127
121
|
return "line tracing style is every line."
|
122
|
+
else
|
123
|
+
return "line tracing style is different consecutive lines."
|
128
124
|
end
|
129
125
|
when /^listsize$/
|
130
126
|
listlines = Command.settings[:listsize]
|
131
127
|
return "Number of source lines to list is #{listlines}."
|
132
|
-
when /^
|
128
|
+
when /^post_mortem$/
|
129
|
+
on_off = Byebug.post_mortem?
|
130
|
+
return "post-mortem mode is #{show_onoff(on_off)}"
|
131
|
+
when /^stack_trace_on_error$/
|
133
132
|
on_off = Command.settings[:stack_trace_on_error]
|
134
133
|
return "Displaying stack trace is #{show_onoff(on_off)}."
|
135
134
|
when /^version$/
|
136
|
-
return "
|
135
|
+
return "Byebug #{Byebug::VERSION}"
|
137
136
|
when /^width$/
|
138
137
|
return "width is #{Command.settings[:width]}."
|
139
138
|
else
|
@@ -147,53 +146,45 @@ module Byebug
|
|
147
146
|
|
148
147
|
Subcommands =
|
149
148
|
[
|
150
|
-
['
|
151
|
-
'
|
152
|
-
'
|
153
|
-
'
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
['post-mortem', 3,
|
182
|
-
'Show whether we go into post-mortem debugging on an uncaught ' \
|
183
|
-
'exception'],
|
184
|
-
['trace', 1,
|
185
|
-
'Show whether a stack trace is displayed when "eval" raises an ' \
|
186
|
-
'exception'],
|
187
|
-
['version', 1, 'Show byebug\'s version'],
|
188
|
-
['width', 1, 'Show the number of characters per line for byebug']
|
149
|
+
['args', 2,
|
150
|
+
'Show argument list to the program being debugged when it is started',
|
151
|
+
'Follow this command with any number of args to be passed to the ' \
|
152
|
+
'program'],
|
153
|
+
['autoeval', 4, 'Show whether unrecognized commands are evaluated'],
|
154
|
+
['autolist', 4, 'Show whether "list" command is run on stopping'],
|
155
|
+
['autoirb', 4, 'Show whether IRB is invoked on stopping'],
|
156
|
+
['autoreload', 4, 'Show whether source code is reloaded when changed'],
|
157
|
+
['basename', 1, 'Show whether basename is used when reporting files'],
|
158
|
+
['callstyle', 2, 'Show paramater style used when showing call frames'],
|
159
|
+
['commands', 2, 'Show the history of commands you typed',
|
160
|
+
'You can supply a command number to start with'],
|
161
|
+
['forcestep', 1,
|
162
|
+
'Show whether "next/step" commands are set to always move to a line'],
|
163
|
+
['fullpath', 2, 'Show whether full paths are displayed in frames'],
|
164
|
+
['history', 2, 'Generic command to show command history parameters',
|
165
|
+
'show history filename -- Show the filename in which to record the ' \
|
166
|
+
'command history' \
|
167
|
+
'show history save -- Show whether history record should be saved ' \
|
168
|
+
'on exit' \
|
169
|
+
'show history size -- Show the size of the command history'],
|
170
|
+
['linetrace', 3, 'Show line execution tracing status'],
|
171
|
+
['linetrace_plus', 10,
|
172
|
+
'Show whether different consecutive lines are shown in tracing'],
|
173
|
+
['listsize', 3, 'Show number of source lines to list by default'],
|
174
|
+
['post-mortem', 3, 'Show whether we should go into post-mortem ' \
|
175
|
+
'debugging on an uncaught exception'],
|
176
|
+
['stack_trace_on_error', 1, 'Show whether a stack trace is displayed ' \
|
177
|
+
'when "eval" raises an exception'],
|
178
|
+
['version', 1, 'Show byebug\'s version'],
|
179
|
+
['width', 1, 'Show the number of characters per line for byebug']
|
189
180
|
].map do |name, min, short_help, long_help|
|
190
|
-
|
181
|
+
Subcmd.new(name, min, short_help, long_help)
|
191
182
|
end unless defined?(Subcommands)
|
192
183
|
|
193
184
|
self.allow_in_control = true
|
194
185
|
|
195
186
|
def regexp
|
196
|
-
/^\s* show (?:\s+(.+))? \s*$/
|
187
|
+
/^\s* show (?:\s+(.+))? \s*$/x
|
197
188
|
end
|
198
189
|
|
199
190
|
def execute
|
data/lib/byebug/commands/skip.rb
CHANGED
@@ -4,7 +4,7 @@ module Byebug
|
|
4
4
|
module SteppingFunctions
|
5
5
|
def parse_stepping_args(command_name, match)
|
6
6
|
if match[1].nil?
|
7
|
-
force = Command.settings[:
|
7
|
+
force = Command.settings[:forcestep]
|
8
8
|
elsif match[1] == '+'
|
9
9
|
force = true
|
10
10
|
elsif match[1] == '-'
|
@@ -39,7 +39,8 @@ module Byebug
|
|
39
39
|
def description
|
40
40
|
%{n[ext][+-]?[ nnn]\tstep over once or nnn times,
|
41
41
|
\t\t'+' forces to move to another line.
|
42
|
-
\t\t'-' is the opposite of '+' and disables the
|
42
|
+
\t\t'-' is the opposite of '+' and disables the :forcestep setting.
|
43
|
+
}
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
@@ -69,8 +70,8 @@ module Byebug
|
|
69
70
|
%{
|
70
71
|
s[tep][+-]?[ nnn]\tstep (into methods) once or nnn times
|
71
72
|
\t\t'+' forces to move to another line.
|
72
|
-
\t\t'-' is the opposite of '+' and disables the
|
73
|
-
|
73
|
+
\t\t'-' is the opposite of '+' and disables the :forcestep setting.
|
74
|
+
}
|
74
75
|
end
|
75
76
|
end
|
76
77
|
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
module Byebug
|
2
|
+
module ThreadFunctions
|
3
|
+
def display_context(context, should_show_top_frame = true)
|
4
|
+
args = thread_arguments(context, should_show_top_frame)
|
5
|
+
print "%s%s%d %s\t%s\n", args[:status_flag], args[:debug_flag], args[:id],
|
6
|
+
args[:thread], args[:file_line]
|
7
|
+
end
|
8
|
+
|
9
|
+
def thread_arguments(context, should_show_top_frame = true)
|
10
|
+
status_flag = if context.suspended?
|
11
|
+
"$"
|
12
|
+
else
|
13
|
+
context.thread == Thread.current ? '+' : ' '
|
14
|
+
end
|
15
|
+
debug_flag = context.ignored? ? '!' : ' '
|
16
|
+
if should_show_top_frame
|
17
|
+
if context.thread == Thread.current
|
18
|
+
file = @state.context.frame_file(0)
|
19
|
+
line = @state.context.frame_line(0)
|
20
|
+
else
|
21
|
+
if context.thread.backtrace_locations && context.thread.backtrace_locations[0]
|
22
|
+
file = context.thread.backtrace_locations[0].path
|
23
|
+
line = context.thread.backtrace_locations[0].lineno
|
24
|
+
end
|
25
|
+
end
|
26
|
+
file_line = "#{file}:#{line}"
|
27
|
+
end
|
28
|
+
{
|
29
|
+
status_flag: status_flag,
|
30
|
+
debug_flag: debug_flag,
|
31
|
+
id: context.thnum,
|
32
|
+
thread: context.thread.inspect,
|
33
|
+
file_line: file_line ? file_line : ''
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_thread_num(subcmd, arg)
|
38
|
+
if '' == arg
|
39
|
+
errmsg "\"#{subcmd}\" needs a thread number"
|
40
|
+
nil
|
41
|
+
else
|
42
|
+
thread_num = get_int(arg, subcmd, 1)
|
43
|
+
return nil unless thread_num
|
44
|
+
get_context(thread_num)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_thread_num_for_cmd(subcmd, arg)
|
49
|
+
c = parse_thread_num(subcmd, arg)
|
50
|
+
return nil unless c
|
51
|
+
case
|
52
|
+
when nil == c
|
53
|
+
errmsg 'No such thread'
|
54
|
+
when @state.context == c
|
55
|
+
errmsg "It's the current thread"
|
56
|
+
when c.ignored?
|
57
|
+
errmsg "Can't #{subcmd} thread #{arg}"
|
58
|
+
else
|
59
|
+
return c
|
60
|
+
end
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class ThreadListCommand < Command
|
67
|
+
self.allow_in_control = true
|
68
|
+
|
69
|
+
def regexp
|
70
|
+
/^\s* th(?:read)? \s+ l(?:ist)? \s*$/x
|
71
|
+
end
|
72
|
+
|
73
|
+
def execute
|
74
|
+
Byebug.contexts.sort_by(&:thnum).each { |c| display_context(c) }
|
75
|
+
end
|
76
|
+
|
77
|
+
class << self
|
78
|
+
def names
|
79
|
+
%w(thread)
|
80
|
+
end
|
81
|
+
|
82
|
+
def description
|
83
|
+
%{
|
84
|
+
th[read] l[ist]\t\t\tlist all threads
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class ThreadCurrentCommand < Command
|
91
|
+
self.need_context = true
|
92
|
+
|
93
|
+
def regexp
|
94
|
+
/^\s* th(?:read)? \s+ (?:cur(?:rent)?)? \s*$/x
|
95
|
+
end
|
96
|
+
|
97
|
+
def execute
|
98
|
+
display_context(@state.context)
|
99
|
+
end
|
100
|
+
|
101
|
+
class << self
|
102
|
+
def names
|
103
|
+
%w(thread)
|
104
|
+
end
|
105
|
+
|
106
|
+
def description
|
107
|
+
%{th[read] [cur[rent]]\t\tshow current thread}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class ThreadStopCommand < Command
|
113
|
+
self.allow_in_control = true
|
114
|
+
self.allow_in_post_mortem = false
|
115
|
+
self.need_context = true
|
116
|
+
|
117
|
+
def regexp
|
118
|
+
/^\s* th(?:read)? \s+ stop \s* (\S*) \s*$/x
|
119
|
+
end
|
120
|
+
|
121
|
+
def execute
|
122
|
+
c = parse_thread_num_for_cmd('thread stop', @match[1])
|
123
|
+
return unless c
|
124
|
+
c.suspend
|
125
|
+
display_context(c)
|
126
|
+
end
|
127
|
+
|
128
|
+
class << self
|
129
|
+
def names
|
130
|
+
%w(thread)
|
131
|
+
end
|
132
|
+
|
133
|
+
def description
|
134
|
+
%{th[read] stop <nnn>\t\tstop thread nnn}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class ThreadResumeCommand < Command
|
140
|
+
self.allow_in_control = true
|
141
|
+
self.allow_in_post_mortem = false
|
142
|
+
self.need_context = true
|
143
|
+
|
144
|
+
def regexp
|
145
|
+
/^\s* th(?:read)? \s+ resume \s* (\S*) \s*$/x
|
146
|
+
end
|
147
|
+
|
148
|
+
def execute
|
149
|
+
c = parse_thread_num_for_cmd('thread resume', @match[1])
|
150
|
+
return unless c
|
151
|
+
if !c.suspended?
|
152
|
+
errmsg 'Already running'
|
153
|
+
return
|
154
|
+
end
|
155
|
+
c.resume
|
156
|
+
display_context(c)
|
157
|
+
end
|
158
|
+
|
159
|
+
class << self
|
160
|
+
def names
|
161
|
+
%w(thread)
|
162
|
+
end
|
163
|
+
|
164
|
+
def description
|
165
|
+
%{th[read] resume <nnn>\t\tresume thread nnn}
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class ThreadSwitchCommand < Command
|
171
|
+
self.allow_in_control = true
|
172
|
+
self.allow_in_post_mortem = false
|
173
|
+
self.need_context = true
|
174
|
+
|
175
|
+
def regexp
|
176
|
+
/^\s* th(?:read)? \s+ (?:sw(?:itch)?\s+)? (\S+) \s*$/x
|
177
|
+
end
|
178
|
+
|
179
|
+
def execute
|
180
|
+
if @match[1] =~ /switch/
|
181
|
+
errmsg '"thread switch" needs a thread number'
|
182
|
+
return
|
183
|
+
end
|
184
|
+
c = parse_thread_num_for_cmd('thread switch', @match[1])
|
185
|
+
return unless c
|
186
|
+
display_context(c)
|
187
|
+
c.step_into 1
|
188
|
+
c.thread.run
|
189
|
+
@state.proceed
|
190
|
+
end
|
191
|
+
|
192
|
+
class << self
|
193
|
+
def names
|
194
|
+
%w(thread)
|
195
|
+
end
|
196
|
+
|
197
|
+
def description
|
198
|
+
%{th[read] [sw[itch]] <nnn>\tswitch thread context to nnn}
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
data/lib/byebug/helper.rb
CHANGED
@@ -11,15 +11,15 @@ module Byebug
|
|
11
11
|
begin
|
12
12
|
int = Integer(str)
|
13
13
|
if min and int < min
|
14
|
-
print "#{cmd} argument \"#{str}\" needs to be at least #{min}.\n"
|
14
|
+
print "\"#{cmd}\" argument \"#{str}\" needs to be at least #{min}.\n"
|
15
15
|
return nil
|
16
16
|
elsif max and int > max
|
17
|
-
print "#{cmd} argument \"#{str}\" needs to be at most #{max}.\n"
|
17
|
+
print "\"#{cmd}\" argument \"#{str}\" needs to be at most #{max}.\n"
|
18
18
|
return nil
|
19
19
|
end
|
20
20
|
return int
|
21
21
|
rescue
|
22
|
-
print "#{cmd} argument \"#{str}\" needs to be a number.\n"
|
22
|
+
print "\"#{cmd}\" argument \"#{str}\" needs to be a number.\n"
|
23
23
|
return nil
|
24
24
|
end
|
25
25
|
end
|
data/lib/byebug/interface.rb
CHANGED
@@ -10,23 +10,8 @@ module Byebug
|
|
10
10
|
# Common routine for reporting byebug error messages.
|
11
11
|
# Derived classes may want to override this to capture output.
|
12
12
|
def errmsg(*args)
|
13
|
-
|
14
|
-
|
15
|
-
print(*args)
|
16
|
-
aprint ''
|
17
|
-
else
|
18
|
-
print '*** '
|
19
|
-
print(*args)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Format msg with gdb-style annotation header
|
24
|
-
def afmt(msg, newline="\n")
|
25
|
-
"\032\032#{msg}#{newline}"
|
26
|
-
end
|
27
|
-
|
28
|
-
def aprint(msg)
|
29
|
-
print afmt(msg) if Byebug.annotate.to_i > 2
|
13
|
+
print '*** '
|
14
|
+
print(*args)
|
30
15
|
end
|
31
16
|
|
32
17
|
def format(*args)
|
@@ -83,9 +68,6 @@ module Byebug
|
|
83
68
|
|
84
69
|
# Things to do before quitting
|
85
70
|
def finalize
|
86
|
-
if Byebug.method_defined?("annotate") and Byebug.annotate.to_i > 2
|
87
|
-
print "\032\032exited\n\n"
|
88
|
-
end
|
89
71
|
if Byebug.respond_to?(:save_history)
|
90
72
|
Byebug.save_history
|
91
73
|
end
|
data/lib/byebug/processor.rb
CHANGED
@@ -9,7 +9,7 @@ module Byebug
|
|
9
9
|
attr_accessor :interface
|
10
10
|
|
11
11
|
extend Forwardable
|
12
|
-
def_delegators :@interface, :errmsg, :print
|
12
|
+
def_delegators :@interface, :errmsg, :print
|
13
13
|
|
14
14
|
def initialize(interface)
|
15
15
|
@interface = interface
|
@@ -19,22 +19,6 @@ module Byebug
|
|
19
19
|
class CommandProcessor < Processor
|
20
20
|
attr_reader :display
|
21
21
|
|
22
|
-
@@Show_breakpoints_postcmd = [ Byebug::BreakCommand.new(nil).regexp,
|
23
|
-
Byebug::ConditionCommand.new(nil).regexp,
|
24
|
-
Byebug::DeleteCommand.new(nil).regexp,
|
25
|
-
Byebug::DisableCommand.new(nil).regexp,
|
26
|
-
Byebug::EnableCommand.new(nil).regexp
|
27
|
-
]
|
28
|
-
@@Show_annotations_run = [ Byebug::ContinueCommand.new(nil).regexp,
|
29
|
-
Byebug::FinishCommand.new(nil).regexp,
|
30
|
-
Byebug::NextCommand.new(nil).regexp,
|
31
|
-
Byebug::StepCommand.new(nil).regexp
|
32
|
-
]
|
33
|
-
@@Show_annotations_postcmd = [ Byebug::DownCommand.new(nil).regexp,
|
34
|
-
Byebug::FrameCommand.new(nil).regexp,
|
35
|
-
Byebug::UpCommand.new(nil).regexp
|
36
|
-
]
|
37
|
-
|
38
22
|
def initialize(interface = LocalInterface.new)
|
39
23
|
super(interface)
|
40
24
|
|
@@ -43,8 +27,6 @@ module Byebug
|
|
43
27
|
@last_cmd = nil # To allow empty (just <RET>) commands
|
44
28
|
@last_file = nil # Filename the last time we stopped
|
45
29
|
@last_line = nil # Line number the last time we stopped
|
46
|
-
@breakpoints_were_empty = false # Show breakpoints 1st time
|
47
|
-
@displays_were_empty = true # No display 1st time
|
48
30
|
@context_was_dead = false # Assume we haven't started.
|
49
31
|
end
|
50
32
|
|
@@ -57,7 +39,7 @@ module Byebug
|
|
57
39
|
|
58
40
|
require 'pathname' # For cleanpath
|
59
41
|
|
60
|
-
|
42
|
+
#
|
61
43
|
# Regularize file name.
|
62
44
|
#
|
63
45
|
# This is also used as a common funnel place if basename is desired or if we
|
@@ -95,17 +77,14 @@ module Byebug
|
|
95
77
|
end
|
96
78
|
|
97
79
|
def at_breakpoint(context, breakpoint)
|
98
|
-
aprint 'stopped'
|
99
80
|
n = Byebug.breakpoints.index(breakpoint) + 1
|
100
81
|
file = CommandProcessor.canonic_file(breakpoint.source)
|
101
82
|
line = breakpoint.pos
|
102
|
-
aprint "source #{file}:#{line}"
|
103
83
|
print "Stopped by breakpoint #{n} at #{file}:#{line}\n"
|
104
84
|
end
|
105
85
|
protect :at_breakpoint
|
106
86
|
|
107
87
|
def at_catchpoint(context, excpt)
|
108
|
-
aprint 'stopped'
|
109
88
|
file = CommandProcessor.canonic_file(context.frame_file(0))
|
110
89
|
line = context.frame_line(0)
|
111
90
|
print "Catchpoint at %s:%d: `%s' (%s)\n", file, line, excpt, excpt.class
|
@@ -120,10 +99,8 @@ module Byebug
|
|
120
99
|
protect :at_catchpoint
|
121
100
|
|
122
101
|
def at_tracing(context, file, line)
|
123
|
-
if file != @last_file || line != @last_line ||
|
124
|
-
|
125
|
-
@last_file = file
|
126
|
-
@last_line = line
|
102
|
+
if file != @last_file || line != @last_line || Command.settings[:linetrace_plus]
|
103
|
+
@last_file, @last_line = file, line
|
127
104
|
print "Tracing: #{CommandProcessor.canonic_file(file)}:#{line} " \
|
128
105
|
"#{Byebug.line_at(file,line)}\n"
|
129
106
|
end
|
@@ -142,16 +119,14 @@ module Byebug
|
|
142
119
|
protect :at_return
|
143
120
|
|
144
121
|
private
|
145
|
-
|
122
|
+
#
|
146
123
|
# Prompt shown before reading a command.
|
147
124
|
#
|
148
125
|
def prompt(context)
|
149
|
-
|
150
|
-
p = afmt("pre-prompt")+p+"\n"+afmt("prompt") if Byebug.annotate.to_i > 2
|
151
|
-
return p
|
126
|
+
return "(byebug#{context.dead? ? ':post-mortem' : ''}) "
|
152
127
|
end
|
153
128
|
|
154
|
-
|
129
|
+
#
|
155
130
|
# Run commands everytime.
|
156
131
|
#
|
157
132
|
# For example display commands or possibly the list or irb in an
|
@@ -181,7 +156,7 @@ module Byebug
|
|
181
156
|
return state, commands
|
182
157
|
end
|
183
158
|
|
184
|
-
|
159
|
+
#
|
185
160
|
# Splits a command line of the form "cmd1 ; cmd2 ; ... ; cmdN" into an
|
186
161
|
# array of commands: [cmd1, cmd2, ..., cmdN]
|
187
162
|
#
|
@@ -201,7 +176,7 @@ module Byebug
|
|
201
176
|
end
|
202
177
|
end
|
203
178
|
|
204
|
-
|
179
|
+
#
|
205
180
|
# Handle byebug commands.
|
206
181
|
#
|
207
182
|
def process_commands(context, file, line)
|
@@ -209,7 +184,7 @@ module Byebug
|
|
209
184
|
$state = Command.settings[:testing] ? state : nil
|
210
185
|
|
211
186
|
preloop(commands, context)
|
212
|
-
|
187
|
+
print state.location if Command.settings[:autolist] == 0
|
213
188
|
|
214
189
|
while !state.proceed?
|
215
190
|
input = @interface.command_queue.empty? ?
|
@@ -225,25 +200,23 @@ module Byebug
|
|
225
200
|
end
|
226
201
|
split_commands(input).each do |cmd|
|
227
202
|
one_cmd(commands, context, cmd)
|
228
|
-
postcmd(commands, context, cmd)
|
229
203
|
end
|
230
204
|
end
|
231
205
|
end
|
232
|
-
postloop(commands, context)
|
233
206
|
end
|
234
207
|
|
235
|
-
|
208
|
+
#
|
236
209
|
# Executes a single byebug command
|
237
210
|
#
|
238
211
|
def one_cmd(commands, context, input)
|
239
|
-
if cmd = commands.find{ |c| c.match(input) }
|
212
|
+
if cmd = commands.find { |c| c.match(input) }
|
240
213
|
if context.dead? && cmd.class.need_context
|
241
214
|
print "Command is unavailable\n"
|
242
215
|
else
|
243
216
|
cmd.execute
|
244
217
|
end
|
245
218
|
else
|
246
|
-
unknown_cmd = commands.find{ |c| c.class.unknown }
|
219
|
+
unknown_cmd = commands.find { |c| c.class.unknown }
|
247
220
|
if unknown_cmd
|
248
221
|
unknown_cmd.execute
|
249
222
|
else
|
@@ -252,65 +225,16 @@ module Byebug
|
|
252
225
|
end
|
253
226
|
end
|
254
227
|
|
228
|
+
#
|
229
|
+
# Tasks to do before processor loop
|
230
|
+
#
|
255
231
|
def preloop(commands, context)
|
256
232
|
@context_was_dead = true if context.dead? and not @context_was_dead
|
257
233
|
|
258
|
-
aprint 'stopped'
|
259
234
|
if @context_was_dead
|
260
|
-
aprint 'exited'
|
261
235
|
print "The program finished.\n"
|
262
236
|
@context_was_dead = false
|
263
237
|
end
|
264
|
-
|
265
|
-
if Byebug.annotate.to_i > 2
|
266
|
-
breakpoint_annotations(commands, context)
|
267
|
-
display_annotations(commands, context)
|
268
|
-
annotation('stack', commands, context, "where")
|
269
|
-
annotation('variables', commands, context, "info variables") unless
|
270
|
-
context.dead?
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
def postcmd(commands, context, cmd)
|
275
|
-
if Byebug.annotate.to_i > 2
|
276
|
-
cmd = @last_cmd unless cmd
|
277
|
-
breakpoint_annotations(commands, context) if
|
278
|
-
@@Show_breakpoints_postcmd.find{|pat| cmd =~ pat}
|
279
|
-
display_annotations(commands, context)
|
280
|
-
if @@Show_annotations_postcmd.find{|pat| cmd =~ pat}
|
281
|
-
annotation('stack', commands, context, "where") if
|
282
|
-
context.stack_size > 0
|
283
|
-
annotation('variables', commands, context, "info variables") unless
|
284
|
-
context.dead?
|
285
|
-
end
|
286
|
-
if not context.dead? and @@Show_annotations_run.find{|pat| cmd =~ pat}
|
287
|
-
afmt 'starting'
|
288
|
-
@context_was_dead = false
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def postloop(commands, context)
|
294
|
-
end
|
295
|
-
|
296
|
-
def annotation(label, commands, context, cmd)
|
297
|
-
print afmt(label)
|
298
|
-
one_cmd(commands, context, cmd)
|
299
|
-
end
|
300
|
-
|
301
|
-
def breakpoint_annotations(commands, context)
|
302
|
-
unless Byebug.breakpoints.empty? and @breakpoints_were_empty
|
303
|
-
annotation('breakpoints', commands, context, "info breakpoints")
|
304
|
-
@breakpoints_were_empty = Byebug.breakpoints.empty?
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
def display_annotations(commands, context)
|
309
|
-
return if display.empty?
|
310
|
-
have_display = display.find{|d| d[0]}
|
311
|
-
return unless have_display and @displays_were_empty
|
312
|
-
@displays_were_empty = have_display
|
313
|
-
annotation('display', commands, context, "display")
|
314
238
|
end
|
315
239
|
|
316
240
|
class State
|
@@ -324,7 +248,7 @@ module Byebug
|
|
324
248
|
end
|
325
249
|
|
326
250
|
extend Forwardable
|
327
|
-
def_delegators :@interface, :
|
251
|
+
def_delegators :@interface, :errmsg, :print, :confirm
|
328
252
|
|
329
253
|
def proceed?
|
330
254
|
@proceed
|
@@ -345,7 +269,6 @@ module Byebug
|
|
345
269
|
|
346
270
|
|
347
271
|
class ControlCommandProcessor < Processor
|
348
|
-
|
349
272
|
def initialize(interface)
|
350
273
|
super(interface)
|
351
274
|
@context_was_dead = false # Assume we haven't started.
|
@@ -359,7 +282,6 @@ module Byebug
|
|
359
282
|
commands = control_cmds.map{|cmd| cmd.new(state) }
|
360
283
|
|
361
284
|
if @context_was_dead
|
362
|
-
aprint 'exited'
|
363
285
|
print "The program finished.\n"
|
364
286
|
@context_was_dead = false
|
365
287
|
end
|
@@ -382,12 +304,11 @@ module Byebug
|
|
382
304
|
@interface.close
|
383
305
|
end
|
384
306
|
|
385
|
-
#
|
386
|
-
#
|
307
|
+
#
|
308
|
+
# Prompt shown before reading a command.
|
309
|
+
#
|
387
310
|
def prompt(context)
|
388
|
-
|
389
|
-
p = afmt("pre-prompt") +p+"\n"+ afmt("prompt") if Byebug.annotate.to_i > 2
|
390
|
-
return p
|
311
|
+
return '(byebug:ctrl) '
|
391
312
|
end
|
392
313
|
|
393
314
|
class State
|