debug 1.6.1 → 1.9.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|