byebug 4.0.5 → 5.0.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/CHANGELOG.md +72 -34
- data/CONTRIBUTING.md +26 -31
- data/README.md +3 -3
- data/lib/byebug/breakpoint.rb +2 -1
- data/lib/byebug/command.rb +27 -49
- data/lib/byebug/commands/break.rb +21 -15
- data/lib/byebug/commands/catch.rb +9 -15
- data/lib/byebug/commands/condition.rb +12 -15
- data/lib/byebug/commands/continue.rb +8 -11
- data/lib/byebug/commands/delete.rb +9 -12
- data/lib/byebug/commands/disable.rb +32 -0
- data/lib/byebug/commands/disable/breakpoints.rb +38 -0
- data/lib/byebug/commands/disable/display.rb +39 -0
- data/lib/byebug/commands/display.rb +18 -51
- data/lib/byebug/commands/down.rb +39 -0
- data/lib/byebug/commands/edit.rb +8 -14
- data/lib/byebug/commands/enable.rb +25 -0
- data/lib/byebug/commands/enable/breakpoints.rb +38 -0
- data/lib/byebug/commands/enable/display.rb +39 -0
- data/lib/byebug/commands/eval.rb +10 -192
- data/lib/byebug/commands/finish.rb +11 -12
- data/lib/byebug/commands/frame.rb +17 -182
- data/lib/byebug/commands/help.rb +18 -18
- data/lib/byebug/commands/history.rb +9 -10
- data/lib/byebug/commands/info.rb +17 -190
- data/lib/byebug/commands/info/args.rb +39 -0
- data/lib/byebug/commands/info/breakpoints.rb +59 -0
- data/lib/byebug/commands/info/catch.rb +39 -0
- data/lib/byebug/commands/info/display.rb +42 -0
- data/lib/byebug/commands/info/file.rb +81 -0
- data/lib/byebug/commands/info/line.rb +31 -0
- data/lib/byebug/commands/info/program.rb +51 -0
- data/lib/byebug/commands/interrupt.rb +5 -9
- data/lib/byebug/commands/irb.rb +5 -9
- data/lib/byebug/commands/kill.rb +6 -12
- data/lib/byebug/commands/list.rb +47 -19
- data/lib/byebug/commands/method.rb +8 -14
- data/lib/byebug/commands/next.rb +36 -0
- data/lib/byebug/commands/pp.rb +41 -0
- data/lib/byebug/commands/pry.rb +5 -9
- data/lib/byebug/commands/ps.rb +44 -0
- data/lib/byebug/commands/putl.rb +43 -0
- data/lib/byebug/commands/quit.rb +8 -12
- data/lib/byebug/commands/restart.rb +6 -12
- data/lib/byebug/commands/save.rb +30 -39
- data/lib/byebug/commands/set.rb +19 -21
- data/lib/byebug/commands/show.rb +10 -16
- data/lib/byebug/commands/source.rb +6 -12
- data/lib/byebug/commands/step.rb +36 -0
- data/lib/byebug/commands/thread.rb +13 -130
- data/lib/byebug/commands/thread/current.rb +35 -0
- data/lib/byebug/commands/thread/list.rb +41 -0
- data/lib/byebug/commands/thread/resume.rb +45 -0
- data/lib/byebug/commands/thread/stop.rb +41 -0
- data/lib/byebug/commands/thread/switch.rb +43 -0
- data/lib/byebug/commands/tracevar.rb +8 -14
- data/lib/byebug/commands/undisplay.rb +12 -15
- data/lib/byebug/commands/untracevar.rb +5 -11
- data/lib/byebug/commands/up.rb +39 -0
- data/lib/byebug/commands/var.rb +15 -94
- data/lib/byebug/commands/var/all.rb +37 -0
- data/lib/byebug/commands/var/const.rb +38 -0
- data/lib/byebug/commands/var/global.rb +33 -0
- data/lib/byebug/commands/var/instance.rb +35 -0
- data/lib/byebug/commands/var/local.rb +35 -0
- data/lib/byebug/commands/where.rb +47 -0
- data/lib/byebug/core.rb +10 -0
- data/lib/byebug/helpers/eval.rb +47 -0
- data/lib/byebug/helpers/file.rb +46 -0
- data/lib/byebug/helpers/frame.rb +76 -0
- data/lib/byebug/helpers/parse.rb +74 -0
- data/lib/byebug/helpers/string.rb +24 -0
- data/lib/byebug/helpers/thread.rb +53 -0
- data/lib/byebug/helpers/toggle.rb +56 -0
- data/lib/byebug/helpers/var.rb +45 -0
- data/lib/byebug/history.rb +2 -4
- data/lib/byebug/interface.rb +5 -3
- data/lib/byebug/interfaces/local_interface.rb +3 -1
- data/lib/byebug/interfaces/remote_interface.rb +3 -1
- data/lib/byebug/interfaces/test_interface.rb +6 -2
- data/lib/byebug/printers/plain.rb +1 -1
- data/lib/byebug/processors/command_processor.rb +9 -11
- data/lib/byebug/processors/control_command_processor.rb +1 -1
- data/lib/byebug/remote.rb +3 -0
- data/lib/byebug/runner.rb +5 -3
- data/lib/byebug/setting.rb +2 -18
- data/lib/byebug/settings/savefile.rb +21 -0
- data/lib/byebug/states/regular_state.rb +15 -6
- data/lib/byebug/subcommand_list.rb +33 -0
- data/lib/byebug/subcommands.rb +53 -0
- data/lib/byebug/version.rb +1 -1
- metadata +45 -6
- data/lib/byebug/commands/enable_disable.rb +0 -132
- data/lib/byebug/commands/stepping.rb +0 -75
- data/lib/byebug/helper.rb +0 -131
@@ -0,0 +1,46 @@
|
|
1
|
+
module Byebug
|
2
|
+
module Helpers
|
3
|
+
#
|
4
|
+
# Utilities for interaction with files
|
5
|
+
#
|
6
|
+
module FileHelper
|
7
|
+
#
|
8
|
+
# Reads lines of source file +filename+ into an array
|
9
|
+
#
|
10
|
+
def get_lines(filename)
|
11
|
+
File.foreach(filename).reduce([]) { |a, e| a << e.chomp }
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# Reads line number +lineno+ from file named +filename+
|
16
|
+
#
|
17
|
+
def get_line(filename, lineno)
|
18
|
+
File.open(filename) do |f|
|
19
|
+
f.gets until f.lineno == lineno - 1
|
20
|
+
f.gets
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Returns the number of lines in file +filename+ in a portable,
|
26
|
+
# one-line-at-a-time way.
|
27
|
+
#
|
28
|
+
def n_lines(filename)
|
29
|
+
File.foreach(filename).reduce(0) { |a, _e| a + 1 }
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Regularize file name.
|
34
|
+
#
|
35
|
+
def normalize(filename)
|
36
|
+
return filename if ['(irb)', '-e'].include?(filename)
|
37
|
+
|
38
|
+
return File.basename(filename) if Setting[:basename]
|
39
|
+
|
40
|
+
path = File.expand_path(filename)
|
41
|
+
|
42
|
+
File.exist?(path) ? File.realpath(path) : filename
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Byebug
|
2
|
+
module Helpers
|
3
|
+
#
|
4
|
+
# Utilities to assist frame navigation
|
5
|
+
#
|
6
|
+
module FrameHelper
|
7
|
+
def switch_to_frame(frame_no)
|
8
|
+
frame_no >= 0 ? frame_no : @state.context.stack_size + frame_no
|
9
|
+
end
|
10
|
+
|
11
|
+
def navigate_to_frame(jump_no)
|
12
|
+
return if jump_no == 0
|
13
|
+
|
14
|
+
current_jumps = 0
|
15
|
+
current_pos = @state.frame
|
16
|
+
|
17
|
+
loop do
|
18
|
+
current_pos += direction(jump_no)
|
19
|
+
break if current_pos < 0 || current_pos >= @state.context.stack_size
|
20
|
+
|
21
|
+
next if @state.c_frame?(current_pos)
|
22
|
+
|
23
|
+
current_jumps += 1
|
24
|
+
break if current_jumps == jump_no.abs
|
25
|
+
end
|
26
|
+
|
27
|
+
current_pos
|
28
|
+
end
|
29
|
+
|
30
|
+
def adjust_frame(frame, absolute)
|
31
|
+
if absolute
|
32
|
+
abs_frame = switch_to_frame(frame)
|
33
|
+
if @state.c_frame?(abs_frame)
|
34
|
+
return errmsg(pr('frame.errors.c_frame'))
|
35
|
+
end
|
36
|
+
else
|
37
|
+
abs_frame = navigate_to_frame(frame)
|
38
|
+
end
|
39
|
+
|
40
|
+
if abs_frame >= @state.context.stack_size
|
41
|
+
return errmsg(pr('frame.errors.too_low'))
|
42
|
+
elsif abs_frame < 0
|
43
|
+
return errmsg(pr('frame.errors.too_high'))
|
44
|
+
end
|
45
|
+
|
46
|
+
@state.frame = abs_frame
|
47
|
+
@state.file = @state.context.frame_file(@state.frame)
|
48
|
+
@state.line = @state.context.frame_line(@state.frame)
|
49
|
+
@state.prev_line = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_pr_arguments(frame_no)
|
53
|
+
file = @state.frame_file(frame_no)
|
54
|
+
full_path = File.expand_path(file)
|
55
|
+
line = @state.frame_line(frame_no)
|
56
|
+
call = @state.frame_call(frame_no)
|
57
|
+
mark = @state.frame_mark(frame_no)
|
58
|
+
pos = @state.frame_pos(frame_no)
|
59
|
+
|
60
|
+
{ mark: mark, pos: pos, call: call, file: file, line: line,
|
61
|
+
full_path: full_path }
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
#
|
67
|
+
# @param [Integer] A positive or negative integer
|
68
|
+
#
|
69
|
+
# @return [Integer] +1 if step is positive / -1 if negative
|
70
|
+
#
|
71
|
+
def direction(step)
|
72
|
+
step / step.abs
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Byebug
|
2
|
+
module Helpers
|
3
|
+
#
|
4
|
+
# Utilities to assist command parsing
|
5
|
+
#
|
6
|
+
module ParseHelper
|
7
|
+
#
|
8
|
+
# Parses +str+ of command +cmd+ as an integer between +min+ and +max+.
|
9
|
+
#
|
10
|
+
# If either +min+ or +max+ is nil, that value has no bound.
|
11
|
+
#
|
12
|
+
# TODO: Remove the `cmd` parameter. It has nothing to do with the methods
|
13
|
+
# purpose.
|
14
|
+
#
|
15
|
+
def get_int(str, cmd, min = nil, max = nil)
|
16
|
+
if str !~ /\A-?[0-9]+\z/
|
17
|
+
err = pr('parse.errors.int.not_number', cmd: cmd, str: str)
|
18
|
+
return nil, errmsg(err)
|
19
|
+
end
|
20
|
+
|
21
|
+
int = str.to_i
|
22
|
+
if min && int < min
|
23
|
+
err = pr('parse.errors.int.too_low', cmd: cmd, str: str, min: min)
|
24
|
+
return min, errmsg(err)
|
25
|
+
elsif max && int > max
|
26
|
+
err = pr('parse.errors.int.too_high', cmd: cmd, str: str, max: max)
|
27
|
+
return max, errmsg(err)
|
28
|
+
end
|
29
|
+
|
30
|
+
int
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# @return true if code is syntactically correct for Ruby, false otherwise
|
35
|
+
#
|
36
|
+
def syntax_valid?(code)
|
37
|
+
return true unless code
|
38
|
+
|
39
|
+
without_stderr do
|
40
|
+
begin
|
41
|
+
RubyVM::InstructionSequence.compile(code)
|
42
|
+
true
|
43
|
+
rescue SyntaxError
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Temporarily disable output to $stderr
|
51
|
+
#
|
52
|
+
def without_stderr
|
53
|
+
stderr = $stderr
|
54
|
+
$stderr.reopen(IO::NULL)
|
55
|
+
|
56
|
+
yield
|
57
|
+
ensure
|
58
|
+
$stderr.reopen(stderr)
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# @return +str+ as an integer or 1 if +str+ is empty.
|
63
|
+
#
|
64
|
+
def parse_steps(str, cmd)
|
65
|
+
return 1 unless str
|
66
|
+
|
67
|
+
steps, err = get_int(str, cmd, 1)
|
68
|
+
return nil, err unless steps
|
69
|
+
|
70
|
+
steps
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Byebug
|
2
|
+
module Helpers
|
3
|
+
#
|
4
|
+
# Utilities for interaction with strings
|
5
|
+
#
|
6
|
+
module StringHelper
|
7
|
+
#
|
8
|
+
# Converts +str+ from an_underscored-or-dasherized_string to
|
9
|
+
# ACamelizedString.
|
10
|
+
#
|
11
|
+
def camelize(str)
|
12
|
+
str.dup.split(/[_-]/).map(&:capitalize).join('')
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Improves indentation and spacing in +str+ for readability in Byebug's
|
17
|
+
# command prompt.
|
18
|
+
#
|
19
|
+
def prettify(str)
|
20
|
+
"\n" + str.gsub(/^ {6}/, '') + "\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Byebug
|
2
|
+
module Helpers
|
3
|
+
#
|
4
|
+
# Utilities for thread subcommands
|
5
|
+
#
|
6
|
+
module ThreadHelper
|
7
|
+
def display_context(context)
|
8
|
+
puts pr('thread.context', thread_arguments(context))
|
9
|
+
end
|
10
|
+
|
11
|
+
def thread_arguments(context)
|
12
|
+
status_flag = if context.suspended?
|
13
|
+
'$'
|
14
|
+
else
|
15
|
+
context.thread == Thread.current ? '+' : ' '
|
16
|
+
end
|
17
|
+
debug_flag = context.ignored? ? '!' : ' '
|
18
|
+
|
19
|
+
if context == Byebug.current_context
|
20
|
+
file_line = "#{@state.file}:#{@state.line}"
|
21
|
+
else
|
22
|
+
backtrace = context.thread.backtrace_locations
|
23
|
+
if backtrace && backtrace[0]
|
24
|
+
file_line = "#{backtrace[0].path}:#{backtrace[0].lineno}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
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 || '',
|
34
|
+
pid: Process.pid,
|
35
|
+
status: context.thread.status,
|
36
|
+
current: (context.thread == Thread.current)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def context_from_thread(thnum)
|
41
|
+
ctx = Byebug.contexts.find { |c| c.thnum.to_s == thnum }
|
42
|
+
|
43
|
+
err = case
|
44
|
+
when ctx.nil? then pr('thread.errors.no_thread')
|
45
|
+
when ctx == @state.context then pr('thread.errors.current_thread')
|
46
|
+
when ctx.ignored? then pr('thread.errors.ignored', arg: thnum)
|
47
|
+
end
|
48
|
+
|
49
|
+
[ctx, err]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'byebug/helpers/parse'
|
2
|
+
|
3
|
+
module Byebug
|
4
|
+
module Helpers
|
5
|
+
#
|
6
|
+
# Utilities to assist breakpoint/display enabling/disabling.
|
7
|
+
#
|
8
|
+
module ToggleHelper
|
9
|
+
include ParseHelper
|
10
|
+
|
11
|
+
def enable_disable_breakpoints(is_enable, args)
|
12
|
+
return errmsg(pr('toggle.errors.no_breakpoints')) if Breakpoint.none?
|
13
|
+
|
14
|
+
all_breakpoints = Byebug.breakpoints.sort_by(&:id)
|
15
|
+
if args.nil?
|
16
|
+
selected_breakpoints = all_breakpoints
|
17
|
+
else
|
18
|
+
selected_ids = []
|
19
|
+
args.split(/ +/).each do |pos|
|
20
|
+
last_id = all_breakpoints.last.id
|
21
|
+
pos, err = get_int(pos, "#{is_enable} breakpoints", 1, last_id)
|
22
|
+
return errmsg(err) unless pos
|
23
|
+
|
24
|
+
selected_ids << pos
|
25
|
+
end
|
26
|
+
selected_breakpoints = all_breakpoints.select do |b|
|
27
|
+
selected_ids.include?(b.id)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
selected_breakpoints.each do |b|
|
32
|
+
enabled = ('enable' == is_enable)
|
33
|
+
if enabled && !syntax_valid?(b.expr)
|
34
|
+
return errmsg(pr('toggle.errors.expression', expr: b.expr))
|
35
|
+
end
|
36
|
+
|
37
|
+
b.enabled = enabled
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def enable_disable_display(is_enable, args)
|
42
|
+
display = @state.display
|
43
|
+
return errmsg(pr('toggle.errors.no_display')) if 0 == display.size
|
44
|
+
|
45
|
+
selected_displays = args.nil? ? [1..display.size + 1] : args.split(/ +/)
|
46
|
+
|
47
|
+
selected_displays.each do |pos|
|
48
|
+
pos, err = get_int(pos, "#{is_enable} display", 1, display.size)
|
49
|
+
return errmsg(err) unless err.nil?
|
50
|
+
|
51
|
+
display[pos - 1][0] = ('enable' == is_enable)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Byebug
|
2
|
+
module Helpers
|
3
|
+
#
|
4
|
+
# Utilities for variable subcommands
|
5
|
+
#
|
6
|
+
module VarHelper
|
7
|
+
def var_list(ary, b = get_binding)
|
8
|
+
vars = ary.sort.map do |v|
|
9
|
+
s = begin
|
10
|
+
b.eval(v.to_s).inspect
|
11
|
+
rescue
|
12
|
+
begin
|
13
|
+
b.eval(v.to_s).to_s
|
14
|
+
rescue
|
15
|
+
'*Error in evaluation*'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
[v, s]
|
19
|
+
end
|
20
|
+
puts prv(vars, 'instance')
|
21
|
+
end
|
22
|
+
|
23
|
+
def var_global
|
24
|
+
globals = global_variables.reject do |v|
|
25
|
+
[:$IGNORECASE, :$=, :$KCODE, :$-K, :$binding].include?(v)
|
26
|
+
end
|
27
|
+
|
28
|
+
var_list(globals)
|
29
|
+
end
|
30
|
+
|
31
|
+
def var_instance(str)
|
32
|
+
obj = bb_warning_eval(str || 'self')
|
33
|
+
|
34
|
+
var_list(obj.instance_variables, obj.instance_eval { binding })
|
35
|
+
end
|
36
|
+
|
37
|
+
def var_local
|
38
|
+
locals = @state.context.frame_locals
|
39
|
+
cur_self = @state.context.frame_self(@state.frame)
|
40
|
+
locals[:self] = cur_self unless cur_self.to_s == 'main'
|
41
|
+
puts prv(locals.keys.sort.map { |k| [k, locals[k]] }, 'instance')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/byebug/history.rb
CHANGED
@@ -27,7 +27,7 @@ module Byebug
|
|
27
27
|
def restore
|
28
28
|
return unless File.exist?(Setting[:histfile])
|
29
29
|
|
30
|
-
File.readlines(Setting[:histfile]).
|
30
|
+
File.readlines(Setting[:histfile]).reverse_each { |l| push(l.chomp) }
|
31
31
|
end
|
32
32
|
|
33
33
|
#
|
@@ -85,9 +85,7 @@ module Byebug
|
|
85
85
|
# Array of ids of the last n commands.
|
86
86
|
#
|
87
87
|
def last_ids(n)
|
88
|
-
|
89
|
-
|
90
|
-
(from..to).to_a
|
88
|
+
(1 + size - n..size).to_a
|
91
89
|
end
|
92
90
|
|
93
91
|
#
|
data/lib/byebug/interface.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'byebug/history'
|
2
|
-
require 'byebug/
|
2
|
+
require 'byebug/helpers/file'
|
3
3
|
|
4
4
|
#
|
5
5
|
# Namespace for all of byebug's code
|
@@ -11,11 +11,14 @@ module Byebug
|
|
11
11
|
# Contains common functionality to all implemented interfaces.
|
12
12
|
#
|
13
13
|
class Interface
|
14
|
+
include Helpers::FileHelper
|
15
|
+
|
14
16
|
attr_accessor :command_queue, :history
|
15
17
|
attr_reader :input, :output, :error
|
16
18
|
|
17
19
|
def initialize
|
18
|
-
@command_queue
|
20
|
+
@command_queue = []
|
21
|
+
@history = History.new
|
19
22
|
end
|
20
23
|
|
21
24
|
#
|
@@ -31,7 +34,6 @@ module Byebug
|
|
31
34
|
command_queue.shift
|
32
35
|
end
|
33
36
|
|
34
|
-
include FileFunctions
|
35
37
|
#
|
36
38
|
# Pushes lines in +filename+ to the command queue.
|
37
39
|
#
|