pry 0.8.4pre1-i386-mswin32 → 0.9.0-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.
- 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
|