super-smart-mod 0.0.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.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/pry-0.16.0/CHANGELOG.md +1211 -0
  3. data/pry-0.16.0/LICENSE +25 -0
  4. data/pry-0.16.0/README.md +469 -0
  5. data/pry-0.16.0/bin/pry +13 -0
  6. data/pry-0.16.0/lib/pry/basic_object.rb +10 -0
  7. data/pry-0.16.0/lib/pry/block_command.rb +22 -0
  8. data/pry-0.16.0/lib/pry/class_command.rb +194 -0
  9. data/pry-0.16.0/lib/pry/cli.rb +211 -0
  10. data/pry-0.16.0/lib/pry/code/code_file.rb +114 -0
  11. data/pry-0.16.0/lib/pry/code/code_range.rb +73 -0
  12. data/pry-0.16.0/lib/pry/code/loc.rb +105 -0
  13. data/pry-0.16.0/lib/pry/code.rb +357 -0
  14. data/pry-0.16.0/lib/pry/code_object.rb +197 -0
  15. data/pry-0.16.0/lib/pry/color_printer.rb +66 -0
  16. data/pry-0.16.0/lib/pry/command.rb +520 -0
  17. data/pry-0.16.0/lib/pry/command_set.rb +418 -0
  18. data/pry-0.16.0/lib/pry/command_state.rb +36 -0
  19. data/pry-0.16.0/lib/pry/commands/amend_line.rb +103 -0
  20. data/pry-0.16.0/lib/pry/commands/bang.rb +24 -0
  21. data/pry-0.16.0/lib/pry/commands/bang_pry.rb +21 -0
  22. data/pry-0.16.0/lib/pry/commands/cat/abstract_formatter.rb +32 -0
  23. data/pry-0.16.0/lib/pry/commands/cat/exception_formatter.rb +90 -0
  24. data/pry-0.16.0/lib/pry/commands/cat/file_formatter.rb +77 -0
  25. data/pry-0.16.0/lib/pry/commands/cat/input_expression_formatter.rb +48 -0
  26. data/pry-0.16.0/lib/pry/commands/cat.rb +70 -0
  27. data/pry-0.16.0/lib/pry/commands/cd.rb +48 -0
  28. data/pry-0.16.0/lib/pry/commands/change_inspector.rb +34 -0
  29. data/pry-0.16.0/lib/pry/commands/change_prompt.rb +51 -0
  30. data/pry-0.16.0/lib/pry/commands/clear_screen.rb +20 -0
  31. data/pry-0.16.0/lib/pry/commands/code_collector.rb +182 -0
  32. data/pry-0.16.0/lib/pry/commands/disable_pry.rb +31 -0
  33. data/pry-0.16.0/lib/pry/commands/easter_eggs.rb +101 -0
  34. data/pry-0.16.0/lib/pry/commands/edit/exception_patcher.rb +29 -0
  35. data/pry-0.16.0/lib/pry/commands/edit/file_and_line_locator.rb +47 -0
  36. data/pry-0.16.0/lib/pry/commands/edit.rb +225 -0
  37. data/pry-0.16.0/lib/pry/commands/exit.rb +47 -0
  38. data/pry-0.16.0/lib/pry/commands/exit_all.rb +33 -0
  39. data/pry-0.16.0/lib/pry/commands/exit_program.rb +27 -0
  40. data/pry-0.16.0/lib/pry/commands/find_method.rb +199 -0
  41. data/pry-0.16.0/lib/pry/commands/fix_indent.rb +23 -0
  42. data/pry-0.16.0/lib/pry/commands/help.rb +171 -0
  43. data/pry-0.16.0/lib/pry/commands/hist.rb +182 -0
  44. data/pry-0.16.0/lib/pry/commands/import_set.rb +27 -0
  45. data/pry-0.16.0/lib/pry/commands/jump_to.rb +33 -0
  46. data/pry-0.16.0/lib/pry/commands/list_inspectors.rb +42 -0
  47. data/pry-0.16.0/lib/pry/commands/ls/config.rb +54 -0
  48. data/pry-0.16.0/lib/pry/commands/ls/constants.rb +75 -0
  49. data/pry-0.16.0/lib/pry/commands/ls/formatter.rb +55 -0
  50. data/pry-0.16.0/lib/pry/commands/ls/globals.rb +50 -0
  51. data/pry-0.16.0/lib/pry/commands/ls/grep.rb +23 -0
  52. data/pry-0.16.0/lib/pry/commands/ls/instance_vars.rb +40 -0
  53. data/pry-0.16.0/lib/pry/commands/ls/interrogatable.rb +24 -0
  54. data/pry-0.16.0/lib/pry/commands/ls/jruby_hacks.rb +55 -0
  55. data/pry-0.16.0/lib/pry/commands/ls/local_names.rb +37 -0
  56. data/pry-0.16.0/lib/pry/commands/ls/local_vars.rb +47 -0
  57. data/pry-0.16.0/lib/pry/commands/ls/ls_entity.rb +65 -0
  58. data/pry-0.16.0/lib/pry/commands/ls/methods.rb +55 -0
  59. data/pry-0.16.0/lib/pry/commands/ls/methods_helper.rb +50 -0
  60. data/pry-0.16.0/lib/pry/commands/ls/self_methods.rb +34 -0
  61. data/pry-0.16.0/lib/pry/commands/ls.rb +114 -0
  62. data/pry-0.16.0/lib/pry/commands/nesting.rb +29 -0
  63. data/pry-0.16.0/lib/pry/commands/play.rb +113 -0
  64. data/pry-0.16.0/lib/pry/commands/pry_backtrace.rb +30 -0
  65. data/pry-0.16.0/lib/pry/commands/pry_version.rb +21 -0
  66. data/pry-0.16.0/lib/pry/commands/raise_up.rb +38 -0
  67. data/pry-0.16.0/lib/pry/commands/reload_code.rb +74 -0
  68. data/pry-0.16.0/lib/pry/commands/reset.rb +22 -0
  69. data/pry-0.16.0/lib/pry/commands/ri.rb +75 -0
  70. data/pry-0.16.0/lib/pry/commands/save_file.rb +63 -0
  71. data/pry-0.16.0/lib/pry/commands/shell_command.rb +75 -0
  72. data/pry-0.16.0/lib/pry/commands/shell_mode.rb +30 -0
  73. data/pry-0.16.0/lib/pry/commands/show_doc.rb +84 -0
  74. data/pry-0.16.0/lib/pry/commands/show_info.rb +234 -0
  75. data/pry-0.16.0/lib/pry/commands/show_input.rb +22 -0
  76. data/pry-0.16.0/lib/pry/commands/show_source.rb +57 -0
  77. data/pry-0.16.0/lib/pry/commands/stat.rb +44 -0
  78. data/pry-0.16.0/lib/pry/commands/switch_to.rb +29 -0
  79. data/pry-0.16.0/lib/pry/commands/toggle_color.rb +28 -0
  80. data/pry-0.16.0/lib/pry/commands/watch_expression/expression.rb +43 -0
  81. data/pry-0.16.0/lib/pry/commands/watch_expression.rb +108 -0
  82. data/pry-0.16.0/lib/pry/commands/whereami.rb +205 -0
  83. data/pry-0.16.0/lib/pry/commands/wtf.rb +95 -0
  84. data/pry-0.16.0/lib/pry/config/attributable.rb +22 -0
  85. data/pry-0.16.0/lib/pry/config/lazy_value.rb +29 -0
  86. data/pry-0.16.0/lib/pry/config/memoized_value.rb +34 -0
  87. data/pry-0.16.0/lib/pry/config/value.rb +24 -0
  88. data/pry-0.16.0/lib/pry/config.rb +321 -0
  89. data/pry-0.16.0/lib/pry/control_d_handler.rb +28 -0
  90. data/pry-0.16.0/lib/pry/core_extensions.rb +144 -0
  91. data/pry-0.16.0/lib/pry/editor.rb +157 -0
  92. data/pry-0.16.0/lib/pry/env.rb +18 -0
  93. data/pry-0.16.0/lib/pry/exception_handler.rb +48 -0
  94. data/pry-0.16.0/lib/pry/exceptions.rb +73 -0
  95. data/pry-0.16.0/lib/pry/forwardable.rb +27 -0
  96. data/pry-0.16.0/lib/pry/helpers/base_helpers.rb +71 -0
  97. data/pry-0.16.0/lib/pry/helpers/command_helpers.rb +146 -0
  98. data/pry-0.16.0/lib/pry/helpers/documentation_helpers.rb +84 -0
  99. data/pry-0.16.0/lib/pry/helpers/options_helpers.rb +34 -0
  100. data/pry-0.16.0/lib/pry/helpers/platform.rb +55 -0
  101. data/pry-0.16.0/lib/pry/helpers/table.rb +121 -0
  102. data/pry-0.16.0/lib/pry/helpers/text.rb +118 -0
  103. data/pry-0.16.0/lib/pry/helpers.rb +8 -0
  104. data/pry-0.16.0/lib/pry/history.rb +153 -0
  105. data/pry-0.16.0/lib/pry/hooks.rb +180 -0
  106. data/pry-0.16.0/lib/pry/indent.rb +414 -0
  107. data/pry-0.16.0/lib/pry/input/simple_stdio.rb +13 -0
  108. data/pry-0.16.0/lib/pry/input_completer.rb +283 -0
  109. data/pry-0.16.0/lib/pry/input_lock.rb +129 -0
  110. data/pry-0.16.0/lib/pry/inspector.rb +39 -0
  111. data/pry-0.16.0/lib/pry/last_exception.rb +61 -0
  112. data/pry-0.16.0/lib/pry/method/disowned.rb +67 -0
  113. data/pry-0.16.0/lib/pry/method/patcher.rb +131 -0
  114. data/pry-0.16.0/lib/pry/method/weird_method_locator.rb +222 -0
  115. data/pry-0.16.0/lib/pry/method.rb +599 -0
  116. data/pry-0.16.0/lib/pry/object_path.rb +91 -0
  117. data/pry-0.16.0/lib/pry/output.rb +136 -0
  118. data/pry-0.16.0/lib/pry/pager.rb +249 -0
  119. data/pry-0.16.0/lib/pry/prompt.rb +214 -0
  120. data/pry-0.16.0/lib/pry/pry_class.rb +371 -0
  121. data/pry-0.16.0/lib/pry/pry_instance.rb +663 -0
  122. data/pry-0.16.0/lib/pry/repl.rb +326 -0
  123. data/pry-0.16.0/lib/pry/repl_file_loader.rb +79 -0
  124. data/pry-0.16.0/lib/pry/ring.rb +89 -0
  125. data/pry-0.16.0/lib/pry/slop/LICENSE +20 -0
  126. data/pry-0.16.0/lib/pry/slop/commands.rb +190 -0
  127. data/pry-0.16.0/lib/pry/slop/option.rb +210 -0
  128. data/pry-0.16.0/lib/pry/slop.rb +672 -0
  129. data/pry-0.16.0/lib/pry/syntax_highlighter.rb +26 -0
  130. data/pry-0.16.0/lib/pry/system_command_handler.rb +17 -0
  131. data/pry-0.16.0/lib/pry/testable/evalable.rb +24 -0
  132. data/pry-0.16.0/lib/pry/testable/mockable.rb +22 -0
  133. data/pry-0.16.0/lib/pry/testable/pry_tester.rb +88 -0
  134. data/pry-0.16.0/lib/pry/testable/utility.rb +34 -0
  135. data/pry-0.16.0/lib/pry/testable/variables.rb +52 -0
  136. data/pry-0.16.0/lib/pry/testable.rb +68 -0
  137. data/pry-0.16.0/lib/pry/version.rb +5 -0
  138. data/pry-0.16.0/lib/pry/warning.rb +20 -0
  139. data/pry-0.16.0/lib/pry/wrapped_module/candidate.rb +145 -0
  140. data/pry-0.16.0/lib/pry/wrapped_module.rb +382 -0
  141. data/pry-0.16.0/lib/pry.rb +148 -0
  142. data/super-smart-mod.gemspec +12 -0
  143. metadata +182 -0
@@ -0,0 +1,357 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'method_source'
4
+
5
+ class Pry
6
+ class << self
7
+ # Convert the given object into an instance of `Pry::Code`, if it isn't
8
+ # already one.
9
+ #
10
+ # @param [Code, Method, UnboundMethod, Proc, Pry::Method, String, Array,
11
+ # IO] obj
12
+ def Code(obj)
13
+ case obj
14
+ when Code
15
+ obj
16
+ when ::Method, UnboundMethod, Proc, Pry::Method
17
+ Code.from_method(obj)
18
+ else
19
+ Code.new(obj)
20
+ end
21
+ end
22
+ end
23
+
24
+ # `Pry::Code` is a class that encapsulates lines of source code and their
25
+ # line numbers and formats them for terminal output. It can read from a file
26
+ # or method definition or be instantiated with a `String` or an `Array`.
27
+ #
28
+ # In general, the formatting methods in `Code` return a new `Code` object
29
+ # which will format the text as specified when `#to_s` is called. This allows
30
+ # arbitrary chaining of formatting methods without mutating the original
31
+ # object.
32
+ class Code
33
+ class << self
34
+ include MethodSource::CodeHelpers
35
+
36
+ # Instantiate a `Code` object containing code loaded from a file or
37
+ # Pry's line buffer.
38
+ #
39
+ # @param [String] filename The name of a file, or "(pry)".
40
+ # @param [Symbol] code_type The type of code the file contains.
41
+ # @return [Code]
42
+ def from_file(filename, code_type = nil)
43
+ code_file = CodeFile.new(filename, code_type)
44
+ new(code_file.code, 1, code_file.code_type)
45
+ end
46
+
47
+ # Instantiate a `Code` object containing code extracted from a
48
+ # `::Method`, `UnboundMethod`, `Proc`, or `Pry::Method` object.
49
+ #
50
+ # @param [::Method, UnboundMethod, Proc, Pry::Method] meth The method
51
+ # object.
52
+ # @param [Integer, nil] start_line The line number to start on, or nil to
53
+ # use the method's original line numbers.
54
+ # @return [Code]
55
+ def from_method(meth, start_line = nil)
56
+ meth = Pry::Method(meth)
57
+ start_line ||= meth.source_line || 1
58
+ new(meth.source, start_line, meth.source_type)
59
+ end
60
+
61
+ # Attempt to extract the source code for module (or class) `mod`.
62
+ #
63
+ # @param [Module, Class] mod The module (or class) of interest.
64
+ # @param [Integer] candidate_rank The module candidate (by rank)
65
+ # to use (see `Pry::WrappedModule::Candidate` for more information).
66
+ # @param [Integer, nil] start_line The line number to start on, or nil to
67
+ # use the method's original line numbers.
68
+ # @return [Code]
69
+ def from_module(mod, candidate_rank = 0, start_line = nil)
70
+ candidate = Pry::WrappedModule(mod).candidate(candidate_rank)
71
+ start_line ||= candidate.line
72
+ new(candidate.source, start_line, :ruby)
73
+ end
74
+ end
75
+
76
+ # @return [Symbol] The type of code stored in this wrapper.
77
+ attr_accessor :code_type
78
+
79
+ # Instantiate a `Code` object containing code from the given `Array`,
80
+ # `String`, or `IO`. The first line will be line 1 unless specified
81
+ # otherwise. If you need non-contiguous line numbers, you can create an
82
+ # empty `Code` object and then use `#push` to insert the lines.
83
+ #
84
+ # @param [Array<String>, String, IO] lines
85
+ # @param [Integer?] start_line
86
+ # @param [Symbol?] code_type
87
+ def initialize(lines = [], start_line = 1, code_type = :ruby)
88
+ lines = lines.lines if lines.is_a? String
89
+ @lines = lines.each_with_index.map do |line, lineno|
90
+ LOC.new(line, lineno + start_line.to_i)
91
+ end
92
+ @code_type = code_type
93
+
94
+ @with_marker = @with_indentation = @with_line_numbers = nil
95
+ end
96
+
97
+ # Append the given line. +lineno+ is one more than the last existing
98
+ # line, unless specified otherwise.
99
+ #
100
+ # @param [String] line
101
+ # @return [void]
102
+ def push(line)
103
+ line_number = @lines.any? ? @lines.last.lineno + 1 : 1
104
+ @lines.push(LOC.new(line, line_number))
105
+ end
106
+ alias << push
107
+
108
+ # Filter the lines using the given block.
109
+ #
110
+ # @yield [LOC]
111
+ # @return [Code]
112
+ def select(&block)
113
+ alter do
114
+ @lines = @lines.select(&block)
115
+ end
116
+ end
117
+
118
+ # Filter the lines using the given block.
119
+ #
120
+ # @yield [LOC]
121
+ # @return [Code]
122
+ def reject(&block)
123
+ alter do
124
+ @lines = @lines.reject(&block)
125
+ end
126
+ end
127
+
128
+ # Remove all lines that aren't in the given range, expressed either as a
129
+ # `Range` object or a first and last line number (inclusive). Negative
130
+ # indices count from the end of the array of lines.
131
+ #
132
+ # @param [Range, Integer] start_line
133
+ # @param [Integer?] end_line
134
+ # @return [Code]
135
+ def between(start_line, end_line = nil)
136
+ return self unless start_line
137
+
138
+ code_range = CodeRange.new(start_line, end_line)
139
+
140
+ alter do
141
+ @lines = @lines[code_range.indices_range(@lines)] || []
142
+ end
143
+ end
144
+
145
+ # Take `num_lines` from `start_line`, forward or backwards.
146
+ #
147
+ # @param [Integer] start_line
148
+ # @param [Integer] num_lines
149
+ # @return [Code]
150
+ def take_lines(start_line, num_lines)
151
+ start_idx =
152
+ if start_line >= 0
153
+ @lines.index { |loc| loc.lineno >= start_line } || @lines.length
154
+ else
155
+ [@lines.length + start_line, 0].max
156
+ end
157
+
158
+ alter do
159
+ @lines = @lines.slice(start_idx, num_lines)
160
+ end
161
+ end
162
+
163
+ # Remove all lines except for the +lines+ up to and excluding +lineno+.
164
+ #
165
+ # @param [Integer] lineno
166
+ # @param [Integer] lines
167
+ # @return [Code]
168
+ def before(lineno, lines = 1)
169
+ return self unless lineno
170
+
171
+ select do |loc|
172
+ loc.lineno >= lineno - lines && loc.lineno < lineno
173
+ end
174
+ end
175
+
176
+ # Remove all lines except for the +lines+ on either side of and including
177
+ # +lineno+.
178
+ #
179
+ # @param [Integer] lineno
180
+ # @param [Integer] lines
181
+ # @return [Code]
182
+ def around(lineno, lines = 1)
183
+ return self unless lineno
184
+
185
+ select do |loc|
186
+ loc.lineno >= lineno - lines && loc.lineno <= lineno + lines
187
+ end
188
+ end
189
+
190
+ # Remove all lines except for the +lines+ after and excluding +lineno+.
191
+ #
192
+ # @param [Integer] lineno
193
+ # @param [Integer] lines
194
+ # @return [Code]
195
+ def after(lineno, lines = 1)
196
+ return self unless lineno
197
+
198
+ select do |loc|
199
+ loc.lineno > lineno && loc.lineno <= lineno + lines
200
+ end
201
+ end
202
+
203
+ # Remove all lines that don't match the given `pattern`.
204
+ #
205
+ # @param [Regexp] pattern
206
+ # @return [Code]
207
+ def grep(pattern)
208
+ return self unless pattern
209
+
210
+ pattern = Regexp.new(pattern)
211
+
212
+ select do |loc|
213
+ loc.line =~ pattern
214
+ end
215
+ end
216
+
217
+ # Format output with line numbers next to it, unless `y_n` is falsy.
218
+ #
219
+ # @param [Boolean?] y_n
220
+ # @return [Code]
221
+ def with_line_numbers(y_n = true)
222
+ alter do
223
+ @with_line_numbers = y_n
224
+ end
225
+ end
226
+
227
+ # Format output with a marker next to the given +lineno+, unless +lineno+ is
228
+ # falsy.
229
+ #
230
+ # @param [Integer?] lineno
231
+ # @return [Code]
232
+ def with_marker(lineno = 1)
233
+ alter do
234
+ @with_marker = !!lineno
235
+ @marker_lineno = lineno
236
+ end
237
+ end
238
+
239
+ # Format output with the specified number of spaces in front of every line,
240
+ # unless `spaces` is falsy.
241
+ #
242
+ # @param [Integer?] spaces
243
+ # @return [Code]
244
+ def with_indentation(spaces = 0)
245
+ alter do
246
+ @with_indentation = !!spaces
247
+ @indentation_num = spaces
248
+ end
249
+ end
250
+
251
+ # @return [Integer] the number of digits in the last line.
252
+ def max_lineno_width
253
+ !@lines.empty? ? @lines.last.lineno.to_s.length : 0
254
+ end
255
+
256
+ # @return [String] a formatted representation (based on the configuration of
257
+ # the object).
258
+ def to_s
259
+ print_to_output(''.dup, false)
260
+ end
261
+
262
+ # @return [String] a (possibly highlighted) copy of the source code.
263
+ def highlighted
264
+ print_to_output(''.dup, true)
265
+ end
266
+
267
+ # Writes a formatted representation (based on the configuration of the
268
+ # object) to the given output, which must respond to `#<<`.
269
+ def print_to_output(output, color = false)
270
+ @lines.each do |loc|
271
+ loc = loc.dup
272
+ loc.colorize(@code_type) if color
273
+ loc.add_line_number(max_lineno_width, color) if @with_line_numbers
274
+ loc.add_marker(@marker_lineno) if @with_marker
275
+ loc.indent(@indentation_num) if @with_indentation
276
+ output << loc.line
277
+ output << "\n"
278
+ end
279
+ output
280
+ end
281
+
282
+ # Get the comment that describes the expression on the given line number.
283
+ #
284
+ # @param [Integer] line_number (1-based)
285
+ # @return [String] the code.
286
+ def comment_describing(line_number)
287
+ self.class.comment_describing(raw, line_number)
288
+ end
289
+
290
+ # Get the multiline expression that starts on the given line number.
291
+ #
292
+ # @param [Integer] line_number (1-based)
293
+ # @return [String] the code.
294
+ def expression_at(line_number, consume = 0)
295
+ self.class.expression_at(raw, line_number, consume: consume)
296
+ end
297
+
298
+ # Get the (approximate) Module.nesting at the give line number.
299
+ #
300
+ # @param [Integer] line_number line number starting from 1
301
+ # @return [Array<Module>] a list of open modules.
302
+ def nesting_at(line_number)
303
+ Pry::Indent.nesting_at(raw, line_number)
304
+ end
305
+
306
+ # Return an unformatted String of the code.
307
+ #
308
+ # @return [String]
309
+ def raw
310
+ @lines.map(&:line).join("\n") << "\n"
311
+ end
312
+
313
+ # Return the number of lines stored.
314
+ #
315
+ # @return [Integer]
316
+ def length
317
+ @lines ? @lines.length : 0
318
+ end
319
+
320
+ # Two `Code` objects are equal if they contain the same lines with the same
321
+ # numbers. Otherwise, call `to_s` and `chomp` and compare as Strings.
322
+ #
323
+ # @param [Code, Object] other
324
+ # @return [Boolean]
325
+ def ==(other)
326
+ if other.is_a?(Code)
327
+ other_lines = other.instance_variable_get(:@lines)
328
+ @lines.each_with_index.all? { |loc, i| loc == other_lines[i] }
329
+ else
330
+ to_s.chomp == other.to_s.chomp
331
+ end
332
+ end
333
+
334
+ # Forward any missing methods to the output of `#to_s`.
335
+ def method_missing(method_name, *args, &block)
336
+ if (string = to_s).respond_to?(method_name)
337
+ string.__send__(method_name, *args, &block)
338
+ else
339
+ super
340
+ end
341
+ end
342
+ undef =~ if method_defined?(:=~)
343
+
344
+ # Check whether String responds to missing methods.
345
+ def respond_to_missing?(method_name, include_private = false)
346
+ ''.respond_to?(method_name, include_private) || super
347
+ end
348
+
349
+ protected
350
+
351
+ # An abstraction of the `dup.instance_eval` pattern used throughout this
352
+ # class.
353
+ def alter(&block)
354
+ dup.tap { |o| o.instance_eval(&block) }
355
+ end
356
+ end
357
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ # This class is responsible for taking a string (identifying a
5
+ # command/class/method/etc) and returning the relevant type of object.
6
+ # For example, if the user looks up "show-source" then a
7
+ # `Pry::Command` will be returned. Alternatively, if the user passes in "Pry#repl" then
8
+ # a `Pry::Method` object will be returned.
9
+ #
10
+ # The `CodeObject.lookup` method is responsible for 1. figuring out what kind of
11
+ # object the user wants (applying precedence rules in doing so -- i.e methods
12
+ # get precedence over commands with the same name) and 2. Returning
13
+ # the appropriate object. If the user fails to provide a string
14
+ # identifier for the object (i.e they pass in `nil` or "") then the
15
+ # object looked up will be the 'current method' or 'current class'
16
+ # associated with the Binding.
17
+ #
18
+ # TODO: This class is a clusterfuck. We need a much more robust
19
+ # concept of what a "Code Object" really is. Currently
20
+ # commands/classes/candidates/methods and so on just share a very
21
+ # ill-defined interface.
22
+ class CodeObject
23
+ module Helpers
24
+ # we need this helper as some Pry::Method objects can wrap Procs
25
+ # @return [Boolean]
26
+ def real_method_object?
27
+ is_a?(::Method) || is_a?(::UnboundMethod)
28
+ end
29
+
30
+ def c_method?
31
+ real_method_object? && source_type == :c
32
+ end
33
+
34
+ def module_with_yard_docs?
35
+ is_a?(WrappedModule) && yard_docs?
36
+ end
37
+
38
+ def command?
39
+ is_a?(Module) && self <= Pry::Command
40
+ end
41
+
42
+ # @return [Boolean] `true` if this module was defined by means of the C API,
43
+ # `false` if it's a Ruby module.
44
+ # @note If a module defined by C was extended with a lot of methods written
45
+ # in Ruby, this method would fail.
46
+ def c_module?
47
+ return unless is_a?(WrappedModule)
48
+
49
+ method_locations = wrapped.methods(false).map do |m|
50
+ wrapped.method(m).source_location
51
+ end
52
+
53
+ method_locations.concat(
54
+ wrapped.instance_methods(false).map do |m|
55
+ wrapped.instance_method(m).source_location
56
+ end
57
+ )
58
+
59
+ c_methods = method_locations.grep(nil).count
60
+ ruby_methods = method_locations.count - c_methods
61
+
62
+ c_methods > ruby_methods
63
+ end
64
+ end
65
+
66
+ include Pry::Helpers::CommandHelpers
67
+
68
+ class << self
69
+ def lookup(str, pry_instance, options = {})
70
+ co = new(str, pry_instance, options)
71
+
72
+ co.default_lookup || co.method_or_class_lookup ||
73
+ co.command_lookup || co.empty_lookup
74
+ end
75
+ end
76
+
77
+ attr_accessor :str
78
+ attr_accessor :target
79
+ attr_accessor :pry_instance
80
+ attr_accessor :super_level
81
+
82
+ def initialize(str, pry_instance, options = {})
83
+ options = {
84
+ super: 0
85
+ }.merge!(options)
86
+
87
+ @str = str
88
+ @pry_instance = pry_instance
89
+ @target = pry_instance.current_context
90
+ @super_level = options[:super]
91
+ end
92
+
93
+ # TODO: just make it so find_command_by_match_or_listing doesn't raise?
94
+ def command_lookup
95
+ pry_instance.commands.find_command_by_match_or_listing(str)
96
+ rescue StandardError
97
+ nil
98
+ end
99
+
100
+ # when no parameter is given (i.e CodeObject.lookup(nil)), then we
101
+ # lookup the 'current object' from the binding.
102
+ def empty_lookup
103
+ return nil if str && !str.empty?
104
+
105
+ obj = if internal_binding?(target)
106
+ mod = target_self.is_a?(Module) ? target_self : target_self.class
107
+ Pry::WrappedModule(mod)
108
+ else
109
+ Pry::Method.from_binding(target)
110
+ end
111
+
112
+ # respect the super level (i.e user might have specified a
113
+ # --super flag to show-source)
114
+ lookup_super(obj, super_level)
115
+ end
116
+
117
+ # lookup variables and constants and `self` that are not modules
118
+ def default_lookup
119
+ # we skip instance methods as we want those to fall through to
120
+ # method_or_class_lookup()
121
+ if safe_to_evaluate?(str) && !looks_like_an_instance_method?(str)
122
+ obj = target.eval(str)
123
+
124
+ # restrict to only objects we KNOW for sure support the full API
125
+ # Do NOT support just any object that responds to source_location
126
+ if sourcable_object?(obj)
127
+ Pry::Method(obj)
128
+ elsif !obj.is_a?(Module)
129
+ Pry::WrappedModule(obj.class)
130
+ end
131
+ end
132
+ rescue Pry::RescuableException
133
+ nil
134
+ end
135
+
136
+ def method_or_class_lookup
137
+ obj =
138
+ case str
139
+ when /\S+\(\)\z/
140
+ Pry::Method.from_str(str.sub(/\(\)\z/, ''), target) ||
141
+ Pry::WrappedModule.from_str(str, target)
142
+ else
143
+ Pry::WrappedModule.from_str(str, target) ||
144
+ Pry::Method.from_str(str, target)
145
+ end
146
+
147
+ lookup_super(obj, super_level)
148
+ end
149
+
150
+ private
151
+
152
+ def sourcable_object?(obj)
153
+ [::Proc, ::Method, ::UnboundMethod].any? { |o| obj.is_a?(o) }
154
+ end
155
+
156
+ # Returns true if `str` looks like a method, i.e Klass#method
157
+ # We need to consider this case because method lookups should fall
158
+ # through to the `method_or_class_lookup()` method but a
159
+ # defined?() on a "Klass#method` string will see the `#` as a
160
+ # comment and only evaluate the `Klass` part.
161
+ # @param [String] str
162
+ # @return [Boolean] Whether the string looks like an instance method.
163
+ def looks_like_an_instance_method?(str)
164
+ str =~ /\S#\S/
165
+ end
166
+
167
+ # We use this method to decide whether code is safe to eval. Method's are
168
+ # generally not, but everything else is.
169
+ # TODO: is just checking != "method" enough??
170
+ # TODO: see duplication of this method in Pry::WrappedModule
171
+ # @param [String] str The string to lookup
172
+ # @return [Boolean]
173
+ def safe_to_evaluate?(str)
174
+ return true if str.strip == "self"
175
+ return false if str =~ /%/
176
+
177
+ kind = target.eval("defined?(#{str})")
178
+ kind =~ /variable|constant/
179
+ end
180
+
181
+ def target_self
182
+ target.eval('self')
183
+ end
184
+
185
+ # grab the nth (`super_level`) super of `obj
186
+ # @param [Object] obj
187
+ # @param [Fixnum] super_level How far up the super chain to ascend.
188
+ def lookup_super(obj, super_level)
189
+ return unless obj
190
+
191
+ sup = obj.super(super_level)
192
+ raise Pry::CommandError, "No superclass found for #{obj.wrapped}" unless sup
193
+
194
+ sup
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pp'
4
+ require 'English'
5
+
6
+ class Pry
7
+ # PP subclass for streaming inspect output in color.
8
+ class ColorPrinter < ::PP
9
+ Pry::SyntaxHighlighter.overwrite_coderay_comment_token!
10
+
11
+ def self.default(_output, value, pry_instance)
12
+ pry_instance.pager.open do |pager|
13
+ pager.print pry_instance.config.output_prefix
14
+ pp(value, pager, pry_instance.output.width - 1)
15
+ end
16
+ end
17
+
18
+ def self.pp(obj, output = $DEFAULT_OUTPUT, max_width = 79)
19
+ queue = ColorPrinter.new(output, max_width, "\n")
20
+ queue.guard_inspect_key { queue.pp(obj) }
21
+ queue.flush
22
+ output << "\n"
23
+ end
24
+
25
+ def pp(object)
26
+ return super unless object.is_a?(String)
27
+
28
+ # Avoid calling Ruby 2.4+ String#pretty_print that prints multiline
29
+ # Strings prettier
30
+ text(object.inspect)
31
+ rescue StandardError => exception
32
+ raise if exception.is_a?(Pry::Pager::StopPaging)
33
+
34
+ text(highlight_object_literal(inspect_object(object)))
35
+ end
36
+
37
+ def text(str, max_width = str.length)
38
+ if str.include?("\e[")
39
+ super("#{str}\e[0m", max_width)
40
+ elsif str.start_with?('#<') || %w[= >].include?(str)
41
+ super(highlight_object_literal(str), max_width)
42
+ else
43
+ super(SyntaxHighlighter.highlight(str), max_width)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def highlight_object_literal(object_literal)
50
+ code = Pry::SyntaxHighlighter.keyword_token_color
51
+ obj_color = code.start_with?("\e") ? code : "\e[0m\e[0;#{code}m"
52
+ "#{obj_color}#{object_literal}\e[0m"
53
+ end
54
+
55
+ def inspect_object(object)
56
+ object.inspect
57
+ rescue StandardError
58
+ # Read the class name off of the singleton class to provide a default
59
+ # inspect.
60
+ singleton = class << object; self; end
61
+ ancestors = Pry::Method.safe_send(singleton, :ancestors)
62
+ klass = ancestors.find { |k| k != singleton }
63
+ "#<#{klass}:0x#{object.__id__.to_s(16)}>"
64
+ end
65
+ end
66
+ end