pry 0.13.1 → 0.15.2
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 +118 -2
- data/README.md +47 -30
- data/lib/pry/basic_object.rb +1 -1
- data/lib/pry/class_command.rb +2 -2
- data/lib/pry/cli.rb +13 -29
- data/lib/pry/code.rb +1 -9
- data/lib/pry/code_object.rb +2 -2
- data/lib/pry/command.rb +1 -1
- data/lib/pry/command_set.rb +2 -2
- data/lib/pry/command_state.rb +11 -6
- data/lib/pry/commands/amend_line.rb +1 -1
- data/lib/pry/commands/cd.rb +2 -0
- data/lib/pry/commands/edit.rb +2 -0
- data/lib/pry/commands/find_method.rb +1 -1
- data/lib/pry/commands/ls/config.rb +54 -0
- data/lib/pry/commands/ls/constants.rb +2 -2
- data/lib/pry/commands/ls.rb +0 -21
- data/lib/pry/commands/raise_up.rb +1 -1
- data/lib/pry/commands/ri.rb +1 -1
- data/lib/pry/commands/shell_command.rb +1 -1
- data/lib/pry/commands/shell_mode.rb +1 -0
- data/lib/pry/commands/show_doc.rb +0 -1
- data/lib/pry/commands/show_source.rb +1 -0
- data/lib/pry/commands/watch_expression/expression.rb +1 -1
- data/lib/pry/commands/watch_expression.rb +4 -6
- data/lib/pry/config.rb +26 -33
- data/lib/pry/control_d_handler.rb +1 -1
- data/lib/pry/core_extensions.rb +1 -1
- data/lib/pry/editor.rb +3 -1
- data/lib/pry/exception_handler.rb +7 -2
- data/lib/pry/helpers/command_helpers.rb +1 -1
- data/lib/pry/helpers/documentation_helpers.rb +2 -1
- data/lib/pry/helpers/platform.rb +1 -6
- data/lib/pry/helpers/text.rb +1 -1
- data/lib/pry/indent.rb +13 -11
- data/lib/pry/input/simple_stdio.rb +13 -0
- data/lib/pry/input_completer.rb +2 -2
- data/lib/pry/method/patcher.rb +2 -2
- data/lib/pry/method/weird_method_locator.rb +2 -2
- data/lib/pry/method.rb +4 -4
- data/lib/pry/pry_class.rb +17 -7
- data/lib/pry/pry_instance.rb +7 -45
- data/lib/pry/repl.rb +73 -4
- data/lib/pry/ring.rb +2 -2
- data/lib/pry/slop.rb +1 -1
- data/lib/pry/syntax_highlighter.rb +1 -1
- data/lib/pry/version.rb +1 -1
- data/lib/pry/warning.rb +3 -10
- data/lib/pry/wrapped_module/candidate.rb +9 -8
- data/lib/pry/wrapped_module.rb +3 -8
- data/lib/pry.rb +3 -1
- metadata +9 -8
- data/lib/pry/plugins.rb +0 -139
data/lib/pry/pry_instance.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'method_source'
|
4
|
-
require 'ostruct'
|
5
4
|
|
6
5
|
##
|
7
6
|
# Pry is a powerful alternative to the standard IRB shell for Ruby. It
|
@@ -20,7 +19,7 @@ require 'ostruct'
|
|
20
19
|
# This will show a list of available commands and their usage. For more
|
21
20
|
# information about Pry you can refer to the following resources:
|
22
21
|
#
|
23
|
-
# *
|
22
|
+
# * https://pry.github.io
|
24
23
|
# * https://github.com/pry/pry
|
25
24
|
# * the IRC channel, which is #pry on the Freenode network
|
26
25
|
#
|
@@ -93,7 +92,6 @@ class Pry
|
|
93
92
|
@input_ring << nil
|
94
93
|
push_initial_binding(target)
|
95
94
|
exec_hook(:when_started, target, options, self)
|
96
|
-
@prompt_warn = false
|
97
95
|
end
|
98
96
|
|
99
97
|
# This is the prompt at the top of the prompt stack.
|
@@ -388,7 +386,7 @@ class Pry
|
|
388
386
|
# @param [*Object] args The arguments to pass to the hook
|
389
387
|
# @return [Object, Exception] The return value of the hook or the exception raised
|
390
388
|
#
|
391
|
-
# If executing a hook raises an exception, we log that and then continue
|
389
|
+
# If executing a hook raises an exception, we log that and then continue successfully.
|
392
390
|
# To debug such errors, use the global variable $pry_hook_error, which is set as a
|
393
391
|
# result.
|
394
392
|
def exec_hook(name, *args, &block)
|
@@ -452,45 +450,17 @@ class Pry
|
|
452
450
|
# @return [String] The prompt.
|
453
451
|
def select_prompt
|
454
452
|
object = current_binding.eval('self')
|
455
|
-
|
456
|
-
|
457
|
-
c = OpenStruct.new(
|
458
|
-
object: object,
|
459
|
-
nesting_level: binding_stack.size - 1,
|
460
|
-
open_token: open_token,
|
461
|
-
session_line: Pry.history.session_line_count + 1,
|
462
|
-
history_line: Pry.history.history_line_count + 1,
|
463
|
-
expr_number: input_ring.count,
|
464
|
-
pry_instance: self,
|
465
|
-
binding_stack: binding_stack,
|
466
|
-
input_ring: input_ring,
|
467
|
-
eval_string: @eval_string,
|
468
|
-
cont: !@eval_string.empty?
|
469
|
-
)
|
453
|
+
nesting_level = binding_stack.size - 1
|
454
|
+
pry_instance = self
|
470
455
|
|
471
456
|
Pry.critical_section do
|
472
457
|
# If input buffer is empty, then use normal prompt. Otherwise use the wait
|
473
458
|
# prompt (indicating multi-line expression).
|
474
459
|
if prompt.is_a?(Pry::Prompt)
|
475
460
|
prompt_proc = eval_string.empty? ? prompt.wait_proc : prompt.incomplete_proc
|
476
|
-
return prompt_proc.call(
|
477
|
-
end
|
478
|
-
|
479
|
-
unless @prompt_warn
|
480
|
-
@prompt_warn = true
|
481
|
-
Kernel.warn(
|
482
|
-
"warning: setting prompt with help of " \
|
483
|
-
"`Pry.config.prompt = [proc {}, proc {}]` is deprecated. " \
|
484
|
-
"Use Pry::Prompt API instead"
|
485
|
-
)
|
486
|
-
end
|
487
|
-
|
488
|
-
# If input buffer is empty then use normal prompt
|
489
|
-
if eval_string.empty?
|
490
|
-
generate_prompt(Array(prompt).first, c)
|
491
|
-
# Otherwise use the wait prompt (indicating multi-line expression)
|
461
|
+
return prompt_proc.call(object, nesting_level, pry_instance)
|
492
462
|
else
|
493
|
-
|
463
|
+
output.puts "ERROR: Use Pry::Prompt API."
|
494
464
|
end
|
495
465
|
end
|
496
466
|
end
|
@@ -549,7 +519,7 @@ class Pry
|
|
549
519
|
# and a mistake in specifying that exception.
|
550
520
|
#
|
551
521
|
# (i.e. raise-up RunThymeError.new should not be the same as
|
552
|
-
# raise-up NameError, "
|
522
|
+
# raise-up NameError, "uninitialized constant RunThymeError")
|
553
523
|
#
|
554
524
|
def raise_up_common(force, *args)
|
555
525
|
exception = if args == []
|
@@ -685,14 +655,6 @@ class Pry
|
|
685
655
|
end
|
686
656
|
end
|
687
657
|
|
688
|
-
def generate_prompt(prompt_proc, conf)
|
689
|
-
if prompt_proc.arity == 1
|
690
|
-
prompt_proc.call(conf)
|
691
|
-
else
|
692
|
-
prompt_proc.call(conf.object, conf.nesting_level, conf.pry_instance)
|
693
|
-
end
|
694
|
-
end
|
695
|
-
|
696
658
|
# the array that the prompt stack is stored in
|
697
659
|
def prompt_stack
|
698
660
|
@prompt_stack ||= []
|
data/lib/pry/repl.rb
CHANGED
@@ -100,7 +100,7 @@ class Pry
|
|
100
100
|
# Return nil for EOF, :no_more_input for error, or :control_c for <Ctrl-C>
|
101
101
|
return val unless val.is_a?(String)
|
102
102
|
|
103
|
-
if pry.config.auto_indent
|
103
|
+
if pry.config.auto_indent && !input_multiline?
|
104
104
|
original_val = "#{indentation}#{val}"
|
105
105
|
indented_val = @indent.indent(val)
|
106
106
|
|
@@ -141,8 +141,7 @@ class Pry
|
|
141
141
|
retry
|
142
142
|
|
143
143
|
# Handle <Ctrl+C> like Bash: empty the current input buffer, but don't
|
144
|
-
# quit.
|
145
|
-
# send Interrupt from within Readline.
|
144
|
+
# quit.
|
146
145
|
rescue Interrupt
|
147
146
|
return :control_c
|
148
147
|
|
@@ -180,7 +179,31 @@ class Pry
|
|
180
179
|
end
|
181
180
|
end
|
182
181
|
|
183
|
-
if
|
182
|
+
if reline_available?
|
183
|
+
Reline.output_modifier_proc = lambda do |text, _|
|
184
|
+
if pry.color
|
185
|
+
SyntaxHighlighter.highlight(text)
|
186
|
+
else
|
187
|
+
text
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
if pry.config.auto_indent
|
192
|
+
Reline.auto_indent_proc = lambda do |lines, line_index, _byte_ptr, _newline|
|
193
|
+
if line_index == 0
|
194
|
+
0
|
195
|
+
else
|
196
|
+
pry_indentation = Pry::Indent.new
|
197
|
+
pry_indentation.indent(lines.join("\n"))
|
198
|
+
pry_indentation.last_indent_level.length
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
if input_multiline?
|
205
|
+
input_readmultiline(current_prompt, false)
|
206
|
+
elsif readline_available?
|
184
207
|
set_readline_output
|
185
208
|
input_readline(current_prompt, false) # false since we'll add it manually
|
186
209
|
elsif coolline_available?
|
@@ -193,12 +216,29 @@ class Pry
|
|
193
216
|
end
|
194
217
|
end
|
195
218
|
|
219
|
+
def input_readmultiline(*args)
|
220
|
+
Pry::InputLock.for(:all).interruptible_region do
|
221
|
+
input.readmultiline(*args) do |multiline_input|
|
222
|
+
Pry.commands.find_command(multiline_input) ||
|
223
|
+
(complete_expression?(multiline_input) && !Reline::IOGate.in_pasting?)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
196
228
|
def input_readline(*args)
|
197
229
|
Pry::InputLock.for(:all).interruptible_region do
|
198
230
|
input.readline(*args)
|
199
231
|
end
|
200
232
|
end
|
201
233
|
|
234
|
+
def input_multiline?
|
235
|
+
!!pry.config.multiline && reline_available?
|
236
|
+
end
|
237
|
+
|
238
|
+
def reline_available?
|
239
|
+
defined?(Reline) && input == Reline
|
240
|
+
end
|
241
|
+
|
202
242
|
def readline_available?
|
203
243
|
defined?(Readline) && input == Readline
|
204
244
|
end
|
@@ -207,6 +247,20 @@ class Pry
|
|
207
247
|
defined?(Coolline) && input.is_a?(Coolline)
|
208
248
|
end
|
209
249
|
|
250
|
+
def prism_available?
|
251
|
+
@prism_available ||= begin
|
252
|
+
# rubocop:disable Lint/SuppressedException
|
253
|
+
begin
|
254
|
+
require 'prism'
|
255
|
+
rescue LoadError
|
256
|
+
end
|
257
|
+
# rubocop:enable Lint/SuppressedException
|
258
|
+
|
259
|
+
defined?(Prism::VERSION) &&
|
260
|
+
Gem::Version.new(Prism::VERSION) >= Gem::Version.new('0.25.0')
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
210
264
|
# If `$stdout` is not a tty, it's probably a pipe.
|
211
265
|
# @example
|
212
266
|
# # `piping?` returns `false`
|
@@ -228,6 +282,21 @@ class Pry
|
|
228
282
|
@readline_output = (Readline.output = Pry.config.output) if piping?
|
229
283
|
end
|
230
284
|
|
285
|
+
UNEXPECTED_TOKENS = %i[unexpected_token_ignore lambda_open].freeze
|
286
|
+
|
287
|
+
def complete_expression?(multiline_input)
|
288
|
+
if prism_available?
|
289
|
+
lex = Prism.lex(multiline_input)
|
290
|
+
|
291
|
+
errors = lex.errors
|
292
|
+
return true if errors.empty?
|
293
|
+
|
294
|
+
errors.any? { |error| UNEXPECTED_TOKENS.include?(error.type) }
|
295
|
+
else
|
296
|
+
Pry::Code.complete_expression?(multiline_input)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
231
300
|
# Calculates correct overhang for current line. Supports vi Readline
|
232
301
|
# mode and its indicators such as "(ins)" or "(cmd)".
|
233
302
|
#
|
data/lib/pry/ring.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
class Pry
|
4
4
|
# A ring is a thread-safe fixed-capacity array to which you can only add
|
5
5
|
# elements. Older entries are overwritten as you add new elements, so that the
|
6
|
-
# ring can never contain more than `max_size`
|
6
|
+
# ring can never contain more than `max_size` elements.
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# ring = Pry::Ring.new(3)
|
@@ -56,8 +56,8 @@ class Pry
|
|
56
56
|
# exist
|
57
57
|
def [](index)
|
58
58
|
@mutex.synchronize do
|
59
|
-
return @buffer[(count + index) % max_size] if index.is_a?(Integer)
|
60
59
|
return @buffer[index] if count <= max_size
|
60
|
+
return @buffer[(count + index) % max_size] if index.is_a?(Integer)
|
61
61
|
|
62
62
|
transpose_buffer_tail[index]
|
63
63
|
end
|
data/lib/pry/slop.rb
CHANGED
@@ -73,7 +73,7 @@ class Pry
|
|
73
73
|
# Build a Slop object from a option specification.
|
74
74
|
#
|
75
75
|
# This allows you to design your options via a simple String rather
|
76
|
-
# than
|
76
|
+
# than programmatically. Do note though that with this method, you're
|
77
77
|
# unable to pass any advanced options to the on() method when creating
|
78
78
|
# options.
|
79
79
|
#
|
data/lib/pry/version.rb
CHANGED
data/lib/pry/warning.rb
CHANGED
@@ -10,16 +10,9 @@ class Pry
|
|
10
10
|
# @param [String] message
|
11
11
|
# @return [void]
|
12
12
|
def self.warn(message)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
lineno = location.lineno
|
17
|
-
else
|
18
|
-
# Ruby 1.9.3 support.
|
19
|
-
frame = caller[1].split(':') # rubocop:disable Performance/Caller
|
20
|
-
path = frame.first
|
21
|
-
lineno = frame[1]
|
22
|
-
end
|
13
|
+
location = caller_locations(2..2).first
|
14
|
+
path = location.path
|
15
|
+
lineno = location.lineno
|
23
16
|
|
24
17
|
Kernel.warn("#{path}:#{lineno}: warning: #{message}")
|
25
18
|
end
|
@@ -20,9 +20,9 @@ class Pry
|
|
20
20
|
|
21
21
|
# Methods to delegate to associated `Pry::WrappedModule
|
22
22
|
# instance`.
|
23
|
-
private_delegates = [
|
24
|
-
public_delegates = [
|
25
|
-
|
23
|
+
private_delegates = %i[lines_for_file method_candidates yard_docs? name]
|
24
|
+
public_delegates = %i[wrapped module? class? nonblank_name
|
25
|
+
number_of_candidates]
|
26
26
|
|
27
27
|
def_delegators :@wrapper, *public_delegates
|
28
28
|
def_private_delegators :@wrapper, *private_delegates
|
@@ -98,14 +98,15 @@ class Pry
|
|
98
98
|
# line number is one-indexed.
|
99
99
|
def first_line_of_module_definition(file, line)
|
100
100
|
searchable_lines = lines_for_file(file)[0..(line - 2)]
|
101
|
-
searchable_lines.rindex { |v|
|
101
|
+
searchable_lines.rindex { |v| module_definition_first_line?(v) } + 1
|
102
102
|
end
|
103
103
|
|
104
|
-
def
|
104
|
+
def module_definition_first_line?(line)
|
105
105
|
mod_type_string = wrapped.class.to_s.downcase
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
wrapped_name_last = wrapped.name.split(/::/).last
|
107
|
+
/(^|=)\s*#{mod_type_string}\s+(?:(?:\w*)::)*?#{wrapped_name_last}/ =~ line ||
|
108
|
+
/^\s*(::)?#{wrapped_name_last}\s*?=\s*?#{wrapped.class}/ =~ line ||
|
109
|
+
/^\s*(::)?#{wrapped_name_last}\.(class|instance)_eval/ =~ line
|
109
110
|
end
|
110
111
|
|
111
112
|
# This method is used by `Candidate#source_location` as a
|
data/lib/pry/wrapped_module.rb
CHANGED
@@ -246,19 +246,14 @@ class Pry
|
|
246
246
|
method_candidates.count
|
247
247
|
end
|
248
248
|
|
249
|
-
# @
|
250
|
-
# away its ability to be quick (when there are lots of monkey patches,
|
251
|
-
# like in Rails). However, it should be efficient enough on other rubies.
|
252
|
-
# @see https://github.com/jruby/jruby/issues/525
|
253
|
-
# @return [Enumerator, Array] on JRuby 1.9 and higher returns Array, on
|
254
|
-
# other rubies returns Enumerator
|
249
|
+
# @return [Array]
|
255
250
|
def candidates
|
256
251
|
enum = Enumerator.new do |y|
|
257
252
|
(0...number_of_candidates).each do |num|
|
258
253
|
y.yield candidate(num)
|
259
254
|
end
|
260
255
|
end
|
261
|
-
|
256
|
+
enum
|
262
257
|
end
|
263
258
|
|
264
259
|
# @return [Boolean] Whether YARD docs are available for this module.
|
@@ -291,7 +286,7 @@ class Pry
|
|
291
286
|
# highest rank, that is the 'monkey patch' of this module with the
|
292
287
|
# highest number of methods, which contains a source code line that
|
293
288
|
# defines the module. It is considered the 'canonical' definition
|
294
|
-
# for the module. In the
|
289
|
+
# for the module. In the absence of a suitable candidate, the
|
295
290
|
# candidate of rank 0 will be returned, or a CommandError raised if
|
296
291
|
# there are no candidates at all.
|
297
292
|
def primary_candidate
|
data/lib/pry.rb
CHANGED
@@ -13,7 +13,6 @@ require 'pry/helpers'
|
|
13
13
|
|
14
14
|
require 'pry/basic_object'
|
15
15
|
require 'pry/prompt'
|
16
|
-
require 'pry/plugins'
|
17
16
|
require 'pry/code_object'
|
18
17
|
require 'pry/exceptions'
|
19
18
|
require 'pry/hooks'
|
@@ -35,6 +34,7 @@ require 'pry/env'
|
|
35
34
|
|
36
35
|
Pry::Commands = Pry::CommandSet.new unless defined?(Pry::Commands)
|
37
36
|
|
37
|
+
require 'pry/commands/ls/config'
|
38
38
|
require 'pry/commands/ls/jruby_hacks'
|
39
39
|
require 'pry/commands/ls/methods_helper'
|
40
40
|
require 'pry/commands/ls/interrogatable'
|
@@ -58,6 +58,8 @@ require 'pry/config/memoized_value'
|
|
58
58
|
require 'pry/config/lazy_value'
|
59
59
|
require 'pry/config'
|
60
60
|
|
61
|
+
require 'pry/input/simple_stdio'
|
62
|
+
|
61
63
|
require 'pry/pry_class'
|
62
64
|
require 'pry/pry_instance'
|
63
65
|
require 'pry/inspector'
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mair (banisterfiend)
|
8
8
|
- Conrad Irwin
|
9
9
|
- Ryan Fitzgerald
|
10
10
|
- Kyrylo Silin
|
11
|
-
autorequire:
|
11
|
+
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2024-12-24 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: coderay
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- lib/pry/commands/jump_to.rb
|
103
103
|
- lib/pry/commands/list_inspectors.rb
|
104
104
|
- lib/pry/commands/ls.rb
|
105
|
+
- lib/pry/commands/ls/config.rb
|
105
106
|
- lib/pry/commands/ls/constants.rb
|
106
107
|
- lib/pry/commands/ls/formatter.rb
|
107
108
|
- lib/pry/commands/ls/globals.rb
|
@@ -160,6 +161,7 @@ files:
|
|
160
161
|
- lib/pry/history.rb
|
161
162
|
- lib/pry/hooks.rb
|
162
163
|
- lib/pry/indent.rb
|
164
|
+
- lib/pry/input/simple_stdio.rb
|
163
165
|
- lib/pry/input_completer.rb
|
164
166
|
- lib/pry/input_lock.rb
|
165
167
|
- lib/pry/inspector.rb
|
@@ -171,7 +173,6 @@ files:
|
|
171
173
|
- lib/pry/object_path.rb
|
172
174
|
- lib/pry/output.rb
|
173
175
|
- lib/pry/pager.rb
|
174
|
-
- lib/pry/plugins.rb
|
175
176
|
- lib/pry/prompt.rb
|
176
177
|
- lib/pry/pry_class.rb
|
177
178
|
- lib/pry/pry_instance.rb
|
@@ -201,7 +202,7 @@ metadata:
|
|
201
202
|
changelog_uri: https://github.com/pry/pry/blob/master/CHANGELOG.md
|
202
203
|
source_code_uri: https://github.com/pry/pry
|
203
204
|
bug_tracker_uri: https://github.com/pry/pry/issues
|
204
|
-
post_install_message:
|
205
|
+
post_install_message:
|
205
206
|
rdoc_options: []
|
206
207
|
require_paths:
|
207
208
|
- lib
|
@@ -209,15 +210,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
209
210
|
requirements:
|
210
211
|
- - ">="
|
211
212
|
- !ruby/object:Gem::Version
|
212
|
-
version:
|
213
|
+
version: '2.0'
|
213
214
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
214
215
|
requirements:
|
215
216
|
- - ">="
|
216
217
|
- !ruby/object:Gem::Version
|
217
218
|
version: '0'
|
218
219
|
requirements: []
|
219
|
-
rubygems_version: 3.
|
220
|
-
signing_key:
|
220
|
+
rubygems_version: 3.4.14
|
221
|
+
signing_key:
|
221
222
|
specification_version: 4
|
222
223
|
summary: A runtime developer console and IRB alternative with powerful introspection
|
223
224
|
capabilities.
|
data/lib/pry/plugins.rb
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'ostruct'
|
4
|
-
|
5
|
-
class Pry
|
6
|
-
class PluginManager
|
7
|
-
PRY_PLUGIN_PREFIX = /^pry-/.freeze
|
8
|
-
|
9
|
-
# Placeholder when no associated gem found, displays warning
|
10
|
-
class NoPlugin
|
11
|
-
def initialize(name)
|
12
|
-
@name = name
|
13
|
-
end
|
14
|
-
|
15
|
-
def method_missing(*)
|
16
|
-
warn "Warning: The plugin '#{@name}' was not found! (no gem found)"
|
17
|
-
super
|
18
|
-
end
|
19
|
-
|
20
|
-
def respond_to_missing?(*)
|
21
|
-
false
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
class Plugin
|
26
|
-
attr_accessor :name, :gem_name, :enabled, :spec, :active
|
27
|
-
|
28
|
-
def initialize(name, gem_name, spec, enabled)
|
29
|
-
@name = name
|
30
|
-
@gem_name = gem_name
|
31
|
-
@enabled = enabled
|
32
|
-
@spec = spec
|
33
|
-
end
|
34
|
-
|
35
|
-
# Disable a plugin. (prevents plugin from being loaded, cannot
|
36
|
-
# disable an already activated plugin)
|
37
|
-
def disable!
|
38
|
-
self.enabled = false
|
39
|
-
end
|
40
|
-
|
41
|
-
# Enable a plugin. (does not load it immediately but puts on
|
42
|
-
# 'white list' to be loaded)
|
43
|
-
def enable!
|
44
|
-
self.enabled = true
|
45
|
-
end
|
46
|
-
|
47
|
-
# Load the Command line options defined by this plugin (if they exist)
|
48
|
-
def load_cli_options
|
49
|
-
cli_options_file = File.join(spec.full_gem_path, "lib/#{spec.name}/cli.rb")
|
50
|
-
return unless File.exist?(cli_options_file)
|
51
|
-
|
52
|
-
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4.4")
|
53
|
-
cli_options_file = File.realpath(cli_options_file)
|
54
|
-
end
|
55
|
-
require cli_options_file
|
56
|
-
end
|
57
|
-
|
58
|
-
# Activate the plugin (require the gem - enables/loads the
|
59
|
-
# plugin immediately at point of call, even if plugin is
|
60
|
-
# disabled)
|
61
|
-
# Does not reload plugin if it's already active.
|
62
|
-
def activate!
|
63
|
-
# Create the configuration object for the plugin.
|
64
|
-
Pry.config.send("#{gem_name.tr('-', '_')}=", OpenStruct.new)
|
65
|
-
|
66
|
-
begin
|
67
|
-
require gem_name unless active?
|
68
|
-
rescue LoadError => e
|
69
|
-
warn "Found plugin #{gem_name}, but could not require '#{gem_name}'"
|
70
|
-
warn e
|
71
|
-
rescue StandardError => e
|
72
|
-
warn "require '#{gem_name}' # Failed, saying: #{e}"
|
73
|
-
end
|
74
|
-
|
75
|
-
self.active = true
|
76
|
-
self.enabled = true
|
77
|
-
end
|
78
|
-
|
79
|
-
alias active? active
|
80
|
-
alias enabled? enabled
|
81
|
-
|
82
|
-
def supported?
|
83
|
-
pry_version = Gem::Version.new(VERSION)
|
84
|
-
spec.dependencies.each do |dependency|
|
85
|
-
if dependency.name == "pry"
|
86
|
-
return dependency.requirement.satisfied_by?(pry_version)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
true
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def initialize
|
94
|
-
@plugins = []
|
95
|
-
end
|
96
|
-
|
97
|
-
# Find all installed Pry plugins and store them in an internal array.
|
98
|
-
def locate_plugins
|
99
|
-
gem_list.each do |gem|
|
100
|
-
next if gem.name !~ PRY_PLUGIN_PREFIX
|
101
|
-
|
102
|
-
plugin_name = gem.name.split('-', 2).last
|
103
|
-
plugin = Plugin.new(plugin_name, gem.name, gem, false)
|
104
|
-
@plugins << plugin.tap(&:enable!) if plugin.supported? && !plugin_located?(plugin)
|
105
|
-
end
|
106
|
-
@plugins
|
107
|
-
end
|
108
|
-
|
109
|
-
# @return [Hash] A hash with all plugin names (minus the 'pry-') as
|
110
|
-
# keys and Plugin objects as values.
|
111
|
-
def plugins
|
112
|
-
h = Hash.new { |_, key| NoPlugin.new(key) }
|
113
|
-
@plugins.each do |plugin|
|
114
|
-
h[plugin.name] = plugin
|
115
|
-
end
|
116
|
-
h
|
117
|
-
end
|
118
|
-
|
119
|
-
# Require all enabled plugins, disabled plugins are skipped.
|
120
|
-
def load_plugins
|
121
|
-
@plugins.each do |plugin|
|
122
|
-
plugin.activate! if plugin.enabled?
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
private
|
127
|
-
|
128
|
-
def plugin_located?(plugin)
|
129
|
-
@plugins.any? { |existing| existing.gem_name == plugin.gem_name }
|
130
|
-
end
|
131
|
-
|
132
|
-
def gem_list
|
133
|
-
Gem.refresh
|
134
|
-
return Gem::Specification if Gem::Specification.respond_to?(:each)
|
135
|
-
|
136
|
-
Gem.source_index.find_name('')
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|