pry 0.10.1 → 0.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +378 -11
- data/LICENSE +1 -1
- data/README.md +352 -306
- 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 +81 -74
- 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 +49 -30
- 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 +81 -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 +109 -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 +317 -20
- data/lib/pry/control_d_handler.rb +28 -0
- data/lib/pry/core_extensions.rb +22 -9
- data/lib/pry/editor.rb +53 -33
- data/lib/pry/env.rb +18 -0
- data/lib/pry/exception_handler.rb +43 -0
- data/lib/pry/exceptions.rb +13 -17
- 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 +20 -12
- data/lib/pry/helpers/options_helpers.rb +15 -8
- data/lib/pry/helpers/platform.rb +60 -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 +72 -66
- 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 -43
- data/lib/pry/method.rb +177 -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/plugins.rb +49 -13
- data/lib/pry/prompt.rb +213 -25
- data/lib/pry/pry_class.rb +106 -93
- data/lib/pry/pry_instance.rb +261 -224
- data/lib/pry/repl.rb +82 -27
- 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 +27 -0
- data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +29 -27
- data/lib/pry/wrapped_module.rb +67 -57
- data/lib/pry.rb +134 -149
- metadata +49 -59
- 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/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
|
@@ -58,7 +58,7 @@ class Pry
|
|
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
60
|
IGNORE_TOKENS = [:space, :content, :string, :method, :ident,
|
61
|
-
:constant, :pre_constant, :predefined_constant]
|
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 + [:regexp, :integer, :float,
|
70
|
-
:delimiter, :reserved
|
69
|
+
STATEMENT_END_TOKENS = IGNORE_TOKENS + [: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,7 +101,8 @@ 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
|
|
@@ -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
|
|