pry 0.8.4pre1-i386-mingw32 → 0.9.0-i386-mingw32

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 (60) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG +25 -6
  3. data/README.markdown +11 -4
  4. data/Rakefile +15 -19
  5. data/TODO +28 -2
  6. data/bin/pry +28 -11
  7. data/examples/example_basic.rb +2 -4
  8. data/examples/example_command_override.rb +2 -5
  9. data/examples/example_commands.rb +1 -4
  10. data/examples/example_hooks.rb +2 -5
  11. data/examples/example_image_edit.rb +4 -8
  12. data/examples/example_input.rb +1 -4
  13. data/examples/example_input2.rb +1 -4
  14. data/examples/example_output.rb +1 -4
  15. data/examples/example_print.rb +2 -5
  16. data/examples/example_prompt.rb +2 -5
  17. data/examples/helper.rb +6 -0
  18. data/lib/pry.rb +59 -3
  19. data/lib/pry/command_context.rb +10 -9
  20. data/lib/pry/command_processor.rb +51 -73
  21. data/lib/pry/command_set.rb +79 -28
  22. data/lib/pry/commands.rb +9 -123
  23. data/lib/pry/completion.rb +30 -29
  24. data/lib/pry/config.rb +100 -0
  25. data/lib/pry/default_commands/basic.rb +37 -0
  26. data/lib/pry/default_commands/context.rb +16 -15
  27. data/lib/pry/default_commands/documentation.rb +73 -54
  28. data/lib/pry/default_commands/easter_eggs.rb +1 -20
  29. data/lib/pry/default_commands/gems.rb +31 -40
  30. data/lib/pry/default_commands/input.rb +223 -15
  31. data/lib/pry/default_commands/introspection.rb +108 -73
  32. data/lib/pry/default_commands/ls.rb +25 -11
  33. data/lib/pry/default_commands/shell.rb +29 -39
  34. data/lib/pry/extended_commands/experimental.rb +17 -0
  35. data/lib/pry/extended_commands/user_command_api.rb +22 -0
  36. data/lib/pry/helpers.rb +1 -0
  37. data/lib/pry/helpers/base_helpers.rb +15 -104
  38. data/lib/pry/helpers/command_helpers.rb +96 -59
  39. data/lib/pry/helpers/text.rb +83 -0
  40. data/lib/pry/history_array.rb +105 -0
  41. data/lib/pry/plugins.rb +79 -0
  42. data/lib/pry/pry_class.rb +102 -114
  43. data/lib/pry/pry_instance.rb +123 -55
  44. data/lib/pry/version.rb +1 -1
  45. data/pry.gemspec +45 -0
  46. data/test/helper.rb +57 -7
  47. data/test/test_command_processor.rb +205 -0
  48. data/test/{test_commandset.rb → test_command_set.rb} +18 -12
  49. data/test/test_default_commands.rb +59 -0
  50. data/test/test_default_commands/test_context.rb +64 -0
  51. data/test/test_default_commands/test_documentation.rb +31 -0
  52. data/test/test_default_commands/test_gems.rb +14 -0
  53. data/test/test_default_commands/test_input.rb +327 -0
  54. data/test/test_default_commands/test_introspection.rb +155 -0
  55. data/test/test_history_array.rb +65 -0
  56. data/test/test_pry.rb +548 -313
  57. metadata +48 -15
  58. data/lib/pry/hooks.rb +0 -17
  59. data/lib/pry/print.rb +0 -16
  60. data/lib/pry/prompts.rb +0 -31
@@ -0,0 +1,83 @@
1
+ class Pry
2
+ module Helpers
3
+
4
+ # The methods defined on {Text} are available to custom commands via {Pry::CommandContext#text}.
5
+ module Text
6
+
7
+ COLORS =
8
+ {
9
+ "black" => 0,
10
+ "red" => 1,
11
+ "green" => 2,
12
+ "yellow" => 3,
13
+ "blue" => 4,
14
+ "purple" => 5,
15
+ "magenta" => 5,
16
+ "cyan" => 6,
17
+ "white" => 7
18
+ }
19
+
20
+ class << self
21
+
22
+ COLORS.each_pair do |color, value|
23
+ define_method color do |text|
24
+ Pry.color ? "\033[0;#{30+value}m#{text}\033[0m" : text.to_s
25
+ end
26
+
27
+ define_method "bright_#{color}" do |text|
28
+ Pry.color ? "\033[1;#{30+value}m#{text}\033[0m" : text.to_s
29
+ end
30
+ end
31
+
32
+ alias_method :grey, :bright_black
33
+ alias_method :gray, :bright_black
34
+
35
+
36
+ # Remove any color codes from _text_.
37
+ #
38
+ # @param [String, #to_s] text
39
+ # @return [String] _text_ stripped of any color codes.
40
+ def strip_color text
41
+ text.to_s.gsub(/\e\[.*?(\d)+m/ , '')
42
+ end
43
+
44
+ # Returns _text_ as bold text for use on a terminal.
45
+ # _Pry.color_ must be true for this method to perform any transformations.
46
+ #
47
+ # @param [String, #to_s] text
48
+ # @return [String] _text_
49
+ def bold text
50
+ Pry.color ? "\e[1m#{text}\e[0m" : text.to_s
51
+ end
52
+
53
+ # Executes _block_ with _Pry.color_ set to false.
54
+ #
55
+ # @param [Proc]
56
+ # @return [void]
57
+ def no_color &block
58
+ boolean = Pry.color
59
+ Pry.color = false
60
+ yield
61
+ ensure
62
+ Pry.color = boolean
63
+ end
64
+
65
+ # Returns _text_ in a numbered list, beginning at _offset_.
66
+ #
67
+ # @param [#each_line] text
68
+ # @param [Fixnum] offset
69
+ # @return [String]
70
+ def with_line_numbers text, offset
71
+ lines = text.each_line.to_a
72
+ lines.each_with_index.map do |line, index|
73
+ adjusted_index = index + offset
74
+ "#{self.blue adjusted_index}: #{line}"
75
+ end.join
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
83
+
@@ -0,0 +1,105 @@
1
+ class Pry
2
+ # A history array is an array to which you can only add elements. Older
3
+ # entries are removed progressively, so that the aray never contains more than
4
+ # N elements.
5
+ #
6
+ # History arrays are used by Pry to store the output of the last commands.
7
+ #
8
+ # @example
9
+ # ary = Pry::HistoryArray.new 10
10
+ # ary << 1 << 2 << 3
11
+ # ary[0] # => 1
12
+ # ary[1] # => 2
13
+ # 10.times { |n| ary << n }
14
+ # ary[0] # => nil
15
+ # ary[-1] # => 9
16
+ class HistoryArray
17
+ include Enumerable
18
+
19
+ # @param [Integer] size Maximum amount of objects in the array
20
+ def initialize(size)
21
+ @max_size = size
22
+
23
+ @hash = {}
24
+ @count = 0
25
+ end
26
+
27
+ # Pushes an object at the end of the array
28
+ # @param [Object] value Object to be added
29
+ def <<(value)
30
+ @hash[@count] = value
31
+
32
+ if @hash.size > max_size
33
+ @hash.delete(@count - max_size)
34
+ end
35
+
36
+ @count += 1
37
+
38
+ self
39
+ end
40
+
41
+ # @overload [](index)
42
+ # @param [Integer] index Index of the item to access.
43
+ # @return [Object, nil] Item at that index or nil if it has been removed.
44
+ # @overload [](index, size)
45
+ # @param [Integer] index Index of the first item to access.
46
+ # @param [Integer] size Amount of items to access
47
+ # @return [Array, nil] The selected items. Nil if index is greater than
48
+ # the size of the array.
49
+ # @overload [](range)
50
+ # @param [Range<Integer>] range Range of indices to access.
51
+ # @return [Array, nil] The selected items. Nil if index is greater than
52
+ # the size of the array.
53
+ def [](index_or_range, size = nil)
54
+ if index_or_range.is_a? Integer
55
+ index = convert_index(index_or_range)
56
+
57
+ if size
58
+ end_index = index + size
59
+ index > @count ? nil : (index...[end_index, @count].min).map do |n|
60
+ @hash[n]
61
+ end
62
+ else
63
+ @hash[index]
64
+ end
65
+ else
66
+ range = convert_range(index_or_range)
67
+ range.begin > @count ? nil : range.map { |n| @hash[n] }
68
+ end
69
+ end
70
+
71
+ # @return [Integer] Amount of objects in the array
72
+ def size
73
+ @count
74
+ end
75
+
76
+ def each
77
+ ((@count - size)...@count).each do |n|
78
+ yield @hash[n]
79
+ end
80
+ end
81
+
82
+ def to_a
83
+ ((@count - size)...@count).map { |n| @hash[n] }
84
+ end
85
+
86
+ def inspect
87
+ "#<#{self.class} size=#{size} first=#{@count - size} max_size=#{max_size}>"
88
+ end
89
+
90
+ # @return [Integer] Maximum amount of objects in the array
91
+ attr_reader :max_size
92
+
93
+ private
94
+ def convert_index(n)
95
+ n >= 0 ? n : @count + n
96
+ end
97
+
98
+ def convert_range(range)
99
+ end_index = convert_index(range.end)
100
+ end_index += 1 unless range.exclude_end?
101
+
102
+ Range.new(convert_index(range.begin), [end_index, @count].min, true)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,79 @@
1
+ class Pry
2
+ class PluginManager
3
+ PRY_PLUGIN_PREFIX = /^pry-/
4
+ PluginNotFound = Class.new(LoadError)
5
+
6
+ MessageSink = Object.new.tap { |o| def o.method_missing(*args) end }
7
+
8
+ class Plugin
9
+ attr_accessor :name, :gem_name, :enabled, :spec, :active
10
+
11
+ def initialize(name, gem_name, spec, enabled)
12
+ @name, @gem_name, @enabled, @spec = name, gem_name, enabled, spec
13
+ end
14
+
15
+ # Disable a plugin.
16
+ def disable!
17
+ self.enabled = false
18
+ end
19
+
20
+ # Enable a plugin.
21
+ def enable!
22
+ self.enabled = true
23
+ end
24
+
25
+ # Activate the plugin (require the gem).
26
+ def activate!
27
+ begin
28
+ require gem_name
29
+ rescue LoadError
30
+ raise PluginNotFound, "The plugin '#{gem_name}' was not found!"
31
+ end
32
+ self.active = true
33
+ self.enabled = true
34
+ end
35
+
36
+ alias active? active
37
+ alias enabled? enabled
38
+ end
39
+
40
+ def initialize
41
+ @plugins = []
42
+ end
43
+
44
+ # Find all installed Pry plugins and store them in an internal array.
45
+ def locate_plugins
46
+ Gem.refresh
47
+ (Gem::Specification.respond_to?(:each) ? Gem::Specification : Gem.source_index.find_name('')).each do |gem|
48
+ next if gem.name !~ PRY_PLUGIN_PREFIX
49
+ plugin_name = gem.name.split('-', 2).last
50
+ @plugins << Plugin.new(plugin_name, gem.name, gem, true) if !gem_located?(gem.name)
51
+ end
52
+ @plugins
53
+ end
54
+
55
+ # @return [Hash] A hash with all plugin names (minus the 'pry-') as
56
+ # keys and Plugin objects as values.
57
+ def plugins
58
+ h = Pry.config.plugins.strict_loading ? {} : Hash.new { MessageSink }
59
+ @plugins.each do |plugin|
60
+ h[plugin.name] = plugin
61
+ end
62
+ h
63
+ end
64
+
65
+ # Require all enabled plugins, disabled plugins are skipped.
66
+ def load_plugins
67
+ @plugins.each do |plugin|
68
+ plugin.activate! if plugin.enabled?
69
+ end
70
+ end
71
+
72
+ private
73
+ def gem_located?(gem_name)
74
+ @plugins.any? { |plugin| plugin.gem_name == gem_name }
75
+ end
76
+ end
77
+
78
+ end
79
+
@@ -1,3 +1,7 @@
1
+ require 'ostruct'
2
+ require 'forwardable'
3
+ require 'pry/config'
4
+
1
5
  # @author John Mair (banisterfiend)
2
6
  class Pry
3
7
 
@@ -6,6 +10,13 @@ class Pry
6
10
 
7
11
  # class accessors
8
12
  class << self
13
+ extend Forwardable
14
+
15
+ # convenience method
16
+ def self.delegate_accessors(delagatee, *names)
17
+ def_delegators delagatee, *names
18
+ def_delegators delagatee, *names.map { |v| "#{v}=" }
19
+ end
9
20
 
10
21
  # Get nesting data.
11
22
  # This method should not need to be accessed directly.
@@ -27,41 +38,6 @@ class Pry
27
38
  # @return [Pry] The active Pry instance.
28
39
  attr_accessor :active_instance
29
40
 
30
- # Get/Set the object to use for input by default by all Pry instances.
31
- # @return [#readline] The object to use for input by default by all
32
- # Pry instances.
33
- attr_accessor :input
34
-
35
- # Get/Set the object to use for output by default by all Pry instances.
36
- # @return [#puts] The object to use for output by default by all
37
- # Pry instances.
38
- attr_accessor :output
39
-
40
- # Get/Set the object to use for commands by default by all Pry instances.
41
- # @return [Pry::CommandBase] The object to use for commands by default by all
42
- # Pry instances.
43
- attr_accessor :commands
44
-
45
- # Get/Set the Proc to use for printing by default by all Pry
46
- # instances.
47
- # This is the 'print' component of the REPL.
48
- # @return [Proc] The Proc to use for printing by default by all
49
- # Pry instances.
50
- attr_accessor :print
51
-
52
- # @return [Proc] The Proc to use for printing exceptions by default by all
53
- # Pry instances.
54
- attr_accessor :exception_handler
55
-
56
- # Get/Set the Hash that defines Pry hooks used by default by all Pry
57
- # instances.
58
- # @return [Hash] The hooks used by default by all Pry instances.
59
- # @example
60
- # Pry.hooks :before_session => proc { puts "hello" },
61
- # :after_session => proc { puts "goodbye" }
62
- attr_accessor :hooks
63
-
64
-
65
41
  # Get/Set the Proc that defines extra Readline completions (on top
66
42
  # of the ones defined for IRB).
67
43
  # @return [Proc] The Proc that defines extra Readline completions (on top
@@ -69,49 +45,31 @@ class Pry
69
45
  # Pry.custom_completions = proc { Dir.entries('.') }
70
46
  attr_accessor :custom_completions
71
47
 
72
- # Get the array of Procs to be used for the prompts by default by
73
- # all Pry instances.
74
- # @return [Array<Proc>] The array of Procs to be used for the
75
- # prompts by default by all Pry instances.
76
- attr_accessor :prompt
77
-
78
48
  # Value returned by last executed Pry command.
79
49
  # @return [Object] The command value
80
50
  attr_accessor :cmd_ret_value
81
51
 
82
- # Determines whether colored output is enabled.
83
- # @return [Boolean]
84
- attr_accessor :color
52
+ # @return [Fixnum] The current input line.
53
+ attr_accessor :current_line
54
+
55
+ # @return [Array] The Array of evaluated expressions.
56
+ attr_accessor :line_buffer
85
57
 
86
- # Determines whether paging (of long blocks of text) is enabled.
87
- # @return [Boolean]
88
- attr_accessor :pager
58
+ # @return [String] The __FILE__ for the `eval()`. Should be "(pry)"
59
+ # by default.
60
+ attr_accessor :eval_path
89
61
 
90
- # Determines whether the rc file (~/.pryrc) should be loaded.
91
- # @return [Boolean]
92
- attr_accessor :should_load_rc
62
+ # @return [OpenStruct] Return Pry's config object.
63
+ attr_accessor :config
93
64
 
94
- # Set to true if Pry is invoked from command line using `pry` executable
95
- # @return [Boolean]
65
+ # @return [Boolean] Whether Pry was activated from the command line.
96
66
  attr_accessor :cli
97
67
 
98
- # Set to true if the pry-doc extension is loaded.
99
- # @return [Boolean]
100
- attr_accessor :has_pry_doc
101
-
102
- # The default editor to use. Defaults to $EDITOR or nano if
103
- # $EDITOR is not defined.
104
- # If `editor` is a String then that string is used as the shell
105
- # command to invoke the editor. If `editor` is callable (e.g a
106
- # Proc) then `file` and `line` are passed in as parameters and the
107
- # return value of that callable invocation is used as the exact
108
- # shell command to invoke the editor.
109
- # @example String
110
- # Pry.editor = "emacsclient"
111
- # @example Callable
112
- # Pry.editor = proc { |file, line| "emacsclient #{file} +#{line}" }
113
- # @return [String, #call]
114
- attr_accessor :editor
68
+ # plugin forwardables
69
+ def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins
70
+
71
+ delegate_accessors :@config, :input, :output, :commands, :prompt, :print, :exception_handler,
72
+ :hooks, :color, :pager, :editor, :memory_size
115
73
  end
116
74
 
117
75
  # Load the rc files given in the `Pry::RC_FILES` array.
@@ -133,25 +91,26 @@ class Pry
133
91
  # @example
134
92
  # Pry.start(Object.new, :input => MyInput.new)
135
93
  def self.start(target=TOPLEVEL_BINDING, options={})
136
- if should_load_rc && !@rc_loaded
137
- load_rc
138
- @rc_loaded = true
94
+ if initial_session?
95
+ # note these have to be loaded here rather than in pry_instance as
96
+ # we only want them loaded once per entire Pry lifetime, not
97
+ # multiple times per each new session (i.e in debugging)
98
+ load_rc if Pry.config.should_load_rc
99
+ load_plugins if Pry.config.plugins.enabled
100
+ load_history if Pry.config.history.should_load
101
+
102
+ @initial_session = false
139
103
  end
140
104
 
141
105
  new(options).repl(target)
142
106
  end
143
107
 
144
- # A custom version of `Kernel#inspect`.
108
+ # A custom version of `Kernel#pretty_inspect`.
145
109
  # This method should not need to be accessed directly.
146
110
  # @param obj The object to view.
147
111
  # @return [String] The string representation of `obj`.
148
112
  def self.view(obj)
149
- case obj
150
- when String, Hash, Array, Symbol, Exception, nil
151
- obj.inspect
152
- else
153
- obj.to_s
154
- end
113
+ obj.pretty_inspect
155
114
 
156
115
  rescue NoMethodError
157
116
  "unknown"
@@ -163,17 +122,27 @@ class Pry
163
122
  # @param max_size The maximum number of chars before clipping occurs.
164
123
  # @return [String] The string representation of `obj`.
165
124
  def self.view_clip(obj, max_size=60)
166
- if Pry.view(obj).size < max_size
167
- Pry.view(obj)
125
+ if obj.inspect.size < max_size
126
+ obj.inspect
168
127
  else
169
128
  "#<#{obj.class}:%#x>" % (obj.object_id << 1)
170
129
  end
171
130
  end
172
131
 
132
+ # Load Readline history if required.
133
+ def self.load_history
134
+ history_file = File.expand_path(Pry.config.history.file)
135
+ Readline::HISTORY.push(*File.readlines(history_file).map(&:chomp)) if File.exists?(history_file)
136
+ end
137
+
138
+ # @return [Boolean] Whether this is the first time a Pry session has
139
+ # been started since loading the Pry class.
140
+ def self.initial_session?
141
+ @initial_session
142
+ end
143
+
173
144
  # Run a Pry command from outside a session. The commands available are
174
145
  # those referenced by `Pry.commands` (the default command set).
175
- # Command output is suppresed by default, this is because the return
176
- # value (if there is one) is likely to be more useful.
177
146
  # @param [String] arg_string The Pry command (including arguments,
178
147
  # if any).
179
148
  # @param [Hash] options Optional named parameters.
@@ -181,35 +150,24 @@ class Pry
181
150
  # @option options [Object, Binding] :context The object context to run the
182
151
  # command under. Defaults to `TOPLEVEL_BINDING` (main).
183
152
  # @option options [Boolean] :show_output Whether to show command
184
- # output. Defaults to false.
153
+ # output. Defaults to true.
185
154
  # @example Run at top-level with no output.
186
155
  # Pry.run_command "ls"
187
156
  # @example Run under Pry class, returning only public methods.
188
157
  # Pry.run_command "ls -m", :context => Pry
189
158
  # @example Display command output.
190
159
  # Pry.run_command "ls -av", :show_output => true
191
- def self.run_command(arg_string, options={})
192
- name, arg_string = arg_string.split(/\s+/, 2)
193
- arg_string = "" if !arg_string
194
-
160
+ def self.run_command(command_string, options={})
195
161
  options = {
196
162
  :context => TOPLEVEL_BINDING,
197
- :show_output => false,
163
+ :show_output => true,
198
164
  :output => Pry.output,
199
165
  :commands => Pry.commands
200
166
  }.merge!(options)
201
167
 
202
- null_output = StringIO.new
168
+ output = options[:show_output] ? options[:output] : StringIO.new
203
169
 
204
- context = CommandContext.new
205
- commands = options[:commands]
206
-
207
- context.opts = {}
208
- context.output = options[:show_output] ? options[:output] : null_output
209
- context.target = Pry.binding_for(options[:context])
210
- context.command_set = commands
211
-
212
- commands.run_command(context, name, *Shellwords.shellwords(arg_string))
170
+ Pry.new(:output => output, :input => StringIO.new(command_string), :commands => options[:commands]).rep(options[:context])
213
171
  end
214
172
 
215
173
  def self.default_editor_for_platform
@@ -220,25 +178,53 @@ class Pry
220
178
  end
221
179
  end
222
180
 
181
+ def self.set_config_defaults
182
+ config.input = Readline
183
+ config.output = $stdout
184
+ config.commands = Pry::Commands
185
+ config.prompt = DEFAULT_PROMPT
186
+ config.print = DEFAULT_PRINT
187
+ config.exception_handler = DEFAULT_EXCEPTION_HANDLER
188
+ config.hooks = DEFAULT_HOOKS
189
+ config.color = true
190
+ config.pager = true
191
+ config.editor = default_editor_for_platform
192
+ config.should_load_rc = true
193
+
194
+ config.plugins ||= OpenStruct.new
195
+ config.plugins.enabled = true
196
+ config.plugins.strict_loading = true
197
+
198
+ config.history ||= OpenStruct.new
199
+ config.history.should_save = true
200
+ config.history.should_load = true
201
+ config.history.file = File.expand_path("~/.pry_history")
202
+
203
+ config.memory_size = 100
204
+ config.results_pager = true
205
+ end
206
+
223
207
  # Set all the configurable options back to their default values
224
208
  def self.reset_defaults
225
- @input = Readline
226
- @output = $stdout
227
- @commands = Pry::Commands
228
- @prompt = DEFAULT_PROMPT
229
- @print = DEFAULT_PRINT
230
- @exception_handler = DEFAULT_EXCEPTION_HANDLER
231
- @hooks = DEFAULT_HOOKS
232
- @custom_completions = DEFAULT_CUSTOM_COMPLETIONS
233
- @color = true
234
- @pager = true
235
- @should_load_rc = true
236
- @rc_loaded = false
237
- @cli = false
238
- @editor = default_editor_for_platform
209
+ set_config_defaults
210
+
211
+ @initial_session = true
212
+
213
+ self.custom_completions = DEFAULT_CUSTOM_COMPLETIONS
214
+ self.cli = false
215
+ self.current_line = 0
216
+ self.line_buffer = []
217
+ self.eval_path = "(pry)"
239
218
  end
240
219
 
241
- self.reset_defaults
220
+ # Basic initialization.
221
+ def self.init
222
+ @plugin_manager ||= PluginManager.new
223
+
224
+ self.config ||= Config.new
225
+ reset_defaults
226
+ locate_plugins
227
+ end
242
228
 
243
229
  @nesting = []
244
230
  def @nesting.level
@@ -269,3 +255,5 @@ class Pry
269
255
  end
270
256
  end
271
257
  end
258
+
259
+ Pry.init