pry 0.12.0 → 0.14.0

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +162 -1
  3. data/LICENSE +1 -1
  4. data/README.md +331 -269
  5. data/bin/pry +5 -0
  6. data/lib/pry.rb +132 -119
  7. data/lib/pry/basic_object.rb +8 -4
  8. data/lib/pry/block_command.rb +22 -0
  9. data/lib/pry/class_command.rb +194 -0
  10. data/lib/pry/cli.rb +43 -51
  11. data/lib/pry/code.rb +40 -28
  12. data/lib/pry/code/code_file.rb +28 -24
  13. data/lib/pry/code/code_range.rb +4 -2
  14. data/lib/pry/code/loc.rb +15 -8
  15. data/lib/pry/code_object.rb +40 -38
  16. data/lib/pry/color_printer.rb +47 -46
  17. data/lib/pry/command.rb +166 -369
  18. data/lib/pry/command_set.rb +76 -73
  19. data/lib/pry/command_state.rb +31 -0
  20. data/lib/pry/commands/amend_line.rb +86 -81
  21. data/lib/pry/commands/bang.rb +18 -14
  22. data/lib/pry/commands/bang_pry.rb +15 -11
  23. data/lib/pry/commands/cat.rb +61 -54
  24. data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
  25. data/lib/pry/commands/cat/exception_formatter.rb +71 -60
  26. data/lib/pry/commands/cat/file_formatter.rb +55 -49
  27. data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
  28. data/lib/pry/commands/cd.rb +40 -35
  29. data/lib/pry/commands/change_inspector.rb +29 -22
  30. data/lib/pry/commands/change_prompt.rb +44 -39
  31. data/lib/pry/commands/clear_screen.rb +16 -10
  32. data/lib/pry/commands/code_collector.rb +148 -133
  33. data/lib/pry/commands/disable_pry.rb +23 -19
  34. data/lib/pry/commands/easter_eggs.rb +19 -30
  35. data/lib/pry/commands/edit.rb +184 -161
  36. data/lib/pry/commands/edit/exception_patcher.rb +21 -17
  37. data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
  38. data/lib/pry/commands/exit.rb +39 -35
  39. data/lib/pry/commands/exit_all.rb +24 -20
  40. data/lib/pry/commands/exit_program.rb +20 -16
  41. data/lib/pry/commands/find_method.rb +168 -160
  42. data/lib/pry/commands/fix_indent.rb +16 -12
  43. data/lib/pry/commands/help.rb +140 -133
  44. data/lib/pry/commands/hist.rb +151 -150
  45. data/lib/pry/commands/import_set.rb +20 -16
  46. data/lib/pry/commands/jump_to.rb +25 -21
  47. data/lib/pry/commands/list_inspectors.rb +35 -28
  48. data/lib/pry/commands/ls.rb +124 -102
  49. data/lib/pry/commands/ls/constants.rb +59 -42
  50. data/lib/pry/commands/ls/formatter.rb +50 -46
  51. data/lib/pry/commands/ls/globals.rb +38 -34
  52. data/lib/pry/commands/ls/grep.rb +17 -13
  53. data/lib/pry/commands/ls/instance_vars.rb +29 -27
  54. data/lib/pry/commands/ls/interrogatable.rb +18 -12
  55. data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
  56. data/lib/pry/commands/ls/local_names.rb +26 -22
  57. data/lib/pry/commands/ls/local_vars.rb +38 -28
  58. data/lib/pry/commands/ls/ls_entity.rb +47 -51
  59. data/lib/pry/commands/ls/methods.rb +44 -43
  60. data/lib/pry/commands/ls/methods_helper.rb +46 -42
  61. data/lib/pry/commands/ls/self_methods.rb +23 -22
  62. data/lib/pry/commands/nesting.rb +21 -17
  63. data/lib/pry/commands/play.rb +93 -82
  64. data/lib/pry/commands/pry_backtrace.rb +22 -17
  65. data/lib/pry/commands/pry_version.rb +15 -11
  66. data/lib/pry/commands/raise_up.rb +27 -22
  67. data/lib/pry/commands/reload_code.rb +60 -48
  68. data/lib/pry/commands/reset.rb +16 -12
  69. data/lib/pry/commands/ri.rb +55 -45
  70. data/lib/pry/commands/save_file.rb +45 -43
  71. data/lib/pry/commands/shell_command.rb +51 -51
  72. data/lib/pry/commands/shell_mode.rb +21 -17
  73. data/lib/pry/commands/show_doc.rb +80 -68
  74. data/lib/pry/commands/show_info.rb +189 -171
  75. data/lib/pry/commands/show_input.rb +16 -11
  76. data/lib/pry/commands/show_source.rb +110 -45
  77. data/lib/pry/commands/stat.rb +35 -31
  78. data/lib/pry/commands/switch_to.rb +21 -15
  79. data/lib/pry/commands/toggle_color.rb +20 -16
  80. data/lib/pry/commands/watch_expression.rb +89 -86
  81. data/lib/pry/commands/watch_expression/expression.rb +32 -27
  82. data/lib/pry/commands/whereami.rb +156 -148
  83. data/lib/pry/commands/wtf.rb +75 -50
  84. data/lib/pry/config.rb +307 -25
  85. data/lib/pry/config/attributable.rb +22 -0
  86. data/lib/pry/config/lazy_value.rb +29 -0
  87. data/lib/pry/config/memoized_value.rb +34 -0
  88. data/lib/pry/config/value.rb +24 -0
  89. data/lib/pry/control_d_handler.rb +28 -0
  90. data/lib/pry/core_extensions.rb +9 -7
  91. data/lib/pry/editor.rb +48 -21
  92. data/lib/pry/env.rb +18 -0
  93. data/lib/pry/exception_handler.rb +43 -0
  94. data/lib/pry/exceptions.rb +13 -16
  95. data/lib/pry/forwardable.rb +5 -1
  96. data/lib/pry/helpers.rb +2 -0
  97. data/lib/pry/helpers/base_helpers.rb +68 -197
  98. data/lib/pry/helpers/command_helpers.rb +50 -61
  99. data/lib/pry/helpers/documentation_helpers.rb +20 -13
  100. data/lib/pry/helpers/options_helpers.rb +14 -7
  101. data/lib/pry/helpers/platform.rb +7 -5
  102. data/lib/pry/helpers/table.rb +33 -26
  103. data/lib/pry/helpers/text.rb +17 -14
  104. data/lib/pry/history.rb +48 -56
  105. data/lib/pry/hooks.rb +21 -12
  106. data/lib/pry/indent.rb +54 -50
  107. data/lib/pry/input_completer.rb +248 -230
  108. data/lib/pry/input_lock.rb +8 -9
  109. data/lib/pry/inspector.rb +36 -24
  110. data/lib/pry/last_exception.rb +45 -45
  111. data/lib/pry/method.rb +141 -94
  112. data/lib/pry/method/disowned.rb +16 -4
  113. data/lib/pry/method/patcher.rb +12 -3
  114. data/lib/pry/method/weird_method_locator.rb +68 -44
  115. data/lib/pry/object_path.rb +33 -25
  116. data/lib/pry/output.rb +121 -35
  117. data/lib/pry/pager.rb +186 -180
  118. data/lib/pry/prompt.rb +123 -54
  119. data/lib/pry/pry_class.rb +61 -103
  120. data/lib/pry/pry_instance.rb +217 -215
  121. data/lib/pry/repl.rb +18 -22
  122. data/lib/pry/repl_file_loader.rb +27 -21
  123. data/lib/pry/ring.rb +11 -6
  124. data/lib/pry/slop.rb +574 -563
  125. data/lib/pry/slop/commands.rb +164 -169
  126. data/lib/pry/slop/option.rb +172 -168
  127. data/lib/pry/syntax_highlighter.rb +26 -0
  128. data/lib/pry/system_command_handler.rb +17 -0
  129. data/lib/pry/testable.rb +59 -61
  130. data/lib/pry/testable/evalable.rb +21 -12
  131. data/lib/pry/testable/mockable.rb +18 -10
  132. data/lib/pry/testable/pry_tester.rb +71 -56
  133. data/lib/pry/testable/utility.rb +29 -21
  134. data/lib/pry/testable/variables.rb +49 -43
  135. data/lib/pry/version.rb +3 -1
  136. data/lib/pry/warning.rb +27 -0
  137. data/lib/pry/wrapped_module.rb +51 -42
  138. data/lib/pry/wrapped_module/candidate.rb +21 -14
  139. metadata +35 -35
  140. data/lib/pry/commands.rb +0 -6
  141. data/lib/pry/commands/disabled_commands.rb +0 -2
  142. data/lib/pry/commands/gem_cd.rb +0 -26
  143. data/lib/pry/commands/gem_install.rb +0 -32
  144. data/lib/pry/commands/gem_list.rb +0 -33
  145. data/lib/pry/commands/gem_open.rb +0 -29
  146. data/lib/pry/commands/gem_readme.rb +0 -25
  147. data/lib/pry/commands/gem_search.rb +0 -40
  148. data/lib/pry/commands/gem_stats.rb +0 -83
  149. data/lib/pry/commands/gist.rb +0 -102
  150. data/lib/pry/commands/install_command.rb +0 -54
  151. data/lib/pry/config/behavior.rb +0 -255
  152. data/lib/pry/config/convenience.rb +0 -28
  153. data/lib/pry/config/default.rb +0 -159
  154. data/lib/pry/config/memoization.rb +0 -48
  155. data/lib/pry/platform.rb +0 -91
  156. data/lib/pry/plugins.rb +0 -122
  157. data/lib/pry/rubygem.rb +0 -84
  158. data/lib/pry/terminal.rb +0 -91
data/lib/pry/pager.rb CHANGED
@@ -1,111 +1,116 @@
1
- require 'pry/terminal'
1
+ # frozen_string_literal: true
2
2
 
3
3
  # A pager is an `IO`-like object that accepts text and either prints it
4
4
  # immediately, prints it one page at a time, or streams it to an external
5
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). If you want to send text through in chunks as you generate it, use `open`
18
- # to get a writable object instead.
19
- #
20
- # @param [String] text
21
- # Text to run through a pager.
22
- #
23
- def page(text)
24
- open do |pager|
25
- pager << text
6
+ class Pry
7
+ class Pager
8
+ class StopPaging < StandardError
26
9
  end
27
- end
28
10
 
29
- # Yields a pager object (`NullPager`, `SimplePager`, or `SystemPager`). All
30
- # pagers accept output with `#puts`, `#print`, `#write`, and `#<<`.
31
- def open
32
- pager = best_available
33
- yield pager
34
- rescue StopPaging
35
- ensure
36
- pager.close if pager
37
- end
11
+ attr_reader :pry_instance
38
12
 
39
- private
40
-
41
- def enabled?; !!@enabled; end
42
-
43
- def output; @output; end
44
-
45
- # Return an instance of the "best" available pager class -- `SystemPager` if
46
- # possible, `SimplePager` if `SystemPager` isn't available, and `NullPager`
47
- # if the user has disabled paging. All pagers accept output with `#puts`,
48
- # `#print`, `#write`, and `#<<`. You must call `#close` when you're done
49
- # writing output to a pager, and you must rescue `Pry::Pager::StopPaging`.
50
- # These requirements can be avoided by using `.open` instead.
51
- def best_available
52
- if !_pry_.config.pager
53
- NullPager.new(_pry_.output)
54
- elsif !SystemPager.available? || Helpers::Platform.jruby?
55
- SimplePager.new(_pry_.output)
56
- else
57
- SystemPager.new(_pry_.output)
13
+ def initialize(pry_instance)
14
+ @pry_instance = pry_instance
58
15
  end
59
- end
60
16
 
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
17
+ # Send the given text through the best available pager (if
18
+ # `Pry.config.pager` is enabled). If you want to send text through in
19
+ # chunks as you generate it, use `open` to get a writable object
20
+ # instead.
21
+ #
22
+ # @param [String] text
23
+ # Text to run through a pager.
24
+ #
25
+ def page(text)
26
+ open do |pager|
27
+ pager << text
28
+ end
66
29
  end
67
30
 
68
- def puts(str)
69
- print "#{str.chomp}\n"
31
+ # Yields a pager object (`NullPager`, `SimplePager`, or `SystemPager`).
32
+ # All pagers accept output with `#puts`, `#print`, `#write`, and `#<<`.
33
+ def open
34
+ pager = best_available
35
+ yield pager
36
+ rescue StopPaging # rubocop:disable Lint/HandleExceptions
37
+ ensure
38
+ pager.close if pager
70
39
  end
71
40
 
72
- def print(str)
73
- write str
74
- end
75
- alias << print
41
+ private
76
42
 
77
- def write(str)
78
- @out.write str
43
+ def enabled?
44
+ !!@enabled
79
45
  end
80
46
 
81
- def close
47
+ attr_reader :output
48
+
49
+ # Return an instance of the "best" available pager class --
50
+ # `SystemPager` if possible, `SimplePager` if `SystemPager` isn't
51
+ # available, and `NullPager` if the user has disabled paging. All
52
+ # pagers accept output with `#puts`, `#print`, `#write`, and `#<<`. You
53
+ # must call `#close` when you're done writing output to a pager, and
54
+ # you must rescue `Pry::Pager::StopPaging`. These requirements can be
55
+ # avoided by using `.open` instead.
56
+ def best_available
57
+ if !pry_instance.config.pager
58
+ NullPager.new(pry_instance.output)
59
+ elsif !SystemPager.available? || Helpers::Platform.jruby?
60
+ SimplePager.new(pry_instance.output)
61
+ else
62
+ SystemPager.new(pry_instance.output)
63
+ end
82
64
  end
83
65
 
84
- private
66
+ # `NullPager` is a "pager" that actually just prints all output as it
67
+ # comes in. Used when `Pry.config.pager` is false.
68
+ class NullPager
69
+ def initialize(out)
70
+ @out = out
71
+ end
85
72
 
86
- def height
87
- @height ||= Pry::Terminal.height!
88
- end
73
+ def puts(str)
74
+ print "#{str.chomp}\n"
75
+ end
89
76
 
90
- def width
91
- @width ||= Pry::Terminal.width!
92
- end
93
- end
77
+ def print(str)
78
+ write str
79
+ end
80
+ alias << print
81
+
82
+ def write(str)
83
+ @out.write str
84
+ end
85
+
86
+ def close; end
87
+
88
+ private
89
+
90
+ def height
91
+ @height ||= @out.height
92
+ end
94
93
 
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)
94
+ def width
95
+ @width ||= @out.width
96
+ end
101
97
  end
102
98
 
103
- def write(str)
104
- str.lines.each do |line|
105
- @out.print line
106
- @tracker.record line
99
+ # `SimplePager` is a straightforward pure-Ruby pager. We use it on
100
+ # JRuby and when we can't find a usable external pager.
101
+ class SimplePager < NullPager
102
+ def initialize(*)
103
+ super
104
+ @tracker = PageTracker.new(height - 3, width)
105
+ end
106
+
107
+ def write(str)
108
+ str.lines.each do |line|
109
+ @out.print line
110
+ @tracker.record line
111
+
112
+ next unless @tracker.page?
107
113
 
108
- if @tracker.page?
109
114
  @out.print "\n"
110
115
  @out.print "\e[0m"
111
116
  @out.print "<page break> --- Press enter to continue " \
@@ -116,128 +121,129 @@ class Pry::Pager
116
121
  end
117
122
  end
118
123
  end
119
- end
120
-
121
- # `SystemPager` buffers output until we're pretty sure it's at least a page
122
- # long, then invokes an external pager and starts streaming output to it. If
123
- # `#close` is called before then, it just prints out the buffered content.
124
- class SystemPager < NullPager
125
- def self.default_pager
126
- pager = ENV["PAGER"] || ""
127
124
 
128
- # Default to less, and make sure less is being passed the correct options
129
- if pager.strip.empty? or pager =~ /^less\b/
130
- pager = "less -R -F -X"
131
- end
125
+ # `SystemPager` buffers output until we're pretty sure it's at least a
126
+ # page long, then invokes an external pager and starts streaming output
127
+ # to it. If `#close` is called before then, it just prints out the
128
+ # buffered content.
129
+ class SystemPager < NullPager
130
+ def self.default_pager
131
+ pager = Pry::Env['PAGER'] || ''
132
132
 
133
- pager
134
- end
133
+ # Default to less, and make sure less is being passed the correct
134
+ # options
135
+ pager = "less -R -F -X" if pager.strip.empty? || pager =~ /^less\b/
135
136
 
136
- @system_pager = nil
137
+ pager
138
+ end
137
139
 
138
- def self.available?
139
- if @system_pager.nil?
140
- @system_pager = begin
141
- pager_executable = default_pager.split(' ').first
142
- if Helpers::Platform.windows? || Helpers::Platform.windows_ansi?
143
- `where /Q #{pager_executable}`
144
- else
145
- `which #{pager_executable}`
146
- end
147
- $?.success?
148
- rescue
149
- false
140
+ @system_pager = nil
141
+
142
+ def self.available?
143
+ if @system_pager.nil?
144
+ @system_pager =
145
+ begin
146
+ pager_executable = default_pager.split(' ').first
147
+ if Helpers::Platform.windows? || Helpers::Platform.windows_ansi?
148
+ `where /Q #{pager_executable}`
149
+ else
150
+ `which #{pager_executable}`
151
+ end
152
+ $CHILD_STATUS.success?
153
+ rescue StandardError
154
+ false
155
+ end
156
+ else
157
+ @system_pager
150
158
  end
151
- else
152
- @system_pager
153
159
  end
154
- end
155
160
 
156
- def initialize(*)
157
- super
158
- @tracker = PageTracker.new(height, width)
159
- @buffer = ""
160
- @pager = nil
161
- end
161
+ def initialize(*)
162
+ super
163
+ @tracker = PageTracker.new(height, width)
164
+ @buffer = ""
165
+ @pager = nil
166
+ end
162
167
 
163
- def write(str)
164
- if invoked_pager?
165
- write_to_pager str
166
- else
167
- @tracker.record str
168
- @buffer << str
168
+ def write(str)
169
+ if invoked_pager?
170
+ write_to_pager str
171
+ else
172
+ @tracker.record str
173
+ @buffer += str
169
174
 
170
- if @tracker.page?
171
- write_to_pager @buffer
175
+ write_to_pager @buffer if @tracker.page?
172
176
  end
177
+ rescue Errno::EPIPE
178
+ raise StopPaging
173
179
  end
174
- rescue Errno::EPIPE
175
- raise StopPaging
176
- end
177
180
 
178
- def close
179
- if invoked_pager?
180
- pager.close
181
- else
182
- @out.puts @buffer
181
+ def close
182
+ if invoked_pager?
183
+ pager.close
184
+ else
185
+ @out.puts @buffer
186
+ end
183
187
  end
184
- end
185
188
 
186
- private
189
+ private
187
190
 
188
- def write_to_pager(text)
189
- pager.write @out.decolorize_maybe(text)
190
- end
191
+ def write_to_pager(text)
192
+ pager.write @out.decolorize_maybe(text)
193
+ end
191
194
 
192
- def invoked_pager?
193
- @pager
194
- end
195
+ def invoked_pager?
196
+ @pager
197
+ end
195
198
 
196
- def pager
197
- @pager ||= IO.popen(self.class.default_pager, 'w')
199
+ def pager
200
+ @pager ||= IO.popen(self.class.default_pager, 'w')
201
+ end
198
202
  end
199
- end
200
203
 
201
- # `PageTracker` tracks output to determine whether it's likely to take up a
202
- # whole page. This doesn't need to be super precise, but we can use it for
203
- # `SimplePager` and to avoid invoking the system pager unnecessarily.
204
- #
205
- # One simplifying assumption is that we don't need `#page?` to return `true`
206
- # on the basis of an incomplete line. Long lines should be counted as
207
- # multiple lines, but we don't have to transition from `false` to `true`
208
- # until we see a newline.
209
- class PageTracker
210
- def initialize(rows, cols)
211
- @rows, @cols = rows, cols
212
- reset
213
- end
204
+ # `PageTracker` tracks output to determine whether it's likely to take
205
+ # up a whole page. This doesn't need to be super precise, but we can
206
+ # use it for `SimplePager` and to avoid invoking the system pager
207
+ # unnecessarily.
208
+ #
209
+ # One simplifying assumption is that we don't need `#page?` to return
210
+ # `true` on the basis of an incomplete line. Long lines should be
211
+ # counted as multiple lines, but we don't have to transition from
212
+ # `false` to `true` until we see a newline.
213
+ class PageTracker
214
+ def initialize(rows, cols)
215
+ @rows = rows
216
+ @cols = cols
217
+ reset
218
+ end
214
219
 
215
- def record(str)
216
- str.lines.each do |line|
217
- if line.end_with? "\n"
218
- @row += ((@col + line_length(line) - 1) / @cols) + 1
219
- @col = 0
220
- else
221
- @col += line_length(line)
220
+ def record(str)
221
+ str.lines.each do |line|
222
+ if line.end_with? "\n"
223
+ @row += ((@col + line_length(line) - 1) / @cols) + 1
224
+ @col = 0
225
+ else
226
+ @col += line_length(line)
227
+ end
222
228
  end
223
229
  end
224
- end
225
230
 
226
- def page?
227
- @row >= @rows
228
- end
231
+ def page?
232
+ @row >= @rows
233
+ end
229
234
 
230
- def reset
231
- @row = 0
232
- @col = 0
233
- end
235
+ def reset
236
+ @row = 0
237
+ @col = 0
238
+ end
234
239
 
235
- private
240
+ private
236
241
 
237
- # Approximation of the printable length of a given line, without the
238
- # newline and without ANSI color codes.
239
- def line_length(line)
240
- line.chomp.gsub(/\e\[[\d;]*m/, '').length
242
+ # Approximation of the printable length of a given line, without the
243
+ # newline and without ANSI color codes.
244
+ def line_length(line)
245
+ line.chomp.gsub(/\e\[[\d;]*m/, '').length
246
+ end
241
247
  end
242
248
  end
243
249
  end
data/lib/pry/prompt.rb CHANGED
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
2
4
  # Prompt represents the Pry prompt, which can be used with Readline-like
3
5
  # libraries. It defines a few default prompts (default prompt, simple prompt,
4
- # etc) and also provides an API to add custom prompts.
6
+ # etc) and also provides an API for adding and implementing custom prompts.
5
7
  #
6
- # @example
8
+ # @example Registering a new Pry prompt
7
9
  # Pry::Prompt.add(
8
10
  # :ipython,
9
11
  # 'IPython-like prompt', [':', '...:']
10
- # ) do |_context, _nesting, _pry_, sep|
11
- # sep == ':' ? "In [#{_pry_.input_ring.count}]: " : ' ...: '
12
+ # ) do |_context, _nesting, pry_instance, sep|
13
+ # sep == ':' ? "In [#{pry_instance.input_ring.count}]: " : ' ...: '
12
14
  # end
13
15
  #
14
16
  # # Produces:
@@ -17,20 +19,23 @@ class Pry
17
19
  # # ...: end
18
20
  # # => :foo
19
21
  # # In [4]:
22
+ #
23
+ # @example Manually instantiating the Prompt class
24
+ # prompt_procs = [
25
+ # proc { '#{rand(1)}>" },
26
+ # proc { "#{('a'..'z').to_a.sample}*" }
27
+ # ]
28
+ # prompt = Pry::Prompt.new(
29
+ # :random,
30
+ # 'Random number or letter prompt.',
31
+ # prompt_procs
32
+ # )
33
+ # prompt.wait_proc.call(...) #=>
34
+ # prompt.incomplete_proc.call(...)
35
+ #
20
36
  # @since v0.11.0
21
37
  # @api public
22
- module Prompt
23
- # @return [String]
24
- DEFAULT_NAME = 'pry'.freeze
25
-
26
- # @return [Array<Object>] the list of objects that are known to have a
27
- # 1-line #inspect output suitable for prompt
28
- SAFE_CONTEXTS = [String, Numeric, Symbol, nil, true, false].freeze
29
-
30
- # @deprecated Use {Pry::Prompt.add} instead.
31
- MAP = {}
32
- deprecate_constant(:MAP) if respond_to?(:deprecate_constant)
33
-
38
+ class Prompt
34
39
  # A Hash that holds all prompts. The keys of the Hash are prompt
35
40
  # names, the values are Hash instances of the format {:description, :value}.
36
41
  @prompts = {}
@@ -39,13 +44,13 @@ class Pry
39
44
  # Retrieves a prompt.
40
45
  #
41
46
  # @example
42
- # Prompt[:my_prompt][:value]
47
+ # Prompt[:my_prompt]
43
48
  #
44
- # @param [Symbol] prompt_name The name of the prompt you want to access
49
+ # @param [Symbol] name The name of the prompt you want to access
45
50
  # @return [Hash{Symbol=>Object}]
46
51
  # @since v0.12.0
47
- def [](prompt_name)
48
- all[prompt_name.to_s]
52
+ def [](name)
53
+ @prompts[name.to_s]
49
54
  end
50
55
 
51
56
  # @return [Hash{Symbol=>Hash}] the duplicate of the internal prompts hash
@@ -57,89 +62,153 @@ class Pry
57
62
 
58
63
  # Adds a new prompt to the prompt hash.
59
64
  #
60
- # @param [Symbol] prompt_name
65
+ # @param [Symbol] name
61
66
  # @param [String] description
62
67
  # @param [Array<String>] separators The separators to differentiate
63
68
  # between prompt modes (default mode and class/method definition mode).
64
69
  # The Array *must* have a size of 2.
65
- # @yield [context, nesting, _pry_, sep]
70
+ # @yield [context, nesting, pry_instance, sep]
66
71
  # @yieldparam context [Object] the context where Pry is currently in
67
72
  # @yieldparam nesting [Integer] whether the context is nested
68
- # @yieldparam _pry_ [Pry] the Pry instance
73
+ # @yieldparam pry_instance [Pry] the Pry instance
69
74
  # @yieldparam separator [String] separator string
70
75
  # @return [nil]
71
76
  # @raise [ArgumentError] if the size of `separators` is not 2
77
+ # @raise [ArgumentError] if `prompt_name` is already occupied
72
78
  # @since v0.12.0
73
- def add(prompt_name, description = '', separators = %w[> *])
79
+ def add(name, description = '', separators = %w[> *])
80
+ name = name.to_s
81
+
74
82
  unless separators.size == 2
75
83
  raise ArgumentError, "separators size must be 2, given #{separators.size}"
76
84
  end
77
85
 
78
- @prompts[prompt_name.to_s] = {
79
- description: description,
80
- value: separators.map do |sep|
81
- proc { |context, nesting, _pry_| yield(context, nesting, _pry_, sep) }
86
+ if @prompts.key?(name)
87
+ raise ArgumentError, "the '#{name}' prompt was already added"
88
+ end
89
+
90
+ @prompts[name] = new(
91
+ name,
92
+ description,
93
+ separators.map do |sep|
94
+ proc do |context, nesting, pry_instance|
95
+ yield(context, nesting, pry_instance, sep)
96
+ end
82
97
  end
83
- }
98
+ )
84
99
 
85
100
  nil
86
101
  end
102
+ end
87
103
 
88
- private
104
+ # @return [String]
105
+ attr_reader :name
89
106
 
90
- def prompt_name(name)
91
- return name unless name.is_a?(Pry::Config::Lazy)
107
+ # @return [String]
108
+ attr_reader :description
109
+
110
+ # @return [Array<Proc>] the array of procs that hold
111
+ # `[wait_proc, incomplete_proc]`
112
+ attr_reader :prompt_procs
113
+
114
+ # @param [String] name
115
+ # @param [String] description
116
+ # @param [Array<Proc>] prompt_procs
117
+ def initialize(name, description, prompt_procs)
118
+ @name = name
119
+ @description = description
120
+ @prompt_procs = prompt_procs
121
+ end
122
+
123
+ # @return [Proc] the proc which builds the wait prompt (`>`)
124
+ def wait_proc
125
+ @prompt_procs.first
126
+ end
127
+
128
+ # @return [Proc] the proc which builds the prompt when in the middle of an
129
+ # expression such as open method, etc. (`*`)
130
+ def incomplete_proc
131
+ @prompt_procs.last
132
+ end
92
133
 
93
- name.call
134
+ # @deprecated Use a `Pry::Prompt` instance directly
135
+ def [](key)
136
+ key = key.to_s
137
+ if %w[name description].include?(key)
138
+ Pry::Warning.warn(
139
+ "`Pry::Prompt[:#{@name}][:#{key}]` is deprecated. " \
140
+ "Use `#{self.class}##{key}` instead"
141
+ )
142
+ public_send(key)
143
+ elsif key.to_s == 'value'
144
+ Pry::Warning.warn(
145
+ "`#{self.class}[:#{@name}][:value]` is deprecated. Use " \
146
+ "`#{self.class}#prompt_procs` instead or an instance of " \
147
+ "`#{self.class}` directly"
148
+ )
149
+ @prompt_procs
94
150
  end
95
151
  end
96
152
 
97
- add(:default, <<DESC) do |context, nesting, _pry_, sep|
98
- The default Pry prompt. Includes information about the current expression
99
- number, evaluation context, and nesting level, plus a reminder that you're
100
- using Pry.
101
- DESC
153
+ add(
154
+ :default,
155
+ "The default Pry prompt. Includes information about the current expression \n" \
156
+ "number, evaluation context, and nesting level, plus a reminder that you're \n" \
157
+ 'using Pry.'
158
+ ) do |context, nesting, pry_instance, sep|
102
159
  format(
103
160
  "[%<in_count>s] %<name>s(%<context>s)%<nesting>s%<separator>s ",
104
- in_count: _pry_.input_ring.count,
105
- name: prompt_name(_pry_.config.prompt_name),
161
+ in_count: pry_instance.input_ring.count,
162
+ name: pry_instance.config.prompt_name,
106
163
  context: Pry.view_clip(context),
107
164
  nesting: (nesting > 0 ? ":#{nesting}" : ''),
108
165
  separator: sep
109
166
  )
110
167
  end
111
168
 
112
- add(:simple, "A simple `>>`.\n", ['>> ', ' | ']) do |_, _, _, sep|
169
+ add(
170
+ :simple,
171
+ "A simple `>>`.",
172
+ ['>> ', ' | ']
173
+ ) do |_, _, _, sep|
113
174
  sep
114
175
  end
115
176
 
116
- add(:nav, <<DESC, %w[> *]) do |context, nesting, _pry_, sep|
117
- A prompt that displays the binding stack as a path and includes information
118
- about #{Helpers::Text.bold('_in_')} and #{Helpers::Text.bold('_out_')}.
119
- DESC
120
- tree = _pry_.binding_stack.map { |b| Pry.view_clip(b.eval('self')) }
177
+ add(
178
+ :nav,
179
+ "A prompt that displays the binding stack as a path and includes information \n" \
180
+ "about #{Helpers::Text.bold('_in_')} and #{Helpers::Text.bold('_out_')}.",
181
+ %w[> *]
182
+ ) do |_context, _nesting, pry_instance, sep|
183
+ tree = pry_instance.binding_stack.map { |b| Pry.view_clip(b.eval('self')) }
121
184
  format(
122
185
  "[%<in_count>s] (%<name>s) %<tree>s: %<stack_size>s%<separator>s ",
123
- in_count: _pry_.input_ring.count,
124
- name: prompt_name(_pry_.config.prompt_name),
186
+ in_count: pry_instance.input_ring.count,
187
+ name: pry_instance.config.prompt_name,
125
188
  tree: tree.join(' / '),
126
- stack_size: _pry_.binding_stack.size - 1,
189
+ stack_size: pry_instance.binding_stack.size - 1,
127
190
  separator: sep
128
191
  )
129
192
  end
130
193
 
131
- add(:shell, <<DESC, %w[$ *]) do |context, nesting, _pry_, sep|
132
- A prompt that displays `$PWD` as you change it.
133
- DESC
194
+ add(
195
+ :shell,
196
+ 'A prompt that displays `$PWD` as you change it.',
197
+ %w[$ *]
198
+ ) do |context, _nesting, pry_instance, sep|
134
199
  format(
135
200
  "%<name>s %<context>s:%<pwd>s %<separator>s ",
136
- name: prompt_name(_pry_.config.prompt_name),
201
+ name: pry_instance.config.prompt_name,
137
202
  context: Pry.view_clip(context),
138
203
  pwd: Dir.pwd,
139
204
  separator: sep
140
205
  )
141
206
  end
142
207
 
143
- add(:none, 'Wave goodbye to the Pry prompt.', Array.new(2)) { '' }
208
+ add(
209
+ :none,
210
+ 'Wave goodbye to the Pry prompt.',
211
+ Array.new(2)
212
+ ) { '' }
144
213
  end
145
214
  end