byebug 2.1.1 → 2.2.0
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/.gitignore +1 -0
- data/CHANGELOG.md +9 -0
- data/CONTRIBUTING.md +13 -1
- data/GUIDE.md +181 -1
- data/README.md +67 -211
- data/Rakefile +1 -0
- data/bin/byebug +1 -8
- data/ext/byebug/byebug.c +66 -25
- data/ext/byebug/context.c +16 -20
- data/ext/byebug/extconf.rb +2 -1
- data/lib/byebug.rb +16 -9
- data/lib/byebug/command.rb +3 -3
- data/lib/byebug/commands/condition.rb +2 -2
- data/lib/byebug/commands/edit.rb +12 -9
- data/lib/byebug/commands/eval.rb +0 -16
- data/lib/byebug/commands/frame.rb +7 -17
- data/lib/byebug/commands/info.rb +2 -9
- data/lib/byebug/commands/list.rb +1 -1
- data/lib/byebug/commands/reload.rb +11 -0
- data/lib/byebug/commands/repl.rb +3 -6
- data/lib/byebug/commands/set.rb +5 -5
- data/lib/byebug/commands/show.rb +5 -0
- data/lib/byebug/commands/threads.rb +4 -4
- data/lib/byebug/commands/trace.rb +2 -1
- data/lib/byebug/context.rb +14 -5
- data/lib/byebug/interface.rb +1 -1
- data/lib/byebug/processor.rb +1 -1
- data/lib/byebug/remote.rb +1 -24
- data/lib/byebug/version.rb +1 -1
- data/old_doc/byebug.1 +0 -3
- data/old_doc/byebug.texi +2 -3
- data/test/breakpoints_test.rb +75 -52
- data/test/conditions_test.rb +2 -3
- data/test/continue_test.rb +6 -0
- data/test/edit_test.rb +3 -3
- data/test/eval_test.rb +14 -5
- data/test/examples/breakpoint.rb +4 -13
- data/test/examples/breakpoint_deep.rb +1 -21
- data/test/examples/conditions.rb +1 -1
- data/test/examples/continue.rb +2 -1
- data/test/examples/edit.rb +1 -0
- data/test/examples/eval.rb +1 -11
- data/test/examples/finish.rb +0 -17
- data/test/examples/frame.rb +2 -26
- data/test/examples/frame_deep.rb +0 -19
- data/test/examples/help.rb +0 -1
- data/test/examples/info.rb +4 -36
- data/test/examples/kill.rb +1 -1
- data/test/examples/list.rb +1 -1
- data/test/examples/method.rb +2 -13
- data/test/examples/post_mortem.rb +1 -16
- data/test/examples/quit.rb +1 -1
- data/test/examples/reload.rb +1 -1
- data/test/examples/restart.rb +1 -1
- data/test/examples/show.rb +0 -1
- data/test/examples/stepping.rb +2 -19
- data/test/examples/thread.rb +0 -27
- data/test/examples/variables.rb +0 -22
- data/test/finish_test.rb +22 -6
- data/test/frame_test.rb +89 -56
- data/test/info_test.rb +71 -46
- data/test/kill_test.rb +6 -1
- data/test/list_test.rb +1 -2
- data/test/method_test.rb +32 -13
- data/test/post_mortem_test.rb +34 -21
- data/test/quit_test.rb +0 -1
- data/test/restart_test.rb +6 -0
- data/test/set_test.rb +1 -1
- data/test/show_test.rb +17 -17
- data/test/source_test.rb +2 -3
- data/test/stepping_test.rb +31 -7
- data/test/support/test_dsl.rb +11 -1
- data/test/test_helper.rb +9 -0
- data/test/thread_test.rb +57 -23
- data/test/trace_test.rb +0 -1
- data/test/variables_test.rb +36 -17
- metadata +3 -9
- data/test/examples/breakpoint2.rb +0 -7
- data/test/examples/jump.rb +0 -14
- data/test/examples/set_annotate.rb +0 -12
data/Rakefile
CHANGED
data/bin/byebug
CHANGED
@@ -62,9 +62,8 @@ require File.dirname(__FILE__) + "/../lib/byebug"
|
|
62
62
|
|
63
63
|
def debug_program(options)
|
64
64
|
# Make sure Ruby script syntax checks okay.
|
65
|
-
# Otherwise we get a load message that looks like byebug has a problem.
|
66
65
|
output = `ruby -c "#{Byebug::PROG_SCRIPT}" 2>&1`
|
67
|
-
if $?.exitstatus != 0
|
66
|
+
if $?.exitstatus != 0
|
68
67
|
puts output
|
69
68
|
exit $?.exitstatus
|
70
69
|
end
|
@@ -96,7 +95,6 @@ options = OpenStruct.new(
|
|
96
95
|
'script' => nil,
|
97
96
|
'stop' => true,
|
98
97
|
'tracing' => false,
|
99
|
-
'verbose_long' => false
|
100
98
|
)
|
101
99
|
|
102
100
|
def process_options(options)
|
@@ -158,10 +156,6 @@ EOB
|
|
158
156
|
puts "byebug #{Byebug::VERSION}"
|
159
157
|
exit
|
160
158
|
end
|
161
|
-
opts.on('--verbose', 'Turn on verbose mode') do
|
162
|
-
$VERBOSE = true
|
163
|
-
options.verbose_long = true
|
164
|
-
end
|
165
159
|
opts.on_tail('-v', 'Print version number, then turn on verbose mode') do
|
166
160
|
puts "byebug #{Byebug::VERSION}"
|
167
161
|
$VERBOSE = true
|
@@ -198,7 +192,6 @@ rescue StandardError => e
|
|
198
192
|
end
|
199
193
|
|
200
194
|
if ARGV.empty?
|
201
|
-
exit if $VERBOSE and not options.verbose_long
|
202
195
|
puts opts
|
203
196
|
puts
|
204
197
|
puts 'Must specify a script to run'
|
data/ext/byebug/byebug.c
CHANGED
@@ -4,7 +4,7 @@ static VALUE mByebug; /* Ruby Byebug Module object */
|
|
4
4
|
|
5
5
|
static VALUE tracing = Qfalse;
|
6
6
|
static VALUE post_mortem = Qfalse;
|
7
|
-
static VALUE
|
7
|
+
static VALUE verbose = Qfalse;
|
8
8
|
|
9
9
|
static VALUE catchpoints = Qnil;
|
10
10
|
static VALUE breakpoints = Qnil;
|
@@ -69,7 +69,7 @@ cleanup(debug_context_t *dc)
|
|
69
69
|
VALUE context; \
|
70
70
|
thread_context_lookup(rb_thread_current(), &context); \
|
71
71
|
Data_Get_Struct(context, debug_context_t, dc); \
|
72
|
-
if (
|
72
|
+
if (verbose == Qtrue) trace_print(trace_arg, dc); \
|
73
73
|
|
74
74
|
#define EVENT_COMMON if (!trace_common(trace_arg, dc)) { return; }
|
75
75
|
|
@@ -182,13 +182,15 @@ call_at_line_check(VALUE context_obj, debug_context_t *dc,
|
|
182
182
|
static void
|
183
183
|
line_event(VALUE trace_point, void *data)
|
184
184
|
{
|
185
|
+
VALUE breakpoint, file, line, binding;
|
186
|
+
int moved = 0;
|
187
|
+
|
185
188
|
EVENT_SETUP
|
186
189
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
int moved = 0;
|
190
|
+
breakpoint = Qnil;
|
191
|
+
file = rb_tracearg_path(trace_arg);
|
192
|
+
line = rb_tracearg_lineno(trace_arg);
|
193
|
+
binding = rb_tracearg_binding(trace_arg);
|
192
194
|
|
193
195
|
EVENT_COMMON
|
194
196
|
|
@@ -209,7 +211,12 @@ line_event(VALUE trace_point, void *data)
|
|
209
211
|
if (dc->stack_size <= dc->dest_frame)
|
210
212
|
{
|
211
213
|
dc->lines = dc->lines <= 0 ? -1 : dc->lines - 1;
|
212
|
-
dc->
|
214
|
+
if (dc->stack_size < dc->dest_frame)
|
215
|
+
{
|
216
|
+
dc->dest_frame = dc->stack_size;
|
217
|
+
rb_funcall(mByebug, rb_intern("print"), 1,
|
218
|
+
rb_str_new2("Next went up a frame because previous frame finished\n"));
|
219
|
+
}
|
213
220
|
}
|
214
221
|
}
|
215
222
|
|
@@ -227,19 +234,21 @@ line_event(VALUE trace_point, void *data)
|
|
227
234
|
static void
|
228
235
|
call_event(VALUE trace_point, void *data)
|
229
236
|
{
|
237
|
+
VALUE breakpoint, klass, mid, binding, self, file, line;
|
238
|
+
|
230
239
|
EVENT_SETUP
|
231
240
|
|
232
241
|
dc->stack_size++;
|
233
242
|
|
234
243
|
EVENT_COMMON
|
235
244
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
245
|
+
breakpoint = Qnil;
|
246
|
+
klass = rb_tracearg_defined_class(trace_arg);
|
247
|
+
mid = SYM2ID(rb_tracearg_method_id(trace_arg));
|
248
|
+
binding = rb_tracearg_binding(trace_arg);
|
249
|
+
self = rb_tracearg_self(trace_arg);
|
250
|
+
file = rb_tracearg_path(trace_arg);
|
251
|
+
line = rb_tracearg_lineno(trace_arg);
|
243
252
|
|
244
253
|
breakpoint = find_breakpoint_by_method(breakpoints, klass, mid, binding, self);
|
245
254
|
if (breakpoint != Qnil)
|
@@ -262,9 +271,11 @@ return_event(VALUE trace_point, void *data)
|
|
262
271
|
|
263
272
|
if (dc->stack_size + 1 == dc->before_frame)
|
264
273
|
{
|
274
|
+
VALUE file, line;
|
275
|
+
|
265
276
|
reset_stepping_stop_points(dc);
|
266
|
-
|
267
|
-
|
277
|
+
file = rb_tracearg_path(trace_arg);
|
278
|
+
line = rb_tracearg_lineno(trace_arg);
|
268
279
|
call_at_return(context, dc, file, line);
|
269
280
|
}
|
270
281
|
|
@@ -304,19 +315,22 @@ c_return_event(VALUE trace_point, void *data)
|
|
304
315
|
static void
|
305
316
|
raise_event(VALUE trace_point, void *data)
|
306
317
|
{
|
307
|
-
EVENT_SETUP
|
308
|
-
|
309
318
|
VALUE expn_class, aclass;
|
310
|
-
VALUE err
|
319
|
+
VALUE err;
|
311
320
|
VALUE ancestors;
|
312
321
|
int i;
|
313
322
|
debug_context_t *new_dc;
|
323
|
+
VALUE binding, path, lineno;
|
324
|
+
|
325
|
+
EVENT_SETUP
|
326
|
+
|
327
|
+
err = rb_errinfo();
|
314
328
|
|
315
329
|
EVENT_COMMON
|
316
330
|
|
317
|
-
|
318
|
-
|
319
|
-
|
331
|
+
binding = rb_tracearg_binding(trace_arg);
|
332
|
+
path = rb_tracearg_path(trace_arg);
|
333
|
+
lineno = rb_tracearg_lineno(trace_arg);
|
320
334
|
|
321
335
|
if (post_mortem == Qtrue)
|
322
336
|
{
|
@@ -374,8 +388,6 @@ register_tracepoints(VALUE self)
|
|
374
388
|
|
375
389
|
if (NIL_P(traces))
|
376
390
|
{
|
377
|
-
traces = rb_ary_new();
|
378
|
-
|
379
391
|
int line_msk = RUBY_EVENT_LINE;
|
380
392
|
int call_msk = RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS;
|
381
393
|
int return_msk = RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END;
|
@@ -390,6 +402,7 @@ register_tracepoints(VALUE self)
|
|
390
402
|
VALUE tpCReturn = rb_tracepoint_new(Qnil, c_return_msk, c_return_event, 0);
|
391
403
|
VALUE tpRaise = rb_tracepoint_new(Qnil, raise_msk , raise_event , 0);
|
392
404
|
|
405
|
+
traces = rb_ary_new();
|
393
406
|
rb_ary_push(traces, tpLine);
|
394
407
|
rb_ary_push(traces, tpCall);
|
395
408
|
rb_ary_push(traces, tpReturn);
|
@@ -613,6 +626,32 @@ bb_load(int argc, VALUE *argv, VALUE self)
|
|
613
626
|
return status;
|
614
627
|
}
|
615
628
|
|
629
|
+
/*
|
630
|
+
* call-seq:
|
631
|
+
* Byebug.verbose -> bool
|
632
|
+
*
|
633
|
+
* Returns +true+ if verbose output of TracePoint API events is enabled.
|
634
|
+
*/
|
635
|
+
static VALUE
|
636
|
+
bb_verbose(VALUE self)
|
637
|
+
{
|
638
|
+
return verbose;
|
639
|
+
}
|
640
|
+
|
641
|
+
/*
|
642
|
+
* call-seq:
|
643
|
+
* Byebug.verbose = bool
|
644
|
+
*
|
645
|
+
* Enable verbose output of every TracePoint API events, useful for debugging
|
646
|
+
* byebug.
|
647
|
+
*/
|
648
|
+
static VALUE
|
649
|
+
bb_set_verbose(VALUE self, VALUE value)
|
650
|
+
{
|
651
|
+
verbose = RTEST(value) ? Qtrue : Qfalse;
|
652
|
+
return value;
|
653
|
+
}
|
654
|
+
|
616
655
|
static VALUE
|
617
656
|
set_current_skipped_status(VALUE status)
|
618
657
|
{
|
@@ -784,6 +823,8 @@ Init_byebug()
|
|
784
823
|
rb_define_module_function(mByebug, "thread_context" , bb_thread_context , 1);
|
785
824
|
rb_define_module_function(mByebug, "tracing?" , bb_tracing , 0);
|
786
825
|
rb_define_module_function(mByebug, "tracing=" , bb_set_tracing , 1);
|
826
|
+
rb_define_module_function(mByebug, "verbose" , bb_verbose , 0);
|
827
|
+
rb_define_module_function(mByebug, "verbose=" , bb_set_verbose , 1);
|
787
828
|
|
788
829
|
cThreadsTable = rb_define_class_under(mByebug, "ThreadsTable", rb_cObject);
|
789
830
|
|
data/ext/byebug/context.c
CHANGED
@@ -45,13 +45,9 @@ context_free(void *data)
|
|
45
45
|
}
|
46
46
|
|
47
47
|
static int
|
48
|
-
real_stack_size(
|
48
|
+
real_stack_size()
|
49
49
|
{
|
50
|
-
|
51
|
-
if (locs == Qnil)
|
52
|
-
return 0;
|
53
|
-
|
54
|
-
return (int)RARRAY_LEN(locs);
|
50
|
+
return FIX2INT(rb_funcall(cContext, rb_intern("real_stack_size"), 0));
|
55
51
|
}
|
56
52
|
|
57
53
|
extern VALUE
|
@@ -62,7 +58,7 @@ context_create(VALUE thread)
|
|
62
58
|
context->last_file = Qnil;
|
63
59
|
context->last_line = Qnil;
|
64
60
|
context->flags = 0;
|
65
|
-
context->stack_size = real_stack_size(
|
61
|
+
context->stack_size = real_stack_size();
|
66
62
|
context->thnum = ++thnum_max;
|
67
63
|
context->thread = thread;
|
68
64
|
reset_stepping_stop_points(context);
|
@@ -97,13 +93,15 @@ static VALUE
|
|
97
93
|
dc_frame_get(const debug_context_t *context, int frame_index,
|
98
94
|
enum frame_component type)
|
99
95
|
{
|
96
|
+
VALUE frame;
|
97
|
+
|
100
98
|
if (NIL_P(dc_backtrace(context)))
|
101
99
|
rb_raise(rb_eRuntimeError, "Backtrace information is not available");
|
102
100
|
|
103
101
|
if (frame_index >= RARRAY_LEN(dc_backtrace(context)))
|
104
102
|
rb_raise(rb_eRuntimeError, "That frame doesn't exist!");
|
105
103
|
|
106
|
-
|
104
|
+
frame = rb_ary_entry(dc_backtrace(context), frame_index);
|
107
105
|
return rb_ary_entry(frame, type);
|
108
106
|
}
|
109
107
|
|
@@ -243,9 +241,11 @@ Context_frame_class(int argc, VALUE *argv, VALUE self)
|
|
243
241
|
static VALUE
|
244
242
|
Context_frame_file(int argc, VALUE *argv, VALUE self)
|
245
243
|
{
|
244
|
+
VALUE loc;
|
245
|
+
|
246
246
|
FRAME_SETUP
|
247
247
|
|
248
|
-
|
248
|
+
loc = dc_frame_location(context, frame_n);
|
249
249
|
|
250
250
|
return rb_funcall(loc, rb_intern("path"), 0);
|
251
251
|
}
|
@@ -259,9 +259,11 @@ Context_frame_file(int argc, VALUE *argv, VALUE self)
|
|
259
259
|
static VALUE
|
260
260
|
Context_frame_line(int argc, VALUE *argv, VALUE self)
|
261
261
|
{
|
262
|
+
VALUE loc;
|
263
|
+
|
262
264
|
FRAME_SETUP
|
263
265
|
|
264
|
-
|
266
|
+
loc = dc_frame_location(context, frame_n);
|
265
267
|
|
266
268
|
return rb_funcall(loc, rb_intern("lineno"), 0);
|
267
269
|
}
|
@@ -275,9 +277,11 @@ Context_frame_line(int argc, VALUE *argv, VALUE self)
|
|
275
277
|
static VALUE
|
276
278
|
Context_frame_method(int argc, VALUE *argv, VALUE self)
|
277
279
|
{
|
280
|
+
VALUE loc;
|
281
|
+
|
278
282
|
FRAME_SETUP
|
279
283
|
|
280
|
-
|
284
|
+
loc = dc_frame_location(context, frame_n);
|
281
285
|
|
282
286
|
return rb_str_intern(rb_funcall(loc, rb_intern("label"), 0));
|
283
287
|
}
|
@@ -354,16 +358,8 @@ Context_stack_size(VALUE self)
|
|
354
358
|
{
|
355
359
|
debug_context_t *context;
|
356
360
|
Data_Get_Struct(self, debug_context_t, context);
|
357
|
-
VALUE backtrace = dc_backtrace(context);
|
358
|
-
|
359
|
-
if (NIL_P(backtrace))
|
360
|
-
return INT2FIX(context->stack_size);
|
361
|
-
|
362
|
-
if (context->stack_size != RARRAY_LEN(backtrace))
|
363
|
-
rb_warn("Calculated stack size is %d but there are actually %ld frames",
|
364
|
-
context->stack_size, RARRAY_LEN(backtrace));
|
365
361
|
|
366
|
-
return INT2FIX(
|
362
|
+
return INT2FIX(context->stack_size);
|
367
363
|
}
|
368
364
|
|
369
365
|
static VALUE
|
data/ext/byebug/extconf.rb
CHANGED
data/lib/byebug.rb
CHANGED
@@ -4,12 +4,11 @@ require_relative 'byebug/context'
|
|
4
4
|
require_relative 'byebug/processor'
|
5
5
|
require_relative 'byebug/remote'
|
6
6
|
require 'stringio'
|
7
|
+
require 'tracer'
|
7
8
|
require 'linecache19'
|
8
9
|
|
9
10
|
module Byebug
|
10
11
|
|
11
|
-
self.handler = CommandProcessor.new
|
12
|
-
|
13
12
|
# List of files byebug will ignore while debugging
|
14
13
|
IGNORED_FILES = Dir[Pathname.new(__FILE__) + "../**/*.rb"].map {
|
15
14
|
|f| File.expand_path(f) }
|
@@ -26,14 +25,17 @@ module Byebug
|
|
26
25
|
|
27
26
|
class << self
|
28
27
|
|
28
|
+
# processor modules provide +handler+ object
|
29
|
+
attr_accessor :handler
|
30
|
+
Byebug.handler = CommandProcessor.new
|
31
|
+
|
29
32
|
attr_accessor :last_exception
|
30
33
|
Byebug.last_exception = nil
|
31
34
|
|
32
35
|
def source_reload
|
33
|
-
Object.send(:remove_const,
|
34
|
-
Object.const_defined?(
|
35
|
-
Object.const_set(
|
36
|
-
LineCache::clear_file_cache
|
36
|
+
Object.send(:remove_const, 'SCRIPT_LINES__') if
|
37
|
+
Object.const_defined?('SCRIPT_LINES__')
|
38
|
+
Object.const_set('SCRIPT_LINES__', {})
|
37
39
|
end
|
38
40
|
|
39
41
|
#
|
@@ -42,9 +44,11 @@ module Byebug
|
|
42
44
|
# @return "\n" if there was a problem. Leaking blanks are stripped off.
|
43
45
|
#
|
44
46
|
def line_at(filename, line_number)
|
45
|
-
|
46
|
-
|
47
|
-
return "\n" unless
|
47
|
+
source_reload
|
48
|
+
|
49
|
+
return "\n" unless File.exist?(filename)
|
50
|
+
line = Tracer::Single.get_line(filename, line_number)
|
51
|
+
|
48
52
|
return "#{line.gsub(/^\s+/, '').chomp}"
|
49
53
|
end
|
50
54
|
|
@@ -69,6 +73,9 @@ module Byebug
|
|
69
73
|
handler.interface = value
|
70
74
|
end
|
71
75
|
|
76
|
+
extend Forwardable
|
77
|
+
def_delegators :"handler.interface", :print
|
78
|
+
|
72
79
|
#
|
73
80
|
# Byebug.start(options) -> bool
|
74
81
|
# Byebug.start(options) { ... } -> obj
|
data/lib/byebug/command.rb
CHANGED
@@ -31,7 +31,7 @@ module Byebug
|
|
31
31
|
need_context: false } unless defined?(DEF_OPTIONS)
|
32
32
|
|
33
33
|
def help(args)
|
34
|
-
output = description.gsub(/^ +/, '')
|
34
|
+
output = description.gsub(/^ +/, '') + "\n"
|
35
35
|
|
36
36
|
if defined? self::Subcommands
|
37
37
|
return output += format_subcmds unless args and args[1]
|
@@ -176,7 +176,7 @@ module Byebug
|
|
176
176
|
register_setting_var(:argv, Byebug::ARGV)
|
177
177
|
|
178
178
|
def initialize(state)
|
179
|
-
@state = state
|
179
|
+
@match, @state = nil, state
|
180
180
|
end
|
181
181
|
|
182
182
|
def match(input)
|
@@ -197,7 +197,7 @@ module Byebug
|
|
197
197
|
eval(str, b)
|
198
198
|
rescue StandardError, ScriptError => e
|
199
199
|
if Command.settings[:stack_trace_on_error]
|
200
|
-
at = eval("Thread.current.backtrace_locations
|
200
|
+
at = eval("Thread.current.backtrace_locations", b)
|
201
201
|
print "#{at.shift}: #{e.class} Exception(#{e.message})\n"
|
202
202
|
for i in at
|
203
203
|
print "\tfrom #{i}\n"
|
@@ -17,8 +17,8 @@ module Byebug
|
|
17
17
|
return print "No breakpoints have been set.\n" if 0 == largest
|
18
18
|
return unless pos = get_int(@match[1], "Condition", 1, largest)
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
breakpoint = breakpoints.select{ |b| b.id == pos }.first
|
21
|
+
breakpoint.expr = @match[2] if breakpoint
|
22
22
|
end
|
23
23
|
|
24
24
|
class << self
|
data/lib/byebug/commands/edit.rb
CHANGED
@@ -9,21 +9,24 @@ module Byebug
|
|
9
9
|
|
10
10
|
def execute
|
11
11
|
if not @match[1]
|
12
|
-
unless @state.
|
13
|
-
errmsg "We are not in a state that has an associated file.\n"
|
14
|
-
return
|
12
|
+
unless @state.file
|
13
|
+
return errmsg "We are not in a state that has an associated file.\n"
|
15
14
|
end
|
16
15
|
file = @state.file
|
17
|
-
|
16
|
+
line = @state.line if @state.line
|
18
17
|
elsif @pos_match = /([^:]+)[:]([0-9]+)/.match(@match[1])
|
19
|
-
file,
|
18
|
+
file, line = @pos_match.captures
|
19
|
+
elsif File.exist?(@match[1])
|
20
|
+
file = @match[1]
|
20
21
|
else
|
21
|
-
errmsg "Invalid file
|
22
|
-
return
|
22
|
+
return errmsg "Invalid file[:line] number specification: #{@match[1]}\n"
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
|
+
editor = ENV['EDITOR'] || 'vim'
|
26
|
+
|
25
27
|
if File.readable?(file)
|
26
|
-
system("#{editor} +#{
|
28
|
+
system("#{editor} +#{line} #{file}") if line
|
29
|
+
system("#{editor} #{file}") unless line
|
27
30
|
else
|
28
31
|
errmsg "File \"#{file}\" is not readable.\n"
|
29
32
|
end
|