pry 0.10.3 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +439 -16
- data/LICENSE +1 -1
- data/README.md +362 -302
- data/bin/pry +4 -7
- data/lib/pry/basic_object.rb +10 -0
- data/lib/pry/block_command.rb +22 -0
- data/lib/pry/class_command.rb +194 -0
- data/lib/pry/cli.rb +84 -97
- data/lib/pry/code/code_file.rb +37 -26
- data/lib/pry/code/code_range.rb +7 -5
- data/lib/pry/code/loc.rb +26 -13
- data/lib/pry/code.rb +42 -31
- data/lib/pry/code_object.rb +53 -28
- data/lib/pry/color_printer.rb +46 -35
- data/lib/pry/command.rb +197 -369
- data/lib/pry/command_set.rb +89 -114
- data/lib/pry/command_state.rb +31 -0
- data/lib/pry/commands/amend_line.rb +86 -82
- data/lib/pry/commands/bang.rb +18 -14
- data/lib/pry/commands/bang_pry.rb +15 -11
- data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
- data/lib/pry/commands/cat/exception_formatter.rb +85 -72
- data/lib/pry/commands/cat/file_formatter.rb +56 -46
- data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
- data/lib/pry/commands/cat.rb +62 -54
- data/lib/pry/commands/cd.rb +40 -35
- data/lib/pry/commands/change_inspector.rb +29 -22
- data/lib/pry/commands/change_prompt.rb +48 -23
- data/lib/pry/commands/clear_screen.rb +20 -0
- data/lib/pry/commands/code_collector.rb +148 -131
- data/lib/pry/commands/disable_pry.rb +23 -19
- data/lib/pry/commands/easter_eggs.rb +23 -34
- 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/edit.rb +185 -157
- data/lib/pry/commands/exit.rb +40 -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 -162
- data/lib/pry/commands/fix_indent.rb +16 -12
- data/lib/pry/commands/help.rb +140 -133
- data/lib/pry/commands/hist.rb +151 -149
- data/lib/pry/commands/import_set.rb +20 -15
- data/lib/pry/commands/jump_to.rb +25 -21
- data/lib/pry/commands/list_inspectors.rb +35 -28
- data/lib/pry/commands/ls/constants.rb +59 -31
- data/lib/pry/commands/ls/formatter.rb +42 -36
- data/lib/pry/commands/ls/globals.rb +38 -36
- data/lib/pry/commands/ls/grep.rb +17 -15
- data/lib/pry/commands/ls/instance_vars.rb +29 -28
- 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 -24
- data/lib/pry/commands/ls/local_vars.rb +38 -30
- data/lib/pry/commands/ls/ls_entity.rb +47 -52
- data/lib/pry/commands/ls/methods.rb +49 -51
- data/lib/pry/commands/ls/methods_helper.rb +46 -42
- data/lib/pry/commands/ls/self_methods.rb +23 -21
- data/lib/pry/commands/ls.rb +124 -103
- data/lib/pry/commands/nesting.rb +21 -17
- data/lib/pry/commands/play.rb +92 -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 +33 -27
- data/lib/pry/commands/reload_code.rb +60 -48
- data/lib/pry/commands/reset.rb +16 -12
- data/lib/pry/commands/ri.rb +57 -42
- data/lib/pry/commands/save_file.rb +45 -43
- data/lib/pry/commands/shell_command.rb +56 -29
- data/lib/pry/commands/shell_mode.rb +22 -18
- data/lib/pry/commands/show_doc.rb +80 -70
- data/lib/pry/commands/show_info.rb +194 -155
- data/lib/pry/commands/show_input.rb +16 -11
- data/lib/pry/commands/show_source.rb +110 -42
- 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/expression.rb +32 -27
- data/lib/pry/commands/watch_expression.rb +89 -84
- data/lib/pry/commands/whereami.rb +156 -141
- data/lib/pry/commands/wtf.rb +78 -40
- 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/config.rb +310 -20
- data/lib/pry/control_d_handler.rb +28 -0
- data/lib/pry/core_extensions.rb +22 -9
- data/lib/pry/editor.rb +56 -34
- data/lib/pry/env.rb +18 -0
- data/lib/pry/exception_handler.rb +43 -0
- data/lib/pry/exceptions.rb +13 -18
- data/lib/pry/forwardable.rb +27 -0
- data/lib/pry/helpers/base_helpers.rb +20 -62
- data/lib/pry/helpers/command_helpers.rb +52 -62
- data/lib/pry/helpers/documentation_helpers.rb +21 -12
- data/lib/pry/helpers/options_helpers.rb +15 -8
- data/lib/pry/helpers/platform.rb +55 -0
- data/lib/pry/helpers/table.rb +44 -32
- data/lib/pry/helpers/text.rb +96 -85
- data/lib/pry/helpers.rb +3 -0
- data/lib/pry/history.rb +81 -55
- data/lib/pry/hooks.rb +60 -110
- data/lib/pry/indent.rb +74 -68
- data/lib/pry/input_completer.rb +199 -158
- data/lib/pry/input_lock.rb +7 -10
- data/lib/pry/inspector.rb +36 -24
- data/lib/pry/last_exception.rb +45 -45
- data/lib/pry/method/disowned.rb +19 -5
- data/lib/pry/method/patcher.rb +14 -8
- data/lib/pry/method/weird_method_locator.rb +79 -45
- data/lib/pry/method.rb +178 -124
- data/lib/pry/object_path.rb +37 -28
- data/lib/pry/output.rb +102 -16
- data/lib/pry/pager.rb +187 -174
- data/lib/pry/prompt.rb +213 -25
- data/lib/pry/pry_class.rb +119 -98
- data/lib/pry/pry_instance.rb +261 -224
- data/lib/pry/repl.rb +83 -29
- data/lib/pry/repl_file_loader.rb +27 -22
- data/lib/pry/ring.rb +89 -0
- data/lib/pry/slop/LICENSE +20 -0
- data/lib/pry/slop/commands.rb +190 -0
- data/lib/pry/slop/option.rb +210 -0
- data/lib/pry/slop.rb +672 -0
- data/lib/pry/syntax_highlighter.rb +26 -0
- data/lib/pry/system_command_handler.rb +17 -0
- data/lib/pry/testable/evalable.rb +24 -0
- data/lib/pry/testable/mockable.rb +22 -0
- data/lib/pry/testable/pry_tester.rb +88 -0
- data/lib/pry/testable/utility.rb +34 -0
- data/lib/pry/testable/variables.rb +52 -0
- data/lib/pry/testable.rb +68 -0
- data/lib/pry/version.rb +3 -1
- data/lib/pry/warning.rb +20 -0
- data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +35 -32
- data/lib/pry/wrapped_module.rb +68 -63
- data/lib/pry.rb +133 -149
- metadata +58 -69
- 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/gist.rb +0 -101
- data/lib/pry/commands/install_command.rb +0 -53
- data/lib/pry/commands/list_prompts.rb +0 -35
- data/lib/pry/commands/simple_prompt.rb +0 -22
- data/lib/pry/commands.rb +0 -6
- data/lib/pry/config/behavior.rb +0 -139
- data/lib/pry/config/convenience.rb +0 -25
- data/lib/pry/config/default.rb +0 -161
- data/lib/pry/history_array.rb +0 -121
- data/lib/pry/plugins.rb +0 -103
- data/lib/pry/rbx_path.rb +0 -22
- data/lib/pry/rubygem.rb +0 -82
- data/lib/pry/terminal.rb +0 -79
- data/lib/pry/test/helper.rb +0 -170
data/lib/pry/hooks.rb
CHANGED
@@ -1,37 +1,33 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
#
|
5
|
-
# provided by Pry, these
|
6
|
-
# A hook must
|
7
|
-
# `Pry::Hooks#add_hook`
|
3
|
+
class Pry
|
4
|
+
# Implements a hooks system for Pry. A hook is a callable that is associated
|
5
|
+
# with an event. A number of events are currently provided by Pry, these
|
6
|
+
# include: `:when_started`, `:before_session`, `:after_session`. A hook must
|
7
|
+
# have a name, and is connected with an event by the `Pry::Hooks#add_hook`
|
8
|
+
# method.
|
9
|
+
#
|
8
10
|
# @example Adding a hook for the `:before_session` event.
|
9
11
|
# Pry.config.hooks.add_hook(:before_session, :say_hi) do
|
10
12
|
# puts "hello"
|
11
13
|
# end
|
12
14
|
class Hooks
|
15
|
+
def self.default
|
16
|
+
hooks = new
|
17
|
+
hooks.add_hook(:before_session, :default) do |_out, _target, pry_instance|
|
18
|
+
next if pry_instance.quiet?
|
13
19
|
|
14
|
-
|
15
|
-
# this way are anonymous. This functionality is primarily to
|
16
|
-
# provide backwards-compatibility with the old hash-based hook
|
17
|
-
# system in Pry versions < 0.9.8
|
18
|
-
# @param [Hash] hash The hash to convert to `Pry::Hooks`.
|
19
|
-
# @return [Pry::Hooks] The resulting `Pry::Hooks` instance.
|
20
|
-
def self.from_hash(hash)
|
21
|
-
return hash if hash.instance_of?(self)
|
22
|
-
instance = new
|
23
|
-
hash.each do |k, v|
|
24
|
-
instance.add_hook(k, nil, v)
|
20
|
+
pry_instance.run_command('whereami --quiet')
|
25
21
|
end
|
26
|
-
|
22
|
+
hooks
|
27
23
|
end
|
28
24
|
|
29
25
|
def initialize
|
30
|
-
@hooks = {}
|
26
|
+
@hooks = Hash.new { |h, k| h[k] = [] }
|
31
27
|
end
|
32
28
|
|
33
|
-
# Ensure that duplicates have their @hooks object
|
34
|
-
def initialize_copy(
|
29
|
+
# Ensure that duplicates have their @hooks object.
|
30
|
+
def initialize_copy(_orig)
|
35
31
|
hooks_dup = @hooks.dup
|
36
32
|
@hooks.each do |k, v|
|
37
33
|
hooks_dup[k] = v.dup
|
@@ -40,63 +36,50 @@ class Pry
|
|
40
36
|
@hooks = hooks_dup
|
41
37
|
end
|
42
38
|
|
43
|
-
def hooks
|
44
|
-
@hooks
|
45
|
-
end
|
46
|
-
protected :hooks
|
47
|
-
|
48
39
|
def errors
|
49
40
|
@errors ||= []
|
50
41
|
end
|
51
42
|
|
52
43
|
# Destructively merge the contents of two `Pry:Hooks` instances.
|
44
|
+
#
|
53
45
|
# @param [Pry::Hooks] other The `Pry::Hooks` instance to merge
|
54
|
-
# @return [Pry:Hooks]
|
55
|
-
# @
|
56
|
-
# hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
|
57
|
-
# Pry::Hooks.new.merge!(hooks)
|
46
|
+
# @return [Pry:Hooks] The receiver.
|
47
|
+
# @see #merge
|
58
48
|
def merge!(other)
|
59
|
-
@hooks.merge!(other.dup.hooks) do |
|
60
|
-
|
61
|
-
|
49
|
+
@hooks.merge!(other.dup.hooks) do |_key, array, other_array|
|
50
|
+
temp_hash = {}
|
51
|
+
output = []
|
62
52
|
|
63
|
-
|
64
|
-
|
53
|
+
(array + other_array).reverse_each do |pair|
|
54
|
+
temp_hash[pair.first] ||= output.unshift(pair)
|
55
|
+
end
|
65
56
|
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
private :merge_arrays
|
57
|
+
output
|
58
|
+
end
|
70
59
|
|
71
|
-
|
72
|
-
hash, output = {}, []
|
73
|
-
input.reverse.each{ |i| hash[block[i]] ||= (output.unshift i) }
|
74
|
-
output
|
60
|
+
self
|
75
61
|
end
|
76
|
-
private :uniq_keeping_last
|
77
62
|
|
78
|
-
# Return a new `Pry::Hooks` instance containing a merge of the contents of two `Pry:Hooks` instances,
|
79
|
-
# @param [Pry::Hooks] other The `Pry::Hooks` instance to merge
|
80
|
-
# @return [Pry::Hooks] The new hash.
|
81
63
|
# @example
|
82
64
|
# hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
|
83
65
|
# Pry::Hooks.new.merge(hooks)
|
66
|
+
# @param [Pry::Hooks] other The `Pry::Hooks` instance to merge
|
67
|
+
# @return [Pry::Hooks] a new `Pry::Hooks` instance containing a merge of the
|
68
|
+
# contents of two `Pry:Hooks` instances.
|
84
69
|
def merge(other)
|
85
|
-
|
70
|
+
dup.tap do |v|
|
86
71
|
v.merge!(other)
|
87
72
|
end
|
88
73
|
end
|
89
74
|
|
90
|
-
# Add a new hook to be executed for the `
|
75
|
+
# Add a new hook to be executed for the `event_name` event.
|
91
76
|
# @param [Symbol] event_name The name of the event.
|
92
77
|
# @param [Symbol] hook_name The name of the hook.
|
93
78
|
# @param [#call] callable The callable.
|
94
|
-
# @yield The block to use as the callable (if `callable`
|
95
|
-
# @return [Pry:Hooks]
|
96
|
-
|
97
|
-
|
98
|
-
def add_hook(event_name, hook_name, callable=nil, &block)
|
99
|
-
@hooks[event_name] ||= []
|
79
|
+
# @yield The block to use as the callable (if no `callable` provided).
|
80
|
+
# @return [Pry:Hooks] The receiver.
|
81
|
+
def add_hook(event_name, hook_name, callable = nil, &block)
|
82
|
+
event_name = event_name.to_s
|
100
83
|
|
101
84
|
# do not allow duplicates, but allow multiple `nil` hooks
|
102
85
|
# (anonymous hooks)
|
@@ -104,12 +87,10 @@ class Pry
|
|
104
87
|
raise ArgumentError, "Hook with name '#{hook_name}' already defined!"
|
105
88
|
end
|
106
89
|
|
107
|
-
if !block && !callable
|
108
|
-
raise ArgumentError, "Must provide a block or callable."
|
109
|
-
end
|
90
|
+
raise ArgumentError, "Must provide a block or callable." if !block && !callable
|
110
91
|
|
111
92
|
# ensure we only have one anonymous hook
|
112
|
-
@hooks[event_name].delete_if { |h,
|
93
|
+
@hooks[event_name].delete_if { |h, _k| h.nil? } if hook_name.nil?
|
113
94
|
|
114
95
|
if block
|
115
96
|
@hooks[event_name] << [hook_name, block]
|
@@ -124,13 +105,8 @@ class Pry
|
|
124
105
|
# @param [Symbol] event_name The name of the event.
|
125
106
|
# @param [Array] args The arguments to pass to each hook function.
|
126
107
|
# @return [Object] The return value of the last executed hook.
|
127
|
-
# @example
|
128
|
-
# my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
|
129
|
-
# my_hooks.exec_hook(:before_session) #=> OUTPUT: "hi!"
|
130
108
|
def exec_hook(event_name, *args, &block)
|
131
|
-
@hooks[event_name]
|
132
|
-
|
133
|
-
@hooks[event_name].map do |hook_name, callable|
|
109
|
+
@hooks[event_name.to_s].map do |_hook_name, callable|
|
134
110
|
begin
|
135
111
|
callable.call(*args, &block)
|
136
112
|
rescue RescuableException => e
|
@@ -140,56 +116,38 @@ class Pry
|
|
140
116
|
end.last
|
141
117
|
end
|
142
118
|
|
143
|
-
# Return the number of hook functions registered for the `event_name` event.
|
144
119
|
# @param [Symbol] event_name The name of the event.
|
145
120
|
# @return [Fixnum] The number of hook functions for `event_name`.
|
146
|
-
# @example
|
147
|
-
# my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
|
148
|
-
# my_hooks.count(:before_session) #=> 1
|
149
121
|
def hook_count(event_name)
|
150
|
-
@hooks[event_name]
|
151
|
-
@hooks[event_name].size
|
122
|
+
@hooks[event_name.to_s].size
|
152
123
|
end
|
153
124
|
|
154
|
-
# Return a specific hook for a given event.
|
155
125
|
# @param [Symbol] event_name The name of the event.
|
156
126
|
# @param [Symbol] hook_name The name of the hook
|
157
|
-
# @return [#call]
|
158
|
-
# @example
|
159
|
-
# my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
|
160
|
-
# my_hooks.get_hook(:before_session, :say_hi).call #=> "hi!"
|
127
|
+
# @return [#call] a specific hook for a given event.
|
161
128
|
def get_hook(event_name, hook_name)
|
162
|
-
@hooks[event_name]
|
163
|
-
|
129
|
+
hook = @hooks[event_name.to_s].find do |current_hook_name, _callable|
|
130
|
+
current_hook_name == hook_name
|
131
|
+
end
|
164
132
|
hook.last if hook
|
165
133
|
end
|
166
134
|
|
167
|
-
# Return the hash of hook names / hook functions for a
|
168
|
-
# given event. (Note that modifying the returned hash does not
|
169
|
-
# alter the hooks, use add_hook/delete_hook for that).
|
170
135
|
# @param [Symbol] event_name The name of the event.
|
171
136
|
# @return [Hash] The hash of hook names / hook functions.
|
172
|
-
# @
|
173
|
-
#
|
174
|
-
# my_hooks.get_hooks(:before_session) #=> {:say_hi=>#<Proc:0x00000101645e18@(pry):9>}
|
137
|
+
# @note Modifying the returned hash does not alter the hooks, use
|
138
|
+
# `add_hook`/`delete_hook` for that.
|
175
139
|
def get_hooks(event_name)
|
176
|
-
@hooks[event_name]
|
177
|
-
Hash[@hooks[event_name]]
|
140
|
+
Hash[@hooks[event_name.to_s]]
|
178
141
|
end
|
179
142
|
|
180
|
-
# Delete a hook for an event.
|
181
143
|
# @param [Symbol] event_name The name of the event.
|
182
144
|
# @param [Symbol] hook_name The name of the hook.
|
183
145
|
# to delete.
|
184
146
|
# @return [#call] The deleted hook.
|
185
|
-
# @example
|
186
|
-
# my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
|
187
|
-
# my_hooks.delete_hook(:before_session, :say_hi)
|
188
147
|
def delete_hook(event_name, hook_name)
|
189
|
-
@hooks[event_name] ||= []
|
190
148
|
deleted_callable = nil
|
191
149
|
|
192
|
-
@hooks[event_name].delete_if do |current_hook_name, callable|
|
150
|
+
@hooks[event_name.to_s].delete_if do |current_hook_name, callable|
|
193
151
|
if current_hook_name == hook_name
|
194
152
|
deleted_callable = callable
|
195
153
|
true
|
@@ -201,30 +159,22 @@ class Pry
|
|
201
159
|
end
|
202
160
|
|
203
161
|
# Clear all hooks functions for a given event.
|
162
|
+
#
|
204
163
|
# @param [String] event_name The name of the event.
|
205
|
-
# @
|
206
|
-
|
207
|
-
|
208
|
-
def delete_hooks(event_name)
|
209
|
-
@hooks[event_name] = []
|
210
|
-
end
|
211
|
-
|
212
|
-
alias_method :clear, :delete_hooks
|
213
|
-
|
214
|
-
# Remove all events and hooks, clearing out the Pry::Hooks
|
215
|
-
# instance completely.
|
216
|
-
# @example
|
217
|
-
# my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
|
218
|
-
# my_hooks.clear_all
|
219
|
-
def clear_all
|
220
|
-
@hooks = {}
|
164
|
+
# @return [void]
|
165
|
+
def clear_event_hooks(event_name)
|
166
|
+
@hooks[event_name.to_s] = []
|
221
167
|
end
|
222
168
|
|
223
169
|
# @param [Symbol] event_name Name of the event.
|
224
170
|
# @param [Symbol] hook_name Name of the hook.
|
225
|
-
# @return [Boolean] Whether the hook by the name `hook_name
|
171
|
+
# @return [Boolean] Whether the hook by the name `hook_name`.
|
226
172
|
def hook_exists?(event_name, hook_name)
|
227
|
-
|
173
|
+
@hooks[event_name.to_s].map(&:first).include?(hook_name)
|
228
174
|
end
|
175
|
+
|
176
|
+
protected
|
177
|
+
|
178
|
+
attr_reader :hooks
|
229
179
|
end
|
230
180
|
end
|
data/lib/pry/indent.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Pry
|
4
4
|
##
|
@@ -21,35 +21,35 @@ class Pry
|
|
21
21
|
attr_reader :stack
|
22
22
|
|
23
23
|
# The amount of spaces to insert for each indent level.
|
24
|
-
SPACES = ' '
|
24
|
+
SPACES = ' '.freeze
|
25
25
|
|
26
26
|
# Hash containing all the tokens that should increase the indentation
|
27
27
|
# level. The keys of this hash are open tokens, the values the matching
|
28
28
|
# tokens that should prevent a line from being indented if they appear on
|
29
29
|
# the same line.
|
30
30
|
OPEN_TOKENS = {
|
31
|
-
'def'
|
32
|
-
'class'
|
31
|
+
'def' => 'end',
|
32
|
+
'class' => 'end',
|
33
33
|
'module' => 'end',
|
34
|
-
'do'
|
35
|
-
'if'
|
34
|
+
'do' => 'end',
|
35
|
+
'if' => 'end',
|
36
36
|
'unless' => 'end',
|
37
|
-
'while'
|
38
|
-
'until'
|
39
|
-
'for'
|
40
|
-
'case'
|
41
|
-
'begin'
|
42
|
-
'['
|
43
|
-
'{'
|
44
|
-
'('
|
45
|
-
}
|
37
|
+
'while' => 'end',
|
38
|
+
'until' => 'end',
|
39
|
+
'for' => 'end',
|
40
|
+
'case' => 'end',
|
41
|
+
'begin' => 'end',
|
42
|
+
'[' => ']',
|
43
|
+
'{' => '}',
|
44
|
+
'(' => ')'
|
45
|
+
}.freeze
|
46
46
|
|
47
47
|
# Which tokens can either be open tokens, or appear as modifiers on
|
48
48
|
# a single-line.
|
49
|
-
SINGLELINE_TOKENS = %w
|
49
|
+
SINGLELINE_TOKENS = %w[if while until unless rescue].freeze
|
50
50
|
|
51
51
|
# Which tokens can be followed by an optional "do" keyword.
|
52
|
-
OPTIONAL_DO_TOKENS = %w
|
52
|
+
OPTIONAL_DO_TOKENS = %w[for while until].freeze
|
53
53
|
|
54
54
|
# Collection of token types that should be ignored. Without this list
|
55
55
|
# keywords such as "class" inside strings would cause the code to be
|
@@ -57,8 +57,8 @@ class Pry
|
|
57
57
|
#
|
58
58
|
# :pre_constant and :preserved_constant are the CodeRay 0.9.8 and 1.0.0
|
59
59
|
# classifications of "true", "false", and "nil".
|
60
|
-
IGNORE_TOKENS = [
|
61
|
-
|
60
|
+
IGNORE_TOKENS = %i[space content string method ident
|
61
|
+
constant pre_constant predefined_constant].freeze
|
62
62
|
|
63
63
|
# Tokens that indicate the end of a statement (i.e. that, if they appear
|
64
64
|
# directly before an "if" indicates that that if applies to the same line,
|
@@ -66,12 +66,14 @@ class Pry
|
|
66
66
|
#
|
67
67
|
# :reserved and :keywords are the CodeRay 0.9.8 and 1.0.0 respectively
|
68
68
|
# classifications of "super", "next", "return", etc.
|
69
|
-
STATEMENT_END_TOKENS = IGNORE_TOKENS + [
|
70
|
-
|
69
|
+
STATEMENT_END_TOKENS = IGNORE_TOKENS + %i[regexp integer float
|
70
|
+
keyword delimiter reserved
|
71
|
+
instance_variable
|
72
|
+
class_variable global_variable]
|
71
73
|
|
72
74
|
# Collection of tokens that should appear dedented even though they
|
73
75
|
# don't affect the surrounding code.
|
74
|
-
MIDWAY_TOKENS = %w
|
76
|
+
MIDWAY_TOKENS = %w[when else elsif ensure rescue].freeze
|
75
77
|
|
76
78
|
# Clean the indentation of a fragment of ruby.
|
77
79
|
#
|
@@ -99,14 +101,15 @@ class Pry
|
|
99
101
|
indent.module_nesting
|
100
102
|
end
|
101
103
|
|
102
|
-
def initialize
|
104
|
+
def initialize(pry_instance = Pry.new)
|
105
|
+
@pry_instance = pry_instance
|
103
106
|
reset
|
104
107
|
end
|
105
108
|
|
106
109
|
# reset internal state
|
107
110
|
def reset
|
108
111
|
@stack = []
|
109
|
-
@indent_level =
|
112
|
+
@indent_level = String.new # rubocop:disable Style/EmptyLiteral
|
110
113
|
@heredoc_queue = []
|
111
114
|
@close_heredocs = {}
|
112
115
|
@string_start = nil
|
@@ -141,10 +144,11 @@ class Pry
|
|
141
144
|
prefix = indent_level
|
142
145
|
|
143
146
|
input.lines.each do |line|
|
144
|
-
|
145
147
|
if in_string?
|
146
148
|
tokens = tokenize("#{open_delimiters_line}\n#{line}")
|
147
|
-
tokens = tokens.drop_while
|
149
|
+
tokens = tokens.drop_while do |token, _type|
|
150
|
+
!(token.is_a?(String) && token.include?("\n"))
|
151
|
+
end
|
148
152
|
previously_in_string = true
|
149
153
|
else
|
150
154
|
tokens = tokenize(line)
|
@@ -153,7 +157,7 @@ class Pry
|
|
153
157
|
|
154
158
|
before, after = indentation_delta(tokens)
|
155
159
|
|
156
|
-
before.times{ prefix.sub! SPACES, '' }
|
160
|
+
before.times { prefix.sub! SPACES, '' }
|
157
161
|
new_prefix = prefix + SPACES * after
|
158
162
|
|
159
163
|
line = prefix + line.lstrip unless previously_in_string
|
@@ -165,7 +169,7 @@ class Pry
|
|
165
169
|
|
166
170
|
@indent_level = prefix
|
167
171
|
|
168
|
-
|
172
|
+
output
|
169
173
|
end
|
170
174
|
|
171
175
|
# Get the indentation for the start of the next line.
|
@@ -192,7 +196,6 @@ class Pry
|
|
192
196
|
# @return [Array[Integer]]
|
193
197
|
#
|
194
198
|
def indentation_delta(tokens)
|
195
|
-
|
196
199
|
# We need to keep track of whether we've seen a "for" on this line because
|
197
200
|
# if the line ends with "do" then that "do" should be discounted (i.e. we're
|
198
201
|
# only opening one level not two) To do this robustly we want to keep track
|
@@ -203,29 +206,37 @@ class Pry
|
|
203
206
|
# When deciding whether an "if" token is the start of a multiline statement,
|
204
207
|
# or just the middle of a single-line if statement, we just look at the
|
205
208
|
# preceding token, which is tracked here.
|
206
|
-
last_token
|
209
|
+
last_token = nil
|
210
|
+
last_kind = nil
|
207
211
|
|
208
212
|
# delta keeps track of the total difference from the start of each line after
|
209
213
|
# the given token, 0 is just the level at which the current line started for
|
210
214
|
# reference.
|
211
|
-
remove_before
|
215
|
+
remove_before = 0
|
216
|
+
add_after = 0
|
212
217
|
|
213
218
|
# If the list of tokens contains a matching closing token the line should
|
214
219
|
# not be indented (and thus we should return true).
|
215
220
|
tokens.each do |token, kind|
|
216
|
-
is_singleline_if
|
221
|
+
is_singleline_if =
|
222
|
+
SINGLELINE_TOKENS.include?(token) && end_of_statement?(last_token, last_kind)
|
217
223
|
is_optional_do = (token == "do" && seen_for_at.include?(add_after - 1))
|
218
224
|
|
219
|
-
|
225
|
+
unless kind == :space
|
226
|
+
last_token = token
|
227
|
+
last_kind = kind
|
228
|
+
end
|
220
229
|
next if IGNORE_TOKENS.include?(kind)
|
221
230
|
|
222
231
|
track_module_nesting(token, kind)
|
223
232
|
|
224
233
|
seen_for_at << add_after if OPTIONAL_DO_TOKENS.include?(token)
|
225
234
|
|
235
|
+
next if is_singleline_if
|
236
|
+
|
226
237
|
if kind == :delimiter
|
227
238
|
track_delimiter(token)
|
228
|
-
elsif OPEN_TOKENS.
|
239
|
+
elsif OPEN_TOKENS.key?(token) && !is_optional_do && !is_singleline_if
|
229
240
|
@stack << token
|
230
241
|
add_after += 1
|
231
242
|
elsif token == OPEN_TOKENS[@stack.last]
|
@@ -244,20 +255,21 @@ class Pry
|
|
244
255
|
end
|
245
256
|
end
|
246
257
|
|
247
|
-
|
258
|
+
[remove_before, add_after]
|
248
259
|
end
|
249
260
|
|
250
|
-
# If the code just before an "if" or "while" token on a line looks like the
|
251
|
-
# then we want to treat that "if" as a singleline, not
|
261
|
+
# If the code just before an "if" or "while" token on a line looks like the
|
262
|
+
# end of a statement, then we want to treat that "if" as a singleline, not
|
263
|
+
# multiline statement.
|
252
264
|
def end_of_statement?(last_token, last_kind)
|
253
|
-
(last_token =~
|
265
|
+
(last_token =~ %r{^[)\]\}/]$} || STATEMENT_END_TOKENS.include?(last_kind))
|
254
266
|
end
|
255
267
|
|
256
268
|
# Are we currently in the middle of a string literal.
|
257
269
|
#
|
258
|
-
# This is used to determine whether to re-indent a given line, we mustn't
|
259
|
-
# within string literals because to do so would actually change
|
260
|
-
# String!
|
270
|
+
# This is used to determine whether to re-indent a given line, we mustn't
|
271
|
+
# re-indent within string literals because to do so would actually change
|
272
|
+
# the value of the String!
|
261
273
|
#
|
262
274
|
# @return Boolean
|
263
275
|
def in_string?
|
@@ -269,16 +281,17 @@ class Pry
|
|
269
281
|
# @param [String] string The Ruby to lex
|
270
282
|
# @return [Array] An Array of pairs of [token_value, token_type]
|
271
283
|
def tokenize(string)
|
272
|
-
tokens =
|
284
|
+
tokens = SyntaxHighlighter.tokenize(string)
|
273
285
|
tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens) # Coderay 1.0.0
|
274
286
|
tokens.to_a
|
275
287
|
end
|
276
288
|
|
277
289
|
# Update the internal state about what kind of strings are open.
|
278
290
|
#
|
279
|
-
# Most of the complication here comes from the fact that HEREDOCs can be
|
280
|
-
# normal strings (which can't be nested) we assume that CodeRay
|
281
|
-
# open-and-close delimiters so we don't bother checking what
|
291
|
+
# Most of the complication here comes from the fact that HEREDOCs can be
|
292
|
+
# nested. For normal strings (which can't be nested) we assume that CodeRay
|
293
|
+
# correctly pairs open-and-close delimiters so we don't bother checking what
|
294
|
+
# they are.
|
282
295
|
#
|
283
296
|
# @param [String] token The token (of type :delimiter)
|
284
297
|
def track_delimiter(token)
|
@@ -289,11 +302,7 @@ class Pry
|
|
289
302
|
when @close_heredocs[@heredoc_queue.first]
|
290
303
|
@heredoc_queue.shift
|
291
304
|
else
|
292
|
-
|
293
|
-
@string_start = nil
|
294
|
-
else
|
295
|
-
@string_start = token
|
296
|
-
end
|
305
|
+
@string_start = @string_start ? nil : token
|
297
306
|
end
|
298
307
|
end
|
299
308
|
|
@@ -309,7 +318,7 @@ class Pry
|
|
309
318
|
#
|
310
319
|
# @return String
|
311
320
|
def open_delimiters_line
|
312
|
-
"puts #{open_delimiters.join(
|
321
|
+
"puts #{open_delimiters.join(', ')}"
|
313
322
|
end
|
314
323
|
|
315
324
|
# Update the internal state relating to module nesting.
|
@@ -330,7 +339,7 @@ class Pry
|
|
330
339
|
# @param [String] token a token from Coderay
|
331
340
|
# @param [Symbol] kind the kind of that token
|
332
341
|
def track_module_nesting(token, kind)
|
333
|
-
if kind == :keyword &&
|
342
|
+
if kind == :keyword && %w[class module].include?(token)
|
334
343
|
@module_nesting << [token, nil]
|
335
344
|
@awaiting_class = true
|
336
345
|
elsif @awaiting_class
|
@@ -354,10 +363,8 @@ class Pry
|
|
354
363
|
#
|
355
364
|
# @param [String] token a token from Coderay
|
356
365
|
# @param [Symbol] kind the kind of that token
|
357
|
-
def track_module_nesting_end(token, kind
|
358
|
-
if kind == :keyword &&
|
359
|
-
@module_nesting.pop
|
360
|
-
end
|
366
|
+
def track_module_nesting_end(token, kind = :keyword)
|
367
|
+
@module_nesting.pop if kind == :keyword && %w[class module].include?(token)
|
361
368
|
end
|
362
369
|
|
363
370
|
# Return a list of strings which can be used to re-construct the Module.nesting at
|
@@ -378,25 +385,24 @@ class Pry
|
|
378
385
|
# the correct indentation. Mostly useful for fixing 'end'.
|
379
386
|
#
|
380
387
|
# @param [String] prompt The user's prompt
|
381
|
-
# @param [String] code
|
382
|
-
# @param [
|
383
|
-
# the difference in length between the old line and the new one)
|
384
|
-
#
|
385
|
-
|
388
|
+
# @param [String] code The code the user just typed in
|
389
|
+
# @param [Integer] overhang The number of characters to erase afterwards (the
|
390
|
+
# the difference in length between the old line and the new one)
|
391
|
+
#
|
392
|
+
# @return [String] correctly indented line
|
393
|
+
def correct_indentation(prompt, code, overhang = 0)
|
386
394
|
prompt = prompt.delete("\001\002")
|
387
395
|
line_to_measure = Pry::Helpers::Text.strip_color(prompt) << code
|
388
396
|
whitespace = ' ' * overhang
|
389
397
|
|
390
|
-
|
391
|
-
|
392
|
-
cols = cols.to_i
|
393
|
-
lines = (cols != 0 ? (line_to_measure.length / cols + 1) : 1).to_i
|
398
|
+
cols = @pry_instance.output.width
|
399
|
+
lines = cols == 0 ? 1 : (line_to_measure.length / cols + 1).to_i
|
394
400
|
|
395
|
-
if
|
396
|
-
move_up
|
401
|
+
if Helpers::Platform.windows_ansi?
|
402
|
+
move_up = "\e[#{lines}F"
|
397
403
|
move_down = "\e[#{lines}E"
|
398
404
|
else
|
399
|
-
move_up
|
405
|
+
move_up = "\e[#{lines}A\e[0G"
|
400
406
|
move_down = "\e[#{lines}B\e[0G"
|
401
407
|
end
|
402
408
|
|