pry 0.3.0 → 0.4.0pre1

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.
data/lib/pry.rb CHANGED
@@ -4,254 +4,17 @@
4
4
  direc = File.dirname(__FILE__)
5
5
 
6
6
  require "method_source"
7
+ require "readline"
7
8
  require "#{direc}/pry/version"
8
- require "#{direc}/pry/input"
9
- require "#{direc}/pry/output"
9
+ require "#{direc}/pry/hooks"
10
+ require "#{direc}/pry/print"
11
+ require "#{direc}/pry/command_base"
12
+ require "#{direc}/pry/commands"
13
+ require "#{direc}/pry/prompts"
14
+ require "#{direc}/pry/completion"
15
+ require "#{direc}/pry/core_extensions"
16
+ require "#{direc}/pry/pry_class"
17
+ require "#{direc}/pry/pry_instance"
10
18
 
11
- class Pry
12
- def self.start(target=TOPLEVEL_BINDING)
13
- new.repl(target)
14
- end
15
19
 
16
- def self.view(obj)
17
- case obj
18
- when String, Array, Hash, Symbol, nil
19
- obj.inspect
20
- else
21
- obj.to_s
22
- end
23
- end
24
20
 
25
- # class accessors
26
- class << self
27
- attr_reader :nesting
28
- attr_accessor :last_result
29
- attr_accessor :default_prompt, :wait_prompt
30
- end
31
-
32
- self.default_prompt = proc do |v, nest|
33
- if nest == 0
34
- "pry(#{Pry.view(v)})> "
35
- else
36
- "pry(#{Pry.view(v)}):#{Pry.view(nest)}> "
37
- end
38
- end
39
-
40
- self.wait_prompt = proc do |v, nest|
41
- if nest == 0
42
- "pry(#{Pry.view(v)})* "
43
- else
44
- "pry(#{Pry.view(v)}):#{Pry.view(nest)}* "
45
- end
46
- end
47
-
48
- attr_accessor :input, :output
49
- attr_accessor :default_prompt, :wait_prompt
50
- attr_reader :last_result
51
-
52
- def initialize(input = Input.new, output = Output.new)
53
- @input = input
54
- @output = output
55
-
56
- @default_prompt = Pry.default_prompt
57
- @wait_prompt = Pry.wait_prompt
58
- end
59
-
60
- @nesting = []
61
-
62
- def @nesting.level
63
- last.is_a?(Array) ? last.first : nil
64
- end
65
-
66
- def nesting
67
- self.class.nesting
68
- end
69
-
70
- def nesting=(v)
71
- self.class.nesting = v
72
- end
73
-
74
- # loop
75
- def repl(target=TOPLEVEL_BINDING)
76
- target = binding_for(target)
77
- target_self = target.eval('self')
78
- output.session_start(target_self)
79
-
80
- nesting_level = nesting.size
81
-
82
- # Make sure _ exists
83
- target.eval("_ = Pry.last_result")
84
-
85
- break_level = catch(:breakout) do
86
- nesting << [nesting.size, target_self]
87
- loop do
88
- rep(target)
89
- end
90
- end
91
-
92
- nesting.pop
93
- output.session_end(target_self)
94
-
95
- # we only enter here if :breakout has been thrown
96
- if nesting_level != break_level
97
- throw :breakout, break_level
98
- end
99
-
100
- target_self
101
- end
102
-
103
- # print
104
- def rep(target=TOPLEVEL_BINDING)
105
- target = binding_for(target)
106
- output.print re(target)
107
- end
108
-
109
- # eval
110
- def re(target=TOPLEVEL_BINDING)
111
- target = binding_for(target)
112
- Pry.last_result = target.eval r(target)
113
- target.eval("_ = Pry.last_result")
114
- rescue SystemExit => e
115
- exit
116
- rescue Exception => e
117
- e
118
- end
119
-
120
- # read
121
- def r(target=TOPLEVEL_BINDING)
122
- target = binding_for(target)
123
- eval_string = ""
124
- loop do
125
- val = input.read(prompt(eval_string, target, nesting.level))
126
- eval_string += "#{val.chomp}\n"
127
- process_commands(val, eval_string, target)
128
-
129
- break eval_string if valid_expression?(eval_string)
130
- end
131
- end
132
-
133
- def process_commands(val, eval_string, target)
134
- def eval_string.clear() replace("") end
135
-
136
- case val
137
- when "exit_program", "quit_program"
138
- output.exit_program
139
- exit
140
- when "!"
141
- output.refresh
142
- eval_string.clear
143
- when "help"
144
- output.show_help
145
- eval_string.clear
146
- when "nesting"
147
- output.show_nesting(nesting)
148
- eval_string.clear
149
- when "status"
150
- output.show_status(nesting, target)
151
- eval_string.clear
152
- when "exit_all"
153
- throw(:breakout, 0)
154
- when "exit", "quit", "back", /^cd\s*\.\./
155
- output.exit
156
- throw(:breakout, nesting.level)
157
- when "ls"
158
- output.ls(target)
159
- eval_string.clear
160
- when /^cat\s+(.+)/
161
- var = $~.captures.first
162
- output.cat(target, var)
163
- eval_string.clear
164
- when /^cd\s+(.+)/
165
- obj = $~.captures.first
166
- target.eval("#{obj}.pry")
167
- eval_string.clear
168
- when /^show_doc\s*(.+)/
169
- meth_name = ($~.captures).first
170
- doc = target.eval("method(:#{meth_name})").comment
171
- output.show_doc doc
172
- eval_string.clear
173
- when /^show_idoc\s*(.+)/
174
- meth_name = ($~.captures).first
175
- doc = target.eval("instance_method(:#{meth_name})").comment
176
- output.show_doc doc
177
- eval_string.clear
178
- when /^show_method\s*(.+)/
179
- meth_name = ($~.captures).first
180
- code = target.eval("method(:#{meth_name})").source
181
- output.show_method code
182
- eval_string.clear
183
- when /^show_instance_method\s*(.+)/, /^show_imethod\s*(.+)/
184
- meth_name = ($~.captures).first
185
- code = target.eval("instance_method(:#{meth_name})").source
186
- output.show_method code
187
- eval_string.clear
188
- when /^jump_to\s*(\d*)/
189
- break_level = ($~.captures).first.to_i
190
- output.jump_to(break_level)
191
-
192
- case break_level
193
- when nesting.level
194
- output.warn_already_at_level(nesting.level)
195
- eval_string.clear
196
- when (0...nesting.level)
197
- throw(:breakout, break_level + 1)
198
- else
199
- output.err_invalid_nest_level(break_level,
200
- nesting.level - 1)
201
- eval_string.clear
202
- end
203
- end
204
- end
205
-
206
- def prompt(eval_string, target, nest)
207
- target_self = target.eval('self')
208
-
209
- if eval_string.empty?
210
- default_prompt.call(target_self, nest)
211
- else
212
- wait_prompt.call(target_self, nest)
213
- end
214
- end
215
-
216
- if RUBY_VERSION =~ /1.9/
217
- require 'ripper'
218
-
219
- def valid_expression?(code)
220
- !!Ripper::SexpBuilder.new(code).parse
221
- end
222
-
223
- else
224
- require 'ruby_parser'
225
-
226
- def valid_expression?(code)
227
- RubyParser.new.parse(code)
228
- rescue Racc::ParseError, SyntaxError
229
- false
230
- else
231
- true
232
- end
233
-
234
- end
235
-
236
- def binding_for(target)
237
- if target.is_a?(Binding)
238
- target
239
- else
240
- if target == TOPLEVEL_BINDING.eval('self')
241
- TOPLEVEL_BINDING
242
- else
243
- target.instance_eval { binding }
244
- end
245
- end
246
- end
247
-
248
- module ObjectExtensions
249
- def pry(target=self)
250
- Pry.start(target)
251
- end
252
- end
253
- end
254
-
255
- class Object
256
- include Pry::ObjectExtensions
257
- end
@@ -0,0 +1,114 @@
1
+ class Pry
2
+
3
+ # Basic command functionality. All user-defined commands must
4
+ # inherit from this class. It provides the `command` method.
5
+ class CommandBase
6
+ class << self
7
+ attr_accessor :commands
8
+ attr_accessor :command_info
9
+ attr_accessor :opts, :output, :target
10
+
11
+ # private because we want to force function style invocation. We require
12
+ # that the location where the block is defined has the `opts`
13
+ # method in scope.
14
+ private
15
+
16
+ # Defines a new Pry command.
17
+ # @param [String, Array] names The name of the command (or array of
18
+ # command name aliases).
19
+ # @param [String] description A description of the command.
20
+ # @yield The action to perform. The parameters in the block
21
+ # determines the parameters the command will receive. All
22
+ # parameters passed into the block will be strings. Successive
23
+ # command parameters are separated by whitespace at the Pry prompt.
24
+ # @example
25
+ # class MyCommands < Pry::CommandBase
26
+ # command "greet", "Greet somebody" do |name|
27
+ # puts "Good afternoon #{name.capitalize}!"
28
+ # end
29
+ # end
30
+ #
31
+ # # From pry:
32
+ # # pry(main)> _pry_.commands = MyCommands
33
+ # # pry(main)> greet john
34
+ # # Good afternoon John!
35
+ # # pry(main)> help greet
36
+ # # Greet somebody
37
+ def command(names, description="No description.", &block)
38
+ @commands ||= {}
39
+
40
+ Array(names).each do |name|
41
+ commands[name] = { :description => description, :action => block }
42
+ end
43
+ end
44
+
45
+ # Delete a command or an array of commands.
46
+ # Useful when inheriting from another command set and pruning
47
+ # those commands down to the ones you want.
48
+ # @param [Array<String>] names The command name or array
49
+ # of command names you want to delete
50
+ # @example Deleteing inherited commands
51
+ # class MyCommands < Pry::Commands
52
+ # delete "show_method", "show_imethod", "show_doc", "show_idoc"
53
+ # end
54
+ # Pry.commands = MyCommands
55
+ def delete(*names)
56
+ names.each { |name| commands.delete(name) }
57
+ end
58
+
59
+ # Execute a command (this enables commands to call other commands).
60
+ # @param [String] name The command to execute
61
+ # @param [Array] args The parameters to pass to the command.
62
+ # @example Wrap one command with another
63
+ # class MyCommands < Pry::Commands
64
+ # command "ls2" do
65
+ # output.puts "before ls"
66
+ # run "ls"
67
+ # output.puts "after ls"
68
+ # end
69
+ # end
70
+ def run(name, *args)
71
+ action = opts[:commands][name][:action]
72
+ instance_exec(*args, &action)
73
+ end
74
+
75
+ # Import commands from another command object.
76
+ # @param [Pry::CommandBase] klass The class to import from (must
77
+ # be a subclass of `Pry::CommandBase`)
78
+ # @param [Array<String>] names The commands to import.
79
+ # @example
80
+ # class MyCommands < Pry::CommandBase
81
+ # import_from Pry::Commands, "ls", "show_method", "cd"
82
+ # end
83
+ def import_from(klass, *names)
84
+ imported_hash = Hash[klass.commands.select { |k, v| names.include?(k) }]
85
+ commands.merge!(imported_hash)
86
+ end
87
+ end
88
+
89
+ command "help", "This menu." do |cmd|
90
+ command_info = opts[:commands]
91
+ param = cmd
92
+
93
+ if !param
94
+ output.puts "Command list:"
95
+ output.puts "--"
96
+ command_info.each do |k, data|
97
+ output.puts "#{k}".ljust(18) + data[:description] if !data[:description].empty?
98
+ end
99
+ else
100
+ if command_info[param]
101
+ output.puts command_info[param][:description]
102
+ else
103
+ output.puts "No info for command: #{param}"
104
+ end
105
+ end
106
+ end
107
+
108
+ # Ensures that commands can be inherited
109
+ def self.inherited(klass)
110
+ klass.commands = commands.dup
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,115 @@
1
+ direc = File.dirname(__FILE__)
2
+ require "#{direc}/command_base"
3
+
4
+ class Pry
5
+
6
+ # Default commands used by Pry.
7
+ class Commands < CommandBase
8
+
9
+ command "!", "Refresh the REPL" do
10
+ output.puts "Refreshed REPL"
11
+ opts[:eval_string].clear
12
+ end
13
+
14
+ command "!pry", "Start a Pry session on current self; this even works mid-expression." do
15
+ Pry.start(target)
16
+ end
17
+
18
+ command ["exit_program", "quit_program"], "End the current program." do
19
+ exit
20
+ end
21
+
22
+ command "nesting", "Show nesting information." do
23
+ out = output
24
+ nesting = opts[:nesting]
25
+
26
+ out.puts "Nesting status:"
27
+ out.puts "--"
28
+ nesting.each do |level, obj|
29
+ if level == 0
30
+ out.puts "#{level}. #{Pry.view(obj)} (Pry top level)"
31
+ else
32
+ out.puts "#{level}. #{Pry.view(obj)}"
33
+ end
34
+ end
35
+ end
36
+
37
+ command "status", "Show status information." do
38
+ out = output
39
+ nesting = opts[:nesting]
40
+
41
+ out.puts "Status:"
42
+ out.puts "--"
43
+ out.puts "Receiver: #{Pry.view(target.eval('self'))}"
44
+ out.puts "Nesting level: #{nesting.level}"
45
+ out.puts "Local variables: #{Pry.view(target.eval('local_variables'))}"
46
+ out.puts "Pry instance: #{Pry.active_instance}"
47
+ out.puts "Last result: #{Pry.view(Pry.last_result)}"
48
+ end
49
+
50
+ command "exit_all", "End all nested Pry sessions." do
51
+ throw(:breakout, 0)
52
+ end
53
+
54
+ command "ls", "Show the list of vars in the current scope." do
55
+ output.puts "#{Pry.view(target.eval('local_variables + instance_variables'))}"
56
+ end
57
+
58
+ command "cat", "Show output of <var>.inspect." do |obj|
59
+ out = output
60
+ out.puts target.eval("#{obj}.inspect")
61
+ end
62
+
63
+ command "cd", "Start a Pry session on <var> (use `cd ..` to go back)" do |obj|
64
+ throw(:breakout, opts[:nesting].level) if obj == ".."
65
+ target.eval("#{obj}.pry")
66
+ end
67
+
68
+ command "show_doc", "Show the comments above <methname>" do |meth_name|
69
+ doc = target.eval("method(:#{meth_name})").comment
70
+ output.puts doc
71
+ end
72
+
73
+ command "show_idoc", "Show the comments above instance method <methname>" do |meth_name|
74
+ doc = target.eval("instance_method(:#{meth_name})").comment
75
+ output.puts doc
76
+ end
77
+
78
+ command "show_method", "Show sourcecode for method <methname>." do |meth_name|
79
+ doc = target.eval("method(:#{meth_name})").source
80
+ output.puts doc
81
+ end
82
+
83
+ command "show_imethod", "Show sourcecode for instance method <methname>." do |meth_name|
84
+ doc = target.eval("instance_method(:#{meth_name})").source
85
+ output.puts doc
86
+ end
87
+
88
+ command "jump_to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
89
+ break_level = break_level.to_i
90
+ nesting = opts[:nesting]
91
+
92
+ case break_level
93
+ when nesting.level
94
+ output.puts "Already at nesting level #{nesting.level}"
95
+ when (0...nesting.level)
96
+ throw(:breakout, break_level + 1)
97
+ else
98
+ max_nest_level = nesting.level - 1
99
+ output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
100
+ end
101
+ end
102
+
103
+ command "ls_methods", "List all methods defined on class of receiver." do
104
+ output.puts "#{Pry.view(target.eval('public_methods(false) + private_methods(false) + protected_methods(false)'))}"
105
+ end
106
+
107
+ command "ls_imethods", "List all instance methods defined on class of receiver." do
108
+ output.puts "#{Pry.view(target.eval('public_instance_methods(false) + private_instance_methods(false) + protected_instance_methods(false)'))}"
109
+ end
110
+
111
+ command ["exit", "quit", "back"], "End the current Pry session." do
112
+ throw(:breakout, opts[:nesting].level)
113
+ end
114
+ end
115
+ end