pry 0.7.7.2-i386-mswin32 → 0.8.0-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,303 @@
1
+ class Pry
2
+ class Commands < CommandBase
3
+ module CommandHelpers
4
+
5
+ private
6
+
7
+ def try_to_load_pry_doc
8
+
9
+ # YARD crashes on rbx, so do not require it
10
+ if !Object.const_defined?(:RUBY_ENGINE) || RUBY_ENGINE !~ /rbx/
11
+ require "pry-doc"
12
+ end
13
+ rescue LoadError
14
+ end
15
+
16
+ def meth_name_from_binding(b)
17
+ meth_name = b.eval('__method__')
18
+ if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
19
+ nil
20
+ else
21
+ meth_name
22
+ end
23
+ end
24
+
25
+ def set_file_and_dir_locals(file_name)
26
+ return if !target
27
+ $_file_temp = File.expand_path(file_name)
28
+ $_dir_temp = File.dirname($_file_temp)
29
+ target.eval("_file_ = $_file_temp")
30
+ target.eval("_dir_ = $_dir_temp")
31
+ end
32
+
33
+ def add_line_numbers(lines, start_line)
34
+ line_array = lines.each_line.to_a
35
+ line_array.each_with_index.map do |line, idx|
36
+ adjusted_index = idx + start_line
37
+ if Pry.color
38
+ cindex = CodeRay.scan("#{adjusted_index}", :ruby).term
39
+ "#{cindex}: #{line}"
40
+ else
41
+ "#{idx}: #{line}"
42
+ end
43
+ end.join
44
+ end
45
+
46
+ # if start_line is not false then add line numbers starting with start_line
47
+ def render_output(should_flood, start_line, doc)
48
+ if start_line
49
+ doc = add_line_numbers(doc, start_line)
50
+ end
51
+
52
+ if should_flood
53
+ output.puts doc
54
+ else
55
+ stagger_output(doc)
56
+ end
57
+ end
58
+
59
+ def check_for_dynamically_defined_method(meth)
60
+ file, _ = meth.source_location
61
+ if file =~ /(\(.*\))|<.*>/
62
+ raise "Cannot retrieve source for dynamically defined method."
63
+ end
64
+ end
65
+
66
+ def remove_first_word(text)
67
+ text.split.drop(1).join(' ')
68
+ end
69
+
70
+ # turn off color for duration of block
71
+ def no_color(&block)
72
+ old_color_state = Pry.color
73
+ Pry.color = false
74
+ yield
75
+ ensure
76
+ Pry.color = old_color_state
77
+ end
78
+
79
+ def code_and_code_type_for(meth)
80
+ case code_type = code_type_for(meth)
81
+ when nil
82
+ return nil
83
+ when :c
84
+ code = Pry::MethodInfo.info_for(meth).source
85
+ code = strip_comments_from_c_code(code)
86
+ when :ruby
87
+ code = strip_leading_whitespace(meth.source)
88
+ set_file_and_dir_locals(meth.source_location.first)
89
+ end
90
+
91
+ [code, code_type]
92
+ end
93
+
94
+ def doc_and_code_type_for(meth)
95
+ case code_type = code_type_for(meth)
96
+ when nil
97
+ return nil
98
+ when :c
99
+ doc = Pry::MethodInfo.info_for(meth).docstring
100
+ when :ruby
101
+ doc = meth.comment
102
+ doc = strip_leading_hash_and_whitespace_from_ruby_comments(doc)
103
+ set_file_and_dir_locals(meth.source_location.first)
104
+ end
105
+
106
+ [doc, code_type]
107
+ end
108
+
109
+ def get_method_object(meth_name, target, options)
110
+ if !meth_name
111
+ return nil
112
+ end
113
+
114
+ if options[:M]
115
+ target.eval("instance_method(:#{meth_name})")
116
+ elsif options[:m]
117
+ target.eval("method(:#{meth_name})")
118
+ else
119
+ begin
120
+ target.eval("instance_method(:#{meth_name})")
121
+ rescue
122
+ begin
123
+ target.eval("method(:#{meth_name})")
124
+ rescue
125
+ return nil
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ def make_header(meth, code_type, content)
132
+ num_lines = "Number of lines: #{bold(content.each_line.count.to_s)}"
133
+ case code_type
134
+ when :ruby
135
+ file, line = meth.source_location
136
+ "\n#{bold('From:')} #{file} @ line #{line}:\n#{num_lines}\n\n"
137
+ else
138
+ file = Pry::MethodInfo.info_for(meth).file
139
+ "\n#{bold('From:')} #{file} in Ruby Core (C Method):\n#{num_lines}\n\n"
140
+ end
141
+ end
142
+
143
+ def is_a_c_method?(meth)
144
+ meth.source_location.nil?
145
+ end
146
+
147
+ def should_use_pry_doc?(meth)
148
+ Pry.has_pry_doc && is_a_c_method?(meth)
149
+ end
150
+
151
+ def code_type_for(meth)
152
+ # only C methods
153
+ if should_use_pry_doc?(meth)
154
+ info = Pry::MethodInfo.info_for(meth)
155
+ if info && info.source
156
+ code_type = :c
157
+ else
158
+ output.puts "Cannot find C method: #{meth.name}"
159
+ code_type = nil
160
+ end
161
+ else
162
+ if is_a_c_method?(meth)
163
+ output.puts "Cannot locate this method: #{meth.name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
164
+ code_type = nil
165
+ else
166
+ check_for_dynamically_defined_method(meth)
167
+ code_type = :ruby
168
+ end
169
+ end
170
+ code_type
171
+ end
172
+
173
+ def file_map
174
+ {
175
+ [".c", ".h"] => :c,
176
+ [".cpp", ".hpp", ".cc", ".h", "cxx"] => :cpp,
177
+ [".rb", "Rakefile", ".irbrc", ".gemspec", ".pryrc"] => :ruby,
178
+ ".py" => :python,
179
+ ".diff" => :diff,
180
+ ".css" => :css,
181
+ ".html" => :html,
182
+ [".yaml", ".yml"] => :yaml,
183
+ ".xml" => :xml,
184
+ ".php" => :php,
185
+ ".js" => :javascript,
186
+ ".java" => :java,
187
+ ".rhtml" => :rhtml,
188
+ ".json" => :json
189
+ }
190
+ end
191
+
192
+ def syntax_highlight_by_file_type_or_specified(contents, file_name, file_type)
193
+ _, language_detected = file_map.find do |k, v|
194
+ Array(k).any? do |matcher|
195
+ matcher == File.extname(file_name) || matcher == File.basename(file_name)
196
+ end
197
+ end
198
+
199
+ language_detected = file_type if file_type
200
+ CodeRay.scan(contents, language_detected).term
201
+ end
202
+
203
+ # convert negative line numbers to positive by wrapping around
204
+ # last line (as per array indexing with negative numbers)
205
+ def normalized_line_number(line_number, total_lines)
206
+ line_number < 0 ? line_number + total_lines : line_number
207
+ end
208
+
209
+ # returns the file content between the lines and the normalized
210
+ # start and end line numbers.
211
+ def read_between_the_lines(file_name, start_line, end_line)
212
+ content = File.read(File.expand_path(file_name))
213
+ lines_array = content.each_line.to_a
214
+
215
+ [lines_array[start_line..end_line].join, normalized_line_number(start_line, lines_array.size),
216
+ normalized_line_number(end_line, lines_array.size)]
217
+ end
218
+
219
+ # documentation related helpers
220
+ def strip_color_codes(str)
221
+ str.gsub(/\e\[.*?(\d)+m/, '')
222
+ end
223
+
224
+ def process_rdoc(comment, code_type)
225
+ comment = comment.dup
226
+ comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
227
+ gsub(/<em>(?:\s*\n)?(.*?)\s*<\/em>/m) { Pry.color ? "\e[32m#{$1}\e[0m": $1 }.
228
+ gsub(/<i>(?:\s*\n)?(.*?)\s*<\/i>/m) { Pry.color ? "\e[34m#{$1}\e[0m" : $1 }.
229
+ gsub(/\B\+(\w*?)\+\B/) { Pry.color ? "\e[32m#{$1}\e[0m": $1 }.
230
+ gsub(/((?:^[ \t]+.+(?:\n+|\Z))+)/) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
231
+ gsub(/`(?:\s*\n)?(.*?)\s*`/) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }
232
+ end
233
+
234
+ def process_yardoc_tag(comment, tag)
235
+ in_tag_block = nil
236
+ output = comment.lines.map do |v|
237
+ if in_tag_block && v !~ /^\S/
238
+ strip_color_codes(strip_color_codes(v))
239
+ elsif in_tag_block
240
+ in_tag_block = false
241
+ v
242
+ else
243
+ in_tag_block = true if v =~ /^@#{tag}/
244
+ v
245
+ end
246
+ end.join
247
+ end
248
+
249
+ def process_yardoc(comment)
250
+ yard_tags = ["param", "return", "option", "yield", "attr", "attr_reader", "attr_writer",
251
+ "deprecate", "example"]
252
+ (yard_tags - ["example"]).inject(comment) { |a, v| process_yardoc_tag(a, v) }.
253
+ gsub(/^@(#{yard_tags.join("|")})/) { Pry.color ? "\e[33m#{$1}\e[0m": $1 }
254
+ end
255
+
256
+ def process_comment_markup(comment, code_type)
257
+ process_yardoc process_rdoc(comment, code_type)
258
+ end
259
+
260
+ # strip leading whitespace but preserve indentation
261
+ def strip_leading_whitespace(text)
262
+ return text if text.empty?
263
+ leading_spaces = text.lines.first[/^(\s+)/, 1]
264
+ text.gsub(/^#{leading_spaces}/, '')
265
+ end
266
+
267
+ def strip_leading_hash_and_whitespace_from_ruby_comments(comment)
268
+ comment = comment.dup
269
+ comment.gsub!(/\A\#+?$/, '')
270
+ comment.gsub!(/^\s*#/, '')
271
+ strip_leading_whitespace(comment)
272
+ end
273
+
274
+ def strip_comments_from_c_code(code)
275
+ code.sub /\A\s*\/\*.*?\*\/\s*/m, ''
276
+ end
277
+
278
+ def prompt(message, options="Yn")
279
+ opts = options.scan(/./)
280
+ optstring = opts.join("/") # case maintained
281
+ defaults = opts.select{|o| o.upcase == o }
282
+ opts = opts.map{|o| o.downcase}
283
+
284
+ raise "Error: Too many default values for the prompt: #{default.inspect}" if defaults.size > 1
285
+
286
+ default = defaults.first
287
+
288
+ loop do
289
+ response = Pry.input.readline("#{message} (#{optstring}) ").downcase
290
+ case response
291
+ when *opts
292
+ return response
293
+ when ""
294
+ return default.downcase
295
+ else
296
+ output.puts " |_ Invalid option: #{response.inspect}. Try again."
297
+ end
298
+ end
299
+ end
300
+
301
+ end
302
+ end
303
+ end
@@ -0,0 +1,174 @@
1
+ require 'forwardable'
2
+
3
+ class Pry
4
+ class CommandProcessor
5
+ SYSTEM_COMMAND_DELIMITER = "."
6
+ SYSTEM_COMMAND_REGEX = /^#{Regexp.escape(SYSTEM_COMMAND_DELIMITER)}(.*)/
7
+
8
+ extend Forwardable
9
+
10
+ attr_accessor :pry_instance
11
+
12
+ def initialize(pry_instance)
13
+ @pry_instance = pry_instance
14
+ end
15
+
16
+ def_delegators :@pry_instance, :commands, :nesting, :output
17
+
18
+ # Is the string a command valid?
19
+ # @param [String] val The string passed in from the Pry prompt.
20
+ # @return [Boolean] Whether the string is a valid command.
21
+ def valid_command?(val)
22
+ system_command?(val) || pry_command?(val)
23
+ end
24
+
25
+ # Is the string a valid system command?
26
+ # @param [String] val The string passed in from the Pry prompt.
27
+ # @return [Boolean] Whether the string is a valid system command.
28
+ def system_command?(val)
29
+ !!(SYSTEM_COMMAND_REGEX =~ val)
30
+ end
31
+
32
+ # Is the string a valid pry command?
33
+ # A Pry command is a command that is not a system command.
34
+ # @param [String] val The string passed in from the Pry prompt.
35
+ # @return [Boolean] Whether the string is a valid Pry command.
36
+ def pry_command?(val)
37
+ !!command_matched(val).first
38
+ end
39
+
40
+ # Revaluate the string (str) and perform interpolation.
41
+ # @param [String] str The string to reevaluate with interpolation.
42
+ # @param [Binding] target The context where the string should be
43
+ # reevaluated in.
44
+ # @return [String] The reevaluated string with interpolations
45
+ # applied (if any).
46
+ def interpolate_string(str, target)
47
+ dumped_str = str.dump
48
+ dumped_str.gsub!(/\\\#\{/, '#{')
49
+ target.eval(dumped_str)
50
+ end
51
+
52
+ # Execute a given system command.
53
+ # The commands first have interpolation applied against the
54
+ # `target` context.
55
+ # All system command are forwarded to a shell. Note that the `cd`
56
+ # command is special-cased and is converted internallly to a `Dir.chdir`
57
+ # @param [String] val The system command to execute.
58
+ # @param [Binding] target The context in which to perform string interpolation.
59
+ def execute_system_command(val, target)
60
+ SYSTEM_COMMAND_REGEX =~ val
61
+ cmd = interpolate_string($1, target)
62
+
63
+ if cmd =~ /^cd\s+(.+)/i
64
+ begin
65
+ @@cd_history ||= []
66
+ if $1 == "-"
67
+ dest = @@cd_history.pop || Dir.pwd
68
+ else
69
+ dest = File.expand_path($1)
70
+ end
71
+
72
+ @@cd_history << Dir.pwd
73
+ Dir.chdir(dest)
74
+ rescue Errno::ENOENT
75
+ output.puts "No such directory: #{dest}"
76
+ end
77
+ else
78
+ if !system(cmd)
79
+ output.puts "Error: there was a problem executing system command: #{cmd}"
80
+ end
81
+ end
82
+
83
+ # Tick, tock, im getting rid of this shit soon.
84
+ val.replace("")
85
+ end
86
+
87
+ # Determine whether a Pry command was matched and return command data
88
+ # and argument string.
89
+ # This method should not need to be invoked directly.
90
+ # @param [String] val The line of input.
91
+ # @return [Array] The command data and arg string pair
92
+ def command_matched(val)
93
+ _, cmd_data = commands.commands.find do |name, cmd_data|
94
+ /^#{Regexp.escape(name)}(?!\S)(?:\s+(.+))?/ =~ val
95
+ end
96
+
97
+ [cmd_data, $1]
98
+ end
99
+
100
+ # Process Pry commands. Pry commands are not Ruby methods and are evaluated
101
+ # prior to Ruby expressions.
102
+ # Commands can be modified/configured by the user: see `Pry::Commands`
103
+ # This method should not need to be invoked directly - it is called
104
+ # by `Pry#r`.
105
+ # @param [String] val The current line of input.
106
+ # @param [String] eval_string The cumulative lines of input for
107
+ # multi-line input.
108
+ # @param [Binding] target The receiver of the commands.
109
+ def process_commands(val, eval_string, target)
110
+ def val.clear() replace("") end
111
+ def eval_string.clear() replace("") end
112
+
113
+ if system_command?(val)
114
+ execute_system_command(val, target)
115
+ return
116
+ end
117
+
118
+ # no command was matched, so return to caller
119
+ return if !pry_command?(val)
120
+
121
+ val.replace interpolate_string(val, target)
122
+ cmd_data, args_string = command_matched(val)
123
+
124
+ args = args_string ? Shellwords.shellwords(args_string) : []
125
+ action = cmd_data[:action]
126
+ keep_retval = cmd_data[:keep_retval]
127
+
128
+ options = {
129
+ :val => val,
130
+ :eval_string => eval_string,
131
+ :nesting => nesting,
132
+ :commands => commands.commands
133
+ }
134
+
135
+ ret_value = execute_command(target, action, options, *args)
136
+
137
+ # return value of block only if :keep_retval is true
138
+ ret_value if keep_retval
139
+ end
140
+
141
+ # Execute a Pry command.
142
+ # This method should not need to be invoked directly.
143
+ # @param [Binding] target The target of the Pry session.
144
+ # @param [Proc] action The proc that implements the command.
145
+ # @param [Hash] options The options to set on the Commands object.
146
+ # @param [Array] args The command arguments.
147
+ def execute_command(target, action, options, *args)
148
+
149
+ # set some useful methods to be used by the action blocks
150
+ commands.opts = options
151
+ commands.target = target
152
+ commands.output = output
153
+
154
+ case action.arity <=> 0
155
+ when -1
156
+
157
+ # Use instance_exec() to make the `opts` method, etc available
158
+ ret_val = commands.instance_exec(*args, &action)
159
+ when 1, 0
160
+
161
+ # ensure that we get the right number of parameters
162
+ # since 1.8.7 complains about incorrect arity (1.9.2
163
+ # doesn't care)
164
+ args_with_corrected_arity = args.values_at *0..(action.arity - 1)
165
+ ret_val = commands.instance_exec(*args_with_corrected_arity, &action)
166
+ end
167
+
168
+ # Tick, tock, im getting rid of this shit soon.
169
+ options[:val].clear
170
+
171
+ ret_val
172
+ end
173
+ end
174
+ end