pry 0.9.7.4-i386-mswin32 → 0.9.8-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 (65) hide show
  1. data/.gitignore +2 -3
  2. data/CHANGELOG +43 -0
  3. data/README.markdown +3 -1
  4. data/Rakefile +51 -32
  5. data/bin/pry +2 -80
  6. data/lib/pry.rb +33 -26
  7. data/lib/pry/cli.rb +152 -0
  8. data/lib/pry/code.rb +351 -0
  9. data/lib/pry/command.rb +422 -0
  10. data/lib/pry/command_set.rb +259 -129
  11. data/lib/pry/commands.rb +0 -1
  12. data/lib/pry/config.rb +43 -9
  13. data/lib/pry/default_commands/context.rb +109 -92
  14. data/lib/pry/default_commands/documentation.rb +174 -63
  15. data/lib/pry/default_commands/easter_eggs.rb +26 -2
  16. data/lib/pry/default_commands/gems.rb +65 -37
  17. data/lib/pry/default_commands/input.rb +175 -243
  18. data/lib/pry/default_commands/introspection.rb +173 -112
  19. data/lib/pry/default_commands/ls.rb +96 -114
  20. data/lib/pry/default_commands/shell.rb +175 -70
  21. data/lib/pry/helpers/base_helpers.rb +7 -2
  22. data/lib/pry/helpers/command_helpers.rb +71 -77
  23. data/lib/pry/helpers/options_helpers.rb +10 -41
  24. data/lib/pry/helpers/text.rb +24 -4
  25. data/lib/pry/history.rb +55 -17
  26. data/lib/pry/history_array.rb +2 -0
  27. data/lib/pry/hooks.rb +252 -0
  28. data/lib/pry/indent.rb +9 -5
  29. data/lib/pry/method.rb +149 -50
  30. data/lib/pry/plugins.rb +12 -4
  31. data/lib/pry/pry_class.rb +69 -26
  32. data/lib/pry/pry_instance.rb +187 -115
  33. data/lib/pry/version.rb +1 -1
  34. data/lib/pry/wrapped_module.rb +73 -0
  35. data/man/pry.1 +195 -0
  36. data/man/pry.1.html +204 -0
  37. data/man/pry.1.ronn +141 -0
  38. data/pry.gemspec +29 -32
  39. data/test/helper.rb +32 -36
  40. data/test/test_cli.rb +78 -0
  41. data/test/test_code.rb +201 -0
  42. data/test/test_command.rb +327 -0
  43. data/test/test_command_integration.rb +512 -0
  44. data/test/test_command_set.rb +338 -12
  45. data/test/test_completion.rb +1 -1
  46. data/test/test_default_commands.rb +1 -2
  47. data/test/test_default_commands/test_context.rb +27 -5
  48. data/test/test_default_commands/test_documentation.rb +20 -8
  49. data/test/test_default_commands/test_input.rb +84 -45
  50. data/test/test_default_commands/test_introspection.rb +74 -17
  51. data/test/test_default_commands/test_ls.rb +9 -36
  52. data/test/test_default_commands/test_shell.rb +240 -13
  53. data/test/test_hooks.rb +490 -0
  54. data/test/test_indent.rb +2 -0
  55. data/test/test_method.rb +60 -0
  56. data/test/test_pry.rb +29 -904
  57. data/test/test_pry_defaults.rb +380 -0
  58. data/test/test_pry_history.rb +24 -24
  59. data/test/test_syntax_checking.rb +63 -0
  60. data/test/test_wrapped_module.rb +71 -0
  61. metadata +50 -39
  62. data/lib/pry/command_context.rb +0 -53
  63. data/lib/pry/command_processor.rb +0 -181
  64. data/lib/pry/extended_commands/user_command_api.rb +0 -65
  65. data/test/test_command_processor.rb +0 -176
@@ -3,55 +3,24 @@ class Pry
3
3
  module OptionsHelpers
4
4
  module_function
5
5
 
6
- # Use Slop to parse the arguments given.
7
- #
8
- # @param [Array] args The options are stripped out by Slop.
9
- # @param [*Symbol] extras Extra features you want returned.
10
- # @param [&Block] used to add custom arguments to Slop.
11
- #
12
- # @option [Extra] :method_object Returns a method object.
13
- #
14
- # @return Slop::Options iff you don't pass any extras.
15
- # @return [Array] If you do pass extras, an array is returned where the first argument is the
16
- # Slop::Options object, and the remainder are the extras you requested in order.
17
- #
18
- def parse_options!(args, *extras, &block)
19
- opts = Slop.parse!(args) do |opt|
20
- extras.each{ |extra| send(:"add_#{extra}_options", opt) }
21
-
22
- yield opt
23
-
24
- opt.on :h, :help, "This message" do
25
- output.puts opt
26
- throw :command_done
27
- end
28
- end
29
-
30
- if extras.empty?
31
- opts
32
- else
33
- [opts] + extras.map{ |extra| send(:"process_#{extra}_options", args, opts) }
34
- end
35
- end
36
-
37
- # Add the method object options to an unused Slop instance.
38
- def add_method_object_options(opt)
6
+ # Add method options to the Slop instance
7
+ def method_options(opt)
39
8
  @method_target = target
40
9
  opt.on :M, "instance-methods", "Operate on instance methods."
41
10
  opt.on :m, :methods, "Operate on methods."
42
- opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors."
11
+ opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors.", :as => :count
43
12
  opt.on :c, :context, "Select object context to run under.", true do |context|
44
13
  @method_target = Pry.binding_for(target.eval(context))
45
14
  end
46
15
  end
47
16
 
48
- # Add the derived :method_object option to a used Slop instance.
49
- def process_method_object_options(args, opts)
50
- opts[:instance] = opts['instance-methods'] if opts.m?
51
- # TODO: de-hack when we upgrade Slop: https://github.com/injekt/slop/pull/30
52
- opts.options[:super].force_argument_value opts.options[:super].count if opts.super?
53
-
54
- get_method_or_raise(args.empty? ? nil : args.join(" "), @method_target, opts.to_hash(true))
17
+ # Get the method object parsed by the slop instance
18
+ def method_object
19
+ @method_object ||= get_method_or_raise(args.empty? ? nil : args.join(" "), @method_target,
20
+ :super => opts[:super],
21
+ :instance => opts.present?(:'instance-methods') && !opts.present?(:'methods'),
22
+ :methods => opts.present?(:'methods') && !opts.present?(:'instance-methods')
23
+ )
55
24
  end
56
25
  end
57
26
  end
@@ -1,7 +1,7 @@
1
1
  class Pry
2
2
  module Helpers
3
3
 
4
- # The methods defined on {Text} are available to custom commands via {Pry::CommandContext#text}.
4
+ # The methods defined on {Text} are available to custom commands via {Pry::Command#text}.
5
5
  module Text
6
6
 
7
7
  COLORS =
@@ -61,11 +61,23 @@ class Pry
61
61
  # @param [Proc]
62
62
  # @return [void]
63
63
  def no_color &block
64
- boolean = Pry.color
65
- Pry.color = false
64
+ boolean = Pry.config.color
65
+ Pry.config.color = false
66
66
  yield
67
67
  ensure
68
- Pry.color = boolean
68
+ Pry.config.color = boolean
69
+ end
70
+
71
+ # Executes _block_ with _Pry.config.pager_ set to false.
72
+ #
73
+ # @param [Proc]
74
+ # @return [void]
75
+ def no_pager &block
76
+ boolean = Pry.config.pager
77
+ Pry.config.pager = false
78
+ yield
79
+ ensure
80
+ Pry.config.pager = boolean
69
81
  end
70
82
 
71
83
  # Returns _text_ in a numbered list, beginning at _offset_.
@@ -81,6 +93,14 @@ class Pry
81
93
  "#{self.send(color, adjusted_index)}: #{line}"
82
94
  end.join
83
95
  end
96
+
97
+ # Returns _text_ indented by _chars_ spaces.
98
+ #
99
+ # @param [String] text
100
+ # @param [Fixnum] chars
101
+ def indent(text, chars)
102
+ text.lines.map { |l| "#{' ' * chars}#{l}" }.join
103
+ end
84
104
  end
85
105
 
86
106
  end
data/lib/pry/history.rb CHANGED
@@ -1,61 +1,99 @@
1
1
  class Pry
2
2
  # The History class is responsible for maintaining the user's input history, both
3
- # internally and within Readline::HISTORY.
3
+ # internally and within Readline.
4
4
  class History
5
+ attr_accessor :loader, :saver, :pusher, :clearer
6
+
5
7
  def initialize
6
8
  @history = []
7
9
  @saved_lines = 0
10
+ restore_default_behavior
11
+ end
12
+
13
+ # Assign the default methods for loading, saving, pushing, and clearing.
14
+ def restore_default_behavior
15
+ @loader = method(:read_from_file)
16
+ @saver = method(:write_to_file)
17
+ @pusher = method(:push_to_readline)
18
+ @clearer = method(:clear_readline)
8
19
  end
9
20
 
10
- # Loads a file's contents into the input history.
11
- # @param [String] filename
21
+ # Load the input history using `History.loader`.
12
22
  # @return [Integer] The number of lines loaded
13
- def load(filename)
14
- File.foreach(filename) do |line|
15
- Readline::HISTORY << line.chomp
23
+ def load
24
+ @loader.call do |line|
25
+ @pusher.call(line.chomp)
16
26
  @history << line.chomp
17
27
  end
18
28
  @saved_lines = @history.length
19
29
  end
20
30
 
21
- # Appends input history from this session to a file.
22
- # @param [String] filename
31
+ # Write this session's history using `History.saver`.
23
32
  # @return [Integer] The number of lines saved
24
- def save(filename)
33
+ def save
25
34
  history_to_save = @history[@saved_lines..-1]
26
- File.open(filename, 'a') do |f|
27
- history_to_save.each { |ln| f.puts ln }
28
- end
35
+ @saver.call(history_to_save)
29
36
  @saved_lines = @history.length
30
37
  history_to_save.length
31
38
  end
32
39
 
33
- # Adds a line to the input history, ignoring blank and duplicate lines.
40
+ # Add a line to the input history, ignoring blank and duplicate lines.
34
41
  # @param [String] line
35
42
  # @return [String] The same line that was passed in
36
43
  def push(line)
37
44
  unless line.empty? || (@history.last && line == @history.last)
38
- Readline::HISTORY << line
45
+ @pusher.call(line)
39
46
  @history << line
40
47
  end
41
48
  line
42
49
  end
43
50
  alias << push
44
51
 
45
- # Clears all history. Anything the user entered before this point won't be
52
+ # Clear all history. Anything the user entered before this point won't be
46
53
  # saved, but anything they put in afterwards will still be appended to the
47
54
  # history file on exit.
48
55
  def clear
49
- Readline::HISTORY.shift until Readline::HISTORY.empty?
56
+ @clearer.call
50
57
  @history = []
51
58
  @saved_lines = 0
52
59
  end
53
60
 
54
- # Returns an Array containing all stored history.
61
+ # Return an Array containing all stored history.
55
62
  # @return [Array<String>] An Array containing all lines of history loaded
56
63
  # or entered by the user in the current session.
57
64
  def to_a
58
65
  @history.dup
59
66
  end
67
+
68
+ private
69
+ # The default loader. Yields lines from `Pry.history.config.file`.
70
+ def read_from_file
71
+ history_file = File.expand_path(Pry.config.history.file)
72
+
73
+ if File.exists?(history_file)
74
+ File.foreach(history_file) { |line| yield(line) }
75
+ end
76
+ end
77
+
78
+ # The default saver. Appends the given lines to `Pry.history.config.file`.
79
+ # @param [Array<String>] lines
80
+ def write_to_file(lines)
81
+ history_file = File.expand_path(Pry.config.history.file)
82
+
83
+ File.open(history_file, 'a') do |f|
84
+ lines.each { |ln| f.puts ln }
85
+ end
86
+ end
87
+
88
+ # The default pusher. Appends the given line to Readline::HISTORY.
89
+ # @param [String] line
90
+ def push_to_readline(line)
91
+ Readline::HISTORY << line
92
+ end
93
+
94
+ # The default clearer. Clears Readline::HISTORY.
95
+ def clear_readline
96
+ Readline::HISTORY.shift until Readline::HISTORY.empty?
97
+ end
60
98
  end
61
99
  end
@@ -72,6 +72,8 @@ class Pry
72
72
  def size
73
73
  @count
74
74
  end
75
+ alias count size
76
+ alias length size
75
77
 
76
78
  def empty?
77
79
  size == 0
data/lib/pry/hooks.rb ADDED
@@ -0,0 +1,252 @@
1
+ class Pry
2
+
3
+ # Implements a hooks system for Pry. A hook is a callable that is
4
+ # associated with an event. A number of events are currently
5
+ # provided by Pry, these include: `:when_started`, `:before_session`, `:after_session`.
6
+ # A hook must have a name, and is connected with an event by the
7
+ # `Pry::Hooks#add_hook` method.
8
+ # @example Adding a hook for the `:before_session` event.
9
+ # Pry.config.hooks.add_hook(:before_session, :say_hi) do
10
+ # puts "hello"
11
+ # end
12
+ class Hooks
13
+
14
+ # Converts a hash to a `Pry::Hooks` instance. All hooks defined
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
+ instance = new
22
+ hash.each do |k, v|
23
+ instance.add_hook(k, nil, v)
24
+ end
25
+
26
+ instance
27
+ end
28
+
29
+ def initialize
30
+ @hooks = {}
31
+ end
32
+
33
+ # Ensure that duplicates have their @hooks object
34
+ def initialize_copy(orig)
35
+ hooks_dup = @hooks.dup
36
+ @hooks.each do |k, v|
37
+ hooks_dup[k] = v.dup
38
+ end
39
+
40
+ @hooks = hooks_dup
41
+ end
42
+
43
+ def hooks
44
+ @hooks
45
+ end
46
+ protected :hooks
47
+
48
+ def errors
49
+ @errors ||= []
50
+ end
51
+
52
+ # FIXME:
53
+ # This is a hack to alert people of the new API.
54
+ def [](event_name)
55
+ warn "`Pry.hooks[]` is deprecated! Please use the new `Pry::Hooks` API! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"
56
+
57
+ get_hook(event_name, nil)
58
+ end
59
+
60
+ # FIXME:
61
+ # This is a hack to alert people of the new API.
62
+ def []=(event_name, callable)
63
+ warn "`Pry.hooks[]=` is deprecated! Please use the new `Pry::Hooks` API! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"
64
+
65
+ add_hook(event_name, nil, callable)
66
+ end
67
+
68
+ # Destructively merge the contents of two `Pry:Hooks` instances.
69
+ # @param [Pry::Hooks] other The `Pry::Hooks` instance to merge
70
+ # @return [Pry:Hooks] Returns the receiver.
71
+ # @example
72
+ # hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
73
+ # Pry::Hooks.new.merge!(hooks)
74
+ def merge!(other)
75
+ @hooks.merge!(other.dup.hooks) do |key, v1, v2|
76
+ merge_arrays(v1, v2)
77
+ end
78
+
79
+ self
80
+ end
81
+
82
+ def merge_arrays(array1, array2)
83
+ uniq_keeping_last(array1 + array2, &:first)
84
+ end
85
+ private :merge_arrays
86
+
87
+ def uniq_keeping_last(input, &block)
88
+ hash, output = {}, []
89
+ input.reverse.each{ |i| hash[block[i]] ||= (output.unshift i) }
90
+ output
91
+ end
92
+ private :uniq_keeping_last
93
+
94
+ # Return a new `Pry::Hooks` instance containing a merge of the contents of two `Pry:Hooks` instances,
95
+ # @param [Pry::Hooks] other The `Pry::Hooks` instance to merge
96
+ # @return [Pry::Hooks] The new hash.
97
+ # @example
98
+ # hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
99
+ # Pry::Hooks.new.merge(hooks)
100
+ def merge(other)
101
+ self.dup.tap do |v|
102
+ v.merge!(other)
103
+ end
104
+ end
105
+
106
+ # Add a new hook to be executed for the `name` even.
107
+ # @param [Symbol] event_name The name of the event.
108
+ # @param [Symbol] hook_name The name of the hook.
109
+ # @param [#call] callable The callable.
110
+ # @yield The block to use as the callable (if `callable` parameter not provided)
111
+ # @return [Pry:Hooks] Returns the receiver.
112
+ # @example
113
+ # Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
114
+ def add_hook(event_name, hook_name, callable=nil, &block)
115
+ @hooks[event_name] ||= []
116
+
117
+ # do not allow duplicates, but allow multiple `nil` hooks
118
+ # (anonymous hooks)
119
+ if hook_exists?(event_name, hook_name) && !hook_name.nil?
120
+ raise ArgumentError, "Hook with name '#{hook_name}' already defined!"
121
+ end
122
+
123
+ if !block && !callable
124
+ raise ArgumentError, "Must provide a block or callable."
125
+ end
126
+
127
+ # ensure we only have one anonymous hook
128
+ @hooks[event_name].delete_if { |h, k| h.nil? } if hook_name.nil?
129
+
130
+ if block
131
+ @hooks[event_name] << [hook_name, block]
132
+ elsif callable
133
+ @hooks[event_name] << [hook_name, callable]
134
+ end
135
+
136
+ self
137
+ end
138
+
139
+ # Execute the list of hooks for the `event_name` event.
140
+ # @param [Symbol] event_name The name of the event.
141
+ # @param [Array] args The arguments to pass to each hook function.
142
+ # @return [Object] The return value of the last executed hook.
143
+ # @example
144
+ # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
145
+ # my_hooks.exec_hook(:before_session) #=> OUTPUT: "hi!"
146
+ def exec_hook(event_name, *args, &block)
147
+ @hooks[event_name] ||= []
148
+
149
+ # silence warnings to get rid of 1.8's "warning: multiple values
150
+ # for a block parameter" warnings
151
+ Pry::Helpers::BaseHelpers.silence_warnings do
152
+ @hooks[event_name].map do |hook_name, callable|
153
+ begin
154
+ callable.call(*args, &block)
155
+ rescue RescuableException => e
156
+ errors << e
157
+ e
158
+ end
159
+ end.last
160
+ end
161
+ end
162
+
163
+ # Return the number of hook functions registered for the `event_name` event.
164
+ # @param [Symbol] event_name The name of the event.
165
+ # @return [Fixnum] The number of hook functions for `event_name`.
166
+ # @example
167
+ # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
168
+ # my_hooks.count(:before_session) #=> 1
169
+ def hook_count(event_name)
170
+ @hooks[event_name] ||= []
171
+ @hooks[event_name].size
172
+ end
173
+
174
+ # Return a specific hook for a given event.
175
+ # @param [Symbol] event_name The name of the event.
176
+ # @param [Symbol[ hook_name The name of the hook
177
+ # @return [#call] The requested hook.
178
+ # @example
179
+ # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
180
+ # my_hooks.get_hook(:before_session, :say_hi).call #=> "hi!"
181
+ def get_hook(event_name, hook_name)
182
+ @hooks[event_name] ||= []
183
+ hook = @hooks[event_name].find { |current_hook_name, callable| current_hook_name == hook_name }
184
+ hook.last if hook
185
+ end
186
+
187
+ # Return the hash of hook names / hook functions for a
188
+ # given event. (Note that modifying the returned hash does not
189
+ # alter the hooks, use add_hook/delete_hook for that).
190
+ # @param [Symbol] event_name The name of the event.
191
+ # @return [Hash] The hash of hook names / hook functions.
192
+ # @example
193
+ # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
194
+ # my_hooks.get_hooks(:before_session) #=> {:say_hi=>#<Proc:0x00000101645e18@(pry):9>}
195
+ def get_hooks(event_name)
196
+ @hooks[event_name] ||= []
197
+ Hash[@hooks[event_name]]
198
+ end
199
+
200
+ # Delete a hook for an event.
201
+ # @param [Symbol] event_name The name of the event.
202
+ # @param [Symbol] hook_name The name of the hook.
203
+ # to delete.
204
+ # @return [#call] The deleted hook.
205
+ # @example
206
+ # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
207
+ # my_hooks.delete_hook(:before_session, :say_hi)
208
+ def delete_hook(event_name, hook_name)
209
+ @hooks[event_name] ||= []
210
+ deleted_callable = nil
211
+
212
+ @hooks[event_name].delete_if do |current_hook_name, callable|
213
+ if current_hook_name == hook_name
214
+ deleted_callable = callable
215
+ true
216
+ else
217
+ false
218
+ end
219
+ end
220
+ deleted_callable
221
+ end
222
+
223
+ # Clear all hooks functions for a given event.
224
+ # @param [String] event_name The name of the event.
225
+ # @example
226
+ # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
227
+ # my_hooks.delete_hook(:before_session)
228
+ def delete_hooks(event_name)
229
+ @hooks[event_name] = []
230
+ end
231
+
232
+ alias_method :clear, :delete_hooks
233
+
234
+ # Remove all events and hooks, clearing out the Pry::Hooks
235
+ # instance completely.
236
+ # @example
237
+ # my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
238
+ # my_hooks.clear_all
239
+ def clear_all
240
+ @hooks = {}
241
+ end
242
+
243
+ # @param [Symbol] event_name Name of the event.
244
+ # @param [Symbol] hook_name Name of the hook.
245
+ # @return [Boolean] Whether the hook by the name `hook_name`
246
+ def hook_exists?(event_name, hook_name)
247
+ !!@hooks[event_name].find { |name, _| name == hook_name }
248
+ end
249
+ private :hook_exists?
250
+
251
+ end
252
+ end