pry 0.8.4pre1-i386-mswin32 → 0.9.0-i386-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG +25 -6
- data/README.markdown +11 -4
- data/Rakefile +15 -19
- data/TODO +28 -2
- data/bin/pry +28 -11
- data/examples/example_basic.rb +2 -4
- data/examples/example_command_override.rb +2 -5
- data/examples/example_commands.rb +1 -4
- data/examples/example_hooks.rb +2 -5
- data/examples/example_image_edit.rb +4 -8
- data/examples/example_input.rb +1 -4
- data/examples/example_input2.rb +1 -4
- data/examples/example_output.rb +1 -4
- data/examples/example_print.rb +2 -5
- data/examples/example_prompt.rb +2 -5
- data/examples/helper.rb +6 -0
- data/lib/pry.rb +59 -3
- data/lib/pry/command_context.rb +10 -9
- data/lib/pry/command_processor.rb +51 -73
- data/lib/pry/command_set.rb +79 -28
- data/lib/pry/commands.rb +9 -123
- data/lib/pry/completion.rb +30 -29
- data/lib/pry/config.rb +100 -0
- data/lib/pry/default_commands/basic.rb +37 -0
- data/lib/pry/default_commands/context.rb +16 -15
- data/lib/pry/default_commands/documentation.rb +73 -54
- data/lib/pry/default_commands/easter_eggs.rb +1 -20
- data/lib/pry/default_commands/gems.rb +31 -40
- data/lib/pry/default_commands/input.rb +223 -15
- data/lib/pry/default_commands/introspection.rb +108 -73
- data/lib/pry/default_commands/ls.rb +25 -11
- data/lib/pry/default_commands/shell.rb +29 -39
- data/lib/pry/extended_commands/experimental.rb +17 -0
- data/lib/pry/extended_commands/user_command_api.rb +22 -0
- data/lib/pry/helpers.rb +1 -0
- data/lib/pry/helpers/base_helpers.rb +15 -104
- data/lib/pry/helpers/command_helpers.rb +96 -59
- data/lib/pry/helpers/text.rb +83 -0
- data/lib/pry/history_array.rb +105 -0
- data/lib/pry/plugins.rb +79 -0
- data/lib/pry/pry_class.rb +102 -114
- data/lib/pry/pry_instance.rb +123 -55
- data/lib/pry/version.rb +1 -1
- data/pry.gemspec +45 -0
- data/test/helper.rb +57 -7
- data/test/test_command_processor.rb +205 -0
- data/test/{test_commandset.rb → test_command_set.rb} +18 -12
- data/test/test_default_commands.rb +59 -0
- data/test/test_default_commands/test_context.rb +64 -0
- data/test/test_default_commands/test_documentation.rb +31 -0
- data/test/test_default_commands/test_gems.rb +14 -0
- data/test/test_default_commands/test_input.rb +327 -0
- data/test/test_default_commands/test_introspection.rb +155 -0
- data/test/test_history_array.rb +65 -0
- data/test/test_pry.rb +548 -313
- metadata +48 -15
- data/lib/pry/hooks.rb +0 -17
- data/lib/pry/print.rb +0 -16
- data/lib/pry/prompts.rb +0 -31
data/lib/pry/command_context.rb
CHANGED
@@ -4,25 +4,26 @@ class Pry
|
|
4
4
|
class CommandContext
|
5
5
|
attr_accessor :output
|
6
6
|
attr_accessor :target
|
7
|
+
attr_accessor :captures
|
8
|
+
attr_accessor :eval_string
|
9
|
+
attr_accessor :arg_string
|
7
10
|
attr_accessor :opts
|
8
11
|
attr_accessor :command_set
|
9
12
|
attr_accessor :command_processor
|
10
13
|
|
11
|
-
def run(
|
12
|
-
|
13
|
-
|
14
|
-
command_processor.
|
15
|
-
execute_system_command([name, Shellwords.join(args)].join(' '),
|
16
|
-
target)
|
17
|
-
else
|
18
|
-
command_set.run_command(self, name, *args)
|
19
|
-
end
|
14
|
+
def run(command_string, *args)
|
15
|
+
complete_string = "#{command_string} #{args.join(" ")}"
|
16
|
+
command_processor.process_commands(complete_string, eval_string, target)
|
20
17
|
end
|
21
18
|
|
22
19
|
def commands
|
23
20
|
command_set.commands
|
24
21
|
end
|
25
22
|
|
23
|
+
def text
|
24
|
+
Pry::Helpers::Text
|
25
|
+
end
|
26
|
+
|
26
27
|
include Pry::Helpers::BaseHelpers
|
27
28
|
include Pry::Helpers::CommandHelpers
|
28
29
|
end
|
@@ -2,9 +2,6 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
class Pry
|
4
4
|
class CommandProcessor
|
5
|
-
SYSTEM_COMMAND_DELIMITER = "."
|
6
|
-
SYSTEM_COMMAND_REGEX = /^#{Regexp.escape(SYSTEM_COMMAND_DELIMITER)}(.*)/
|
7
|
-
|
8
5
|
extend Forwardable
|
9
6
|
|
10
7
|
attr_accessor :pry_instance
|
@@ -15,32 +12,31 @@ class Pry
|
|
15
12
|
|
16
13
|
def_delegators :@pry_instance, :commands, :nesting, :output
|
17
14
|
|
18
|
-
# Is the string a command
|
15
|
+
# Is the string a valid command?
|
19
16
|
# @param [String] val The string passed in from the Pry prompt.
|
17
|
+
# @param [Binding] target The context where the string should be
|
18
|
+
# interpolated in.
|
20
19
|
# @return [Boolean] Whether the string is a valid command.
|
21
|
-
def valid_command?(val)
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
# Is the string a valid system command?
|
26
|
-
# @param [String] val The string passed in from the Pry prompt.
|
27
|
-
# @return [Boolean] Whether the string is a valid system command.
|
28
|
-
def system_command?(val)
|
29
|
-
!!(SYSTEM_COMMAND_REGEX =~ val)
|
20
|
+
def valid_command?(val, target=binding)
|
21
|
+
!!(command_matched(val, target)[0])
|
30
22
|
end
|
31
23
|
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# @
|
35
|
-
|
36
|
-
|
37
|
-
|
24
|
+
# Convert the object to a form that can be interpolated into a
|
25
|
+
# Regexp cleanly.
|
26
|
+
# @return [String] The string to interpolate into a Regexp
|
27
|
+
def convert_to_regex(obj)
|
28
|
+
case obj
|
29
|
+
when String
|
30
|
+
Regexp.escape(obj)
|
31
|
+
else
|
32
|
+
obj
|
33
|
+
end
|
38
34
|
end
|
39
35
|
|
40
36
|
# Revaluate the string (str) and perform interpolation.
|
41
37
|
# @param [String] str The string to reevaluate with interpolation.
|
42
38
|
# @param [Binding] target The context where the string should be
|
43
|
-
#
|
39
|
+
# interpolated in.
|
44
40
|
# @return [String] The reevaluated string with interpolations
|
45
41
|
# applied (if any).
|
46
42
|
def interpolate_string(str, target)
|
@@ -49,52 +45,34 @@ class Pry
|
|
49
45
|
target.eval(dumped_str)
|
50
46
|
end
|
51
47
|
|
52
|
-
# Execute a given system command.
|
53
|
-
# The commands first have interpolation applied against the
|
54
|
-
# `target` context.
|
55
|
-
# All system command are forwarded to a shell. Note that the `cd`
|
56
|
-
# command is special-cased and is converted internallly to a `Dir.chdir`
|
57
|
-
# @param [String] val The system command to execute.
|
58
|
-
# @param [Binding] target The context in which to perform string interpolation.
|
59
|
-
def execute_system_command(val, target)
|
60
|
-
SYSTEM_COMMAND_REGEX =~ val
|
61
|
-
cmd = interpolate_string($1, target)
|
62
|
-
|
63
|
-
if cmd =~ /^cd\s+(.+)/i
|
64
|
-
begin
|
65
|
-
@@cd_history ||= []
|
66
|
-
if $1 == "-"
|
67
|
-
dest = @@cd_history.pop || Dir.pwd
|
68
|
-
else
|
69
|
-
dest = File.expand_path($1)
|
70
|
-
end
|
71
|
-
|
72
|
-
@@cd_history << Dir.pwd
|
73
|
-
Dir.chdir(dest)
|
74
|
-
rescue Errno::ENOENT
|
75
|
-
output.puts "No such directory: #{dest}"
|
76
|
-
end
|
77
|
-
else
|
78
|
-
if !system(cmd)
|
79
|
-
output.puts "Error: there was a problem executing system command: #{cmd}"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Tick, tock, im getting rid of this shit soon.
|
84
|
-
val.replace("")
|
85
|
-
end
|
86
|
-
|
87
48
|
# Determine whether a Pry command was matched and return command data
|
88
49
|
# and argument string.
|
89
50
|
# This method should not need to be invoked directly.
|
90
51
|
# @param [String] val The line of input.
|
52
|
+
# @param [Binding] target The binding to perform string
|
53
|
+
# interpolation against.
|
91
54
|
# @return [Array] The command data and arg string pair
|
92
|
-
def command_matched(val)
|
93
|
-
_, cmd_data = commands.commands.find do |name,
|
94
|
-
|
55
|
+
def command_matched(val, target)
|
56
|
+
_, cmd_data = commands.commands.find do |name, data|
|
57
|
+
|
58
|
+
command_regex = /^#{convert_to_regex(name)}(?!\S)/
|
59
|
+
|
60
|
+
if data.options[:interpolate]
|
61
|
+
# If interpolation fails then the command cannot be matched,
|
62
|
+
# so early exit.
|
63
|
+
begin
|
64
|
+
interp_val = interpolate_string(val, target)
|
65
|
+
rescue NameError
|
66
|
+
next
|
67
|
+
end
|
68
|
+
|
69
|
+
val.replace interp_val if command_regex =~ interp_val
|
70
|
+
else
|
71
|
+
command_regex =~ val
|
72
|
+
end
|
95
73
|
end
|
96
74
|
|
97
|
-
[cmd_data,
|
75
|
+
[cmd_data, (Regexp.last_match ? Regexp.last_match.captures : nil), (Regexp.last_match ? Regexp.last_match.end(0) : nil)]
|
98
76
|
end
|
99
77
|
|
100
78
|
# Process Pry commands. Pry commands are not Ruby methods and are evaluated
|
@@ -107,30 +85,27 @@ class Pry
|
|
107
85
|
# multi-line input.
|
108
86
|
# @param [Binding] target The receiver of the commands.
|
109
87
|
def process_commands(val, eval_string, target)
|
110
|
-
def val.clear() replace("") end
|
111
|
-
def eval_string.clear() replace("") end
|
112
|
-
|
113
|
-
if system_command?(val)
|
114
|
-
execute_system_command(val, target)
|
115
|
-
return
|
116
|
-
end
|
117
88
|
|
118
89
|
# no command was matched, so return to caller
|
119
|
-
|
90
|
+
command, captures, pos = command_matched(val, target)
|
91
|
+
return if !command
|
92
|
+
arg_string = val[pos..-1]
|
120
93
|
|
121
|
-
|
122
|
-
|
94
|
+
# remove the one leading space if it exists
|
95
|
+
arg_string.slice!(0) if arg_string.start_with?(" ")
|
123
96
|
|
124
|
-
args =
|
97
|
+
args = arg_string ? Shellwords.shellwords(arg_string) : []
|
125
98
|
|
126
99
|
options = {
|
127
100
|
:val => val,
|
101
|
+
:arg_string => arg_string,
|
128
102
|
:eval_string => eval_string,
|
129
103
|
:nesting => nesting,
|
130
|
-
:commands => commands.commands
|
104
|
+
:commands => commands.commands,
|
105
|
+
:captures => captures
|
131
106
|
}
|
132
107
|
|
133
|
-
execute_command(target, command.name, options, *args)
|
108
|
+
execute_command(target, command.name, options, *(captures + args))
|
134
109
|
end
|
135
110
|
|
136
111
|
# Execute a Pry command.
|
@@ -146,6 +121,9 @@ class Pry
|
|
146
121
|
context.opts = options
|
147
122
|
context.target = target
|
148
123
|
context.output = output
|
124
|
+
context.captures = options[:captures]
|
125
|
+
context.eval_string = options[:eval_string]
|
126
|
+
context.arg_string = options[:arg_string]
|
149
127
|
context.command_set = commands
|
150
128
|
|
151
129
|
context.command_processor = self
|
@@ -153,7 +131,7 @@ class Pry
|
|
153
131
|
ret = commands.run_command(context, command, *args)
|
154
132
|
|
155
133
|
# Tick, tock, im getting rid of this shit soon.
|
156
|
-
options[:val].
|
134
|
+
options[:val].replace("")
|
157
135
|
|
158
136
|
ret
|
159
137
|
end
|
data/lib/pry/command_set.rb
CHANGED
@@ -5,7 +5,7 @@ class Pry
|
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
-
# This class used to create sets of commands. Commands can be
|
8
|
+
# This class is used to create sets of commands. Commands can be imported from
|
9
9
|
# different sets, aliased, removed, etc.
|
10
10
|
class CommandSet
|
11
11
|
class Command < Struct.new(:name, :description, :options, :block)
|
@@ -26,23 +26,21 @@ class Pry
|
|
26
26
|
args
|
27
27
|
when 1, 0
|
28
28
|
# Keep 1.8 happy
|
29
|
-
args.values_at
|
29
|
+
args.values_at 0..(arity - 1)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
include Enumerable
|
34
35
|
include Pry::Helpers::BaseHelpers
|
35
36
|
|
36
37
|
attr_reader :commands
|
37
|
-
attr_reader :name
|
38
38
|
attr_reader :helper_module
|
39
39
|
|
40
|
-
# @param [Symbol] name Name of the command set
|
41
40
|
# @param [Array<CommandSet>] imported_sets Sets which will be imported
|
42
41
|
# automatically
|
43
42
|
# @yield Optional block run to define commands
|
44
|
-
def initialize(
|
45
|
-
@name = name
|
43
|
+
def initialize(*imported_sets, &block)
|
46
44
|
@commands = {}
|
47
45
|
@helper_module = Module.new
|
48
46
|
|
@@ -53,19 +51,29 @@ class Pry
|
|
53
51
|
end
|
54
52
|
|
55
53
|
# Defines a new Pry command.
|
56
|
-
# @param [String,
|
57
|
-
#
|
54
|
+
# @param [String, Regexp] name The name of the command. Can be
|
55
|
+
# Regexp as well as String.
|
58
56
|
# @param [String] description A description of the command.
|
59
57
|
# @param [Hash] options The optional configuration parameters.
|
60
58
|
# @option options [Boolean] :keep_retval Whether or not to use return value
|
61
59
|
# of the block for return of `command` or just to return `nil`
|
62
60
|
# (the default).
|
61
|
+
# @option options [Array<String>] :requires_gem Whether the command has
|
62
|
+
# any gem dependencies, if it does and dependencies not met then
|
63
|
+
# command is disabled and a stub proc giving instructions to
|
64
|
+
# install command is provided.
|
65
|
+
# @option options [Boolean] :interpolate Whether string #{} based
|
66
|
+
# interpolation is applied to the command arguments before
|
67
|
+
# executing the command. Defaults to true.
|
68
|
+
# @option options [String] :listing The listing name of the
|
69
|
+
# command. That is the name by which the command is looked up by
|
70
|
+
# help and by show-command. Necessary for regex based commands.
|
63
71
|
# @yield The action to perform. The parameters in the block
|
64
72
|
# determines the parameters the command will receive. All
|
65
73
|
# parameters passed into the block will be strings. Successive
|
66
74
|
# command parameters are separated by whitespace at the Pry prompt.
|
67
75
|
# @example
|
68
|
-
# MyCommands = Pry::CommandSet.new
|
76
|
+
# MyCommands = Pry::CommandSet.new do
|
69
77
|
# command "greet", "Greet somebody" do |name|
|
70
78
|
# puts "Good afternoon #{name.capitalize}!"
|
71
79
|
# end
|
@@ -77,25 +85,45 @@ class Pry
|
|
77
85
|
# # Good afternoon John!
|
78
86
|
# # pry(main)> help greet
|
79
87
|
# # Greet somebody
|
80
|
-
|
81
|
-
|
88
|
+
# @example Regexp command
|
89
|
+
# MyCommands = Pry::CommandSet.new do
|
90
|
+
# command /number-(\d+)/, "number-N regex command", :listing => "number" do |num, name|
|
91
|
+
# puts "hello #{name}, nice number: #{num}"
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# # From pry:
|
96
|
+
# # pry(main)> _pry_.commands = MyCommands
|
97
|
+
# # pry(main)> number-10 john
|
98
|
+
# # hello john, nice number: 10
|
99
|
+
# # pry(main)> help number
|
100
|
+
# # number-N regex command
|
101
|
+
def command(name, description="No description.", options={}, &block)
|
82
102
|
|
83
|
-
options = {
|
103
|
+
options = {
|
104
|
+
:requires_gem => [],
|
105
|
+
:keep_retval => false,
|
106
|
+
:argument_required => false,
|
107
|
+
:interpolate => true,
|
108
|
+
:listing => name
|
109
|
+
}.merge!(options)
|
84
110
|
|
85
111
|
unless command_dependencies_met? options
|
86
112
|
gems_needed = Array(options[:requires_gem])
|
87
113
|
gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
|
88
114
|
|
89
115
|
options[:stub_info] = proc do
|
90
|
-
output.puts "\
|
91
|
-
output.puts "
|
92
|
-
output.puts "Type `install #{
|
116
|
+
output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
|
117
|
+
output.puts "-"
|
118
|
+
output.puts "Type `install #{name}` to install the required gems and activate this command."
|
93
119
|
end
|
94
120
|
end
|
95
121
|
|
96
|
-
|
97
|
-
|
98
|
-
|
122
|
+
commands[name] = Command.new(name, description, options, block)
|
123
|
+
end
|
124
|
+
|
125
|
+
def each &block
|
126
|
+
@commands.each(&block)
|
99
127
|
end
|
100
128
|
|
101
129
|
# Removes some commands from the set
|
@@ -125,7 +153,7 @@ class Pry
|
|
125
153
|
# Aliases a command
|
126
154
|
# @param [String] new_name New name of the command.
|
127
155
|
# @param [String] old_name Old name of the command.
|
128
|
-
# @
|
156
|
+
# @param [String, nil] desc New description of the command.
|
129
157
|
def alias_command(new_name, old_name, desc = nil)
|
130
158
|
commands[new_name] = commands[old_name].dup
|
131
159
|
commands[new_name].name = new_name
|
@@ -140,12 +168,17 @@ class Pry
|
|
140
168
|
# @raise [NoCommandError] If the command is not defined in this set
|
141
169
|
def run_command(context, name, *args)
|
142
170
|
context.extend helper_module
|
171
|
+
command = commands[name]
|
143
172
|
|
144
|
-
if command
|
145
|
-
command.call(context, *args)
|
146
|
-
else
|
173
|
+
if command.nil?
|
147
174
|
raise NoCommandError.new(name, self)
|
148
175
|
end
|
176
|
+
|
177
|
+
if command.options[:argument_required] && args.empty?
|
178
|
+
puts "The command '#{command.name}' requires an argument."
|
179
|
+
else
|
180
|
+
command.call context, *args
|
181
|
+
end
|
149
182
|
end
|
150
183
|
|
151
184
|
# Sets the description for a command (replacing the old
|
@@ -153,7 +186,7 @@ class Pry
|
|
153
186
|
# @param [String] name The command name.
|
154
187
|
# @param [String] description The command description.
|
155
188
|
# @example
|
156
|
-
# MyCommands = Pry::CommandSet.new
|
189
|
+
# MyCommands = Pry::CommandSet.new do
|
157
190
|
# desc "help", "help description"
|
158
191
|
# end
|
159
192
|
def desc(name, description)
|
@@ -176,8 +209,15 @@ class Pry
|
|
176
209
|
helper_module.class_eval(&block)
|
177
210
|
end
|
178
211
|
|
212
|
+
|
213
|
+
# @return [Array] The list of commands provided by the command set.
|
214
|
+
def list_commands
|
215
|
+
commands.keys
|
216
|
+
end
|
217
|
+
|
179
218
|
private
|
180
219
|
def define_default_commands
|
220
|
+
|
181
221
|
command "help", "This menu." do |cmd|
|
182
222
|
if !cmd
|
183
223
|
output.puts
|
@@ -185,13 +225,13 @@ class Pry
|
|
185
225
|
|
186
226
|
commands.each do |key, command|
|
187
227
|
if command.description && !command.description.empty?
|
188
|
-
help_text << "#{
|
228
|
+
help_text << "#{command.options[:listing]}".ljust(18) + command.description + "\n"
|
189
229
|
end
|
190
230
|
end
|
191
231
|
|
192
232
|
stagger_output(help_text)
|
193
233
|
else
|
194
|
-
if command =
|
234
|
+
if command = find_command(cmd)
|
195
235
|
output.puts command.description
|
196
236
|
else
|
197
237
|
output.puts "No info for command: #{cmd}"
|
@@ -200,7 +240,8 @@ class Pry
|
|
200
240
|
end
|
201
241
|
|
202
242
|
command "install", "Install a disabled command." do |name|
|
203
|
-
|
243
|
+
command = find_command(name)
|
244
|
+
stub_info = command.options[:stub_info]
|
204
245
|
|
205
246
|
if !stub_info
|
206
247
|
output.puts "Not a command stub. Nothing to do."
|
@@ -208,7 +249,7 @@ class Pry
|
|
208
249
|
end
|
209
250
|
|
210
251
|
output.puts "Attempting to install `#{name}` command..."
|
211
|
-
gems_to_install = Array(
|
252
|
+
gems_to_install = Array(command.options[:requires_gem])
|
212
253
|
|
213
254
|
gem_install_failed = false
|
214
255
|
gems_to_install.each do |g|
|
@@ -226,7 +267,17 @@ class Pry
|
|
226
267
|
next if gem_install_failed
|
227
268
|
|
228
269
|
Gem.refresh
|
229
|
-
|
270
|
+
gems_to_install.each do |g|
|
271
|
+
begin
|
272
|
+
require g
|
273
|
+
rescue LoadError
|
274
|
+
output.puts "Required Gem: `#{g}` installed but not found?!. Aborting command installation."
|
275
|
+
gem_install_failed = true
|
276
|
+
end
|
277
|
+
end
|
278
|
+
next if gem_install_failed
|
279
|
+
|
280
|
+
command.options.delete :stub_info
|
230
281
|
output.puts "Installation of `#{name}` successful! Type `help #{name}` for information"
|
231
282
|
end
|
232
283
|
end
|