gitlab-pry-byebug 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,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
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug"
4
+
5
+ module PryByebug
6
+ module Helpers
7
+ #
8
+ # Common helpers for breakpoint related commands
9
+ #
10
+ module Breakpoints
11
+ #
12
+ # Byebug's array of breakpoints.
13
+ #
14
+ def breakpoints
15
+ Pry::Byebug::Breakpoints
16
+ end
17
+
18
+ #
19
+ # Prints a message with bold font.
20
+ #
21
+ def bold_puts(msg)
22
+ output.puts(bold(msg))
23
+ end
24
+
25
+ #
26
+ # Print out full information about a breakpoint.
27
+ #
28
+ # Includes surrounding code at that point.
29
+ #
30
+ def print_full_breakpoint(breakpoint)
31
+ header = "Breakpoint #{breakpoint.id}:"
32
+ status = breakpoint.enabled? ? "Enabled" : "Disabled"
33
+ code = breakpoint.source_code.with_line_numbers.to_s
34
+ condition = if breakpoint.expr
35
+ "#{bold('Condition:')} #{breakpoint.expr}\n"
36
+ else
37
+ ""
38
+ end
39
+
40
+ output.puts <<-BREAKPOINT.gsub(/ {8}/, "")
41
+
42
+ #{bold(header)} #{breakpoint} (#{status}) #{condition}
43
+
44
+ #{code}
45
+
46
+ BREAKPOINT
47
+ end
48
+
49
+ #
50
+ # Print out concise information about a breakpoint.
51
+ #
52
+ def print_short_breakpoint(breakpoint)
53
+ id = format("%*d", max_width, breakpoint.id)
54
+ status = breakpoint.enabled? ? "Yes" : "No "
55
+ expr = breakpoint.expr ? " #{breakpoint.expr} " : ""
56
+
57
+ output.puts(" #{id} #{status} #{breakpoint}#{expr}")
58
+ end
59
+
60
+ #
61
+ # Prints a header for the breakpoint list.
62
+ #
63
+ def print_breakpoints_header
64
+ header = "#{' ' * (max_width - 1)}# Enabled At "
65
+
66
+ output.puts <<-BREAKPOINTS.gsub(/ {8}/, "")
67
+
68
+ #{bold(header)}
69
+ #{bold('-' * header.size)}
70
+
71
+ BREAKPOINTS
72
+ end
73
+
74
+ #
75
+ # Max width of breakpoints id column
76
+ #
77
+ def max_width
78
+ breakpoints.last ? breakpoints.last.id.to_s.length : 1
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PryByebug
4
+ module Helpers
5
+ #
6
+ # Compatibility helper to handle source location
7
+ #
8
+ module Location
9
+ module_function
10
+
11
+ #
12
+ # Current file in the target binding. Used as the default breakpoint
13
+ # location.
14
+ #
15
+ def current_file(source = target)
16
+ # Guard clause for Ruby >= 2.6 providing now Binding#source_location ...
17
+ return source.source_location[0] if source.respond_to?(:source_location)
18
+
19
+ # ... to avoid warning: 'eval may not return location in binding'
20
+ source.eval("__FILE__")
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PryByebug
4
+ module Helpers
5
+ #
6
+ # Helpers to help handling multiline inputs
7
+ #
8
+ module Multiline
9
+ #
10
+ # Returns true if we are in a multiline context and, as a side effect,
11
+ # updates the partial evaluation string with the current input.
12
+ #
13
+ # Returns false otherwise
14
+ #
15
+ def check_multiline_context
16
+ return false if eval_string.empty?
17
+
18
+ eval_string.replace("#{eval_string}#{match} #{arg_string}\n")
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PryByebug
4
+ module Helpers
5
+ #
6
+ # Helpers to aid breaking out of the REPL loop
7
+ #
8
+ module Navigation
9
+ #
10
+ # Breaks out of the REPL loop and signals tracer
11
+ #
12
+ def breakout_navigation(action, options = {})
13
+ pry_instance.binding_stack.clear
14
+
15
+ throw :breakout_nav, action: action, options: options, pry: pry_instance
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/processors/pry_processor"
4
+ require "byebug/processors/pry_remote_processor"
5
+
6
+ class << Pry
7
+ alias start_without_pry_byebug start
8
+
9
+ def start_with_pry_byebug(target = TOPLEVEL_BINDING, options = {})
10
+ if target.is_a?(Binding) && PryByebug.file_context?(target) && !ENV["DISABLE_PRY"]
11
+ run_remote? ? Byebug::PryRemoteProcessor.start : Byebug::PryProcessor.start
12
+ else
13
+ # No need for the tracer unless we have a file context to step through
14
+ start_without_pry_byebug(target, options)
15
+ end
16
+ end
17
+
18
+ def run_remote?
19
+ PryByebug.current_remote_server
20
+ end
21
+
22
+ alias start start_with_pry_byebug
23
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pry-remote"
4
+
5
+ module PryRemote
6
+ #
7
+ # Overrides PryRemote::Server
8
+ #
9
+ class Server
10
+ #
11
+ # Override the call to Pry.start to save off current Server, and not
12
+ # teardown the server right after Pry.start finishes.
13
+ #
14
+ def run
15
+ raise("Already running a pry-remote session!") if
16
+ PryByebug.current_remote_server
17
+
18
+ PryByebug.current_remote_server = self
19
+
20
+ setup
21
+ Pry.start @object, input: client.input_proxy, output: client.output
22
+ end
23
+
24
+ #
25
+ # Override to reset our saved global current server session.
26
+ #
27
+ alias teardown_without_pry_byebug teardown
28
+ def teardown_with_pry_byebug
29
+ return if @torn
30
+
31
+ teardown_without_pry_byebug
32
+ PryByebug.current_remote_server = nil
33
+ @torn = true
34
+ end
35
+ alias teardown teardown_with_pry_byebug
36
+ end
37
+ end
38
+
39
+ # Ensure cleanup when a program finishes without another break. For example,
40
+ # 'next' on the last line of a program won't hit Byebug::PryProcessor#run,
41
+ # which normally handles cleanup.
42
+ at_exit do
43
+ PryByebug.current_remote_server&.teardown
44
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Main container module for Pry-Byebug functionality
5
+ #
6
+ module PryByebug
7
+ VERSION = "3.9.0"
8
+ end
@@ -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