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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +162 -1
- data/LICENSE +1 -1
- data/README.md +331 -269
- data/bin/pry +5 -0
- data/lib/pry.rb +132 -119
- data/lib/pry/basic_object.rb +8 -4
- data/lib/pry/block_command.rb +22 -0
- data/lib/pry/class_command.rb +194 -0
- data/lib/pry/cli.rb +43 -51
- data/lib/pry/code.rb +40 -28
- data/lib/pry/code/code_file.rb +28 -24
- data/lib/pry/code/code_range.rb +4 -2
- data/lib/pry/code/loc.rb +15 -8
- data/lib/pry/code_object.rb +40 -38
- data/lib/pry/color_printer.rb +47 -46
- data/lib/pry/command.rb +166 -369
- data/lib/pry/command_set.rb +76 -73
- data/lib/pry/command_state.rb +31 -0
- data/lib/pry/commands/amend_line.rb +86 -81
- data/lib/pry/commands/bang.rb +18 -14
- data/lib/pry/commands/bang_pry.rb +15 -11
- data/lib/pry/commands/cat.rb +61 -54
- data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
- data/lib/pry/commands/cat/exception_formatter.rb +71 -60
- data/lib/pry/commands/cat/file_formatter.rb +55 -49
- data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
- data/lib/pry/commands/cd.rb +40 -35
- data/lib/pry/commands/change_inspector.rb +29 -22
- data/lib/pry/commands/change_prompt.rb +44 -39
- data/lib/pry/commands/clear_screen.rb +16 -10
- data/lib/pry/commands/code_collector.rb +148 -133
- data/lib/pry/commands/disable_pry.rb +23 -19
- data/lib/pry/commands/easter_eggs.rb +19 -30
- data/lib/pry/commands/edit.rb +184 -161
- data/lib/pry/commands/edit/exception_patcher.rb +21 -17
- data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
- data/lib/pry/commands/exit.rb +39 -35
- data/lib/pry/commands/exit_all.rb +24 -20
- data/lib/pry/commands/exit_program.rb +20 -16
- data/lib/pry/commands/find_method.rb +168 -160
- data/lib/pry/commands/fix_indent.rb +16 -12
- data/lib/pry/commands/help.rb +140 -133
- data/lib/pry/commands/hist.rb +151 -150
- data/lib/pry/commands/import_set.rb +20 -16
- data/lib/pry/commands/jump_to.rb +25 -21
- data/lib/pry/commands/list_inspectors.rb +35 -28
- data/lib/pry/commands/ls.rb +124 -102
- data/lib/pry/commands/ls/constants.rb +59 -42
- data/lib/pry/commands/ls/formatter.rb +50 -46
- data/lib/pry/commands/ls/globals.rb +38 -34
- data/lib/pry/commands/ls/grep.rb +17 -13
- data/lib/pry/commands/ls/instance_vars.rb +29 -27
- data/lib/pry/commands/ls/interrogatable.rb +18 -12
- data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
- data/lib/pry/commands/ls/local_names.rb +26 -22
- data/lib/pry/commands/ls/local_vars.rb +38 -28
- data/lib/pry/commands/ls/ls_entity.rb +47 -51
- data/lib/pry/commands/ls/methods.rb +44 -43
- data/lib/pry/commands/ls/methods_helper.rb +46 -42
- data/lib/pry/commands/ls/self_methods.rb +23 -22
- data/lib/pry/commands/nesting.rb +21 -17
- data/lib/pry/commands/play.rb +93 -82
- data/lib/pry/commands/pry_backtrace.rb +22 -17
- data/lib/pry/commands/pry_version.rb +15 -11
- data/lib/pry/commands/raise_up.rb +27 -22
- data/lib/pry/commands/reload_code.rb +60 -48
- data/lib/pry/commands/reset.rb +16 -12
- data/lib/pry/commands/ri.rb +55 -45
- data/lib/pry/commands/save_file.rb +45 -43
- data/lib/pry/commands/shell_command.rb +51 -51
- data/lib/pry/commands/shell_mode.rb +21 -17
- data/lib/pry/commands/show_doc.rb +80 -68
- data/lib/pry/commands/show_info.rb +189 -171
- data/lib/pry/commands/show_input.rb +16 -11
- data/lib/pry/commands/show_source.rb +110 -45
- data/lib/pry/commands/stat.rb +35 -31
- data/lib/pry/commands/switch_to.rb +21 -15
- data/lib/pry/commands/toggle_color.rb +20 -16
- data/lib/pry/commands/watch_expression.rb +89 -86
- data/lib/pry/commands/watch_expression/expression.rb +32 -27
- data/lib/pry/commands/whereami.rb +156 -148
- data/lib/pry/commands/wtf.rb +75 -50
- data/lib/pry/config.rb +307 -25
- data/lib/pry/config/attributable.rb +22 -0
- data/lib/pry/config/lazy_value.rb +29 -0
- data/lib/pry/config/memoized_value.rb +34 -0
- data/lib/pry/config/value.rb +24 -0
- data/lib/pry/control_d_handler.rb +28 -0
- data/lib/pry/core_extensions.rb +9 -7
- data/lib/pry/editor.rb +48 -21
- data/lib/pry/env.rb +18 -0
- data/lib/pry/exception_handler.rb +43 -0
- data/lib/pry/exceptions.rb +13 -16
- data/lib/pry/forwardable.rb +5 -1
- data/lib/pry/helpers.rb +2 -0
- data/lib/pry/helpers/base_helpers.rb +68 -197
- data/lib/pry/helpers/command_helpers.rb +50 -61
- data/lib/pry/helpers/documentation_helpers.rb +20 -13
- data/lib/pry/helpers/options_helpers.rb +14 -7
- data/lib/pry/helpers/platform.rb +7 -5
- data/lib/pry/helpers/table.rb +33 -26
- data/lib/pry/helpers/text.rb +17 -14
- data/lib/pry/history.rb +48 -56
- data/lib/pry/hooks.rb +21 -12
- data/lib/pry/indent.rb +54 -50
- data/lib/pry/input_completer.rb +248 -230
- data/lib/pry/input_lock.rb +8 -9
- data/lib/pry/inspector.rb +36 -24
- data/lib/pry/last_exception.rb +45 -45
- data/lib/pry/method.rb +141 -94
- data/lib/pry/method/disowned.rb +16 -4
- data/lib/pry/method/patcher.rb +12 -3
- data/lib/pry/method/weird_method_locator.rb +68 -44
- data/lib/pry/object_path.rb +33 -25
- data/lib/pry/output.rb +121 -35
- data/lib/pry/pager.rb +186 -180
- data/lib/pry/prompt.rb +123 -54
- data/lib/pry/pry_class.rb +61 -103
- data/lib/pry/pry_instance.rb +217 -215
- data/lib/pry/repl.rb +18 -22
- data/lib/pry/repl_file_loader.rb +27 -21
- data/lib/pry/ring.rb +11 -6
- data/lib/pry/slop.rb +574 -563
- data/lib/pry/slop/commands.rb +164 -169
- data/lib/pry/slop/option.rb +172 -168
- data/lib/pry/syntax_highlighter.rb +26 -0
- data/lib/pry/system_command_handler.rb +17 -0
- data/lib/pry/testable.rb +59 -61
- data/lib/pry/testable/evalable.rb +21 -12
- data/lib/pry/testable/mockable.rb +18 -10
- data/lib/pry/testable/pry_tester.rb +71 -56
- data/lib/pry/testable/utility.rb +29 -21
- data/lib/pry/testable/variables.rb +49 -43
- data/lib/pry/version.rb +3 -1
- data/lib/pry/warning.rb +27 -0
- data/lib/pry/wrapped_module.rb +51 -42
- data/lib/pry/wrapped_module/candidate.rb +21 -14
- metadata +35 -35
- data/lib/pry/commands.rb +0 -6
- data/lib/pry/commands/disabled_commands.rb +0 -2
- data/lib/pry/commands/gem_cd.rb +0 -26
- data/lib/pry/commands/gem_install.rb +0 -32
- data/lib/pry/commands/gem_list.rb +0 -33
- data/lib/pry/commands/gem_open.rb +0 -29
- data/lib/pry/commands/gem_readme.rb +0 -25
- data/lib/pry/commands/gem_search.rb +0 -40
- data/lib/pry/commands/gem_stats.rb +0 -83
- data/lib/pry/commands/gist.rb +0 -102
- data/lib/pry/commands/install_command.rb +0 -54
- data/lib/pry/config/behavior.rb +0 -255
- data/lib/pry/config/convenience.rb +0 -28
- data/lib/pry/config/default.rb +0 -159
- data/lib/pry/config/memoization.rb +0 -48
- data/lib/pry/platform.rb +0 -91
- data/lib/pry/plugins.rb +0 -122
- data/lib/pry/rubygem.rb +0 -84
- data/lib/pry/terminal.rb +0 -91
data/lib/pry/pager.rb
CHANGED
@@ -1,111 +1,116 @@
|
|
1
|
-
|
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
|
7
|
-
class
|
8
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
69
|
-
|
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
|
-
|
73
|
-
write str
|
74
|
-
end
|
75
|
-
alias << print
|
41
|
+
private
|
76
42
|
|
77
|
-
def
|
78
|
-
|
43
|
+
def enabled?
|
44
|
+
!!@enabled
|
79
45
|
end
|
80
46
|
|
81
|
-
|
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
|
-
|
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
|
-
|
87
|
-
|
88
|
-
|
73
|
+
def puts(str)
|
74
|
+
print "#{str.chomp}\n"
|
75
|
+
end
|
89
76
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
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
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
134
|
-
|
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
|
-
|
137
|
+
pager
|
138
|
+
end
|
137
139
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
161
|
+
def initialize(*)
|
162
|
+
super
|
163
|
+
@tracker = PageTracker.new(height, width)
|
164
|
+
@buffer = ""
|
165
|
+
@pager = nil
|
166
|
+
end
|
162
167
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
-
|
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
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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
|
-
|
189
|
+
private
|
187
190
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
+
def write_to_pager(text)
|
192
|
+
pager.write @out.decolorize_maybe(text)
|
193
|
+
end
|
191
194
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
+
def invoked_pager?
|
196
|
+
@pager
|
197
|
+
end
|
195
198
|
|
196
|
-
|
197
|
-
|
199
|
+
def pager
|
200
|
+
@pager ||= IO.popen(self.class.default_pager, 'w')
|
201
|
+
end
|
198
202
|
end
|
199
|
-
end
|
200
203
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
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
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
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
|
-
|
227
|
-
|
228
|
-
|
231
|
+
def page?
|
232
|
+
@row >= @rows
|
233
|
+
end
|
229
234
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
235
|
+
def reset
|
236
|
+
@row = 0
|
237
|
+
@col = 0
|
238
|
+
end
|
234
239
|
|
235
|
-
|
240
|
+
private
|
236
241
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
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
|
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,
|
11
|
-
# sep == ':' ? "In [#{
|
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
|
-
|
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]
|
47
|
+
# Prompt[:my_prompt]
|
43
48
|
#
|
44
|
-
# @param [Symbol]
|
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 [](
|
48
|
-
|
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]
|
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,
|
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
|
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(
|
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
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
104
|
+
# @return [String]
|
105
|
+
attr_reader :name
|
89
106
|
|
90
|
-
|
91
|
-
|
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
|
-
|
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(
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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:
|
105
|
-
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(
|
169
|
+
add(
|
170
|
+
:simple,
|
171
|
+
"A simple `>>`.",
|
172
|
+
['>> ', ' | ']
|
173
|
+
) do |_, _, _, sep|
|
113
174
|
sep
|
114
175
|
end
|
115
176
|
|
116
|
-
add(
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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:
|
124
|
-
name:
|
186
|
+
in_count: pry_instance.input_ring.count,
|
187
|
+
name: pry_instance.config.prompt_name,
|
125
188
|
tree: tree.join(' / '),
|
126
|
-
stack_size:
|
189
|
+
stack_size: pry_instance.binding_stack.size - 1,
|
127
190
|
separator: sep
|
128
191
|
)
|
129
192
|
end
|
130
193
|
|
131
|
-
add(
|
132
|
-
|
133
|
-
|
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:
|
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(
|
208
|
+
add(
|
209
|
+
:none,
|
210
|
+
'Wave goodbye to the Pry prompt.',
|
211
|
+
Array.new(2)
|
212
|
+
) { '' }
|
144
213
|
end
|
145
214
|
end
|