pry 0.9.9.6pre2-i386-mswin32 → 0.9.10-i386-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. data/CHANGELOG +41 -0
  2. data/CONTRIBUTORS +27 -26
  3. data/README.markdown +4 -4
  4. data/Rakefile +2 -2
  5. data/lib/pry.rb +25 -19
  6. data/lib/pry/cli.rb +31 -10
  7. data/lib/pry/code.rb +41 -83
  8. data/lib/pry/command.rb +87 -76
  9. data/lib/pry/command_set.rb +13 -20
  10. data/lib/pry/completion.rb +139 -121
  11. data/lib/pry/config.rb +4 -0
  12. data/lib/pry/core_extensions.rb +88 -31
  13. data/lib/pry/default_commands/cd.rb +31 -8
  14. data/lib/pry/default_commands/context.rb +4 -58
  15. data/lib/pry/default_commands/easter_eggs.rb +1 -1
  16. data/lib/pry/default_commands/editing.rb +21 -14
  17. data/lib/pry/default_commands/find_method.rb +5 -7
  18. data/lib/pry/default_commands/gist.rb +187 -0
  19. data/lib/pry/default_commands/hist.rb +6 -6
  20. data/lib/pry/default_commands/input_and_output.rb +73 -129
  21. data/lib/pry/default_commands/introspection.rb +107 -52
  22. data/lib/pry/default_commands/ls.rb +1 -1
  23. data/lib/pry/default_commands/misc.rb +0 -5
  24. data/lib/pry/default_commands/whereami.rb +92 -0
  25. data/lib/pry/helpers/base_helpers.rb +6 -1
  26. data/lib/pry/helpers/command_helpers.rb +30 -9
  27. data/lib/pry/helpers/documentation_helpers.rb +7 -7
  28. data/lib/pry/helpers/options_helpers.rb +1 -1
  29. data/lib/pry/helpers/text.rb +7 -9
  30. data/lib/pry/history.rb +15 -2
  31. data/lib/pry/hooks.rb +1 -1
  32. data/lib/pry/indent.rb +17 -10
  33. data/lib/pry/method.rb +35 -19
  34. data/lib/pry/module_candidate.rb +130 -0
  35. data/lib/pry/pry_class.rb +54 -22
  36. data/lib/pry/pry_instance.rb +71 -14
  37. data/lib/pry/repl_file_loader.rb +80 -0
  38. data/lib/pry/version.rb +1 -1
  39. data/lib/pry/wrapped_module.rb +121 -142
  40. data/pry.gemspec +13 -13
  41. data/test/candidate_helper1.rb +11 -0
  42. data/test/candidate_helper2.rb +8 -0
  43. data/test/helper.rb +16 -0
  44. data/test/test_code.rb +1 -1
  45. data/test/test_command.rb +364 -270
  46. data/test/test_command_integration.rb +235 -267
  47. data/test/test_completion.rb +36 -0
  48. data/test/test_control_d_handler.rb +45 -0
  49. data/test/test_default_commands/example.erb +5 -0
  50. data/test/test_default_commands/test_cd.rb +316 -11
  51. data/test/test_default_commands/test_context.rb +143 -192
  52. data/test/test_default_commands/test_documentation.rb +81 -14
  53. data/test/test_default_commands/test_find_method.rb +10 -2
  54. data/test/test_default_commands/test_input.rb +102 -111
  55. data/test/test_default_commands/test_introspection.rb +17 -12
  56. data/test/test_default_commands/test_ls.rb +8 -6
  57. data/test/test_default_commands/test_shell.rb +18 -15
  58. data/test/test_default_commands/test_show_source.rb +170 -44
  59. data/test/test_exception_whitelist.rb +6 -2
  60. data/test/test_hooks.rb +32 -0
  61. data/test/test_input_stack.rb +19 -16
  62. data/test/test_method.rb +0 -4
  63. data/test/test_prompt.rb +60 -0
  64. data/test/test_pry.rb +23 -31
  65. data/test/test_pry_defaults.rb +75 -57
  66. data/test/test_syntax_checking.rb +12 -11
  67. data/test/test_wrapped_module.rb +103 -0
  68. metadata +72 -26
@@ -4,14 +4,14 @@ class Pry
4
4
  # This class contains methods useful for extracting
5
5
  # documentation from methods and classes.
6
6
  module DocumentationHelpers
7
- def process_rdoc(comment, code_type)
7
+ def process_rdoc(comment)
8
8
  comment = comment.dup
9
- comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
9
+ comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, :ruby).term : $1 }.
10
10
  gsub(/<em>(?:\s*\n)?(.*?)\s*<\/em>/m) { Pry.color ? "\e[1m#{$1}\e[0m": $1 }.
11
11
  gsub(/<i>(?:\s*\n)?(.*?)\s*<\/i>/m) { Pry.color ? "\e[1m#{$1}\e[0m" : $1 }.
12
12
  gsub(/\B\+(\w*?)\+\B/) { Pry.color ? "\e[32m#{$1}\e[0m": $1 }.
13
- gsub(/((?:^[ \t]+.+(?:\n+|\Z))+)/) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
14
- gsub(/`(?:\s*\n)?([^\e]*?)\s*`/) { "`#{Pry.color ? CodeRay.scan($1, code_type).term : $1}`" }
13
+ gsub(/((?:^[ \t]+.+(?:\n+|\Z))+)/) { Pry.color ? CodeRay.scan($1, :ruby).term : $1 }.
14
+ gsub(/`(?:\s*\n)?([^\e]*?)\s*`/) { "`#{Pry.color ? CodeRay.scan($1, :ruby).term : $1}`" }
15
15
  end
16
16
 
17
17
  def process_yardoc_tag(comment, tag)
@@ -31,13 +31,13 @@ class Pry
31
31
 
32
32
  def process_yardoc(comment)
33
33
  yard_tags = ["param", "return", "option", "yield", "attr", "attr_reader", "attr_writer",
34
- "deprecate", "example"]
34
+ "deprecate", "example", "raise"]
35
35
  (yard_tags - ["example"]).inject(comment) { |a, v| process_yardoc_tag(a, v) }.
36
36
  gsub(/^@(#{yard_tags.join("|")})/) { Pry.color ? "\e[33m#{$1}\e[0m": $1 }
37
37
  end
38
38
 
39
- def process_comment_markup(comment, code_type)
40
- process_yardoc process_rdoc(comment, code_type)
39
+ def process_comment_markup(comment)
40
+ process_yardoc process_rdoc(comment)
41
41
  end
42
42
 
43
43
  # @param [String] code
@@ -9,7 +9,7 @@ class Pry
9
9
  opt.on :M, "instance-methods", "Operate on instance methods."
10
10
  opt.on :m, :methods, "Operate on methods."
11
11
  opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors.", :as => :count
12
- opt.on :c, :context, "Select object context to run under.", true do |context|
12
+ opt.on :c, :context, "Select object context to run under.", :argument => true do |context|
13
13
  @method_target = Pry.binding_for(target.eval(context))
14
14
  end
15
15
  end
@@ -46,19 +46,18 @@ class Pry
46
46
  Pry.color ? "\e[1m#{text}\e[0m" : text.to_s
47
47
  end
48
48
 
49
- # Returns _text_ in the default foreground colour.
49
+ # Returns `text` in the default foreground colour.
50
50
  # Use this instead of "black" or "white" when you mean absence of colour.
51
51
  #
52
- # @param [String, #to_s]
53
- # @return [String] _text_
52
+ # @param [String, #to_s] text
53
+ # @return [String]
54
54
  def default(text)
55
55
  text.to_s
56
56
  end
57
57
  alias_method :bright_default, :bold
58
58
 
59
- # Executes _block_ with _Pry.color_ set to false.
60
- #
61
- # @param [Proc]
59
+ # Executes the block with `Pry.color` set to false.
60
+ # @yield
62
61
  # @return [void]
63
62
  def no_color &block
64
63
  boolean = Pry.config.color
@@ -68,9 +67,8 @@ class Pry
68
67
  Pry.config.color = boolean
69
68
  end
70
69
 
71
- # Executes _block_ with _Pry.config.pager_ set to false.
72
- #
73
- # @param [Proc]
70
+ # Executes the block with `Pry.config.pager` set to false.
71
+ # @yield
74
72
  # @return [void]
75
73
  def no_pager &block
76
74
  boolean = Pry.config.pager
data/lib/pry/history.rb CHANGED
@@ -4,9 +4,13 @@ class Pry
4
4
  class History
5
5
  attr_accessor :loader, :saver, :pusher, :clearer
6
6
 
7
+ # @return [Fixnum] Number of lines in history when Pry first loaded.
8
+ attr_reader :original_lines
9
+
7
10
  def initialize
8
11
  @history = []
9
12
  @saved_lines = 0
13
+ @original_lines = 0
10
14
  restore_default_behavior
11
15
  end
12
16
 
@@ -25,7 +29,7 @@ class Pry
25
29
  @pusher.call(line.chomp)
26
30
  @history << line.chomp
27
31
  end
28
- @saved_lines = @history.length
32
+ @saved_lines = @original_lines = @history.length
29
33
  end
30
34
 
31
35
  # Write this session's history using `History.saver`.
@@ -58,6 +62,15 @@ class Pry
58
62
  @saved_lines = 0
59
63
  end
60
64
 
65
+ # @return [Fixnum] The number of lines in history.
66
+ def history_line_count
67
+ @history.count
68
+ end
69
+
70
+ def session_line_count
71
+ @history.count - @original_lines
72
+ end
73
+
61
74
  # Return an Array containing all stored history.
62
75
  # @return [Array<String>] An Array containing all lines of history loaded
63
76
  # or entered by the user in the current session.
@@ -89,7 +102,7 @@ class Pry
89
102
  File.open(history_file, 'a') do |f|
90
103
  lines.each { |ln| f.puts ln }
91
104
  end
92
- rescue Errno::EACCES => error
105
+ rescue Errno::EACCES
93
106
  # We should probably create an option Pry.show_warnings?!?!?!
94
107
  warn 'Unable to write to your history file, history not saved'
95
108
  end
data/lib/pry/hooks.rb CHANGED
@@ -173,7 +173,7 @@ class Pry
173
173
 
174
174
  # Return a specific hook for a given event.
175
175
  # @param [Symbol] event_name The name of the event.
176
- # @param [Symbol[ hook_name The name of the hook
176
+ # @param [Symbol] hook_name The name of the hook
177
177
  # @return [#call] The requested hook.
178
178
  # @example
179
179
  # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
data/lib/pry/indent.rb CHANGED
@@ -17,8 +17,11 @@ class Pry
17
17
  class Indent
18
18
  include Helpers::BaseHelpers
19
19
 
20
- # String containing the spaces to be inserted before the next line.
20
+ # @return [String] String containing the spaces to be inserted before the next line.
21
21
  attr_reader :indent_level
22
+
23
+ # @return [Array<String>] The stack of open tokens.
24
+ attr_reader :stack
22
25
 
23
26
  # The amount of spaces to insert for each indent level.
24
27
  SPACES = ' '
@@ -106,8 +109,7 @@ class Pry
106
109
  # @return [String] The indented version of +input+.
107
110
  #
108
111
  def indent(input)
109
- output = ''
110
- open_tokens = OPEN_TOKENS.keys
112
+ output = ''
111
113
  prefix = indent_level
112
114
 
113
115
  input.lines.each do |line|
@@ -234,8 +236,8 @@ class Pry
234
236
 
235
237
  # Given a string of Ruby code, use CodeRay to export the tokens.
236
238
  #
237
- # @param String The Ruby to lex.
238
- # @return [Array] An Array of pairs of [token_value, token_type]
239
+ # @param [String] string The Ruby to lex
240
+ # @return [Array] An Array of pairs of [token_value, token_type]
239
241
  def tokenize(string)
240
242
  tokens = CodeRay.scan(string, :ruby)
241
243
  tokens = tokens.tokens.each_slice(2) if tokens.respond_to?(:tokens) # Coderay 1.0.0
@@ -248,7 +250,7 @@ class Pry
248
250
  # normal strings (which can't be nested) we assume that CodeRay correctly pairs
249
251
  # open-and-close delimiters so we don't bother checking what they are.
250
252
  #
251
- # @param String The token (of type :delimiter)
253
+ # @param [String] token The token (of type :delimiter)
252
254
  def track_delimiter(token)
253
255
  case token
254
256
  when /^<<-(["'`]?)(.*)\\1/
@@ -297,7 +299,7 @@ class Pry
297
299
  cols = cols.to_i
298
300
  lines = cols != 0 ? (full_line.length / cols + 1) : 1
299
301
 
300
- if defined?(Win32::Console)
302
+ if Pry::Helpers::BaseHelpers.windows_ansi?
301
303
  move_up = "\e[#{lines}F"
302
304
  move_down = "\e[#{lines}E"
303
305
  else
@@ -320,9 +322,14 @@ class Pry
320
322
  Readline.respond_to?(:get_screen_size) && Readline.get_screen_size,
321
323
 
322
324
  # Otherwise try to use the environment (this may be out of date due
323
- # to window resizing, but it better than nothing).
324
- [ENV["ROWS"], ENV["COLUMNS"]]
325
- ].detect do |(rows, cols)|
325
+ # to window resizing, but it's better than nothing).
326
+ [ENV["ROWS"], ENV["COLUMNS"],
327
+
328
+ # If the user is running within ansicon, then use the screen size
329
+ # that it reports (same caveats apply as with ROWS and COLUMNS)
330
+ ENV['ANSICON'] =~ /\((.*)x(.*)\)/ && [$2, $1]
331
+ ]
332
+ ].detect do |(_, cols)|
326
333
  cols.to_i > 0
327
334
  end
328
335
  end
data/lib/pry/method.rb CHANGED
@@ -63,7 +63,7 @@ class Pry
63
63
  #
64
64
  def from_binding(b)
65
65
  meth_name = b.eval('__method__')
66
- if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
66
+ if [:__script__, nil].include?(meth_name)
67
67
  nil
68
68
  else
69
69
  method = begin
@@ -210,7 +210,7 @@ class Pry
210
210
  # A new instance of `Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`.
211
211
  #
212
212
  # @param [::Method, UnboundMethod, Proc] method
213
- # @param [Hash] known_info, can be used to pre-cache expensive to compute stuff.
213
+ # @param [Hash] known_info Can be used to pre-cache expensive to compute stuff.
214
214
  # @return [Pry::Method]
215
215
  def initialize(method, known_info={})
216
216
  @method = method
@@ -253,17 +253,29 @@ class Pry
253
253
  code = strip_comments_from_c_code(info.source)
254
254
  end
255
255
  when :ruby
256
- if Helpers::BaseHelpers.rbx? && !pry_method?
257
- code = core_code
258
- elsif pry_method?
259
- code = Pry::Code.retrieve_complete_expression_from(Pry.line_buffer[source_line..-1])
260
- else
261
- code = @method.source
256
+ # clone of MethodSource.source_helper that knows to use our
257
+ # hacked version of source_location for rbx core methods, and
258
+ # our input buffer for methods defined in (pry)
259
+ file, line = *source_location
260
+ raise SourceNotFoundError, "Could not locate source for #{name_with_owner}!" unless file
261
+
262
+ begin
263
+ code = Pry::Code.from_file(file).expression_at(line)
264
+ rescue SyntaxError => e
265
+ raise MethodSource::SourceNotFoundError.new(e.message)
262
266
  end
263
267
  strip_leading_whitespace(code)
264
268
  end
265
269
  end
266
270
 
271
+ # Can we get the source code for this method?
272
+ # @return [Boolean]
273
+ def source?
274
+ !!source
275
+ rescue MethodSource::SourceNotFoundError
276
+ false
277
+ end
278
+
267
279
  # @return [String, nil] The documentation for the method, or `nil` if it's
268
280
  # unavailable.
269
281
  # @raise [CommandError] Raises when the method was defined in the REPL.
@@ -273,12 +285,10 @@ class Pry
273
285
  info = pry_doc_info
274
286
  info.docstring if info
275
287
  when :ruby
276
- if Helpers::BaseHelpers.rbx? && !pry_method?
277
- strip_leading_hash_and_whitespace_from_ruby_comments(core_doc)
288
+ if Helpers::BaseHelpers.rbx? && !pry_method?
289
+ strip_leading_hash_and_whitespace_from_ruby_comments(core_doc)
278
290
  elsif pry_method?
279
- # raise CommandError, "Can't view doc for a REPL-defined
280
- # method."
281
- strip_leading_hash_and_whitespace_from_ruby_comments(doc_for_pry_method)
291
+ strip_leading_hash_and_whitespace_from_ruby_comments(doc_for_pry_method)
282
292
  else
283
293
  strip_leading_hash_and_whitespace_from_ruby_comments(@method.comment)
284
294
  end
@@ -438,10 +448,10 @@ class Pry
438
448
 
439
449
  # FIXME: a very similar method to this exists on WrappedModule: extract_doc_for_candidate
440
450
  def doc_for_pry_method
441
- _, line = source_location
451
+ _, line_num = source_location
442
452
 
443
453
  buffer = ""
444
- Pry.line_buffer[0..(line - 1)].each do |line|
454
+ Pry.line_buffer[0..(line_num - 1)].each do |line|
445
455
  # Add any line that is a valid ruby comment,
446
456
  # but clear as soon as we hit a non comment line.
447
457
  if (line =~ /^\s*#/) || (line =~ /^\s*$/)
@@ -454,8 +464,8 @@ class Pry
454
464
  buffer
455
465
  end
456
466
 
457
- # @param [Class,Module] the ancestors to investigate
458
- # @return [Method] the unwrapped super-method
467
+ # @param [Class, Module] ancestors The ancestors to investigate
468
+ # @return [Method] The unwrapped super-method
459
469
  def super_using_ancestors(ancestors, times=1)
460
470
  next_owner = self.owner
461
471
  times.times do
@@ -504,8 +514,8 @@ class Pry
504
514
  #
505
515
  # @param [Object] receiver
506
516
  # @param [String] method_name
507
- def initialize(*args)
508
- @receiver, @name = *args
517
+ def initialize(receiver, method_name)
518
+ @receiver, @name = receiver, method_name
509
519
  end
510
520
 
511
521
  # Is the method undefined? (aka `Disowned`)
@@ -514,6 +524,12 @@ class Pry
514
524
  true
515
525
  end
516
526
 
527
+ # Can we get the source for this method?
528
+ # @return [Boolean] false
529
+ def source?
530
+ false
531
+ end
532
+
517
533
  # Get the hypothesized owner of the method.
518
534
  #
519
535
  # @return [Object]
@@ -0,0 +1,130 @@
1
+ require 'pry/helpers/documentation_helpers'
2
+ require 'forwardable'
3
+
4
+ class Pry
5
+ class WrappedModule
6
+
7
+ # This class represents a single candidate for a module/class definition.
8
+ # It provides access to the source, documentation, line and file
9
+ # for a monkeypatch (reopening) of a class/module.
10
+ class Candidate
11
+ extend Forwardable
12
+
13
+ # @return [String] The file where the module definition is located.
14
+ attr_reader :file
15
+
16
+ # @return [Fixnum] The line where the module definition is located.
17
+ attr_reader :line
18
+
19
+ # Methods to delegate to associated `Pry::WrappedModule instance`.
20
+ to_delegate = [:lines_for_file, :method_candidates, :name, :wrapped,
21
+ :yard_docs?, :number_of_candidates, :process_doc,
22
+ :strip_leading_whitespace]
23
+
24
+ def_delegators :@wrapper, *to_delegate
25
+ private(*to_delegate)
26
+
27
+ # @raise [Pry::CommandError] If `rank` is out of bounds.
28
+ # @param [Pry::WrappedModule] wrapper The associated
29
+ # `Pry::WrappedModule` instance that owns the candidates.
30
+ # @param [Fixnum] rank The rank of the candidate to
31
+ # retrieve. Passing 0 returns 'primary candidate' (the candidate with largest
32
+ # number of methods), passing 1 retrieves candidate with
33
+ # second largest number of methods, and so on, up to
34
+ # `Pry::WrappedModule#number_of_candidates() - 1`
35
+ def initialize(wrapper, rank)
36
+ @wrapper = wrapper
37
+
38
+ if number_of_candidates <= 0
39
+ raise CommandError, "Cannot find a definition for #{name} module!"
40
+ elsif rank > (number_of_candidates - 1)
41
+ raise CommandError, "No such module candidate. Allowed candidates range is from 0 to #{number_of_candidates - 1}"
42
+ end
43
+
44
+ @rank = rank
45
+ @file, @line = source_location
46
+ end
47
+
48
+ # @raise [Pry::CommandError] If source code cannot be found.
49
+ # @return [String] The source for the candidate, i.e the
50
+ # complete module/class definition.
51
+ def source
52
+ return @source if @source
53
+ raise CommandError, "Could not locate source for #{wrapped}!" if file.nil?
54
+
55
+ @source = strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line, number_of_lines_in_first_chunk))
56
+ end
57
+
58
+ # @raise [Pry::CommandError] If documentation cannot be found.
59
+ # @return [String] The documentation for the candidate.
60
+ def doc
61
+ return @doc if @doc
62
+ raise CommandError, "Could not locate doc for #{wrapped}!" if file.nil?
63
+
64
+ @doc = process_doc(Pry::Code.from_file(file).comment_describing(line))
65
+ end
66
+
67
+ # @return [Array, nil] A `[String, Fixnum]` pair representing the
68
+ # source location (file and line) for the candidate or `nil`
69
+ # if no source location found.
70
+ def source_location
71
+ return @source_location if @source_location
72
+
73
+ mod_type_string = wrapped.class.to_s.downcase
74
+ file, line = first_method_source_location
75
+
76
+ return nil if !file.is_a?(String)
77
+
78
+ class_regexes = [/^\s*#{mod_type_string}\s*(\w*)(::)?#{wrapped.name.split(/::/).last}/,
79
+ /^\s*(::)?#{wrapped.name.split(/::/).last}\s*?=\s*?#{wrapped.class}/,
80
+ /^\s*(::)?#{wrapped.name.split(/::/).last}\.(class|instance)_eval/]
81
+
82
+ host_file_lines = lines_for_file(file)
83
+
84
+ search_lines = host_file_lines[0..(line - 2)]
85
+ idx = search_lines.rindex { |v| class_regexes.any? { |r| r =~ v } }
86
+
87
+ @source_location = [file, idx + 1]
88
+ rescue Pry::RescuableException
89
+ nil
90
+ end
91
+
92
+ private
93
+
94
+ # This method is used by `Candidate#source_location` as a
95
+ # starting point for the search for the candidate's definition.
96
+ # @return [Array] The source location of the base method used to
97
+ # calculate the source location of the candidate.
98
+ def first_method_source_location
99
+ @first_method_source_location ||= adjusted_source_location(method_candidates[@rank].first.source_location)
100
+ end
101
+
102
+ # @return [Array] The source location of the last method in this
103
+ # candidate's module definition.
104
+ def last_method_source_location
105
+ @end_method_source_location ||= adjusted_source_location(method_candidates[@rank].last.source_location)
106
+ end
107
+
108
+ # Return the number of lines between the start of the class definition
109
+ # and the start of the last method. We use this value so we can
110
+ # quickly grab these lines from the file (without having to
111
+ # check each intervening line for validity, which is expensive) speeding up source extraction.
112
+ # @return [Fixum] Number of lines.
113
+ def number_of_lines_in_first_chunk
114
+ end_method_line = last_method_source_location.last
115
+
116
+ end_method_line - line
117
+ end
118
+
119
+ def adjusted_source_location(sl)
120
+ file, line = sl
121
+
122
+ if file && RbxPath.is_core_path?(file)
123
+ file = RbxPath.convert_path_to_full(file)
124
+ end
125
+
126
+ [file, line]
127
+ end
128
+ end
129
+ end
130
+ end