byebug 3.2.0 → 3.3.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/.rubocop.yml +3 -0
- data/CHANGELOG.md +125 -99
- data/CONTRIBUTING.md +4 -6
- data/GUIDE.md +42 -20
- data/Gemfile +5 -3
- data/README.md +2 -3
- data/Rakefile +11 -7
- data/bin/byebug +2 -252
- data/byebug.gemspec +7 -4
- data/ext/byebug/byebug.c +17 -18
- data/ext/byebug/byebug.h +4 -5
- data/ext/byebug/context.c +37 -39
- data/ext/byebug/threads.c +39 -18
- data/lib/byebug.rb +2 -110
- data/lib/byebug/attacher.rb +23 -0
- data/lib/byebug/breakpoint.rb +60 -0
- data/lib/byebug/command.rb +62 -70
- data/lib/byebug/commands/break.rb +24 -24
- data/lib/byebug/commands/catchpoint.rb +18 -10
- data/lib/byebug/commands/condition.rb +18 -17
- data/lib/byebug/commands/continue.rb +17 -9
- data/lib/byebug/commands/delete.rb +19 -13
- data/lib/byebug/commands/display.rb +19 -53
- data/lib/byebug/commands/edit.rb +7 -4
- data/lib/byebug/commands/enable_disable.rb +130 -0
- data/lib/byebug/commands/eval.rb +40 -22
- data/lib/byebug/commands/finish.rb +13 -4
- data/lib/byebug/commands/frame.rb +65 -45
- data/lib/byebug/commands/help.rb +17 -18
- data/lib/byebug/commands/history.rb +14 -8
- data/lib/byebug/commands/info.rb +160 -182
- data/lib/byebug/commands/interrupt.rb +4 -1
- data/lib/byebug/commands/irb.rb +30 -0
- data/lib/byebug/commands/kill.rb +7 -8
- data/lib/byebug/commands/list.rb +71 -66
- data/lib/byebug/commands/method.rb +14 -6
- data/lib/byebug/commands/pry.rb +35 -0
- data/lib/byebug/commands/quit.rb +9 -6
- data/lib/byebug/commands/reload.rb +5 -2
- data/lib/byebug/commands/restart.rb +13 -9
- data/lib/byebug/commands/save.rb +17 -17
- data/lib/byebug/commands/set.rb +16 -15
- data/lib/byebug/commands/show.rb +10 -11
- data/lib/byebug/commands/source.rb +11 -5
- data/lib/byebug/commands/stepping.rb +38 -24
- data/lib/byebug/commands/threads.rb +45 -31
- data/lib/byebug/commands/trace.rb +22 -9
- data/lib/byebug/commands/undisplay.rb +45 -0
- data/lib/byebug/commands/variables.rb +83 -27
- data/lib/byebug/context.rb +25 -22
- data/lib/byebug/core.rb +82 -0
- data/lib/byebug/helper.rb +37 -28
- data/lib/byebug/history.rb +8 -4
- data/lib/byebug/interface.rb +12 -17
- data/lib/byebug/interfaces/local_interface.rb +11 -8
- data/lib/byebug/interfaces/remote_interface.rb +11 -8
- data/lib/byebug/interfaces/script_interface.rb +9 -6
- data/lib/byebug/options.rb +46 -0
- data/lib/byebug/processor.rb +7 -1
- data/lib/byebug/processors/command_processor.rb +135 -125
- data/lib/byebug/processors/control_command_processor.rb +23 -23
- data/lib/byebug/remote.rb +17 -26
- data/lib/byebug/runner.rb +100 -0
- data/lib/byebug/setting.rb +33 -8
- data/lib/byebug/settings/autoeval.rb +5 -15
- data/lib/byebug/settings/autoirb.rb +4 -1
- data/lib/byebug/settings/autolist.rb +5 -2
- data/lib/byebug/settings/autoreload.rb +5 -2
- data/lib/byebug/settings/autosave.rb +6 -2
- data/lib/byebug/settings/basename.rb +7 -2
- data/lib/byebug/settings/callstyle.rb +4 -1
- data/lib/byebug/settings/forcestep.rb +6 -3
- data/lib/byebug/settings/fullpath.rb +5 -2
- data/lib/byebug/settings/histfile.rb +5 -3
- data/lib/byebug/settings/histsize.rb +5 -3
- data/lib/byebug/settings/linetrace.rb +4 -1
- data/lib/byebug/settings/listsize.rb +5 -1
- data/lib/byebug/settings/post_mortem.rb +21 -13
- data/lib/byebug/settings/stack_on_error.rb +6 -2
- data/lib/byebug/settings/testing.rb +6 -1
- data/lib/byebug/settings/tracing_plus.rb +5 -1
- data/lib/byebug/settings/verbose.rb +13 -2
- data/lib/byebug/settings/width.rb +4 -1
- data/lib/byebug/version.rb +1 -1
- data/test/{break_test.rb → commands/break_test.rb} +41 -53
- data/test/{condition_test.rb → commands/condition_test.rb} +14 -14
- data/test/{continue_test.rb → commands/continue_test.rb} +0 -0
- data/test/{delete_test.rb → commands/delete_test.rb} +2 -2
- data/test/commands/display_test.rb +37 -0
- data/test/{edit_test.rb → commands/edit_test.rb} +0 -0
- data/test/{eval_test.rb → commands/eval_test.rb} +1 -0
- data/test/{finish_test.rb → commands/finish_test.rb} +11 -1
- data/test/{frame_test.rb → commands/frame_test.rb} +12 -16
- data/test/{help_test.rb → commands/help_test.rb} +21 -4
- data/test/{history_test.rb → commands/history_test.rb} +0 -0
- data/test/{info_test.rb → commands/info_test.rb} +5 -55
- data/test/{interrupt_test.rb → commands/interrupt_test.rb} +0 -0
- data/test/commands/irb_test.rb +28 -0
- data/test/{kill_test.rb → commands/kill_test.rb} +1 -1
- data/test/{list_test.rb → commands/list_test.rb} +1 -1
- data/test/{method_test.rb → commands/method_test.rb} +0 -0
- data/test/{post_mortem_test.rb → commands/post_mortem_test.rb} +6 -10
- data/test/{pry_test.rb → commands/pry_test.rb} +4 -13
- data/test/{quit_test.rb → commands/quit_test.rb} +4 -4
- data/test/{reload_test.rb → commands/reload_test.rb} +0 -0
- data/test/{restart_test.rb → commands/restart_test.rb} +6 -0
- data/test/{save_test.rb → commands/save_test.rb} +2 -2
- data/test/{set_test.rb → commands/set_test.rb} +9 -2
- data/test/{show_test.rb → commands/show_test.rb} +1 -1
- data/test/{source_test.rb → commands/source_test.rb} +3 -3
- data/test/{stepping_test.rb → commands/stepping_test.rb} +44 -35
- data/test/{thread_test.rb → commands/thread_test.rb} +0 -0
- data/test/{trace_test.rb → commands/trace_test.rb} +0 -0
- data/test/{display_test.rb → commands/undisplay_test.rb} +7 -45
- data/test/{variables_test.rb → commands/variables_test.rb} +10 -1
- data/test/debugger_alias_test.rb +2 -2
- data/test/runner_test.rb +127 -0
- data/test/support/matchers.rb +27 -25
- data/test/support/test_interface.rb +9 -5
- data/test/support/utils.rb +96 -101
- data/test/test_helper.rb +32 -20
- metadata +93 -68
- data/lib/byebug/commands/enable.rb +0 -154
- data/lib/byebug/commands/repl.rb +0 -126
- data/test/irb_test.rb +0 -47
- data/test/support/breakpoint.rb +0 -13
data/lib/byebug/helper.rb
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Miscelaneous Utilities
|
4
|
+
#
|
2
5
|
module ParseFunctions
|
3
|
-
Position_regexp = '(?:(\d+)|(.+?)[:.#]([^.:\s]+))'
|
4
|
-
|
5
6
|
#
|
6
7
|
# Parse 'str' of command 'cmd' as an integer between min and max. If either
|
7
8
|
# min or max is nil, that value has no bound.
|
8
9
|
#
|
9
|
-
def get_int(str, cmd, min = nil, max = nil
|
10
|
-
|
11
|
-
return
|
12
|
-
print "You need to specify an argument for \"#{cmd}\"\n"
|
13
|
-
return nil
|
10
|
+
def get_int(str, cmd, min = nil, max = nil)
|
11
|
+
if str !~ /\A[0-9]+\z/
|
12
|
+
return nil, "\"#{cmd}\" argument \"#{str}\" needs to be a number"
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
elsif max and int > max
|
22
|
-
print "\"#{cmd}\" argument \"#{str}\" needs to be at most #{max}\n"
|
23
|
-
return nil
|
24
|
-
end
|
25
|
-
return int
|
26
|
-
rescue
|
27
|
-
print "\"#{cmd}\" argument \"#{str}\" needs to be a number\n"
|
28
|
-
return nil
|
15
|
+
int = str.to_i
|
16
|
+
if min && int < min
|
17
|
+
return nil, "\"#{cmd}\" argument \"#{str}\" needs to be at least #{min}"
|
18
|
+
elsif max && int > max
|
19
|
+
return nil, "\"#{cmd}\" argument \"#{str}\" needs to be at most #{max}"
|
29
20
|
end
|
21
|
+
|
22
|
+
int
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Fills SCRIPT_LINES__ entry for <filename> if not already filled.
|
27
|
+
#
|
28
|
+
def lines(filename)
|
29
|
+
SCRIPT_LINES__[filename] ||= File.readlines(filename)
|
30
30
|
end
|
31
31
|
|
32
32
|
#
|
@@ -35,21 +35,17 @@ module Byebug
|
|
35
35
|
def get_lines(filename)
|
36
36
|
return nil unless File.exist?(filename)
|
37
37
|
|
38
|
-
|
39
|
-
lines = File.readlines(filename) rescue []
|
40
|
-
SCRIPT_LINES__[filename] = lines
|
41
|
-
end
|
42
|
-
|
43
|
-
return lines
|
38
|
+
lines(filename)
|
44
39
|
end
|
45
40
|
|
46
41
|
#
|
47
42
|
# Gets a single line in a source code file
|
48
43
|
#
|
49
44
|
def get_line(filename, lineno)
|
50
|
-
|
45
|
+
lines = get_lines(filename)
|
46
|
+
return nil unless lines
|
51
47
|
|
52
|
-
|
48
|
+
lines[lineno - 1]
|
53
49
|
end
|
54
50
|
|
55
51
|
#
|
@@ -60,5 +56,18 @@ module Byebug
|
|
60
56
|
rescue SyntaxError
|
61
57
|
false
|
62
58
|
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Returns the number of steps specified in <str> as an integer or 1 if <str>
|
62
|
+
# 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
|
63
72
|
end
|
64
73
|
end
|
data/lib/byebug/history.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'readline'
|
2
2
|
|
3
3
|
module Byebug
|
4
|
+
#
|
5
|
+
# Handles byebug's history of commands.
|
6
|
+
#
|
4
7
|
class History
|
5
8
|
class << self
|
6
9
|
def load
|
@@ -21,17 +24,18 @@ module Byebug
|
|
21
24
|
end
|
22
25
|
|
23
26
|
def to_s(size = Setting[:histsize])
|
24
|
-
|
27
|
+
rl_size = Readline::HISTORY.length
|
28
|
+
n_entries = rl_size < size ? rl_size : size
|
25
29
|
|
26
|
-
first =
|
30
|
+
first = rl_size - n_entries
|
27
31
|
commands = Readline::HISTORY.to_a.last(n_entries)
|
28
32
|
|
29
33
|
s = ''
|
30
34
|
commands.each_with_index do |command, index|
|
31
|
-
s += ("%5d %s\n"
|
35
|
+
s += format("%5d %s\n", first + index + 1, command)
|
32
36
|
end
|
33
37
|
|
34
|
-
|
38
|
+
s
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
data/lib/byebug/interface.rb
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
+
#
|
2
|
+
# Namespace for all of byebug's code
|
3
|
+
#
|
1
4
|
module Byebug
|
5
|
+
#
|
6
|
+
# Main Interface class
|
7
|
+
#
|
8
|
+
# Contains common functionality to all implemented interfaces.
|
9
|
+
#
|
2
10
|
class Interface
|
3
11
|
attr_accessor :command_queue, :restart_file
|
4
12
|
|
@@ -6,25 +14,12 @@ module Byebug
|
|
6
14
|
@command_queue, @restart_file = [], nil
|
7
15
|
end
|
8
16
|
|
17
|
+
#
|
9
18
|
# Common routine for reporting byebug error messages.
|
10
19
|
# Derived classes may want to override this to capture output.
|
11
|
-
|
12
|
-
|
13
|
-
print(
|
14
|
-
end
|
15
|
-
|
16
|
-
def format(*args)
|
17
|
-
if args.is_a?(Array)
|
18
|
-
new_args = args.first
|
19
|
-
new_args = new_args % args[1..-1] unless args[1..-1].empty?
|
20
|
-
else
|
21
|
-
new_args = args
|
22
|
-
end
|
23
|
-
new_args
|
24
|
-
end
|
25
|
-
|
26
|
-
def escape(msg)
|
27
|
-
msg.gsub('%', '%%')
|
20
|
+
#
|
21
|
+
def errmsg(message)
|
22
|
+
print("*** #{message}\n")
|
28
23
|
end
|
29
24
|
end
|
30
25
|
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'byebug/history'
|
2
2
|
|
3
3
|
module Byebug
|
4
|
+
#
|
5
|
+
# Interface class for standard byebug use.
|
6
|
+
#
|
4
7
|
class LocalInterface < Interface
|
5
8
|
attr_reader :history
|
6
9
|
|
@@ -17,8 +20,8 @@ module Byebug
|
|
17
20
|
readline(prompt, false)
|
18
21
|
end
|
19
22
|
|
20
|
-
def
|
21
|
-
STDOUT.
|
23
|
+
def puts(*args)
|
24
|
+
STDOUT.puts(*args)
|
22
25
|
end
|
23
26
|
|
24
27
|
def close
|
@@ -27,11 +30,11 @@ module Byebug
|
|
27
30
|
|
28
31
|
private
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
def readline(prompt, hist)
|
34
|
+
Readline.readline(prompt, hist)
|
35
|
+
rescue Interrupt
|
36
|
+
puts '^C'
|
37
|
+
retry
|
38
|
+
end
|
36
39
|
end
|
37
40
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'byebug/history'
|
2
2
|
|
3
3
|
module Byebug
|
4
|
+
#
|
5
|
+
# Interface class for remote use of byebug.
|
6
|
+
#
|
4
7
|
class RemoteInterface < Interface
|
5
8
|
attr_reader :history
|
6
9
|
|
@@ -23,17 +26,17 @@ module Byebug
|
|
23
26
|
send_command "PROMPT #{prompt}"
|
24
27
|
end
|
25
28
|
|
26
|
-
def
|
27
|
-
@socket.
|
29
|
+
def puts(message)
|
30
|
+
@socket.puts(message)
|
28
31
|
end
|
29
32
|
|
30
33
|
private
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def send_command(msg)
|
36
|
+
@socket.puts msg
|
37
|
+
result = @socket.gets
|
38
|
+
fail IOError unless result
|
39
|
+
result.chomp
|
40
|
+
end
|
38
41
|
end
|
39
42
|
end
|
@@ -1,13 +1,16 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Interface class for command execution from script files.
|
4
|
+
#
|
2
5
|
class ScriptInterface < Interface
|
3
|
-
def initialize(file, out, verbose=false)
|
6
|
+
def initialize(file, out, verbose = false)
|
4
7
|
super()
|
5
8
|
@file = file.respond_to?(:gets) ? file : open(file)
|
6
9
|
@out, @verbose = out, verbose
|
7
10
|
end
|
8
11
|
|
9
|
-
def read_command(
|
10
|
-
while result = @file.gets
|
12
|
+
def read_command(_prompt)
|
13
|
+
while (result = @file.gets)
|
11
14
|
puts "# #{result}" if @verbose
|
12
15
|
next if result =~ /^\s*#/
|
13
16
|
next if result.strip.empty?
|
@@ -15,12 +18,12 @@ module Byebug
|
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
18
|
-
def confirm(
|
21
|
+
def confirm(_prompt)
|
19
22
|
'y'
|
20
23
|
end
|
21
24
|
|
22
|
-
def
|
23
|
-
@out.printf(
|
25
|
+
def puts(message)
|
26
|
+
@out.printf(message)
|
24
27
|
end
|
25
28
|
|
26
29
|
def close
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Byebug
|
2
|
+
#
|
3
|
+
# Set of options that byebug's script accepts.
|
4
|
+
#
|
5
|
+
class Options
|
6
|
+
def self.parse
|
7
|
+
Slop.parse!(strict: true) do
|
8
|
+
banner <<-EOB.gsub(/^ {8}/, '')
|
9
|
+
|
10
|
+
byebug #{Byebug::VERSION}
|
11
|
+
|
12
|
+
Usage: byebug [options] <script.rb> -- <script.rb parameters>
|
13
|
+
EOB
|
14
|
+
|
15
|
+
on :d, :debug, 'Set $DEBUG=true' do
|
16
|
+
$DEBUG = true
|
17
|
+
end
|
18
|
+
|
19
|
+
on :I, :include=, 'Add to $LOAD_PATH', as: Array, delimiter: ':' do |l|
|
20
|
+
$LOAD_PATH.push(l).flatten!
|
21
|
+
end
|
22
|
+
|
23
|
+
on :q, :quit, 'Quit when script finishes', default: true
|
24
|
+
|
25
|
+
on :s, :stop, 'Stop when script is loaded', default: true
|
26
|
+
|
27
|
+
on :x, :rc, 'Run byebug initialization file', default: true
|
28
|
+
|
29
|
+
on :m, :'post-mortem', 'Run byebug in post-mortem mode', default: false
|
30
|
+
|
31
|
+
on :r, :require=, 'Require library before script' do |name|
|
32
|
+
require name
|
33
|
+
end
|
34
|
+
|
35
|
+
on :R, :remote=, '[HOST:]PORT for remote debugging',
|
36
|
+
as: Array, delimiter: ':', limit: 2
|
37
|
+
|
38
|
+
on :t, :trace, 'Turn on line tracing'
|
39
|
+
|
40
|
+
on :v, :version, 'Print program version'
|
41
|
+
|
42
|
+
on :h, :help, 'Display this message'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/byebug/processor.rb
CHANGED
@@ -5,11 +5,17 @@ module Byebug
|
|
5
5
|
attr_accessor :interface
|
6
6
|
|
7
7
|
extend Forwardable
|
8
|
-
def_delegators :@interface, :errmsg, :
|
8
|
+
def_delegators :@interface, :errmsg, :puts
|
9
9
|
|
10
10
|
def initialize(interface)
|
11
11
|
@interface = interface
|
12
12
|
end
|
13
|
+
|
14
|
+
def without_exceptions
|
15
|
+
yield
|
16
|
+
rescue
|
17
|
+
nil
|
18
|
+
end
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
@@ -1,4 +1,7 @@
|
|
1
1
|
module Byebug
|
2
|
+
#
|
3
|
+
# Processes commands in regular mode
|
4
|
+
#
|
2
5
|
class CommandProcessor < Processor
|
3
6
|
attr_reader :display
|
4
7
|
|
@@ -41,7 +44,7 @@ module Byebug
|
|
41
44
|
|
42
45
|
def self.protect(mname)
|
43
46
|
alias_method "__#{mname}", mname
|
44
|
-
module_eval <<-END, __FILE__, __LINE__+1
|
47
|
+
module_eval <<-END, __FILE__, __LINE__ + 1
|
45
48
|
def #{mname}(*args)
|
46
49
|
@mutex.synchronize do
|
47
50
|
return unless @interface
|
@@ -52,24 +55,26 @@ module Byebug
|
|
52
55
|
rescue SignalException
|
53
56
|
raise
|
54
57
|
rescue
|
55
|
-
|
56
|
-
|
58
|
+
without_exceptions do
|
59
|
+
puts "INTERNAL ERROR!!! #\{$!\}"
|
60
|
+
puts $!.backtrace.map{|l| "\t#\{l\}"}.join("\n")
|
61
|
+
end
|
57
62
|
end
|
58
63
|
END
|
59
64
|
end
|
60
65
|
|
61
|
-
def at_breakpoint(
|
66
|
+
def at_breakpoint(_context, breakpoint)
|
62
67
|
n = Byebug.breakpoints.index(breakpoint) + 1
|
63
68
|
file = self.class.canonic_file(breakpoint.source)
|
64
69
|
line = breakpoint.pos
|
65
|
-
|
70
|
+
puts "Stopped by breakpoint #{n} at #{file}:#{line}"
|
66
71
|
end
|
67
72
|
protect :at_breakpoint
|
68
73
|
|
69
74
|
def at_catchpoint(context, excpt)
|
70
75
|
file = self.class.canonic_file(context.frame_file(0))
|
71
76
|
line = context.frame_line(0)
|
72
|
-
|
77
|
+
puts "Catchpoint at #{file}:#{line}: `#{excpt}' (#{excpt.class})"
|
73
78
|
end
|
74
79
|
protect :at_catchpoint
|
75
80
|
|
@@ -79,7 +84,7 @@ module Byebug
|
|
79
84
|
if file != @last_file || line != @last_line || Setting[:tracing_plus]
|
80
85
|
path = self.class.canonic_file(file)
|
81
86
|
@last_file, @last_line = file, line
|
82
|
-
|
87
|
+
puts "Tracing: #{path}:#{line} #{get_line(file, line)}"
|
83
88
|
end
|
84
89
|
always_run(context, file, line, 2)
|
85
90
|
end
|
@@ -97,152 +102,157 @@ module Byebug
|
|
97
102
|
protect :at_return
|
98
103
|
|
99
104
|
private
|
100
|
-
#
|
101
|
-
# Prompt shown before reading a command.
|
102
|
-
#
|
103
|
-
def prompt(context)
|
104
|
-
return "(byebug#{context.dead? ? ':post-mortem' : ''}) "
|
105
|
-
end
|
106
105
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
#
|
112
|
-
|
113
|
-
# @return List of commands acceptable to run bound to the current state
|
114
|
-
#
|
115
|
-
def always_run(context, file, line, run_level)
|
116
|
-
cmds = Command.commands
|
106
|
+
#
|
107
|
+
# Prompt shown before reading a command.
|
108
|
+
#
|
109
|
+
def prompt(context)
|
110
|
+
"(byebug#{context.dead? ? ':post-mortem' : ''}) "
|
111
|
+
end
|
117
112
|
|
118
|
-
|
113
|
+
#
|
114
|
+
# Run commands everytime.
|
115
|
+
#
|
116
|
+
# For example display commands or possibly the list or irb in an
|
117
|
+
# "autolist" or "autoirb".
|
118
|
+
#
|
119
|
+
# @return List of commands acceptable to run bound to the current state
|
120
|
+
#
|
121
|
+
def always_run(context, file, line, run_level)
|
122
|
+
cmds = Command.commands
|
119
123
|
|
120
|
-
|
121
|
-
Setting[:autolist] = false if ['(irb)', '-e'].include?(file)
|
124
|
+
state = State.new(cmds, context, @display, file, @interface, line)
|
122
125
|
|
123
|
-
|
124
|
-
|
126
|
+
# Change default when in irb or code included in command line
|
127
|
+
Setting[:autolist] = false if ['(irb)', '-e'].include?(file)
|
125
128
|
|
126
|
-
|
127
|
-
|
129
|
+
# Bind commands to the current state.
|
130
|
+
commands = cmds.map { |cmd| cmd.new(state) }
|
128
131
|
|
129
|
-
|
130
|
-
|
132
|
+
commands.select { |cmd| cmd.class.always_run >= run_level }
|
133
|
+
.each { |cmd| cmd.execute }
|
131
134
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
135
|
+
[state, commands]
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Splits a command line of the form "cmd1 ; cmd2 ; ... ; cmdN" into an
|
140
|
+
# array of commands: [cmd1, cmd2, ..., cmdN]
|
141
|
+
#
|
142
|
+
def split_commands(cmd_line)
|
143
|
+
cmd_line.split(/;/).each_with_object([]) do |v, m|
|
144
|
+
if m.empty?
|
145
|
+
m << v
|
146
|
+
else
|
147
|
+
if m.last[-1] == '\\'
|
148
|
+
m.last[-1, 1] = ''
|
149
|
+
m.last << ';' << v
|
140
150
|
else
|
141
|
-
|
142
|
-
m.last[-1,1] = ''
|
143
|
-
m.last << ';' << v
|
144
|
-
else
|
145
|
-
m << v
|
146
|
-
end
|
151
|
+
m << v
|
147
152
|
end
|
148
|
-
m
|
149
153
|
end
|
150
154
|
end
|
155
|
+
end
|
151
156
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
+
#
|
158
|
+
# Handle byebug commands.
|
159
|
+
#
|
160
|
+
def process_commands(context, file, line)
|
161
|
+
state, commands = always_run(context, file, line, 1)
|
157
162
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
+
if Setting[:testing]
|
164
|
+
Thread.current.thread_variable_set('state', state)
|
165
|
+
else
|
166
|
+
Thread.current.thread_variable_set('state', nil)
|
167
|
+
end
|
163
168
|
|
164
|
-
|
165
|
-
|
169
|
+
preloop(commands, context)
|
170
|
+
puts(state.location) if Setting[:autolist] == 0
|
166
171
|
|
167
|
-
|
168
|
-
|
169
|
-
@interface.read_command(prompt(context))
|
172
|
+
until state.proceed?
|
173
|
+
input = if @interface.command_queue.empty?
|
174
|
+
@interface.read_command(prompt(context))
|
175
|
+
else
|
170
176
|
@interface.command_queue.shift
|
171
|
-
|
172
|
-
|
173
|
-
if input == ""
|
174
|
-
next unless @last_cmd
|
175
|
-
input = @last_cmd
|
176
|
-
else
|
177
|
-
@last_cmd = input
|
178
|
-
end
|
179
|
-
split_commands(input).each do |cmd|
|
180
|
-
one_cmd(commands, context, cmd)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
177
|
+
end
|
178
|
+
break unless input
|
185
179
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
def one_cmd(commands, context, input)
|
190
|
-
if cmd = commands.find { |c| c.match(input) }
|
191
|
-
if context.dead? && !cmd.class.allow_in_post_mortem
|
192
|
-
errmsg "Command unavailable in post mortem mode.\n"
|
193
|
-
else
|
194
|
-
cmd.execute
|
195
|
-
end
|
180
|
+
if input == ''
|
181
|
+
next unless @last_cmd
|
182
|
+
input = @last_cmd
|
196
183
|
else
|
197
|
-
|
198
|
-
if unknown_cmd
|
199
|
-
unknown_cmd.execute
|
200
|
-
else
|
201
|
-
errmsg "Unknown command: \"#{input}\". Try \"help\".\n"
|
202
|
-
end
|
184
|
+
@last_cmd = input
|
203
185
|
end
|
186
|
+
split_commands(input).each do |cmd|
|
187
|
+
one_cmd(commands, context, cmd)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
#
|
193
|
+
# Autoevals a single command
|
194
|
+
#
|
195
|
+
def one_unknown_cmd(commands, input)
|
196
|
+
unless Setting[:autoeval]
|
197
|
+
return errmsg("Unknown command: \"#{input}\". Try \"help\"")
|
204
198
|
end
|
205
199
|
|
206
|
-
|
207
|
-
|
208
|
-
#
|
209
|
-
def preloop(commands, context)
|
210
|
-
@context_was_dead = true if context.dead? and not @context_was_dead
|
200
|
+
commands.find { |c| c.is_a?(EvalCommand) }.execute
|
201
|
+
end
|
211
202
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
203
|
+
#
|
204
|
+
# Executes a single byebug command
|
205
|
+
#
|
206
|
+
def one_cmd(commands, context, input)
|
207
|
+
cmd = commands.find { |c| c.match(input) }
|
208
|
+
return one_unknown_cmd(commands, input) unless cmd
|
209
|
+
|
210
|
+
if context.dead? && !cmd.class.allow_in_post_mortem
|
211
|
+
return errmsg('Command unavailable in post mortem mode.')
|
216
212
|
end
|
217
213
|
|
218
|
-
|
219
|
-
|
220
|
-
|
214
|
+
cmd.execute
|
215
|
+
end
|
216
|
+
|
217
|
+
#
|
218
|
+
# Tasks to do before processor loop
|
219
|
+
#
|
220
|
+
def preloop(_commands, context)
|
221
|
+
@context_was_dead = true if context.dead? && !@context_was_dead
|
222
|
+
return unless @context_was_dead
|
221
223
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
@frame_pos, @previous_line, @proceed = 0, nil, false
|
226
|
-
end
|
224
|
+
puts 'The program finished.'
|
225
|
+
@context_was_dead = false
|
226
|
+
end
|
227
227
|
|
228
|
-
|
229
|
-
|
228
|
+
class State
|
229
|
+
attr_accessor :commands, :context, :display, :file, :frame_pos
|
230
|
+
attr_accessor :interface, :line, :previous_line
|
230
231
|
|
231
|
-
|
232
|
-
|
233
|
-
|
232
|
+
def initialize(commands, context, display, file, interface, line)
|
233
|
+
@commands, @context, @display = commands, context, display
|
234
|
+
@file, @interface, @line = file, interface, line
|
235
|
+
@frame_pos, @previous_line, @proceed = 0, nil, false
|
236
|
+
end
|
234
237
|
|
235
|
-
|
236
|
-
|
237
|
-
end
|
238
|
+
extend Forwardable
|
239
|
+
def_delegators :@interface, :errmsg, :puts, :confirm
|
238
240
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
end
|
241
|
+
def proceed?
|
242
|
+
@proceed
|
243
|
+
end
|
244
|
+
|
245
|
+
def proceed
|
246
|
+
@proceed = true
|
246
247
|
end
|
247
|
-
|
248
|
+
|
249
|
+
def location
|
250
|
+
path = self.class.canonic_file(@file)
|
251
|
+
loc = "#{path} @ #{@line}\n"
|
252
|
+
loc += "#{get_line(@file, @line)}\n" unless
|
253
|
+
['(irb)', '-e'].include? @file
|
254
|
+
loc
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
248
258
|
end
|