debug 1.6.1 → 1.9.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 +4 -4
- data/CONTRIBUTING.md +22 -10
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +84 -55
- data/Rakefile +8 -3
- data/TODO.md +8 -8
- data/debug.gemspec +3 -3
- data/exe/rdbg +19 -4
- data/ext/debug/debug.c +33 -5
- data/ext/debug/extconf.rb +1 -0
- data/ext/debug/iseq_collector.c +2 -0
- data/lib/debug/abbrev_command.rb +77 -0
- data/lib/debug/breakpoint.rb +15 -11
- data/lib/debug/client.rb +26 -8
- data/lib/debug/color.rb +0 -0
- data/lib/debug/config.rb +69 -23
- data/lib/debug/console.rb +8 -29
- data/lib/debug/dap_custom/traceInspector.rb +336 -0
- data/lib/debug/frame_info.rb +9 -0
- data/lib/debug/irb_integration.rb +27 -0
- data/lib/debug/local.rb +16 -10
- data/lib/debug/open.rb +0 -0
- data/lib/debug/open_nonstop.rb +0 -0
- data/lib/debug/prelude.rb +2 -1
- data/lib/debug/server.rb +32 -27
- data/lib/debug/server_cdp.rb +360 -155
- data/lib/debug/server_dap.rb +330 -197
- data/lib/debug/session.rb +494 -258
- data/lib/debug/source_repository.rb +41 -21
- data/lib/debug/start.rb +1 -1
- data/lib/debug/thread_client.rb +241 -82
- data/lib/debug/tracer.rb +4 -5
- data/lib/debug/version.rb +1 -1
- data/lib/debug.rb +7 -2
- data/misc/README.md.erb +50 -44
- metadata +13 -10
data/ext/debug/debug.c
CHANGED
@@ -62,21 +62,34 @@ di_body(const rb_debug_inspector_t *dc, void *ptr)
|
|
62
62
|
long i;
|
63
63
|
|
64
64
|
for (i=1; i<len; i++) {
|
65
|
-
VALUE
|
65
|
+
VALUE e;
|
66
66
|
VALUE iseq = rb_debug_inspector_frame_iseq_get(dc, i);
|
67
|
+
VALUE loc = RARRAY_AREF(locs, i);
|
68
|
+
VALUE path;
|
67
69
|
|
68
70
|
if (!NIL_P(iseq)) {
|
69
|
-
|
70
|
-
|
71
|
+
path = iseq_realpath(iseq);
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
// C frame
|
75
|
+
path = rb_funcall(loc, rb_intern("path"), 0);
|
76
|
+
}
|
77
|
+
|
78
|
+
if (!NIL_P(path) && !NIL_P(skip_path_prefix) && str_start_with(path, skip_path_prefix)) {
|
79
|
+
continue;
|
71
80
|
}
|
72
81
|
|
73
|
-
loc = RARRAY_AREF(locs, i);
|
74
82
|
e = di_entry(loc,
|
75
83
|
rb_debug_inspector_frame_self_get(dc, i),
|
76
84
|
rb_debug_inspector_frame_binding_get(dc, i),
|
77
85
|
iseq,
|
78
86
|
rb_debug_inspector_frame_class_get(dc, i),
|
79
|
-
|
87
|
+
#ifdef RB_DEBUG_INSPECTOR_FRAME_DEPTH
|
88
|
+
rb_debug_inspector_frame_depth(dc, i)
|
89
|
+
#else
|
90
|
+
INT2FIX(len - i)
|
91
|
+
#endif
|
92
|
+
);
|
80
93
|
rb_ary_push(ary, e);
|
81
94
|
}
|
82
95
|
|
@@ -89,6 +102,13 @@ capture_frames(VALUE self, VALUE skip_path_prefix)
|
|
89
102
|
return rb_debug_inspector_open(di_body, (void *)skip_path_prefix);
|
90
103
|
}
|
91
104
|
|
105
|
+
#ifdef RB_DEBUG_INSPECTOR_FRAME_DEPTH
|
106
|
+
static VALUE
|
107
|
+
frame_depth(VALUE self)
|
108
|
+
{
|
109
|
+
return rb_debug_inspector_current_depth();
|
110
|
+
}
|
111
|
+
#else
|
92
112
|
static VALUE
|
93
113
|
frame_depth(VALUE self)
|
94
114
|
{
|
@@ -96,6 +116,8 @@ frame_depth(VALUE self)
|
|
96
116
|
VALUE bt = rb_make_backtrace();
|
97
117
|
return INT2FIX(RARRAY_LEN(bt));
|
98
118
|
}
|
119
|
+
#endif
|
120
|
+
|
99
121
|
|
100
122
|
// iseq
|
101
123
|
|
@@ -166,13 +188,17 @@ iseq_last_line(VALUE iseqw)
|
|
166
188
|
}
|
167
189
|
#endif
|
168
190
|
|
191
|
+
#ifdef HAVE_RB_ISEQ
|
169
192
|
void Init_iseq_collector(void);
|
193
|
+
#endif
|
170
194
|
|
171
195
|
void
|
172
196
|
Init_debug(void)
|
173
197
|
{
|
198
|
+
#ifdef HAVE_RB_ISEQ
|
174
199
|
VALUE rb_mRubyVM = rb_const_get(rb_cObject, rb_intern("RubyVM"));
|
175
200
|
VALUE rb_cISeq = rb_const_get(rb_mRubyVM, rb_intern("InstructionSequence"));
|
201
|
+
#endif
|
176
202
|
rb_mDebugger = rb_const_get(rb_cObject, rb_intern("DEBUGGER__"));
|
177
203
|
rb_cFrameInfo = rb_const_get(rb_mDebugger, rb_intern("FrameInfo"));
|
178
204
|
|
@@ -196,5 +222,7 @@ Init_debug(void)
|
|
196
222
|
rb_define_method(rb_cISeq, "last_line", iseq_last_line, 0);
|
197
223
|
#endif
|
198
224
|
|
225
|
+
#ifdef HAVE_RB_ISEQ
|
199
226
|
Init_iseq_collector();
|
227
|
+
#endif
|
200
228
|
}
|
data/ext/debug/extconf.rb
CHANGED
data/ext/debug/iseq_collector.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include <ruby/ruby.h>
|
2
2
|
|
3
|
+
#ifdef HAVE_RB_ISEQ
|
3
4
|
VALUE rb_iseqw_new(VALUE v);
|
4
5
|
void rb_objspace_each_objects(
|
5
6
|
int (*callback)(void *start, void *end, size_t stride, void *data),
|
@@ -89,3 +90,4 @@ Init_iseq_collector(void)
|
|
89
90
|
rb_define_singleton_method(rb_mObjSpace, "each_iseq", each_iseq, 0);
|
90
91
|
rb_define_singleton_method(rb_mObjSpace, "count_iseq", count_iseq, 0);
|
91
92
|
}
|
93
|
+
#endif
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
module DEBUGGER__
|
3
|
+
class AbbrevCommand
|
4
|
+
class TrieNode
|
5
|
+
def initialize
|
6
|
+
@children = {}
|
7
|
+
@types = {} # set
|
8
|
+
end
|
9
|
+
|
10
|
+
def append c, type
|
11
|
+
trie = (@children[c] ||= TrieNode.new)
|
12
|
+
trie.add_type type
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](c)
|
16
|
+
@children[c]
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_type type
|
20
|
+
@types[type] = true
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def types
|
25
|
+
@types.keys
|
26
|
+
end
|
27
|
+
|
28
|
+
def type
|
29
|
+
if @types.size == 1
|
30
|
+
@types.keys.first
|
31
|
+
else
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def candidates
|
37
|
+
@children.map{|c, n|
|
38
|
+
ss = n.candidates
|
39
|
+
ss.empty? ? c :
|
40
|
+
ss.map{|s|
|
41
|
+
c+s
|
42
|
+
}
|
43
|
+
}.flatten
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# config: { type: [commands...], ... }
|
48
|
+
def initialize config
|
49
|
+
@trie = TrieNode.new
|
50
|
+
build config
|
51
|
+
end
|
52
|
+
|
53
|
+
private def build config
|
54
|
+
config.each do |type, commands|
|
55
|
+
commands.each do |command|
|
56
|
+
trie = @trie
|
57
|
+
command.each_char do |c|
|
58
|
+
trie = trie.append(c, type)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def search str, if_none = nil
|
65
|
+
trie = @trie
|
66
|
+
str.each_char do |c|
|
67
|
+
if trie = trie[c]
|
68
|
+
return trie.type if trie.type
|
69
|
+
else
|
70
|
+
return if_none
|
71
|
+
end
|
72
|
+
end
|
73
|
+
yield trie.candidates.map{|s| str + s} if block_given?
|
74
|
+
if_none
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/debug/breakpoint.rb
CHANGED
@@ -6,7 +6,7 @@ module DEBUGGER__
|
|
6
6
|
class Breakpoint
|
7
7
|
include SkipPathHelper
|
8
8
|
|
9
|
-
attr_reader :key
|
9
|
+
attr_reader :key, :skip_src
|
10
10
|
|
11
11
|
def initialize cond, command, path, do_enable: true
|
12
12
|
@deleted = false
|
@@ -141,10 +141,11 @@ module DEBUGGER__
|
|
141
141
|
nbp
|
142
142
|
end
|
143
143
|
|
144
|
-
def initialize path, line, cond: nil, oneshot: false, hook_call: true, command: nil, skip_activate: false
|
144
|
+
def initialize path, line, cond: nil, oneshot: false, hook_call: true, command: nil, skip_activate: false, skip_src: false
|
145
145
|
@line = line
|
146
146
|
@oneshot = oneshot
|
147
147
|
@hook_call = hook_call
|
148
|
+
@skip_src = skip_src
|
148
149
|
@pending = false
|
149
150
|
|
150
151
|
@iseq = nil
|
@@ -196,8 +197,10 @@ module DEBUGGER__
|
|
196
197
|
enable
|
197
198
|
|
198
199
|
if @pending && !@oneshot
|
199
|
-
DEBUGGER__.
|
200
|
+
DEBUGGER__.info "#{self} is activated."
|
200
201
|
end
|
202
|
+
|
203
|
+
@pending = false
|
201
204
|
end
|
202
205
|
|
203
206
|
def activate_exact iseq, events, line
|
@@ -264,13 +267,10 @@ module DEBUGGER__
|
|
264
267
|
|
265
268
|
if !nearest || ((line - nline).abs < (line - nearest.line).abs)
|
266
269
|
nearest = NearestISeq.new(iseq, nline, events)
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
nearest = NearestISeq.new(iseq, nline, events)
|
272
|
-
end
|
273
|
-
end
|
270
|
+
elsif @hook_call &&
|
271
|
+
nearest.line == iseq.first_line &&
|
272
|
+
events.include?(:RUBY_EVENT_CALL)
|
273
|
+
nearest = NearestISeq.new(iseq, nline, events)
|
274
274
|
end
|
275
275
|
end
|
276
276
|
end
|
@@ -293,6 +293,10 @@ module DEBUGGER__
|
|
293
293
|
def inspect
|
294
294
|
"<#{self.class.name} #{self.to_s}>"
|
295
295
|
end
|
296
|
+
|
297
|
+
def path_is? path
|
298
|
+
DEBUGGER__.compare_path(@path, path)
|
299
|
+
end
|
296
300
|
end
|
297
301
|
|
298
302
|
class CatchBreakpoint < Breakpoint
|
@@ -500,7 +504,7 @@ module DEBUGGER__
|
|
500
504
|
retried = false
|
501
505
|
|
502
506
|
@tp.enable(target: @method)
|
503
|
-
DEBUGGER__.
|
507
|
+
DEBUGGER__.info "#{self} is activated." if added
|
504
508
|
|
505
509
|
if @sig_op == '#'
|
506
510
|
@cond_class = @klass if @method.owner != @klass
|
data/lib/debug/client.rb
CHANGED
@@ -25,6 +25,9 @@ module DEBUGGER__
|
|
25
25
|
when 'list-socks'
|
26
26
|
cleanup_unix_domain_sockets
|
27
27
|
puts list_connections
|
28
|
+
when 'list-socks-verbose'
|
29
|
+
cleanup_unix_domain_sockets
|
30
|
+
puts list_connections verbose: true
|
28
31
|
when 'setup-autoload'
|
29
32
|
setup_autoload
|
30
33
|
else
|
@@ -42,7 +45,7 @@ module DEBUGGER__
|
|
42
45
|
when /csh/
|
43
46
|
:csh
|
44
47
|
when /zsh/
|
45
|
-
:
|
48
|
+
:zsh
|
46
49
|
when /dash/
|
47
50
|
:dash
|
48
51
|
else
|
@@ -91,10 +94,24 @@ module DEBUGGER__
|
|
91
94
|
end
|
92
95
|
end
|
93
96
|
|
94
|
-
def list_connections
|
95
|
-
Dir.glob(DEBUGGER__.create_unix_domain_socket_name_prefix + '*').find_all do |path|
|
97
|
+
def list_connections verbose: false
|
98
|
+
socks = Dir.glob(DEBUGGER__.create_unix_domain_socket_name_prefix + '*').find_all do |path|
|
96
99
|
File.socket?(path)
|
97
100
|
end
|
101
|
+
|
102
|
+
if verbose
|
103
|
+
socks = socks.map{|sock_path|
|
104
|
+
Socket.unix(sock_path){|sock|
|
105
|
+
sock.puts "info cookie: #{CONFIG[:cookie] || '-'}"
|
106
|
+
pid = sock.gets.chomp
|
107
|
+
_dbg = sock.gets.chomp
|
108
|
+
_unm = sock.gets.chomp
|
109
|
+
[sock_path, pid]
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
socks
|
98
115
|
end
|
99
116
|
end
|
100
117
|
|
@@ -157,9 +174,10 @@ module DEBUGGER__
|
|
157
174
|
when 1
|
158
175
|
@s = Socket.unix(files.first)
|
159
176
|
else
|
177
|
+
files = Client.list_connections verbose: true
|
160
178
|
$stderr.puts "Please select a debug session:"
|
161
|
-
files.each{|f|
|
162
|
-
$stderr.puts " #{File.basename(f)}"
|
179
|
+
files.each{|(f, desc)|
|
180
|
+
$stderr.puts " #{File.basename(f)} (#{desc})"
|
163
181
|
}
|
164
182
|
exit
|
165
183
|
end
|
@@ -222,7 +240,7 @@ module DEBUGGER__
|
|
222
240
|
when /^ask (\d+) (.*)/
|
223
241
|
pid = $1
|
224
242
|
print $2
|
225
|
-
send "answer #{pid} #{gets || ''}"
|
243
|
+
send "answer #{pid} #{$stdin.gets || ''}"
|
226
244
|
|
227
245
|
when /^quit/
|
228
246
|
raise 'quit'
|
@@ -231,8 +249,8 @@ module DEBUGGER__
|
|
231
249
|
puts "(unknown) #{line.inspect}"
|
232
250
|
end
|
233
251
|
end
|
234
|
-
rescue
|
235
|
-
STDERR.puts "disconnected (#{
|
252
|
+
rescue => e
|
253
|
+
STDERR.puts "disconnected (#{e})"
|
236
254
|
exit
|
237
255
|
ensure
|
238
256
|
deactivate
|
data/lib/debug/color.rb
CHANGED
File without changes
|
data/lib/debug/config.rb
CHANGED
@@ -14,12 +14,15 @@ module DEBUGGER__
|
|
14
14
|
# UI setting
|
15
15
|
log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger", :loglevel, "WARN"],
|
16
16
|
show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint", :int, "10"],
|
17
|
+
show_evaledsrc: ['RUBY_DEBUG_SHOW_EVALEDSRC', "UI: Show actually evaluated source", :bool, "false"],
|
17
18
|
show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint", :int, "2"],
|
18
19
|
use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)", :bool, "false"],
|
19
20
|
no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize", :bool, "false"],
|
20
21
|
no_sigint_hook: ['RUBY_DEBUG_NO_SIGINT_HOOK', "UI: Do not suspend on SIGINT", :bool, "false"],
|
21
22
|
no_reline: ['RUBY_DEBUG_NO_RELINE', "UI: Do not use Reline library", :bool, "false"],
|
22
23
|
no_hint: ['RUBY_DEBUG_NO_HINT', "UI: Do not show the hint on the REPL", :bool, "false"],
|
24
|
+
no_lineno: ['RUBY_DEBUG_NO_LINENO', "UI: Do not show line numbers", :bool, "false"],
|
25
|
+
irb_console: ["RUBY_DEBUG_IRB_CONSOLE", "UI: Use IRB as the console", :bool, "false"],
|
23
26
|
|
24
27
|
# control setting
|
25
28
|
skip_path: ['RUBY_DEBUG_SKIP_PATH', "CONTROL: Skip showing/entering frames for given paths", :path],
|
@@ -33,12 +36,13 @@ module DEBUGGER__
|
|
33
36
|
nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool, "false"],
|
34
37
|
stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool, "false"],
|
35
38
|
init_script: ['RUBY_DEBUG_INIT_SCRIPT', "BOOT: debug command script path loaded at first stop"],
|
36
|
-
commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop.
|
39
|
+
commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop. Commands should be separated by `;;`"],
|
37
40
|
no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool, "false"],
|
38
41
|
history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file", :string, "~/.rdbg_history"],
|
39
42
|
save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines", :int, "10000"],
|
40
43
|
|
41
44
|
# remote setting
|
45
|
+
open: ['RUBY_DEBUG_OPEN', "REMOTE: Open remote port (same as `rdbg --open` option)"],
|
42
46
|
port: ['RUBY_DEBUG_PORT', "REMOTE: TCP/IP remote debugging: port"],
|
43
47
|
host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host", :string, "127.0.0.1"],
|
44
48
|
sock_path: ['RUBY_DEBUG_SOCK_PATH', "REMOTE: UNIX Domain Socket remote debugging: socket path"],
|
@@ -46,7 +50,7 @@ module DEBUGGER__
|
|
46
50
|
local_fs_map: ['RUBY_DEBUG_LOCAL_FS_MAP', "REMOTE: Specify local fs map", :path_map],
|
47
51
|
skip_bp: ['RUBY_DEBUG_SKIP_BP', "REMOTE: Skip breakpoints if no clients are attached", :bool, 'false'],
|
48
52
|
cookie: ['RUBY_DEBUG_COOKIE', "REMOTE: Cookie for negotiation"],
|
49
|
-
|
53
|
+
session_name: ['RUBY_DEBUG_SESSION_NAME', "REMOTE: Session name for differentiating multiple sessions"],
|
50
54
|
chrome_path: ['RUBY_DEBUG_CHROME_PATH', "REMOTE: Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))"],
|
51
55
|
|
52
56
|
# obsolete
|
@@ -63,8 +67,6 @@ module DEBUGGER__
|
|
63
67
|
end
|
64
68
|
|
65
69
|
def initialize argv
|
66
|
-
@skip_all = false
|
67
|
-
|
68
70
|
if self.class.config
|
69
71
|
raise 'Can not make multiple configurations in one process'
|
70
72
|
end
|
@@ -94,14 +96,6 @@ module DEBUGGER__
|
|
94
96
|
set_config(key => val)
|
95
97
|
end
|
96
98
|
|
97
|
-
def skip_all
|
98
|
-
@skip_all = true
|
99
|
-
end
|
100
|
-
|
101
|
-
def skip?
|
102
|
-
@skip_all
|
103
|
-
end
|
104
|
-
|
105
99
|
def set_config(**kw)
|
106
100
|
conf = config.dup
|
107
101
|
kw.each{|k, v|
|
@@ -158,6 +152,12 @@ module DEBUGGER__
|
|
158
152
|
if_updated old_conf, conf, :sigdump_sig do |old_sig, new_sig|
|
159
153
|
setup_sigdump old_sig, new_sig
|
160
154
|
end
|
155
|
+
|
156
|
+
if_updated old_conf, conf, :no_sigint_hook do |old, new|
|
157
|
+
if defined?(SESSION)
|
158
|
+
SESSION.set_no_sigint_hook old, new
|
159
|
+
end
|
160
|
+
end
|
161
161
|
end
|
162
162
|
|
163
163
|
private def if_updated old_conf, new_conf, key
|
@@ -268,6 +268,8 @@ module DEBUGGER__
|
|
268
268
|
require 'optparse'
|
269
269
|
require_relative 'version'
|
270
270
|
|
271
|
+
have_shown_version = false
|
272
|
+
|
271
273
|
opt = OptionParser.new do |o|
|
272
274
|
o.banner = "#{$0} [options] -- [debuggee options]"
|
273
275
|
o.separator ''
|
@@ -308,8 +310,25 @@ module DEBUGGER__
|
|
308
310
|
'If TCP/IP options are not given, a UNIX domain socket will be used.',
|
309
311
|
'If FRONTEND is given, prepare for the FRONTEND.',
|
310
312
|
'Now rdbg, vscode and chrome is supported.') do |f|
|
311
|
-
|
312
|
-
|
313
|
+
|
314
|
+
case f # some format patterns are not documented yet
|
315
|
+
when nil
|
316
|
+
config[:open] = true
|
317
|
+
when /\A\d\z/
|
318
|
+
config[:open] = true
|
319
|
+
config[:port] = f.to_i
|
320
|
+
when /\A(\S+):(\d+)\z/
|
321
|
+
config[:open] = true
|
322
|
+
config[:host] = $1
|
323
|
+
config[:port] = $2.to_i
|
324
|
+
when 'tcp'
|
325
|
+
config[:open] = true
|
326
|
+
config[:port] ||= 0
|
327
|
+
when 'vscode', 'chrome', 'cdp'
|
328
|
+
config[:open] = f&.downcase
|
329
|
+
else
|
330
|
+
raise "Unknown option for --open: #{f}"
|
331
|
+
end
|
313
332
|
end
|
314
333
|
o.on('--sock-path=SOCK_PATH', 'UNIX Domain socket path') do |path|
|
315
334
|
config[:sock_path] = path
|
@@ -323,6 +342,9 @@ module DEBUGGER__
|
|
323
342
|
o.on('--cookie=COOKIE', 'Set a cookie for connection') do |c|
|
324
343
|
config[:cookie] = c
|
325
344
|
end
|
345
|
+
o.on('--session-name=NAME', 'Session name') do |name|
|
346
|
+
config[:session_name] = name
|
347
|
+
end
|
326
348
|
|
327
349
|
rdbg = 'rdbg'
|
328
350
|
|
@@ -358,6 +380,16 @@ module DEBUGGER__
|
|
358
380
|
o.separator ''
|
359
381
|
o.separator 'Other options:'
|
360
382
|
|
383
|
+
o.on('-v', 'Show version number') do
|
384
|
+
puts o.ver
|
385
|
+
have_shown_version = true
|
386
|
+
end
|
387
|
+
|
388
|
+
o.on('--version', 'Show version number and exit') do
|
389
|
+
puts o.ver
|
390
|
+
exit
|
391
|
+
end
|
392
|
+
|
361
393
|
o.on("-h", "--help", "Print help") do
|
362
394
|
puts o
|
363
395
|
exit
|
@@ -381,6 +413,13 @@ module DEBUGGER__
|
|
381
413
|
|
382
414
|
opt.parse!(argv)
|
383
415
|
|
416
|
+
if argv.empty?
|
417
|
+
case
|
418
|
+
when have_shown_version && config[:mode] == :start
|
419
|
+
exit
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
384
423
|
config
|
385
424
|
end
|
386
425
|
|
@@ -411,8 +450,9 @@ module DEBUGGER__
|
|
411
450
|
unless (dir_uid = fs.uid) == (uid = Process.uid)
|
412
451
|
raise "#{path} uid is #{dir_uid}, but Process.uid is #{uid}"
|
413
452
|
end
|
414
|
-
|
415
|
-
|
453
|
+
|
454
|
+
if fs.world_writable? && !fs.sticky?
|
455
|
+
raise "#{path} is world writable but not sticky"
|
416
456
|
end
|
417
457
|
|
418
458
|
path
|
@@ -422,7 +462,7 @@ module DEBUGGER__
|
|
422
462
|
require 'tmpdir'
|
423
463
|
|
424
464
|
if tmpdir = Dir.tmpdir
|
425
|
-
path = File.join(tmpdir, "
|
465
|
+
path = File.join(tmpdir, "rdbg-#{Process.uid}")
|
426
466
|
|
427
467
|
unless File.exist?(path)
|
428
468
|
d = Dir.mktmpdir
|
@@ -435,7 +475,7 @@ module DEBUGGER__
|
|
435
475
|
|
436
476
|
def self.unix_domain_socket_homedir
|
437
477
|
if home = ENV['HOME']
|
438
|
-
path = File.join(home, '.
|
478
|
+
path = File.join(home, '.rdbg-sock')
|
439
479
|
|
440
480
|
unless File.exist?(path)
|
441
481
|
Dir.mkdir(path, 0700)
|
@@ -459,12 +499,14 @@ module DEBUGGER__
|
|
459
499
|
end
|
460
500
|
|
461
501
|
def self.create_unix_domain_socket_name_prefix(base_dir = unix_domain_socket_dir)
|
462
|
-
|
463
|
-
File.join(base_dir, "ruby-debug-#{user}")
|
502
|
+
File.join(base_dir, "rdbg")
|
464
503
|
end
|
465
504
|
|
466
505
|
def self.create_unix_domain_socket_name(base_dir = unix_domain_socket_dir)
|
467
|
-
|
506
|
+
suffix = "-#{Process.pid}"
|
507
|
+
name = CONFIG[:session_name]
|
508
|
+
suffix << "-#{name}" if name
|
509
|
+
create_unix_domain_socket_name_prefix(base_dir) + suffix
|
468
510
|
end
|
469
511
|
|
470
512
|
## Help
|
@@ -479,10 +521,14 @@ module DEBUGGER__
|
|
479
521
|
when /\A\s*### (.+)/
|
480
522
|
cat = $1
|
481
523
|
break if $1 == 'END'
|
482
|
-
when /\A
|
524
|
+
when /\A register_command (.+)/
|
483
525
|
next unless cat
|
484
526
|
next unless desc
|
485
|
-
|
527
|
+
|
528
|
+
ws = []
|
529
|
+
$1.gsub(/'([a-z]+)'/){|w|
|
530
|
+
ws << $1
|
531
|
+
}
|
486
532
|
helps[cat] << [ws, desc]
|
487
533
|
desc = nil
|
488
534
|
max_w = ws.max_by{|w| w.length}
|
data/lib/debug/console.rb
CHANGED
@@ -5,30 +5,9 @@ module DEBUGGER__
|
|
5
5
|
raise LoadError if CONFIG[:no_reline]
|
6
6
|
require 'reline'
|
7
7
|
|
8
|
-
# reline 0.2.7 or later is required.
|
9
|
-
raise LoadError if Reline::VERSION < '0.2.7'
|
10
|
-
|
11
8
|
require_relative 'color'
|
12
|
-
include Color
|
13
|
-
|
14
|
-
begin
|
15
|
-
prev = trap(:SIGWINCH, nil)
|
16
|
-
trap(:SIGWINCH, prev)
|
17
|
-
SIGWINCH_SUPPORTED = true
|
18
|
-
rescue ArgumentError
|
19
|
-
SIGWINCH_SUPPORTED = false
|
20
|
-
end
|
21
9
|
|
22
|
-
|
23
|
-
class ::Reline::LineEditor
|
24
|
-
m = Module.new do
|
25
|
-
def reset(prompt = '', encoding:)
|
26
|
-
super
|
27
|
-
Signal.trap(:SIGWINCH, nil)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
prepend m
|
31
|
-
end if SIGWINCH_SUPPORTED
|
10
|
+
include Color
|
32
11
|
|
33
12
|
def parse_input buff, commands
|
34
13
|
c, rest = get_command buff
|
@@ -56,10 +35,10 @@ module DEBUGGER__
|
|
56
35
|
Reline.prompt_proc = -> args, *kw do
|
57
36
|
case state = parse_input(args.first, commands)
|
58
37
|
when nil, :command
|
59
|
-
[prompt
|
38
|
+
[prompt]
|
60
39
|
when :ruby
|
61
|
-
[prompt.sub('rdbg'){colorize('ruby', [:RED])}]
|
62
|
-
end
|
40
|
+
[prompt.sub('rdbg'){colorize('ruby', [:RED])}]
|
41
|
+
end * args.size
|
63
42
|
end
|
64
43
|
|
65
44
|
Reline.completion_proc = -> given do
|
@@ -96,7 +75,7 @@ module DEBUGGER__
|
|
96
75
|
when nil
|
97
76
|
buff
|
98
77
|
when :ruby
|
99
|
-
colorize_code(buff
|
78
|
+
colorize_code(buff)
|
100
79
|
end
|
101
80
|
end unless CONFIG[:no_hint]
|
102
81
|
|
@@ -224,11 +203,11 @@ module DEBUGGER__
|
|
224
203
|
end
|
225
204
|
|
226
205
|
def load_history
|
227
|
-
read_history_file.
|
206
|
+
read_history_file.each{|line|
|
228
207
|
line.strip!
|
229
208
|
history << line unless line.empty?
|
230
|
-
}
|
209
|
+
} if history.empty?
|
210
|
+
history.count
|
231
211
|
end
|
232
212
|
end # class Console
|
233
213
|
end
|
234
|
-
|