byebug 5.0.0 → 6.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 +26 -1
- data/CONTRIBUTING.md +35 -13
- data/GUIDE.md +256 -198
- data/README.md +5 -11
- data/ext/byebug/byebug.c +5 -43
- data/ext/byebug/byebug.h +6 -1
- data/ext/byebug/context.c +4 -5
- data/lib/byebug/command.rb +64 -64
- data/lib/byebug/command_list.rb +32 -0
- data/lib/byebug/commands.rb +37 -0
- data/lib/byebug/commands/break.rb +45 -37
- data/lib/byebug/commands/catch.rb +52 -28
- data/lib/byebug/commands/condition.rb +19 -13
- data/lib/byebug/commands/continue.rb +15 -11
- data/lib/byebug/commands/delete.rb +18 -12
- data/lib/byebug/commands/disable.rb +9 -10
- data/lib/byebug/commands/disable/breakpoints.rb +13 -11
- data/lib/byebug/commands/disable/display.rb +13 -11
- data/lib/byebug/commands/display.rb +32 -24
- data/lib/byebug/commands/down.rb +18 -14
- data/lib/byebug/commands/edit.rb +42 -26
- data/lib/byebug/commands/enable.rb +9 -3
- data/lib/byebug/commands/enable/breakpoints.rb +13 -11
- data/lib/byebug/commands/enable/display.rb +13 -11
- data/lib/byebug/commands/finish.rb +23 -14
- data/lib/byebug/commands/frame.rb +21 -18
- data/lib/byebug/commands/help.rb +39 -16
- data/lib/byebug/commands/history.rb +16 -10
- data/lib/byebug/commands/info.rb +8 -5
- data/lib/byebug/commands/info/breakpoints.rb +16 -14
- data/lib/byebug/commands/info/display.rb +18 -18
- data/lib/byebug/commands/info/file.rb +22 -22
- data/lib/byebug/commands/info/line.rb +13 -11
- data/lib/byebug/commands/info/program.rb +13 -17
- data/lib/byebug/commands/interrupt.rb +13 -11
- data/lib/byebug/commands/irb.rb +16 -10
- data/lib/byebug/commands/kill.rb +19 -13
- data/lib/byebug/commands/list.rb +35 -24
- data/lib/byebug/commands/method.rb +25 -15
- data/lib/byebug/commands/next.rb +15 -13
- data/lib/byebug/commands/pry.rb +18 -11
- data/lib/byebug/commands/ps.rb +21 -23
- data/lib/byebug/commands/quit.rb +17 -11
- data/lib/byebug/commands/restart.rb +28 -24
- data/lib/byebug/commands/save.rb +23 -15
- data/lib/byebug/commands/set.rb +26 -19
- data/lib/byebug/commands/show.rb +20 -14
- data/lib/byebug/commands/source.rb +15 -14
- data/lib/byebug/commands/step.rb +15 -13
- data/lib/byebug/commands/thread.rb +8 -4
- data/lib/byebug/commands/thread/current.rb +11 -11
- data/lib/byebug/commands/thread/list.rb +14 -14
- data/lib/byebug/commands/thread/resume.rb +14 -14
- data/lib/byebug/commands/thread/stop.rb +14 -14
- data/lib/byebug/commands/thread/switch.rb +15 -14
- data/lib/byebug/commands/tracevar.rb +20 -16
- data/lib/byebug/commands/undisplay.rb +22 -18
- data/lib/byebug/commands/untracevar.rb +13 -11
- data/lib/byebug/commands/up.rb +18 -14
- data/lib/byebug/commands/var.rb +10 -3
- data/lib/byebug/commands/var/all.rb +15 -13
- data/lib/byebug/commands/var/args.rb +37 -0
- data/lib/byebug/commands/var/const.rb +25 -14
- data/lib/byebug/commands/var/global.rb +13 -11
- data/lib/byebug/commands/var/instance.rb +13 -11
- data/lib/byebug/commands/var/local.rb +13 -11
- data/lib/byebug/commands/where.rb +15 -11
- data/lib/byebug/context.rb +71 -73
- data/lib/byebug/core.rb +45 -26
- data/lib/byebug/errors.rb +27 -0
- data/lib/byebug/frame.rb +181 -0
- data/lib/byebug/helpers/eval.rb +67 -26
- data/lib/byebug/helpers/file.rb +18 -3
- data/lib/byebug/helpers/frame.rb +36 -39
- data/lib/byebug/helpers/parse.rb +15 -13
- data/lib/byebug/helpers/path.rb +21 -0
- data/lib/byebug/helpers/reflection.rb +17 -0
- data/lib/byebug/helpers/thread.rb +20 -14
- data/lib/byebug/helpers/toggle.rb +10 -5
- data/lib/byebug/helpers/var.rb +36 -15
- data/lib/byebug/interface.rb +27 -9
- data/lib/byebug/option_setter.rb +93 -0
- data/lib/byebug/printers/base.rb +3 -0
- data/lib/byebug/printers/plain.rb +4 -14
- data/lib/byebug/printers/texts/base.yml +2 -7
- data/lib/byebug/processors/command_processor.rb +101 -102
- data/lib/byebug/processors/control_processor.rb +20 -0
- data/lib/byebug/processors/post_mortem_processor.rb +16 -0
- data/lib/byebug/processors/script_processor.rb +49 -0
- data/lib/byebug/remote.rb +13 -7
- data/lib/byebug/runner.rb +39 -65
- data/lib/byebug/setting.rb +4 -1
- data/lib/byebug/settings/post_mortem.rb +0 -16
- data/lib/byebug/settings/savefile.rb +1 -4
- data/lib/byebug/subcommands.rb +27 -29
- data/lib/byebug/version.rb +4 -1
- metadata +14 -29
- data/lib/byebug/commands/eval.rb +0 -43
- data/lib/byebug/commands/info/args.rb +0 -39
- data/lib/byebug/commands/info/catch.rb +0 -39
- data/lib/byebug/commands/pp.rb +0 -41
- data/lib/byebug/commands/putl.rb +0 -43
- data/lib/byebug/processor.rb +0 -43
- data/lib/byebug/processors/control_command_processor.rb +0 -48
- data/lib/byebug/settings/verbose.rb +0 -20
- data/lib/byebug/state.rb +0 -12
- data/lib/byebug/states/control_state.rb +0 -26
- data/lib/byebug/states/regular_state.rb +0 -187
- data/lib/byebug/subcommand_list.rb +0 -33
data/lib/byebug/interface.rb
CHANGED
@@ -19,6 +19,11 @@ module Byebug
|
|
19
19
|
def initialize
|
20
20
|
@command_queue = []
|
21
21
|
@history = History.new
|
22
|
+
@last_line = ''
|
23
|
+
end
|
24
|
+
|
25
|
+
def last_if_empty(input)
|
26
|
+
@last_line = input.empty? ? @last_line : input
|
22
27
|
end
|
23
28
|
|
24
29
|
#
|
@@ -27,11 +32,7 @@ module Byebug
|
|
27
32
|
def read_command(prompt)
|
28
33
|
return command_queue.shift unless command_queue.empty?
|
29
34
|
|
30
|
-
|
31
|
-
return unless cmds
|
32
|
-
|
33
|
-
command_queue.concat(cmds)
|
34
|
-
command_queue.shift
|
35
|
+
read_input(prompt)
|
35
36
|
end
|
36
37
|
|
37
38
|
#
|
@@ -42,15 +43,32 @@ module Byebug
|
|
42
43
|
end
|
43
44
|
|
44
45
|
#
|
45
|
-
# Reads a new line from the interface's input stream
|
46
|
+
# Reads a new line from the interface's input stream, parses it into
|
47
|
+
# commands and saves it to history.
|
48
|
+
#
|
49
|
+
# @return [String] Representing something to be run by the debugger.
|
46
50
|
#
|
47
51
|
def read_input(prompt, save_hist = true)
|
48
|
-
line =
|
52
|
+
line = prepare_input(prompt)
|
49
53
|
return unless line
|
50
54
|
|
51
55
|
history.push(line) if save_hist
|
52
56
|
|
53
|
-
split_commands(line)
|
57
|
+
command_queue.concat(split_commands(line))
|
58
|
+
command_queue.shift
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Reads a new line from the interface's input stream.
|
63
|
+
#
|
64
|
+
# @return [String] New string read or the previous string if the string
|
65
|
+
# read now was empty.
|
66
|
+
#
|
67
|
+
def prepare_input(prompt)
|
68
|
+
line = readline(prompt)
|
69
|
+
return unless line
|
70
|
+
|
71
|
+
last_if_empty(line)
|
54
72
|
end
|
55
73
|
|
56
74
|
#
|
@@ -106,7 +124,7 @@ module Byebug
|
|
106
124
|
|
107
125
|
cmd_line.split(/;/).each_with_object([]) do |v, m|
|
108
126
|
if m.empty? || m.last[-1] != '\\'
|
109
|
-
m << v
|
127
|
+
m << v.strip
|
110
128
|
next
|
111
129
|
end
|
112
130
|
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Byebug
|
2
|
+
#
|
3
|
+
# Handles byebug's command line options
|
4
|
+
#
|
5
|
+
class OptionSetter
|
6
|
+
def initialize(runner, opts)
|
7
|
+
@runner = runner
|
8
|
+
@opts = opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup
|
12
|
+
debug
|
13
|
+
include_flag
|
14
|
+
post_mortem
|
15
|
+
quit
|
16
|
+
rc
|
17
|
+
stop
|
18
|
+
require_flag
|
19
|
+
remote
|
20
|
+
trace
|
21
|
+
version
|
22
|
+
help
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def debug
|
28
|
+
@opts.on '-d', '--debug', 'Set $DEBUG=true' do
|
29
|
+
$DEBUG = true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def include_flag
|
34
|
+
@opts.on('-I', '--include list', 'Add to paths to $LOAD_PATH') do |list|
|
35
|
+
$LOAD_PATH.push(list.split(':')).flatten!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def post_mortem
|
40
|
+
@opts.on '-m', '--[no-]post-mortem', 'Use post-mortem mode' do |v|
|
41
|
+
Setting[:post_mortem] = v
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def quit
|
46
|
+
@opts.on '-q', '--[no-]quit', 'Quit when script finishes' do |v|
|
47
|
+
@runner.quit = v
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def rc
|
52
|
+
@opts.on '-x', '--[no-]rc', 'Run byebug initialization file' do |v|
|
53
|
+
Byebug.run_init_script if v
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def stop
|
58
|
+
@opts.on '-s', '--[no-]stop', 'Stop when script is loaded' do |v|
|
59
|
+
@runner.stop = v
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def require_flag
|
64
|
+
@opts.on '-r', '--require file', 'Require library before script' do |lib|
|
65
|
+
require lib
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def remote
|
70
|
+
@opts.on '-R', '--remote [host:]port', 'Remote debug [host:]port' do |p|
|
71
|
+
@runner.remote = p
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def trace
|
76
|
+
@opts.on '-t', '--[no-]trace', 'Turn on line tracing' do |v|
|
77
|
+
Setting[:linetrace] = v
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def version
|
82
|
+
@opts.on '-v', '--version', 'Print program version' do
|
83
|
+
@runner.version = Byebug::VERSION
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def help
|
88
|
+
@opts.on('-h', '--help', 'Display this message') do
|
89
|
+
@runner.help = @opts.help
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/byebug/printers/base.rb
CHANGED
@@ -2,9 +2,10 @@ require 'byebug/printers/base'
|
|
2
2
|
|
3
3
|
module Byebug
|
4
4
|
module Printers
|
5
|
+
#
|
6
|
+
# Plain text printer
|
7
|
+
#
|
5
8
|
class Plain < Base
|
6
|
-
include Columnize
|
7
|
-
|
8
9
|
def print(path, args = {})
|
9
10
|
message = translate(locate(path), args)
|
10
11
|
tail = parts(path).include?('confirmations') ? ' (y/n) ' : "\n"
|
@@ -12,16 +13,11 @@ module Byebug
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def print_collection(path, collection, &block)
|
15
|
-
modifier = get_modifier(path)
|
16
16
|
lines = array_of_args(collection, &block).map do |args|
|
17
17
|
print(path, args)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
columnize(lines.map { |l| l.gsub(/\n$/, '') }, Setting[:width])
|
22
|
-
else
|
23
|
-
lines.join('')
|
24
|
-
end
|
20
|
+
lines.join
|
25
21
|
end
|
26
22
|
|
27
23
|
def print_variables(variables, *_)
|
@@ -38,12 +34,6 @@ module Byebug
|
|
38
34
|
|
39
35
|
private
|
40
36
|
|
41
|
-
def get_modifier(path)
|
42
|
-
modifier_regexp = /\|(\w+)$/
|
43
|
-
modifier_match = locate(path).match(modifier_regexp)
|
44
|
-
modifier_match && modifier_match[1]
|
45
|
-
end
|
46
|
-
|
47
37
|
def contents_files
|
48
38
|
[File.expand_path(File.join('..', 'texts', 'plain.yml'), __FILE__)] +
|
49
39
|
super
|
@@ -18,11 +18,11 @@ break:
|
|
18
18
|
delete_all: "Delete all breakpoints?"
|
19
19
|
|
20
20
|
catch:
|
21
|
-
|
21
|
+
added: "Catching exception {exception}."
|
22
|
+
removed: "Catch for exception {exception} removed"
|
22
23
|
errors:
|
23
24
|
off: "Off expected. Got {off}"
|
24
25
|
not_class: "Warning {class} is not known to be a Class"
|
25
|
-
removed: "Catch for exception {exception} removed"
|
26
26
|
not_found: "Catch for exception {exception} not found"
|
27
27
|
confirmations:
|
28
28
|
delete_all: "Delete all catchpoints? (y or n) "
|
@@ -54,10 +54,6 @@ frame:
|
|
54
54
|
too_high: "Can't navigate beyond the newest frame"
|
55
55
|
c_frame: "Can't navigate to c-frame"
|
56
56
|
|
57
|
-
help:
|
58
|
-
errors:
|
59
|
-
undefined: "Undefined command: {cmd}. Try: help"
|
60
|
-
|
61
57
|
info:
|
62
58
|
errors:
|
63
59
|
undefined_file: "{file} is not a valid source file"
|
@@ -87,7 +83,6 @@ show:
|
|
87
83
|
source:
|
88
84
|
errors:
|
89
85
|
not_found: "File \"{file}\" not found"
|
90
|
-
not_available: "Source commmand not available at this time"
|
91
86
|
|
92
87
|
thread:
|
93
88
|
errors:
|
@@ -1,164 +1,163 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'byebug/helpers/eval'
|
4
|
+
require 'byebug/errors'
|
3
5
|
|
4
6
|
module Byebug
|
5
7
|
#
|
6
|
-
# Processes commands in regular mode
|
8
|
+
# Processes commands in regular mode.
|
9
|
+
#
|
10
|
+
# You can override this class to create your own command processor that, for
|
11
|
+
# example, whitelists only certain commands to be executed.
|
12
|
+
#
|
13
|
+
# @see PostMortemProcessor for a example
|
7
14
|
#
|
8
|
-
class CommandProcessor
|
9
|
-
include Helpers::
|
15
|
+
class CommandProcessor
|
16
|
+
include Helpers::EvalHelper
|
10
17
|
|
11
|
-
|
18
|
+
attr_accessor :prev_line
|
19
|
+
attr_reader :context
|
12
20
|
|
13
|
-
def initialize(
|
14
|
-
|
21
|
+
def initialize(context)
|
22
|
+
@context = context
|
15
23
|
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@context_was_dead = false # Assume we haven't started.
|
24
|
+
@proceed = false
|
25
|
+
@prev_line = nil
|
19
26
|
end
|
20
27
|
|
21
|
-
def interface
|
22
|
-
@interface
|
23
|
-
@interface = interface
|
28
|
+
def interface
|
29
|
+
@interface ||= context.class.interface
|
24
30
|
end
|
25
31
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
line = breakpoint.pos
|
32
|
+
def printer
|
33
|
+
@printer ||= Printers::Plain.new
|
34
|
+
end
|
30
35
|
|
31
|
-
|
36
|
+
def frame
|
37
|
+
@context.frame
|
32
38
|
end
|
33
39
|
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
extend Forwardable
|
41
|
+
def_delegator :printer, :print, :pr
|
42
|
+
def_delegator :printer, :print_collection, :prc
|
43
|
+
def_delegator :printer, :print_variables, :prv
|
37
44
|
|
38
|
-
|
39
|
-
end
|
45
|
+
def_delegators :interface, :errmsg, :puts, :confirm
|
40
46
|
|
41
|
-
|
42
|
-
|
47
|
+
#
|
48
|
+
# Available commands
|
49
|
+
#
|
50
|
+
def command_list
|
51
|
+
@command_list ||= CommandList.new(commands)
|
52
|
+
end
|
43
53
|
|
44
|
-
|
54
|
+
def commands
|
55
|
+
Byebug.commands
|
45
56
|
end
|
46
57
|
|
47
|
-
def
|
48
|
-
|
58
|
+
def at_breakpoint(brkpt)
|
59
|
+
number = Byebug.breakpoints.index(brkpt) + 1
|
60
|
+
|
61
|
+
puts "Stopped by breakpoint #{number} at #{frame.file}:#{frame.line}"
|
49
62
|
end
|
50
63
|
|
51
|
-
def
|
52
|
-
|
64
|
+
def at_catchpoint(exception)
|
65
|
+
puts "Catchpoint at #{context.location}: `#{exception}'"
|
53
66
|
end
|
54
67
|
|
55
|
-
|
68
|
+
def at_tracing
|
69
|
+
puts "Tracing: #{context.full_location}"
|
56
70
|
|
57
|
-
|
58
|
-
# Prompt shown before reading a command.
|
59
|
-
#
|
60
|
-
def prompt(context)
|
61
|
-
"(byebug#{context.dead? ? ':post-mortem' : ''}) "
|
71
|
+
run_auto_commands(2)
|
62
72
|
end
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# For example display commands or possibly the list or irb in an "autolist"
|
68
|
-
# or "autoirb".
|
69
|
-
#
|
70
|
-
# @return List of commands acceptable to run bound to the current state
|
71
|
-
#
|
72
|
-
def always_run(context, file, line, run_level)
|
73
|
-
@state = RegularState.new(context, @display, file, @interface, line)
|
74
|
-
|
75
|
-
# Change default when in irb or code included in command line
|
76
|
-
Setting[:autolist] = false if ['(irb)', '-e'].include?(file)
|
74
|
+
def at_line
|
75
|
+
process_commands
|
76
|
+
end
|
77
77
|
|
78
|
-
|
79
|
-
|
78
|
+
def at_return
|
79
|
+
process_commands
|
80
80
|
end
|
81
81
|
|
82
|
-
|
83
|
-
|
82
|
+
#
|
83
|
+
# Let the execution continue
|
84
|
+
#
|
85
|
+
def proceed!
|
86
|
+
@proceed = true
|
84
87
|
end
|
85
88
|
|
86
89
|
#
|
87
90
|
# Handle byebug commands.
|
88
91
|
#
|
89
|
-
def process_commands
|
90
|
-
|
91
|
-
|
92
|
-
puts 'The program finished.' if program_just_finished?(context)
|
93
|
-
puts(state.location) if Setting[:autolist] == 0
|
94
|
-
|
95
|
-
@interface.autorestore
|
92
|
+
def process_commands
|
93
|
+
before_repl
|
96
94
|
|
97
|
-
repl
|
95
|
+
repl
|
98
96
|
ensure
|
99
|
-
|
97
|
+
after_repl
|
100
98
|
end
|
101
99
|
|
100
|
+
protected
|
101
|
+
|
102
102
|
#
|
103
|
-
#
|
103
|
+
# Prompt shown before reading a command.
|
104
104
|
#
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
return unless cmd
|
109
|
-
|
110
|
-
next if cmd == '' && @last_cmd.nil?
|
105
|
+
def prompt
|
106
|
+
'(byebug) '
|
107
|
+
end
|
111
108
|
|
112
|
-
|
109
|
+
private
|
113
110
|
|
114
|
-
|
115
|
-
|
111
|
+
def auto_commands_for(run_level)
|
112
|
+
command_list.select { |cmd| cmd.always_run >= run_level }
|
116
113
|
end
|
117
114
|
|
118
115
|
#
|
119
|
-
#
|
116
|
+
# Run permanent commands.
|
120
117
|
#
|
121
|
-
def
|
122
|
-
|
123
|
-
|
124
|
-
|
118
|
+
def run_auto_commands(run_level)
|
119
|
+
auto_commands_for(run_level).each { |cmd| cmd.new(self).execute }
|
120
|
+
end
|
121
|
+
|
122
|
+
def before_repl
|
123
|
+
@proceed = false
|
124
|
+
@prev_line = nil
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
run_auto_commands(1)
|
127
|
+
interface.autorestore
|
128
|
+
end
|
129
|
+
|
130
|
+
def after_repl
|
131
|
+
interface.autosave
|
129
132
|
end
|
130
133
|
|
131
134
|
#
|
135
|
+
# Main byebug's REPL
|
132
136
|
#
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
+
def repl
|
138
|
+
until @proceed
|
139
|
+
cmd = interface.read_command(prompt)
|
140
|
+
return if cmd.nil?
|
137
141
|
|
138
|
-
|
142
|
+
next if cmd == ''
|
139
143
|
|
140
|
-
|
141
|
-
return errmsg('Command unavailable in post mortem mode.')
|
144
|
+
run_cmd(cmd)
|
142
145
|
end
|
143
|
-
|
144
|
-
cmd.execute
|
145
146
|
end
|
146
147
|
|
147
148
|
#
|
148
|
-
#
|
149
|
+
# Executes the received input
|
149
150
|
#
|
150
|
-
|
151
|
-
|
152
|
-
end
|
153
|
-
|
151
|
+
# Instantiates a command matching the input and runs it. If a matching
|
152
|
+
# command is not found, it evaluates the unknown input.
|
154
153
|
#
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
154
|
+
def run_cmd(input)
|
155
|
+
command = command_list.match(input)
|
156
|
+
return command.new(self, input).execute if command
|
157
|
+
|
158
|
+
puts thread_safe_eval(input)
|
159
|
+
rescue => e
|
160
|
+
errmsg(e)
|
162
161
|
end
|
163
162
|
end
|
164
163
|
end
|