pry-byebug-reloaded 3.10.1

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.
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ module Byebug
5
+ #
6
+ # Wrapper for Byebug.breakpoints that respects our Processor and has better
7
+ # failure behavior. Acts as an Enumerable.
8
+ #
9
+ module Breakpoints
10
+ extend Enumerable
11
+ extend self
12
+
13
+ #
14
+ # Breakpoint in a file:line location
15
+ #
16
+ class FileBreakpoint < SimpleDelegator
17
+ def source_code
18
+ Pry::Code.from_file(source).around(pos, 3).with_marker(pos)
19
+ end
20
+
21
+ def to_s
22
+ "#{source} @ #{pos}"
23
+ end
24
+ end
25
+
26
+ #
27
+ # Breakpoint in a Class#method location
28
+ #
29
+ class MethodBreakpoint < SimpleDelegator
30
+ def initialize(byebug_bp, method)
31
+ __setobj__ byebug_bp
32
+ @method = method
33
+ end
34
+
35
+ def source_code
36
+ Pry::Code.from_method(Pry::Method.from_str(@method))
37
+ end
38
+
39
+ def to_s
40
+ @method
41
+ end
42
+ end
43
+
44
+ def breakpoints
45
+ @breakpoints ||= []
46
+ end
47
+
48
+ #
49
+ # Adds a method breakpoint.
50
+ #
51
+ def add_method(method, expression = nil)
52
+ validate_expression expression
53
+ owner, name = method.split(/[\.#]/)
54
+ byebug_bp = ::Byebug::Breakpoint.add(owner, name.to_sym, expression)
55
+ bp = MethodBreakpoint.new byebug_bp, method
56
+ breakpoints << bp
57
+ bp
58
+ end
59
+
60
+ #
61
+ # Adds a file breakpoint.
62
+ #
63
+ def add_file(file, line, expression = nil)
64
+ real_file = (file != Pry.eval_path)
65
+ raise(ArgumentError, "Invalid file!") if real_file && !File.exist?(file)
66
+
67
+ validate_expression expression
68
+
69
+ path = (real_file ? File.expand_path(file) : file)
70
+ bp = FileBreakpoint.new ::Byebug::Breakpoint.add(path, line, expression)
71
+ breakpoints << bp
72
+ bp
73
+ end
74
+
75
+ #
76
+ # Changes the conditional expression for a breakpoint.
77
+ #
78
+ def change(id, expression = nil)
79
+ validate_expression expression
80
+
81
+ breakpoint = find_by_id(id)
82
+ breakpoint.expr = expression
83
+ breakpoint
84
+ end
85
+
86
+ #
87
+ # Deletes an existing breakpoint with the given ID.
88
+ #
89
+ def delete(id)
90
+ deleted =
91
+ ::Byebug::Breakpoint.remove(id) &&
92
+ breakpoints.delete(find_by_id(id))
93
+
94
+ raise(ArgumentError, "No breakpoint ##{id}") unless deleted
95
+ end
96
+
97
+ #
98
+ # Deletes all breakpoints.
99
+ #
100
+ def delete_all
101
+ @breakpoints = []
102
+ ::Byebug.breakpoints.clear
103
+ end
104
+
105
+ #
106
+ # Enables a disabled breakpoint with the given ID.
107
+ #
108
+ def enable(id)
109
+ change_status id, true
110
+ end
111
+
112
+ #
113
+ # Disables a breakpoint with the given ID.
114
+ #
115
+ def disable(id)
116
+ change_status id, false
117
+ end
118
+
119
+ #
120
+ # Disables all breakpoints.
121
+ #
122
+ def disable_all
123
+ each do |breakpoint|
124
+ breakpoint.enabled = false
125
+ end
126
+ end
127
+
128
+ def to_a
129
+ breakpoints
130
+ end
131
+
132
+ def size
133
+ to_a.size
134
+ end
135
+
136
+ def each(&block)
137
+ to_a.each(&block)
138
+ end
139
+
140
+ def last
141
+ to_a.last
142
+ end
143
+
144
+ def find_by_id(id)
145
+ breakpoint = find { |b| b.id == id }
146
+ raise(ArgumentError, "No breakpoint ##{id}!") unless breakpoint
147
+
148
+ breakpoint
149
+ end
150
+
151
+ private
152
+
153
+ def change_status(id, enabled = true)
154
+ breakpoint = find_by_id(id)
155
+ breakpoint.enabled = enabled
156
+ breakpoint
157
+ end
158
+
159
+ def validate_expression(exp)
160
+ valid = exp && (exp.empty? || !Pry::Code.complete_expression?(exp))
161
+ return unless valid
162
+
163
+ raise("Invalid breakpoint conditional: #{expression}")
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/location"
4
+
5
+ #
6
+ # Main container module for Pry-Byebug functionality
7
+ #
8
+ module PryByebug
9
+ # Reference to currently running pry-remote server. Used by the processor.
10
+ attr_accessor :current_remote_server
11
+
12
+ module_function
13
+
14
+ #
15
+ # Checks that a target binding is in a local file context.
16
+ #
17
+ def file_context?(target)
18
+ file = Helpers::Location.current_file(target)
19
+ file == Pry.eval_path || !Pry::Helpers::BaseHelpers.not_a_real_file?(file)
20
+ end
21
+
22
+ #
23
+ # Ensures that a command is executed in a local file context.
24
+ #
25
+ def check_file_context(target, msg = nil)
26
+ msg ||= "Cannot find local context. Did you use `binding.pry`?"
27
+ raise(Pry::CommandError, msg) unless file_context?(target)
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/base"
4
+ require "pry-byebug/pry_ext"
5
+ require "pry-byebug/commands"
6
+ require "pry-byebug/control_d_handler"
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+
5
+ module PryByebug
6
+ #
7
+ # Display the current stack
8
+ #
9
+ class BacktraceCommand < Pry::ClassCommand
10
+ include Helpers::Navigation
11
+
12
+ match "backtrace"
13
+ group "Byebug"
14
+
15
+ description "Display the current stack."
16
+
17
+ banner <<-BANNER
18
+ Usage: backtrace
19
+
20
+ Display the current stack.
21
+ BANNER
22
+
23
+ def process
24
+ PryByebug.check_file_context(target)
25
+
26
+ breakout_navigation :backtrace
27
+ end
28
+ end
29
+ end
30
+
31
+ Pry::Commands.add_command(PryByebug::BacktraceCommand)
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry/byebug/breakpoints"
4
+ require "pry-byebug/helpers/breakpoints"
5
+ require "pry-byebug/helpers/location"
6
+ require "pry-byebug/helpers/multiline"
7
+
8
+ module PryByebug
9
+ #
10
+ # Add, show and remove breakpoints
11
+ #
12
+ class BreakCommand < Pry::ClassCommand
13
+ include Helpers::Breakpoints
14
+ include Helpers::Location
15
+ include Helpers::Multiline
16
+
17
+ match "break"
18
+ group "Byebug"
19
+ description "Set or edit a breakpoint."
20
+
21
+ banner <<-BANNER
22
+ Usage: break <METHOD | FILE:LINE | LINE> [if CONDITION]
23
+ break --condition N [CONDITION]
24
+ break [--show | --delete | --enable | --disable] N
25
+ break [--delete-all | --disable-all]
26
+ break
27
+
28
+ Set a breakpoint. Accepts a line number in the current file, a file and
29
+ line number, or a method, and an optional condition.
30
+
31
+ Pass appropriate flags to manipulate existing breakpoints.
32
+
33
+ Examples:
34
+
35
+ break SomeClass#run Break at the start of `SomeClass#run`.
36
+ break Foo#bar if baz? Break at `Foo#bar` only if `baz?`.
37
+ break app/models/user.rb:15 Break at line 15 in user.rb.
38
+ break 14 Break at line 14 in the current file.
39
+
40
+ break --condition 4 x > 2 Add/change condition on breakpoint #4.
41
+ break --condition 3 Remove the condition on breakpoint #3.
42
+
43
+ break --delete 5 Delete breakpoint #5.
44
+ break --disable-all Disable all breakpoints.
45
+
46
+ break --show 2 Show details about breakpoint #2.
47
+ break List all breakpoints.
48
+ BANNER
49
+
50
+ def options(opt)
51
+ defaults = { argument: true, as: Integer }
52
+
53
+ opt.on :c, :condition, "Change condition of a breakpoint.", defaults
54
+ opt.on :s, :show, "Show breakpoint details and source.", defaults
55
+ opt.on :D, :delete, "Delete a breakpoint.", defaults
56
+ opt.on :d, :disable, "Disable a breakpoint.", defaults
57
+ opt.on :e, :enable, "Enable a disabled breakpoint.", defaults
58
+ opt.on :'disable-all', "Disable all breakpoints."
59
+ opt.on :'delete-all', "Delete all breakpoints."
60
+ end
61
+
62
+ def process
63
+ return if check_multiline_context
64
+
65
+ PryByebug.check_file_context(target)
66
+
67
+ option, = opts.to_hash.find { |key, _value| opts.present?(key) }
68
+ return send(option_to_method(option)) if option
69
+
70
+ return new_breakpoint unless args.empty?
71
+
72
+ print_all
73
+ end
74
+
75
+ private
76
+
77
+ %w[delete disable enable disable_all delete_all].each do |command|
78
+ define_method(:"process_#{command}") do
79
+ breakpoints.send(*[command, opts[command]].compact)
80
+ print_all
81
+ end
82
+ end
83
+
84
+ def process_show
85
+ print_full_breakpoint(breakpoints.find_by_id(opts[:show]))
86
+ end
87
+
88
+ def process_condition
89
+ expr = args.empty? ? nil : args.join(" ")
90
+ breakpoints.change(opts[:condition], expr)
91
+ end
92
+
93
+ def new_breakpoint
94
+ place = args.shift
95
+ condition = args.join(" ") if args.shift == "if"
96
+
97
+ bp = add_breakpoint(place, condition)
98
+
99
+ print_full_breakpoint(bp)
100
+ end
101
+
102
+ def option_to_method(option)
103
+ "process_#{option.to_s.tr('-', '_')}"
104
+ end
105
+
106
+ def print_all
107
+ print_breakpoints_header
108
+ breakpoints.each { |b| print_short_breakpoint(b) }
109
+ end
110
+
111
+ def add_breakpoint(place, condition)
112
+ case place
113
+ when /^(\d+)$/
114
+ errmsg = "Line number declaration valid only in a file context."
115
+ PryByebug.check_file_context(target, errmsg)
116
+
117
+ lineno = Regexp.last_match[1].to_i
118
+ breakpoints.add_file(current_file, lineno, condition)
119
+ when /^(.+):(\d+)$/
120
+ file = Regexp.last_match[1]
121
+ lineno = Regexp.last_match[2].to_i
122
+ breakpoints.add_file(file, lineno, condition)
123
+ when /^(.*)[.#].+$/ # Method or class name
124
+ if Regexp.last_match[1].strip.empty?
125
+ errmsg = "Method name declaration valid only in a file context."
126
+ PryByebug.check_file_context(target, errmsg)
127
+ place = target.eval("self.class.to_s") + place
128
+ end
129
+ breakpoints.add_method(place, condition)
130
+ else
131
+ raise(ArgumentError, "Cannot identify arguments as breakpoint")
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ Pry::Commands.add_command(PryByebug::BreakCommand)
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+ require "pry-byebug/helpers/breakpoints"
5
+ require "pry-byebug/helpers/location"
6
+
7
+ module PryByebug
8
+ #
9
+ # Continue program execution until the next breakpoint
10
+ #
11
+ class ContinueCommand < Pry::ClassCommand
12
+ include Helpers::Navigation
13
+ include Helpers::Breakpoints
14
+ include Helpers::Location
15
+
16
+ match "continue"
17
+ group "Byebug"
18
+ description "Continue program execution and end the Pry session."
19
+
20
+ banner <<-BANNER
21
+ Usage: continue [LINE]
22
+
23
+ Continue program execution until the next breakpoint, or the program
24
+ ends. Optionally continue to the specified line number.
25
+
26
+ Examples:
27
+ continue #=> Continue until the next breakpoint.
28
+ continue 4 #=> Continue to line number 4.
29
+ BANNER
30
+
31
+ def process
32
+ PryByebug.check_file_context(target)
33
+
34
+ breakpoints.add_file(current_file, args.first.to_i) if args.first
35
+
36
+ breakout_navigation :continue
37
+ ensure
38
+ Byebug.stop if Byebug.stoppable?
39
+ end
40
+ end
41
+ end
42
+
43
+ Pry::Commands.add_command(PryByebug::ContinueCommand)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+
5
+ module PryByebug
6
+ #
7
+ # Travel down the frame stack
8
+ #
9
+ class DownCommand < Pry::ClassCommand
10
+ include Helpers::Navigation
11
+
12
+ match "down"
13
+ group "Byebug"
14
+
15
+ description "Move current frame down."
16
+
17
+ banner <<-BANNER
18
+ Usage: down [TIMES]
19
+
20
+ Move current frame down. By default, moves by 1 frame.
21
+
22
+ Examples:
23
+ down #=> Move down 1 frame.
24
+ down 5 #=> Move down 5 frames.
25
+ BANNER
26
+
27
+ def process
28
+ PryByebug.check_file_context(target)
29
+
30
+ breakout_navigation :down, times: args.first
31
+ end
32
+ end
33
+ end
34
+
35
+ Pry::Commands.add_command(PryByebug::DownCommand)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry/commands/exit_all"
4
+
5
+ module PryByebug
6
+ #
7
+ # Exit pry REPL with Byebug.stop
8
+ #
9
+ class ExitAllCommand < Pry::Command::ExitAll
10
+ def process
11
+ super
12
+ ensure
13
+ Byebug.stop if Byebug.stoppable?
14
+ end
15
+ end
16
+ end
17
+
18
+ Pry::Commands.add_command(PryByebug::ExitAllCommand)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+
5
+ module PryByebug
6
+ #
7
+ # Run until the end of current frame
8
+ #
9
+ class FinishCommand < Pry::ClassCommand
10
+ include PryByebug::Helpers::Navigation
11
+
12
+ match "finish"
13
+ group "Byebug"
14
+ description "Execute until current stack frame returns."
15
+
16
+ banner <<-BANNER
17
+ Usage: finish
18
+ BANNER
19
+
20
+ def process
21
+ PryByebug.check_file_context(target)
22
+
23
+ breakout_navigation :finish
24
+ end
25
+ end
26
+ end
27
+
28
+ Pry::Commands.add_command(PryByebug::FinishCommand)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+
5
+ module PryByebug
6
+ #
7
+ # Move to a specific frame in the callstack
8
+ #
9
+ class FrameCommand < Pry::ClassCommand
10
+ include Helpers::Navigation
11
+
12
+ match "frame"
13
+ group "Byebug"
14
+
15
+ description "Move to specified frame #."
16
+
17
+ banner <<-BANNER
18
+ Usage: frame [TIMES]
19
+
20
+ Move to specified frame #.
21
+
22
+ Examples:
23
+ frame #=> Show current frame #.
24
+ frame 5 #=> Move to frame 5.
25
+ BANNER
26
+
27
+ def process
28
+ PryByebug.check_file_context(target)
29
+
30
+ breakout_navigation :frame, index: args.first
31
+ end
32
+ end
33
+ end
34
+
35
+ Pry::Commands.add_command(PryByebug::FrameCommand)
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+ require "pry-byebug/helpers/multiline"
5
+
6
+ module PryByebug
7
+ #
8
+ # Run a number of lines and then stop again
9
+ #
10
+ class NextCommand < Pry::ClassCommand
11
+ include Helpers::Navigation
12
+ include Helpers::Multiline
13
+
14
+ match "next"
15
+ group "Byebug"
16
+ description "Execute the next line within the current stack frame."
17
+
18
+ banner <<-BANNER
19
+ Usage: next [LINES]
20
+
21
+ Step over within the same frame. By default, moves forward a single
22
+ line.
23
+
24
+ Examples:
25
+ next #=> Move a single line forward.
26
+ next 4 #=> Execute the next 4 lines.
27
+ BANNER
28
+
29
+ def process
30
+ return if check_multiline_context
31
+
32
+ PryByebug.check_file_context(target)
33
+
34
+ breakout_navigation :next, lines: args.first
35
+ end
36
+ end
37
+ end
38
+
39
+ Pry::Commands.add_command(PryByebug::NextCommand)
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+
5
+ module PryByebug
6
+ #
7
+ # Run a number of Ruby statements and then stop again
8
+ #
9
+ class StepCommand < Pry::ClassCommand
10
+ include Helpers::Navigation
11
+
12
+ match "step"
13
+ group "Byebug"
14
+ description "Step execution into the next line or method."
15
+
16
+ banner <<-BANNER
17
+ Usage: step [TIMES]
18
+
19
+ Step execution forward. By default, moves a single step.
20
+
21
+ Examples:
22
+ step #=> Move a single step forward.
23
+ step 5 #=> Execute the next 5 steps.
24
+ BANNER
25
+
26
+ def process
27
+ PryByebug.check_file_context(target)
28
+
29
+ breakout_navigation :step, times: args.first
30
+ end
31
+ end
32
+ end
33
+
34
+ Pry::Commands.add_command(PryByebug::StepCommand)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/helpers/navigation"
4
+
5
+ module PryByebug
6
+ #
7
+ # Travel up the frame stack
8
+ #
9
+ class UpCommand < Pry::ClassCommand
10
+ include Helpers::Navigation
11
+
12
+ match "up"
13
+ group "Byebug"
14
+
15
+ description "Move current frame up."
16
+
17
+ banner <<-BANNER
18
+ Usage: up [TIMES]
19
+
20
+ Move current frame up. By default, moves by 1 frame.
21
+
22
+ Examples:
23
+ up #=> Move up 1 frame.
24
+ up 5 #=> Move up 5 frames.
25
+ BANNER
26
+
27
+ def process
28
+ PryByebug.check_file_context(target)
29
+
30
+ breakout_navigation :up, times: args.first
31
+ end
32
+ end
33
+ end
34
+
35
+ Pry::Commands.add_command(PryByebug::UpCommand)
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-byebug/commands/backtrace"
4
+ require "pry-byebug/commands/next"
5
+ require "pry-byebug/commands/step"
6
+ require "pry-byebug/commands/continue"
7
+ require "pry-byebug/commands/finish"
8
+ require "pry-byebug/commands/up"
9
+ require "pry-byebug/commands/down"
10
+ require "pry-byebug/commands/frame"
11
+ require "pry-byebug/commands/breakpoint"
12
+ require "pry-byebug/commands/exit_all"
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ original_handler = Pry.config.control_d_handler
4
+
5
+ Pry.config.control_d_handler = proc do |pry_instance|
6
+ Byebug.stop if Byebug.stoppable?
7
+
8
+ original_handler.call(pry_instance)
9
+ end