pry 0.10.pre.1-i386-mswin32 → 0.10.0.pre3-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +702 -0
  3. data/LICENSE +2 -2
  4. data/{README.markdown → README.md} +41 -35
  5. data/lib/pry.rb +82 -139
  6. data/lib/pry/cli.rb +77 -30
  7. data/lib/pry/code.rb +122 -183
  8. data/lib/pry/code/code_file.rb +103 -0
  9. data/lib/pry/code/code_range.rb +71 -0
  10. data/lib/pry/code/loc.rb +92 -0
  11. data/lib/pry/code_object.rb +172 -0
  12. data/lib/pry/color_printer.rb +55 -0
  13. data/lib/pry/command.rb +184 -28
  14. data/lib/pry/command_set.rb +113 -59
  15. data/lib/pry/commands.rb +4 -27
  16. data/lib/pry/commands/amend_line.rb +99 -0
  17. data/lib/pry/commands/bang.rb +20 -0
  18. data/lib/pry/commands/bang_pry.rb +17 -0
  19. data/lib/pry/commands/cat.rb +62 -0
  20. data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
  21. data/lib/pry/commands/cat/exception_formatter.rb +77 -0
  22. data/lib/pry/commands/cat/file_formatter.rb +67 -0
  23. data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
  24. data/lib/pry/commands/cd.rb +41 -0
  25. data/lib/pry/commands/change_inspector.rb +27 -0
  26. data/lib/pry/commands/change_prompt.rb +26 -0
  27. data/lib/pry/commands/code_collector.rb +165 -0
  28. data/lib/pry/commands/disable_pry.rb +27 -0
  29. data/lib/pry/commands/disabled_commands.rb +2 -0
  30. data/lib/pry/commands/easter_eggs.rb +112 -0
  31. data/lib/pry/commands/edit.rb +195 -0
  32. data/lib/pry/commands/edit/exception_patcher.rb +25 -0
  33. data/lib/pry/commands/edit/file_and_line_locator.rb +36 -0
  34. data/lib/pry/commands/exit.rb +42 -0
  35. data/lib/pry/commands/exit_all.rb +29 -0
  36. data/lib/pry/commands/exit_program.rb +23 -0
  37. data/lib/pry/commands/find_method.rb +193 -0
  38. data/lib/pry/commands/fix_indent.rb +19 -0
  39. data/lib/pry/commands/gem_cd.rb +26 -0
  40. data/lib/pry/commands/gem_install.rb +32 -0
  41. data/lib/pry/commands/gem_list.rb +33 -0
  42. data/lib/pry/commands/gem_open.rb +29 -0
  43. data/lib/pry/commands/gist.rb +101 -0
  44. data/lib/pry/commands/help.rb +164 -0
  45. data/lib/pry/commands/hist.rb +180 -0
  46. data/lib/pry/commands/import_set.rb +22 -0
  47. data/lib/pry/commands/install_command.rb +53 -0
  48. data/lib/pry/commands/jump_to.rb +29 -0
  49. data/lib/pry/commands/list_inspectors.rb +35 -0
  50. data/lib/pry/commands/list_prompts.rb +35 -0
  51. data/lib/pry/commands/ls.rb +114 -0
  52. data/lib/pry/commands/ls/constants.rb +47 -0
  53. data/lib/pry/commands/ls/formatter.rb +49 -0
  54. data/lib/pry/commands/ls/globals.rb +48 -0
  55. data/lib/pry/commands/ls/grep.rb +21 -0
  56. data/lib/pry/commands/ls/instance_vars.rb +39 -0
  57. data/lib/pry/commands/ls/interrogatable.rb +18 -0
  58. data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
  59. data/lib/pry/commands/ls/local_names.rb +35 -0
  60. data/lib/pry/commands/ls/local_vars.rb +39 -0
  61. data/lib/pry/commands/ls/ls_entity.rb +70 -0
  62. data/lib/pry/commands/ls/methods.rb +57 -0
  63. data/lib/pry/commands/ls/methods_helper.rb +46 -0
  64. data/lib/pry/commands/ls/self_methods.rb +32 -0
  65. data/lib/pry/commands/nesting.rb +25 -0
  66. data/lib/pry/commands/play.rb +103 -0
  67. data/lib/pry/commands/pry_backtrace.rb +25 -0
  68. data/lib/pry/commands/pry_version.rb +17 -0
  69. data/lib/pry/commands/raise_up.rb +32 -0
  70. data/lib/pry/commands/reload_code.rb +62 -0
  71. data/lib/pry/commands/reset.rb +18 -0
  72. data/lib/pry/commands/ri.rb +60 -0
  73. data/lib/pry/commands/save_file.rb +61 -0
  74. data/lib/pry/commands/shell_command.rb +48 -0
  75. data/lib/pry/commands/shell_mode.rb +25 -0
  76. data/lib/pry/commands/show_doc.rb +83 -0
  77. data/lib/pry/commands/show_info.rb +195 -0
  78. data/lib/pry/commands/show_input.rb +17 -0
  79. data/lib/pry/commands/show_source.rb +50 -0
  80. data/lib/pry/commands/simple_prompt.rb +22 -0
  81. data/lib/pry/commands/stat.rb +40 -0
  82. data/lib/pry/commands/switch_to.rb +23 -0
  83. data/lib/pry/commands/toggle_color.rb +24 -0
  84. data/lib/pry/commands/watch_expression.rb +105 -0
  85. data/lib/pry/commands/watch_expression/expression.rb +38 -0
  86. data/lib/pry/commands/whereami.rb +190 -0
  87. data/lib/pry/commands/wtf.rb +57 -0
  88. data/lib/pry/config.rb +20 -229
  89. data/lib/pry/config/behavior.rb +139 -0
  90. data/lib/pry/config/convenience.rb +26 -0
  91. data/lib/pry/config/default.rb +165 -0
  92. data/lib/pry/core_extensions.rb +59 -38
  93. data/lib/pry/editor.rb +133 -0
  94. data/lib/pry/exceptions.rb +77 -0
  95. data/lib/pry/helpers.rb +1 -0
  96. data/lib/pry/helpers/base_helpers.rb +40 -154
  97. data/lib/pry/helpers/command_helpers.rb +19 -130
  98. data/lib/pry/helpers/documentation_helpers.rb +21 -11
  99. data/lib/pry/helpers/table.rb +109 -0
  100. data/lib/pry/helpers/text.rb +8 -9
  101. data/lib/pry/history.rb +61 -45
  102. data/lib/pry/history_array.rb +11 -1
  103. data/lib/pry/hooks.rb +10 -32
  104. data/lib/pry/indent.rb +110 -38
  105. data/lib/pry/input_completer.rb +242 -0
  106. data/lib/pry/input_lock.rb +132 -0
  107. data/lib/pry/inspector.rb +27 -0
  108. data/lib/pry/last_exception.rb +61 -0
  109. data/lib/pry/method.rb +199 -200
  110. data/lib/pry/method/disowned.rb +53 -0
  111. data/lib/pry/method/patcher.rb +125 -0
  112. data/lib/pry/method/weird_method_locator.rb +186 -0
  113. data/lib/pry/module_candidate.rb +39 -33
  114. data/lib/pry/object_path.rb +82 -0
  115. data/lib/pry/output.rb +50 -0
  116. data/lib/pry/pager.rb +234 -0
  117. data/lib/pry/plugins.rb +4 -3
  118. data/lib/pry/prompt.rb +26 -0
  119. data/lib/pry/pry_class.rb +199 -227
  120. data/lib/pry/pry_instance.rb +344 -403
  121. data/lib/pry/rbx_path.rb +1 -1
  122. data/lib/pry/repl.rb +202 -0
  123. data/lib/pry/repl_file_loader.rb +20 -26
  124. data/lib/pry/rubygem.rb +82 -0
  125. data/lib/pry/terminal.rb +79 -0
  126. data/lib/pry/test/helper.rb +170 -0
  127. data/lib/pry/version.rb +1 -1
  128. data/lib/pry/wrapped_module.rb +133 -48
  129. metadata +132 -197
  130. data/.document +0 -2
  131. data/.gemtest +0 -0
  132. data/.gitignore +0 -16
  133. data/.travis.yml +0 -17
  134. data/.yardopts +0 -1
  135. data/CHANGELOG +0 -387
  136. data/CONTRIBUTORS +0 -36
  137. data/Gemfile +0 -2
  138. data/Rakefile +0 -137
  139. data/TODO +0 -117
  140. data/examples/example_basic.rb +0 -15
  141. data/examples/example_command_override.rb +0 -32
  142. data/examples/example_commands.rb +0 -36
  143. data/examples/example_hooks.rb +0 -9
  144. data/examples/example_image_edit.rb +0 -67
  145. data/examples/example_input.rb +0 -7
  146. data/examples/example_input2.rb +0 -29
  147. data/examples/example_output.rb +0 -11
  148. data/examples/example_print.rb +0 -6
  149. data/examples/example_prompt.rb +0 -9
  150. data/examples/helper.rb +0 -6
  151. data/lib/pry/completion.rb +0 -221
  152. data/lib/pry/custom_completions.rb +0 -6
  153. data/lib/pry/default_commands/cd.rb +0 -81
  154. data/lib/pry/default_commands/commands.rb +0 -62
  155. data/lib/pry/default_commands/context.rb +0 -98
  156. data/lib/pry/default_commands/easter_eggs.rb +0 -95
  157. data/lib/pry/default_commands/editing.rb +0 -420
  158. data/lib/pry/default_commands/find_method.rb +0 -169
  159. data/lib/pry/default_commands/gems.rb +0 -84
  160. data/lib/pry/default_commands/gist.rb +0 -187
  161. data/lib/pry/default_commands/help.rb +0 -127
  162. data/lib/pry/default_commands/hist.rb +0 -120
  163. data/lib/pry/default_commands/input_and_output.rb +0 -306
  164. data/lib/pry/default_commands/introspection.rb +0 -410
  165. data/lib/pry/default_commands/ls.rb +0 -272
  166. data/lib/pry/default_commands/misc.rb +0 -38
  167. data/lib/pry/default_commands/navigating_pry.rb +0 -110
  168. data/lib/pry/default_commands/whereami.rb +0 -92
  169. data/lib/pry/extended_commands/experimental.rb +0 -7
  170. data/lib/pry/rbx_method.rb +0 -13
  171. data/man/pry.1 +0 -195
  172. data/man/pry.1.html +0 -204
  173. data/man/pry.1.ronn +0 -141
  174. data/pry.gemspec +0 -46
  175. data/test/candidate_helper1.rb +0 -11
  176. data/test/candidate_helper2.rb +0 -8
  177. data/test/helper.rb +0 -223
  178. data/test/test_cli.rb +0 -78
  179. data/test/test_code.rb +0 -201
  180. data/test/test_command.rb +0 -712
  181. data/test/test_command_helpers.rb +0 -9
  182. data/test/test_command_integration.rb +0 -668
  183. data/test/test_command_set.rb +0 -610
  184. data/test/test_completion.rb +0 -62
  185. data/test/test_control_d_handler.rb +0 -45
  186. data/test/test_default_commands/example.erb +0 -5
  187. data/test/test_default_commands/test_cd.rb +0 -318
  188. data/test/test_default_commands/test_context.rb +0 -280
  189. data/test/test_default_commands/test_documentation.rb +0 -314
  190. data/test/test_default_commands/test_find_method.rb +0 -50
  191. data/test/test_default_commands/test_gems.rb +0 -18
  192. data/test/test_default_commands/test_help.rb +0 -57
  193. data/test/test_default_commands/test_input.rb +0 -428
  194. data/test/test_default_commands/test_introspection.rb +0 -511
  195. data/test/test_default_commands/test_ls.rb +0 -151
  196. data/test/test_default_commands/test_shell.rb +0 -343
  197. data/test/test_default_commands/test_show_source.rb +0 -432
  198. data/test/test_exception_whitelist.rb +0 -21
  199. data/test/test_history_array.rb +0 -65
  200. data/test/test_hooks.rb +0 -521
  201. data/test/test_indent.rb +0 -277
  202. data/test/test_input_stack.rb +0 -86
  203. data/test/test_method.rb +0 -401
  204. data/test/test_pry.rb +0 -463
  205. data/test/test_pry_defaults.rb +0 -419
  206. data/test/test_pry_history.rb +0 -84
  207. data/test/test_pry_output.rb +0 -41
  208. data/test/test_sticky_locals.rb +0 -155
  209. data/test/test_syntax_checking.rb +0 -65
  210. data/test/test_wrapped_module.rb +0 -174
  211. data/test/testrc +0 -2
  212. data/test/testrcbad +0 -2
  213. data/wiki/Customizing-pry.md +0 -397
  214. data/wiki/Home.md +0 -4
@@ -0,0 +1,82 @@
1
+ class Pry
2
+ # `ObjectPath` implements the resolution of "object paths", which are strings
3
+ # that are similar to filesystem paths but meant for traversing Ruby objects.
4
+ # Examples of valid object paths include:
5
+ #
6
+ # x
7
+ # @foo/@bar
8
+ # "string"/upcase
9
+ # Pry/Method
10
+ #
11
+ # Object paths are mostly relevant in the context of the `cd` command.
12
+ # @see https://github.com/pry/pry/wiki/State-navigation
13
+ class ObjectPath
14
+ SPECIAL_TERMS = ["", "::", ".", ".."]
15
+
16
+ # @param [String] path_string The object path expressed as a string.
17
+ # @param [Array<Binding>] current_stack The current state of the binding
18
+ # stack.
19
+ def initialize(path_string, current_stack)
20
+ @path_string = path_string
21
+ @current_stack = current_stack
22
+ end
23
+
24
+ # @return [Array<Binding>] a new stack resulting from applying the given
25
+ # path to the current stack.
26
+ def resolve
27
+ scanner = StringScanner.new(@path_string.strip)
28
+ stack = @current_stack.dup
29
+
30
+ begin
31
+ next_segment = ""
32
+
33
+ loop do
34
+ # Scan for as long as we don't see a slash
35
+ next_segment << scanner.scan(/[^\/]*/)
36
+
37
+ if complete?(next_segment) || scanner.eos?
38
+ scanner.getch # consume the slash
39
+ break
40
+ else
41
+ next_segment << scanner.getch # append the slash
42
+ end
43
+ end
44
+
45
+ case next_segment.chomp
46
+ when ""
47
+ stack = [stack.first]
48
+ when "::"
49
+ stack.push(TOPLEVEL_BINDING)
50
+ when "."
51
+ next
52
+ when ".."
53
+ stack.pop unless stack.size == 1
54
+ else
55
+ stack.push(Pry.binding_for(stack.last.eval(next_segment)))
56
+ end
57
+ rescue RescuableException => e
58
+ return handle_failure(next_segment, e)
59
+ end until scanner.eos?
60
+
61
+ stack
62
+ end
63
+
64
+ private
65
+
66
+ def complete?(segment)
67
+ SPECIAL_TERMS.include?(segment) || Pry::Code.complete_expression?(segment)
68
+ end
69
+
70
+ def handle_failure(context, err)
71
+ msg = [
72
+ "Bad object path: #{@path_string.inspect}",
73
+ "Failed trying to resolve: #{context.inspect}",
74
+ "Exception: #{err.inspect}"
75
+ ].join("\n")
76
+
77
+ raise CommandError.new(msg).tap { |e|
78
+ e.set_backtrace err.backtrace
79
+ }
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,50 @@
1
+ class Pry
2
+ class Output
3
+ attr_reader :_pry_
4
+
5
+ def initialize(_pry_)
6
+ @_pry_ = _pry_
7
+ end
8
+
9
+ def puts(*objs)
10
+ return print "\n" if objs.empty?
11
+
12
+ objs.each do |obj|
13
+ if ary = Array.try_convert(obj)
14
+ puts(*ary)
15
+ else
16
+ print "#{obj.to_s.chomp}\n"
17
+ end
18
+ end
19
+
20
+ nil
21
+ end
22
+
23
+ def print(*objs)
24
+ objs.each do |obj|
25
+ _pry_.config.output.print decolorize_maybe(obj.to_s)
26
+ end
27
+
28
+ nil
29
+ end
30
+ alias << print
31
+ alias write print
32
+
33
+ # If _pry_.config.color is currently false, removes ansi escapes from the string.
34
+ def decolorize_maybe(str)
35
+ if _pry_.config.color
36
+ str
37
+ else
38
+ Helpers::Text.strip_color str
39
+ end
40
+ end
41
+
42
+ def method_missing(name, *args, &block)
43
+ _pry_.config.output.send(name, *args, &block)
44
+ end
45
+
46
+ def respond_to_missing?(*a)
47
+ _pry_.config.respond_to?(*a)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,234 @@
1
+ require 'pry/terminal'
2
+
3
+ # A pager is an `IO`-like object that accepts text and either prints it
4
+ # immediately, prints it one page at a time, or streams it to an external
5
+ # program to print one page at a time.
6
+ class Pry::Pager
7
+ class StopPaging < StandardError
8
+ end
9
+
10
+ attr_reader :_pry_
11
+
12
+ def initialize(_pry_)
13
+ @_pry_ = _pry_
14
+ end
15
+
16
+ # Send the given text through the best available pager (if `Pry.config.pager` is
17
+ # enabled).
18
+ # If you want to send text through in chunks as you generate it, use `open` to
19
+ # get a writable object instead.
20
+ # @param [String] text A piece of text to run through a pager.
21
+ # @param [IO] output (`$stdout`) An object to send output to.
22
+ def page(text)
23
+ open do |pager|
24
+ pager << text
25
+ end
26
+ end
27
+
28
+ # Yields a pager object (`NullPager`, `SimplePager`, or `SystemPager`). All
29
+ # pagers accept output with `#puts`, `#print`, `#write`, and `#<<`.
30
+ # @param [IO] output (`$stdout`) An object to send output to.
31
+ def open
32
+ pager = best_available
33
+ yield pager
34
+ rescue StopPaging
35
+ ensure
36
+ pager.close if pager
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :output
42
+ def enabled?; !!@enabled; end
43
+
44
+ # Return an instance of the "best" available pager class -- `SystemPager` if
45
+ # possible, `SimplePager` if `SystemPager` isn't available, and `NullPager`
46
+ # if the user has disabled paging. All pagers accept output with `#puts`,
47
+ # `#print`, `#write`, and `#<<`. You must call `#close` when you're done
48
+ # writing output to a pager, and you must rescue `Pry::Pager::StopPaging`.
49
+ # These requirements can be avoided by using `.open` instead.
50
+ # @param [#<<] output ($stdout) An object to send output to.
51
+ def best_available
52
+ if !_pry_.config.pager
53
+ NullPager.new(_pry_.output)
54
+ elsif !SystemPager.available? || Pry::Helpers::BaseHelpers.jruby?
55
+ SimplePager.new(_pry_.output)
56
+ else
57
+ SystemPager.new(_pry_.output)
58
+ end
59
+ end
60
+
61
+ # `NullPager` is a "pager" that actually just prints all output as it comes
62
+ # in. Used when `Pry.config.pager` is false.
63
+ class NullPager
64
+ def initialize(out)
65
+ @out = out
66
+ end
67
+
68
+ def puts(str)
69
+ print "#{str.chomp}\n"
70
+ end
71
+
72
+ def print(str)
73
+ write str
74
+ end
75
+ alias << print
76
+
77
+ def write(str)
78
+ @out.write str
79
+ end
80
+
81
+ def close
82
+ end
83
+
84
+ private
85
+
86
+ def height
87
+ @height ||= Pry::Terminal.height!
88
+ end
89
+
90
+ def width
91
+ @width ||= Pry::Terminal.width!
92
+ end
93
+ end
94
+
95
+ # `SimplePager` is a straightforward pure-Ruby pager. We use it on JRuby and
96
+ # when we can't find a usable external pager.
97
+ class SimplePager < NullPager
98
+ def initialize(*)
99
+ super
100
+ @tracker = PageTracker.new(height - 3, width)
101
+ end
102
+
103
+ def write(str)
104
+ str.lines.each do |line|
105
+ @out.print line
106
+ @tracker.record line
107
+
108
+ if @tracker.page?
109
+ @out.print "\n"
110
+ @out.print "\e[0m"
111
+ @out.print "<page break> --- Press enter to continue " \
112
+ "( q<enter> to break ) --- <page break>\n"
113
+ raise StopPaging if Readline.readline("").chomp == "q"
114
+ @tracker.reset
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ # `SystemPager` buffers output until we're pretty sure it's at least a page
121
+ # long, then invokes an external pager and starts streaming output to it. If
122
+ # `#close` is called before then, it just prints out the buffered content.
123
+ class SystemPager < NullPager
124
+ def self.default_pager
125
+ pager = ENV["PAGER"] || ""
126
+
127
+ # Default to less, and make sure less is being passed the correct options
128
+ if pager.strip.empty? or pager =~ /^less\b/
129
+ pager = "less -R -F -X"
130
+ end
131
+
132
+ pager
133
+ end
134
+
135
+ def self.available?
136
+ if @system_pager.nil?
137
+ @system_pager = begin
138
+ pager_executable = default_pager.split(' ').first
139
+ `which #{ pager_executable }`
140
+ rescue
141
+ false
142
+ end
143
+ else
144
+ @system_pager
145
+ end
146
+ end
147
+
148
+ def initialize(*)
149
+ super
150
+ @tracker = PageTracker.new(height, width)
151
+ @buffer = ""
152
+ end
153
+
154
+ def write(str)
155
+ if invoked_pager?
156
+ write_to_pager str
157
+ else
158
+ @tracker.record str
159
+ @buffer << str
160
+
161
+ if @tracker.page?
162
+ write_to_pager @buffer
163
+ end
164
+ end
165
+ rescue Errno::EPIPE
166
+ raise StopPaging
167
+ end
168
+
169
+ def close
170
+ if invoked_pager?
171
+ pager.close
172
+ else
173
+ @out.puts @buffer
174
+ end
175
+ end
176
+
177
+ private
178
+
179
+ def write_to_pager(text)
180
+ pager.write @out.decolorize_maybe(text)
181
+ end
182
+
183
+ def invoked_pager?
184
+ @pager
185
+ end
186
+
187
+ def pager
188
+ @pager ||= IO.popen(self.class.default_pager, 'w')
189
+ end
190
+ end
191
+
192
+ # `PageTracker` tracks output to determine whether it's likely to take up a
193
+ # whole page. This doesn't need to be super precise, but we can use it for
194
+ # `SimplePager` and to avoid invoking the system pager unnecessarily.
195
+ #
196
+ # One simplifying assumption is that we don't need `#page?` to return `true`
197
+ # on the basis of an incomplete line. Long lines should be counted as
198
+ # multiple lines, but we don't have to transition from `false` to `true`
199
+ # until we see a newline.
200
+ class PageTracker
201
+ def initialize(rows, cols)
202
+ @rows, @cols = rows, cols
203
+ reset
204
+ end
205
+
206
+ def record(str)
207
+ str.lines.each do |line|
208
+ if line.end_with? "\n"
209
+ @row += ((@col + line_length(line) - 1) / @cols) + 1
210
+ @col = 0
211
+ else
212
+ @col += line_length(line)
213
+ end
214
+ end
215
+ end
216
+
217
+ def page?
218
+ @row >= @rows
219
+ end
220
+
221
+ def reset
222
+ @row = 0
223
+ @col = 0
224
+ end
225
+
226
+ private
227
+
228
+ # Approximation of the printable length of a given line, without the
229
+ # newline and without ANSI color codes.
230
+ def line_length(line)
231
+ line.chomp.gsub(/\e\[[\d;]*m/, '').length
232
+ end
233
+ end
234
+ end
@@ -43,13 +43,15 @@ class Pry
43
43
  # Does not reload plugin if it's already active.
44
44
  def activate!
45
45
  # Create the configuration object for the plugin.
46
- Pry.config.send("#{gem_name.gsub('-', '_')}=", OpenStruct.new)
46
+ Pry.config.send("#{gem_name.gsub('-', '_')}=", Pry::Config.from_hash({}))
47
47
 
48
48
  begin
49
49
  require gem_name if !active?
50
50
  rescue LoadError => e
51
- warn "Warning: The plugin '#{gem_name}' was not found! (gem found but could not be loaded)"
51
+ warn "Found plugin #{gem_name}, but could not require '#{gem_name}'"
52
52
  warn e
53
+ rescue => e
54
+ warn "require '#{gem_name}' # Failed, saying: #{e}"
53
55
  end
54
56
 
55
57
  self.active = true
@@ -99,4 +101,3 @@ class Pry
99
101
  end
100
102
 
101
103
  end
102
-
@@ -0,0 +1,26 @@
1
+ class Pry::Prompt
2
+ MAP = {
3
+ "default" => {
4
+ value: Pry::DEFAULT_PROMPT,
5
+ description: "The default Pry prompt. Includes information about the\n" \
6
+ "current expression number, evaluation context, and nesting\n" \
7
+ "level, plus a reminder that you're using Pry."
8
+ },
9
+
10
+ "simple" => {
11
+ value: Pry::SIMPLE_PROMPT,
12
+ description: "A simple '>>'."
13
+ },
14
+
15
+ "nav" => {
16
+ value: Pry::NAV_PROMPT,
17
+ description: "A prompt that displays the binding stack as a path and\n" \
18
+ "includes information about _in_ and _out_."
19
+ },
20
+
21
+ "none" => {
22
+ value: Pry::NO_PROMPT,
23
+ description: "Wave goodbye to the Pry prompt."
24
+ }
25
+ }
26
+ end
@@ -1,85 +1,88 @@
1
- require 'ostruct'
2
- require 'forwardable'
3
1
  require 'pry/config'
4
-
5
2
  class Pry
6
3
 
7
- # The RC Files to load.
8
- RC_FILES = ["~/.pryrc"]
4
+ HOME_RC_FILE = ENV["PRYRC"] || "~/.pryrc"
9
5
  LOCAL_RC_FILE = "./.pryrc"
10
6
 
11
- # class accessors
12
7
  class << self
13
8
  extend Forwardable
14
-
15
- # convenience method
16
- def self.delegate_accessors(delagatee, *names)
17
- def_delegators delagatee, *names
18
- def_delegators delagatee, *names.map { |v| "#{v}=" }
19
- end
20
-
21
- # Get/Set the Proc that defines extra Readline completions (on top
22
- # of the ones defined for IRB).
23
- # @return [Proc] The Proc that defines extra Readline completions (on top
24
- # @example Add file names to completion list
25
- # Pry.custom_completions = proc { Dir.entries('.') }
26
9
  attr_accessor :custom_completions
27
-
28
- # @return [Fixnum] The current input line.
29
10
  attr_accessor :current_line
30
-
31
- # @return [Array] The Array of evaluated expressions.
32
11
  attr_accessor :line_buffer
33
-
34
- # @return [String] The __FILE__ for the `eval()`. Should be "(pry)"
35
- # by default.
36
12
  attr_accessor :eval_path
37
-
38
- # @return [OpenStruct] Return Pry's config object.
13
+ attr_accessor :cli
14
+ attr_accessor :quiet
15
+ attr_accessor :last_internal_error
39
16
  attr_accessor :config
17
+ attr_writer :history
40
18
 
41
- # @return [History] Return Pry's line history object.
42
- attr_accessor :history
19
+ def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins
43
20
 
44
- # @return [Boolean] Whether Pry was activated from the command line.
45
- attr_accessor :cli
21
+ extend Pry::Config::Convenience
22
+ config_shortcut *Pry::Config.shortcuts
46
23
 
47
- # @return [Boolean] Whether Pry sessions are quiet by default.
48
- attr_accessor :quiet
24
+ def prompt=(value)
25
+ config.prompt = value
26
+ end
49
27
 
50
- # @return [Binding] A top level binding with no local variables
51
- attr_accessor :toplevel_binding
28
+ def prompt
29
+ config.prompt
30
+ end
52
31
 
53
- # plugin forwardables
54
- def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins
32
+ def history
33
+ @history ||= History.new
34
+ end
35
+ end
55
36
 
56
- delegate_accessors :@config, :input, :output, :commands, :prompt, :print, :exception_handler,
57
- :hooks, :color, :pager, :editor, :memory_size, :input_stack, :extra_sticky_locals
37
+ #
38
+ # @return [main]
39
+ # returns the special instance of Object, "main".
40
+ #
41
+ def self.main
42
+ @main ||= TOPLEVEL_BINDING.eval "self"
58
43
  end
59
44
 
45
+ #
46
+ # @return [Pry::Config]
47
+ # Returns a value store for an instance of Pry running on the current thread.
48
+ #
49
+ def self.current
50
+ Thread.current[:__pry__] ||= Pry::Config.from_hash({}, nil)
51
+ end
60
52
 
61
53
  # Load the given file in the context of `Pry.toplevel_binding`
62
- # @param [String] file_name The unexpanded file path.
63
- def self.load_file_at_toplevel(file_name)
64
- full_name = File.expand_path(file_name)
65
- begin
66
- toplevel_binding.eval(File.read(full_name)) if File.exists?(full_name)
67
- rescue RescuableException => e
68
- puts "Error loading #{file_name}: #{e}"
69
- end
54
+ # @param [String] file The unexpanded file path.
55
+ def self.load_file_at_toplevel(file)
56
+ toplevel_binding.eval(File.read(file), file)
57
+ rescue RescuableException => e
58
+ puts "Error loading #{file}: #{e}\n#{e.backtrace.first}"
70
59
  end
71
60
 
72
- # Load the rc files given in the `Pry::RC_FILES` array.
61
+ # Load HOME_RC_FILE and LOCAL_RC_FILE if appropriate
73
62
  # This method can also be used to reload the files if they have changed.
74
- def self.load_rc
75
- RC_FILES.uniq.each do |file_name|
76
- load_file_at_toplevel(file_name)
63
+ def self.load_rc_files
64
+ rc_files_to_load.each do |file|
65
+ critical_section do
66
+ load_file_at_toplevel(file)
67
+ end
77
68
  end
78
69
  end
79
70
 
80
71
  # Load the local RC file (./.pryrc)
81
- def self.load_local_rc
82
- load_file_at_toplevel(LOCAL_RC_FILE)
72
+ def self.rc_files_to_load
73
+ files = []
74
+ files << HOME_RC_FILE if Pry.config.should_load_rc
75
+ files << LOCAL_RC_FILE if Pry.config.should_load_local_rc
76
+ files.map { |file| real_path_to(file) }.compact.uniq
77
+ end
78
+
79
+ # Expand a file to its canonical name (following symlinks as appropriate)
80
+ def self.real_path_to(file)
81
+ expanded = Pathname.new(File.expand_path(file)).realpath.to_s
82
+ # For rbx 1.9 mode [see rubinius issue #2165]
83
+ File.exist?(expanded) ? expanded : nil
84
+ rescue Errno::ENOENT
85
+ nil
83
86
  end
84
87
 
85
88
  # Load any Ruby files specified with the -r flag on the command line.
@@ -95,68 +98,78 @@ class Pry
95
98
  trap('INT'){ raise Interrupt }
96
99
  end
97
100
 
101
+ def self.load_win32console
102
+ begin
103
+ require 'win32console'
104
+ # The mswin and mingw versions of pry require win32console, so this should
105
+ # only fail on jruby (where win32console doesn't work).
106
+ # Instead we'll recommend ansicon, which does.
107
+ rescue LoadError
108
+ warn <<-WARNING if Pry.config.windows_console_warning
109
+ For a better Pry experience on Windows, please use ansicon:
110
+ https://github.com/adoxa/ansicon
111
+ If you use an alternative to ansicon and don't want to see this warning again,
112
+ you can add "Pry.config.windows_console_warning = false" to your .pryrc.
113
+ WARNING
114
+ end
115
+ end
116
+
98
117
  # Do basic setup for initial session.
99
118
  # Including: loading .pryrc, loading plugins, loading requires, and
100
119
  # loading history.
101
120
  def self.initial_session_setup
102
-
103
- return if !initial_session?
121
+ return unless initial_session?
122
+ @initial_session = false
104
123
 
105
124
  # note these have to be loaded here rather than in pry_instance as
106
125
  # we only want them loaded once per entire Pry lifetime.
107
- load_rc if Pry.config.should_load_rc
108
- load_local_rc if Pry.config.should_load_local_rc
126
+ load_rc_files
109
127
  load_plugins if Pry.config.should_load_plugins
110
128
  load_requires if Pry.config.should_load_requires
111
129
  load_history if Pry.config.history.should_load
112
130
  load_traps if Pry.config.should_trap_interrupts
113
-
114
- @initial_session = false
131
+ load_win32console if Pry::Helpers::BaseHelpers.windows? && !Pry::Helpers::BaseHelpers.windows_ansi?
115
132
  end
116
133
 
117
134
  # Start a Pry REPL.
118
- # This method also loads the files specified in `Pry::RC_FILES` the
135
+ # This method also loads `~/.pryrc` and `./.pryrc` as necessary the
119
136
  # first time it is invoked.
120
137
  # @param [Object, Binding] target The receiver of the Pry session
121
138
  # @param [Hash] options
122
139
  # @option options (see Pry#initialize)
123
140
  # @example
124
141
  # Pry.start(Object.new, :input => MyInput.new)
125
- def self.start(target=toplevel_binding, options={})
126
- target = Pry.binding_for(target)
127
- initial_session_setup
128
-
129
- # create the Pry instance to manage the session
130
- pry_instance = new(options)
131
-
132
- # save backtrace
133
- pry_instance.backtrace = caller
142
+ def self.start(target=nil, options={})
143
+ return if ENV['DISABLE_PRY']
144
+ options = options.to_hash
145
+
146
+ if in_critical_section?
147
+ output.puts "ERROR: Pry started inside Pry."
148
+ output.puts "This can happen if you have a binding.pry inside a #to_s or #inspect function."
149
+ return
150
+ end
134
151
 
135
- # if Pry was started via binding.pry, elide that from the backtrace.
136
- pry_instance.backtrace.shift if pry_instance.backtrace.first =~ /pry.*core_extensions.*pry/
152
+ options[:target] = Pry.binding_for(target || toplevel_binding)
153
+ options[:hooks] = Pry::Hooks.from_hash options.delete(:hooks) if options.key?(:hooks)
154
+ initial_session_setup
137
155
 
138
- # yield the binding_stack to the hook for modification
139
- pry_instance.exec_hook(
140
- :when_started,
141
- target,
142
- options,
143
- pry_instance
144
- )
156
+ # Unless we were given a backtrace, save the current one
157
+ if options[:backtrace].nil?
158
+ options[:backtrace] = caller
145
159
 
146
- if !pry_instance.binding_stack.empty?
147
- head = pry_instance.binding_stack.pop
148
- else
149
- head = target
160
+ # If Pry was started via `binding.pry`, elide that from the backtrace
161
+ if options[:backtrace].first =~ /pry.*core_extensions.*pry/
162
+ options[:backtrace].shift
163
+ end
150
164
  end
151
165
 
152
- # Clear the line before starting Pry. This fixes the issue discussed here:
153
- # https://github.com/pry/pry/issues/566
154
- if Pry.config.auto_indent
155
- Kernel.print Pry::Helpers::BaseHelpers.windows_ansi? ? "\e[0F" : "\e[0G"
156
- end
166
+ driver = options[:driver] || Pry::REPL
157
167
 
158
168
  # Enter the matrix
159
- pry_instance.repl(head)
169
+ driver.start(options)
170
+ rescue Pry::TooSafeException
171
+ puts "ERROR: Pry cannot work with $SAFE > 0"
172
+ raise
160
173
  end
161
174
 
162
175
  # Execute the file through the REPL loop, non-interactively.
@@ -166,23 +179,40 @@ class Pry
166
179
  REPLFileLoader.new(file_name).load
167
180
  end
168
181
 
182
+ #
169
183
  # An inspector that clips the output to `max_length` chars.
170
184
  # In case of > `max_length` chars the `#<Object...> notation is used.
171
- # @param obj The object to view.
172
- # @param max_length The maximum number of chars before clipping occurs.
173
- # @return [String] The string representation of `obj`.
174
- def self.view_clip(obj, max_length = 60)
175
- if obj.kind_of?(Module) && obj.name.to_s != "" && obj.name.to_s.length <= max_length
185
+ #
186
+ # @param [Object] obj
187
+ # The object to view.
188
+ #
189
+ # @param [Hash] options
190
+ # @option options [Integer] :max_length (60)
191
+ # The maximum number of chars before clipping occurs.
192
+ #
193
+ # @option options [Boolean] :id (false)
194
+ # Boolean to indicate whether or not a hex reprsentation of the object ID
195
+ # is attached to the return value when the length of inspect is greater than
196
+ # value of `:max_length`.
197
+ #
198
+ # @return [String]
199
+ # The string representation of `obj`.
200
+ #
201
+ def self.view_clip(obj, options = {})
202
+ max = options.fetch :max_length, 60
203
+ id = options.fetch :id, false
204
+ if obj.kind_of?(Module) && obj.name.to_s != "" && obj.name.to_s.length <= max
176
205
  obj.name.to_s
177
- elsif TOPLEVEL_BINDING.eval('self') == obj
178
- # special case for 'main' object :)
206
+ elsif Pry.main == obj
207
+ # special-case to support jruby.
208
+ # fixed as of https://github.com/jruby/jruby/commit/d365ebd309cf9df3dde28f5eb36ea97056e0c039
209
+ # we can drop in the future.
179
210
  obj.to_s
180
- elsif [String, Numeric, Symbol, nil, true, false].any? { |v| v === obj } && obj.inspect.length <= max_length
211
+ elsif Pry.config.prompt_safe_objects.any? { |v| v === obj } && obj.inspect.length <= max
181
212
  obj.inspect
182
213
  else
183
- "#<#{obj.class}>"#:%x>"# % (obj.object_id << 1)
214
+ id == true ? "#<#{obj.class}:0x%x>" % (obj.object_id << 1) : "#<#{obj.class}>"
184
215
  end
185
-
186
216
  rescue RescuableException
187
217
  "unknown"
188
218
  end
@@ -192,11 +222,6 @@ class Pry
192
222
  Pry.history.load
193
223
  end
194
224
 
195
- # Save new lines of Readline history if required.
196
- def self.save_history
197
- Pry.history.save
198
- end
199
-
200
225
  # @return [Boolean] Whether this is the first time a Pry session has
201
226
  # been started since loading the Pry class.
202
227
  def self.initial_session?
@@ -204,38 +229,40 @@ class Pry
204
229
  end
205
230
 
206
231
  # Run a Pry command from outside a session. The commands available are
207
- # those referenced by `Pry.commands` (the default command set).
232
+ # those referenced by `Pry.config.commands` (the default command set).
208
233
  # @param [String] command_string The Pry command (including arguments,
209
234
  # if any).
210
235
  # @param [Hash] options Optional named parameters.
211
236
  # @return [Object] The return value of the Pry command.
212
- # @option options [Object, Binding] :context The object context to run the
237
+ # @option options [Object, Binding] :target The object to run the
213
238
  # command under. Defaults to `TOPLEVEL_BINDING` (main).
214
239
  # @option options [Boolean] :show_output Whether to show command
215
240
  # output. Defaults to true.
216
241
  # @example Run at top-level with no output.
217
242
  # Pry.run_command "ls"
218
243
  # @example Run under Pry class, returning only public methods.
219
- # Pry.run_command "ls -m", :context => Pry
244
+ # Pry.run_command "ls -m", :target => Pry
220
245
  # @example Display command output.
221
246
  # Pry.run_command "ls -av", :show_output => true
222
247
  def self.run_command(command_string, options={})
223
248
  options = {
224
- :context => TOPLEVEL_BINDING,
249
+ :target => TOPLEVEL_BINDING,
225
250
  :show_output => true,
226
- :output => Pry.output,
227
- :commands => Pry.commands
251
+ :output => Pry.config.output,
252
+ :commands => Pry.config.commands
228
253
  }.merge!(options)
229
254
 
255
+ # :context for compatibility with <= 0.9.11.4
256
+ target = options[:context] || options[:target]
230
257
  output = options[:show_output] ? options[:output] : StringIO.new
231
258
 
232
- Pry.new(:output => output, :input => StringIO.new(command_string), :commands => options[:commands], :prompt => proc {""}, :hooks => Pry::Hooks.new).rep(options[:context])
259
+ pry = Pry.new(:output => output, :target => target, :commands => options[:commands])
260
+ pry.eval command_string
233
261
  end
234
262
 
235
263
  def self.default_editor_for_platform
236
264
  return ENV['VISUAL'] if ENV['VISUAL'] and not ENV['VISUAL'].empty?
237
265
  return ENV['EDITOR'] if ENV['EDITOR'] and not ENV['EDITOR'].empty?
238
-
239
266
  if Helpers::BaseHelpers.windows?
240
267
  'notepad'
241
268
  else
@@ -245,129 +272,50 @@ class Pry
245
272
  end
246
273
  end
247
274
 
248
- def self.set_config_defaults
249
- config.input = Readline
250
- config.output = $stdout
251
- config.commands = Pry::Commands
252
- config.prompt = DEFAULT_PROMPT
253
- config.print = DEFAULT_PRINT
254
- config.exception_handler = DEFAULT_EXCEPTION_HANDLER
255
- config.exception_whitelist = DEFAULT_EXCEPTION_WHITELIST
256
- config.default_window_size = 5
257
- config.hooks = DEFAULT_HOOKS
258
- config.input_stack = []
259
- config.color = Helpers::BaseHelpers.use_ansi_codes?
260
- config.pager = true
261
- config.system = DEFAULT_SYSTEM
262
- config.editor = default_editor_for_platform
263
- config.should_load_rc = true
264
- config.should_load_local_rc = true
265
- config.should_trap_interrupts = Helpers::BaseHelpers.jruby?
266
- config.disable_auto_reload = false
267
- config.command_prefix = ""
268
- config.auto_indent = Helpers::BaseHelpers.use_ansi_codes?
269
- config.correct_indent = true
270
- config.collision_warning = false
271
-
272
- config.gist ||= OpenStruct.new
273
- config.gist.inspecter = proc(&:pretty_inspect)
274
-
275
- config.should_load_plugins = true
276
-
277
- config.requires ||= []
278
- config.should_load_requires = true
279
-
280
- config.history ||= OpenStruct.new
281
- config.history.should_save = true
282
- config.history.should_load = true
283
- config.history.file = File.expand_path("~/.pry_history") rescue nil
284
-
285
- if config.history.file.nil?
286
- config.should_load_rc = false
287
- config.history.should_save = false
288
- config.history.should_load = false
289
- end
290
-
291
- config.control_d_handler = DEFAULT_CONTROL_D_HANDLER
275
+ def self.auto_resize!
276
+ Pry.config.input # by default, load Readline
292
277
 
293
- config.memory_size = 100
294
-
295
- config.extra_sticky_locals = {}
296
-
297
- config.ls ||= OpenStruct.new({
298
- :heading_color => :default,
299
-
300
- :public_method_color => :default,
301
- :private_method_color => :green,
302
- :protected_method_color => :yellow,
303
- :method_missing_color => :bright_red,
304
-
305
- :local_var_color => :default,
306
- :pry_var_color => :red, # e.g. _, _pry_, _file_
307
-
308
- :instance_var_color => :blue, # e.g. @foo
309
- :class_var_color => :bright_blue, # e.g. @@foo
310
-
311
- :global_var_color => :default, # e.g. $CODERAY_DEBUG, $eventmachine_library
312
- :builtin_global_color => :cyan, # e.g. $stdin, $-w, $PID
313
- :pseudo_global_color => :cyan, # e.g. $~, $1..$9, $LAST_MATCH_INFO
314
-
315
- :constant_color => :default, # e.g. VERSION, ARGF
316
- :class_constant_color => :blue, # e.g. Object, Kernel
317
- :exception_constant_color => :magenta, # e.g. Exception, RuntimeError
318
- :unloaded_constant_color => :yellow, # Any constant that is still in .autoload? state
278
+ if !defined?(Readline) || Pry.config.input != Readline
279
+ warn "Sorry, you must be using Readline for Pry.auto_resize! to work."
280
+ return
281
+ end
319
282
 
320
- # What should separate items listed by ls? (TODO: we should allow a columnar layout)
321
- :separator => " ",
283
+ if Readline::VERSION =~ /edit/i
284
+ warn <<-EOT
285
+ Readline version #{Readline::VERSION} detected - will not auto_resize! correctly.
286
+ For the fix, use GNU Readline instead:
287
+ https://github.com/guard/guard/wiki/Add-proper-Readline-support-to-Ruby-on-Mac-OS-X
288
+ EOT
289
+ return
290
+ end
322
291
 
323
- # Any methods defined on these classes, or modules included into these classes, will not
324
- # be shown by ls unless the -v flag is used.
325
- # A user of Rails may wih to add ActiveRecord::Base to the list.
326
- # add the following to your .pryrc:
327
- # Pry.config.ls.ceiling << ActiveRecord::Base if defined? ActiveRecordBase
328
- :ceiling => [Object, Module, Class]
329
- })
292
+ trap :WINCH do
293
+ begin
294
+ Readline.set_screen_size(*Terminal.size!)
295
+ rescue => e
296
+ warn "\nPry.auto_resize!'s Readline.set_screen_size failed: #{e}"
297
+ end
298
+ begin
299
+ Readline.refresh_line
300
+ rescue => e
301
+ warn "\nPry.auto_resize!'s Readline.refresh_line failed: #{e}"
302
+ end
303
+ end
330
304
  end
331
305
 
332
306
  # Set all the configurable options back to their default values
333
307
  def self.reset_defaults
334
- set_config_defaults
335
-
336
308
  @initial_session = true
337
-
338
- self.custom_completions = DEFAULT_CUSTOM_COMPLETIONS
309
+ self.config = Pry::Config.new Pry::Config::Default.new
339
310
  self.cli = false
340
311
  self.current_line = 1
341
312
  self.line_buffer = [""]
342
313
  self.eval_path = "(pry)"
343
-
344
- fix_coderay_colors
345
- end
346
-
347
- # To avoid mass-confusion, we change the default colour of "white" to
348
- # "blue" enabling global legibility
349
- def self.fix_coderay_colors
350
- to_fix = if (CodeRay::Encoders::Terminal::TOKEN_COLORS rescue nil)
351
- # CodeRay 1.0.0
352
- CodeRay::Encoders::Terminal::TOKEN_COLORS
353
- else
354
- # CodeRay 0.9
355
- begin
356
- require 'coderay/encoders/term'
357
- CodeRay::Encoders::Term::TOKEN_COLORS
358
- rescue
359
- end
360
- end
361
-
362
- to_fix[:comment] = "0;34" if to_fix
363
314
  end
364
315
 
365
316
  # Basic initialization.
366
317
  def self.init
367
318
  @plugin_manager ||= PluginManager.new
368
- self.config ||= Config.new
369
- self.history ||= History.new
370
-
371
319
  reset_defaults
372
320
  locate_plugins
373
321
  end
@@ -381,23 +329,47 @@ class Pry
381
329
  if Binding === target
382
330
  target
383
331
  else
384
- if TOPLEVEL_BINDING.eval('self') == target
332
+ if Pry.main == target
385
333
  TOPLEVEL_BINDING
386
334
  else
387
335
  target.__binding__
388
336
  end
389
337
  end
390
338
  end
391
- end
392
339
 
393
- # Grab a copy of the TOPLEVEL_BINDING without any local variables.
394
- # This binding has a default definee of Object, and new methods are
395
- # private (just as in TOPLEVEL_BINDING).
396
- def self.__binding_impl__
397
- binding
340
+ def self.toplevel_binding
341
+ unless defined?(@toplevel_binding) && @toplevel_binding
342
+ # Grab a copy of the TOPLEVEL_BINDING without any local variables.
343
+ # This binding has a default definee of Object, and new methods are
344
+ # private (just as in TOPLEVEL_BINDING).
345
+ TOPLEVEL_BINDING.eval <<-RUBY
346
+ def self.__pry__
347
+ binding
348
+ end
349
+ Pry.toplevel_binding = __pry__
350
+ class << self; undef __pry__; end
351
+ RUBY
352
+ end
353
+ @toplevel_binding.eval('private')
354
+ @toplevel_binding
355
+ end
356
+
357
+ def self.toplevel_binding=(binding)
358
+ @toplevel_binding = binding
359
+ end
360
+
361
+ def self.in_critical_section?
362
+ Thread.current[:pry_critical_section] ||= 0
363
+ Thread.current[:pry_critical_section] > 0
364
+ end
365
+
366
+ def self.critical_section(&block)
367
+ Thread.current[:pry_critical_section] ||= 0
368
+ Thread.current[:pry_critical_section] += 1
369
+ yield
370
+ ensure
371
+ Thread.current[:pry_critical_section] -= 1
372
+ end
398
373
  end
399
- Pry.toplevel_binding = __binding_impl__
400
- Pry.toplevel_binding.eval("private")
401
- class << self; undef __binding_impl__; end
402
374
 
403
375
  Pry.init