pry 0.9.7.4-i386-mingw32 → 0.9.8-i386-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
@@ -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