pry 0.9.8.4-i386-mingw32 → 0.9.9-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 (46) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG +26 -0
  3. data/README.markdown +3 -3
  4. data/lib/pry.rb +9 -1
  5. data/lib/pry/code.rb +93 -0
  6. data/lib/pry/command.rb +35 -22
  7. data/lib/pry/command_set.rb +97 -67
  8. data/lib/pry/config.rb +63 -10
  9. data/lib/pry/core_extensions.rb +24 -18
  10. data/lib/pry/default_commands/context.rb +72 -12
  11. data/lib/pry/default_commands/easter_eggs.rb +4 -0
  12. data/lib/pry/default_commands/editing.rb +43 -15
  13. data/lib/pry/default_commands/find_method.rb +171 -0
  14. data/lib/pry/default_commands/hist.rb +10 -6
  15. data/lib/pry/default_commands/introspection.rb +183 -30
  16. data/lib/pry/default_commands/ls.rb +77 -7
  17. data/lib/pry/default_commands/misc.rb +1 -0
  18. data/lib/pry/default_commands/navigating_pry.rb +1 -8
  19. data/lib/pry/helpers/base_helpers.rb +10 -2
  20. data/lib/pry/helpers/command_helpers.rb +23 -40
  21. data/lib/pry/helpers/documentation_helpers.rb +65 -0
  22. data/lib/pry/indent.rb +17 -4
  23. data/lib/pry/method.rb +61 -45
  24. data/lib/pry/pry_class.rb +9 -3
  25. data/lib/pry/pry_instance.rb +99 -65
  26. data/lib/pry/rbx_method.rb +2 -9
  27. data/lib/pry/version.rb +1 -1
  28. data/lib/pry/wrapped_module.rb +236 -1
  29. data/pry.gemspec +5 -5
  30. data/test/helper.rb +22 -0
  31. data/test/test_command.rb +29 -0
  32. data/test/test_command_integration.rb +193 -10
  33. data/test/test_command_set.rb +82 -17
  34. data/test/test_default_commands/test_cd.rb +16 -0
  35. data/test/test_default_commands/test_context.rb +61 -0
  36. data/test/test_default_commands/test_documentation.rb +163 -43
  37. data/test/test_default_commands/test_find_method.rb +42 -0
  38. data/test/test_default_commands/test_input.rb +32 -0
  39. data/test/test_default_commands/test_introspection.rb +50 -197
  40. data/test/test_default_commands/test_ls.rb +22 -0
  41. data/test/test_default_commands/test_show_source.rb +306 -0
  42. data/test/test_pry.rb +3 -3
  43. data/test/test_pry_defaults.rb +21 -0
  44. data/test/test_sticky_locals.rb +81 -1
  45. data/test/test_syntax_checking.rb +7 -6
  46. metadata +24 -16
data/.gitignore CHANGED
@@ -13,3 +13,4 @@ coverage/
13
13
  .rvmrc
14
14
  Gemfile.lock
15
15
  *.swp
16
+ **/*~
data/CHANGELOG CHANGED
@@ -1,3 +1,29 @@
1
+ 18/4/2012 version 0.9.9
2
+
3
+ MAJOR NEW FEATURES
4
+ * lines of input are syntax highlighted upon 'enter' keypress
5
+ * show-source command can now show class/module sourcecode (use -a to see all monkeypatches). Hard dependency on ruby18_source_location gem in MRI 1.8
6
+ * show-doc command can show class/module docs (use -a to see docs for all monkeypatches) Hard dependency on ruby18_source_location gem in MRI 1.8.
7
+ * new `find-method` command, performs a recursive search in a namespace for the existence of methods. Can find methods whose names match a regex or methods which contain provided CODE! This command is like a ruby-aware 'grep', very cool (thanks swarley)
8
+ * pry-coolline now works properly with Pry (https://github.com/pry/pry-coolline)
9
+ * alias_command method now much more powerful, e.g: alias_command "lM", "ls -M"
10
+ * `whereami` is now more intelligent, automatically showing entire sourcecode of current method if current context is a method (thanks robgleeson).
11
+
12
+ remaining items:
13
+ * fixed windows crashing bug when paging
14
+ * lines ending with \ are incomplete (kudos to fowl)
15
+ * `edit-method -n` no longer blocks (thanks misfo)s
16
+ * show instance methods of modules by default in ls
17
+ * docs for REPL defined methods can now be displayed using show-doc
18
+ * autoload ruby18_source_location on mri18, when available (https://github.com/conradirwin/ruby18_source_location)
19
+ * tab completion should work on first line now (historic bug fixed)
20
+ * :quiet => true option added to `Pry.start`, turns off whereami
21
+ * another easter egg added
22
+ * show unloaded constants in yellow for ls
23
+ * improved documentation for Pry.config options
24
+ * improved auto indentation
25
+ * JRuby: heuristics used to clean up 'ls' output (less internal methods polluting output)
26
+
1
27
  6/3/2012 version 0.9.8.4 major bugfix
2
28
  * ~/.pry_history wasnt being created (if it did not exist)! FIXED
3
29
  * `hist --save` saved colors! FIXED
data/README.markdown CHANGED
@@ -33,9 +33,9 @@ these include:
33
33
  * Gist integration
34
34
  * Navigation around state (`cd`, `ls` and friends)
35
35
  * Runtime invocation (use Pry as a developer console or debugger)
36
- * Exotic object support (BasicObject ins
37
- * tances, IClasses, ...)
38
- * A Powerful and flexible command system* Ability to view and replay history
36
+ * Exotic object support (BasicObject instances, IClasses, ...)
37
+ * A Powerful and flexible command system
38
+ * Ability to view and replay history
39
39
 
40
40
  * Many convenience commands inspired by IPython, Smalltalk and other advanced REPLs
41
41
  * A wide-range number of [plugins](https://github.com/pry/pry/wiki/Available-plugins) that provide remote sessions, full debugging functionality, and more.
data/lib/pry.rb CHANGED
@@ -9,12 +9,13 @@ require 'pry/hooks'
9
9
  class Pry
10
10
  # The default hooks - display messages when beginning and ending Pry sessions.
11
11
  DEFAULT_HOOKS = Pry::Hooks.new.add_hook(:before_session, :default) do |out, target, _pry_|
12
+ next if _pry_.quiet?
12
13
  # ensure we're actually in a method
13
14
  file = target.eval('__FILE__')
14
15
 
15
16
  # /unknown/ for rbx
16
17
  if file !~ /(\(.*\))|<.*>/ && file !~ /__unknown__/ && file != "" && file != "-e" || file == Pry.eval_path
17
- _pry_.run_command("whereami 5", "", target)
18
+ _pry_.run_command("whereami", "", target)
18
19
  end
19
20
  end
20
21
 
@@ -158,6 +159,13 @@ class Pry
158
159
  end
159
160
  end
160
161
 
162
+ if Pry::Helpers::BaseHelpers.mri_18?
163
+ begin
164
+ require 'ruby18_source_location'
165
+ rescue LoadError
166
+ end
167
+ end
168
+
161
169
  require "method_source"
162
170
  require 'shellwords'
163
171
  require "readline"
data/lib/pry/code.rb CHANGED
@@ -27,6 +27,72 @@ class Pry
27
27
  # object.
28
28
  class Code
29
29
  class << self
30
+
31
+ # Determine if a string of code is a complete Ruby expression.
32
+ # @param [String] code The code to validate.
33
+ # @return [Boolean] Whether or not the code is a complete Ruby expression.
34
+ # @raise [SyntaxError] Any SyntaxError that does not represent incompleteness.
35
+ # @example
36
+ # complete_expression?("class Hello") #=> false
37
+ # complete_expression?("class Hello; end") #=> true
38
+ def complete_expression?(str)
39
+ if defined?(Rubinius::Melbourne19) && RUBY_VERSION =~ /^1\.9/
40
+ Rubinius::Melbourne19.parse_string(str, Pry.eval_path)
41
+ elsif defined?(Rubinius::Melbourne)
42
+ Rubinius::Melbourne.parse_string(str, Pry.eval_path)
43
+ else
44
+ catch(:valid) do
45
+ Helpers::BaseHelpers.silence_warnings do
46
+ eval("BEGIN{throw :valid}\n#{str}", binding, Pry.eval_path)
47
+ end
48
+ end
49
+ end
50
+
51
+ # Assert that a line which ends with a , or \ is incomplete.
52
+ str !~ /[,\\]\s*\z/
53
+ rescue SyntaxError => e
54
+ if incomplete_user_input_exception?(e)
55
+ false
56
+ else
57
+ raise e
58
+ end
59
+ end
60
+
61
+ # Check whether the exception indicates that the user should input more.
62
+ #
63
+ # @param [SyntaxError] the exception object that was raised.
64
+ # @param [Array<String>] The stack frame of the function that executed eval.
65
+ # @return [Boolean]
66
+ #
67
+ def incomplete_user_input_exception?(ex)
68
+ case ex.message
69
+ when /unexpected (\$end|end-of-file|END_OF_FILE)/, # mri, jruby, ironruby
70
+ /unterminated (quoted string|string|regexp) meets end of file/, # "quoted string" is ironruby
71
+ /missing 'end' for/, /: expecting '[})\]]'$/, /can't find string ".*" anywhere before EOF/, /: expecting keyword_end/, /expecting kWHEN/ # rbx
72
+ true
73
+ else
74
+ false
75
+ end
76
+ end
77
+ private :incomplete_user_input_exception?
78
+
79
+ # Retrieve the first complete expression from the passed string.
80
+ #
81
+ # @param [String, Array<String>] str The string (or array of lines) to extract the complete
82
+ # expression from.
83
+ # @return [String, nil] The first complete expression, or `nil` if
84
+ # none found.
85
+ def retrieve_complete_expression_from(str_or_lines)
86
+ lines = str_or_lines.is_a?(Array) ? str_or_lines : str_or_lines.each_line.to_a
87
+
88
+ code = ""
89
+ lines.each do |v|
90
+ code << v
91
+ return code if complete_expression?(code)
92
+ end
93
+ nil
94
+ end
95
+
30
96
  # Instantiate a `Code` object containing code loaded from a file or
31
97
  # Pry's line buffer.
32
98
  #
@@ -63,6 +129,16 @@ class Pry
63
129
  new(meth.source, start_line, meth.source_type)
64
130
  end
65
131
 
132
+ # Attempt to extract the source code for module (or class) `mod`.
133
+ #
134
+ # @param [Module, Class] mod The module (or class) of interest.
135
+ # @return [Code]
136
+ def from_module(mod, start_line=nil)
137
+ mod = Pry::WrappedModule(mod)
138
+ start_line ||= mod.source_line || 1
139
+ new(mod.source, start_line, :ruby)
140
+ end
141
+
66
142
  protected
67
143
  # Guess the CodeRay type of a file from its extension, or nil if
68
144
  # unknown.
@@ -173,6 +249,23 @@ class Pry
173
249
  end
174
250
  end
175
251
 
252
+ # Take `num_lines` from `start_line`, forward or backwards
253
+ #
254
+ # @param [Fixnum] start_line
255
+ # @param [Fixnum] num_lines
256
+ # @return [Code]
257
+ def take_lines(start_line, num_lines)
258
+ if start_line >= 0
259
+ start_idx = @lines.index { |l| l.last >= start_line } || @lines.length
260
+ else
261
+ start_idx = @lines.length + start_line
262
+ end
263
+
264
+ alter do
265
+ @lines = @lines.slice(start_idx, num_lines)
266
+ end
267
+ end
268
+
176
269
  # Remove all lines except for the `lines` up to and excluding `line_num`.
177
270
  #
178
271
  # @param [Fixnum] line_num
data/lib/pry/command.rb CHANGED
@@ -14,10 +14,15 @@ class Pry
14
14
  # Properties of the command itself (as passed as arguments to
15
15
  # {CommandSet#command} or {CommandSet#create_command}).
16
16
  class << self
17
- attr_accessor :block
18
- attr_accessor :name
17
+ attr_writer :block
19
18
  attr_writer :description
20
19
  attr_writer :command_options
20
+ attr_writer :match
21
+
22
+ def match(arg=nil)
23
+ @match = arg if arg
24
+ @match
25
+ end
21
26
 
22
27
  # Define or get the command's description
23
28
  def description(arg=nil)
@@ -40,24 +45,31 @@ class Pry
40
45
  @banner = arg if arg
41
46
  @banner || description
42
47
  end
43
- end
44
48
 
49
+ def block
50
+ @block || instance_method(:process) && instance_method(:process)
51
+ end
52
+ end
45
53
 
46
54
  # Make those properties accessible to instances
47
55
  def name; self.class.name; end
56
+ def match; self.class.match; end
48
57
  def description; self.class.description; end
49
58
  def block; self.class.block; end
50
59
  def command_options; self.class.options; end
51
60
  def command_name; command_options[:listing]; end
52
61
 
53
62
  class << self
63
+ def name
64
+ super.to_s == "" ? "#<class(Pry::Command #{match.inspect})>" : super
65
+ end
54
66
  def inspect
55
- "#<class(Pry::Command #{name.inspect})>"
67
+ name
56
68
  end
57
69
 
58
70
  # Create a new command with the given properties.
59
71
  #
60
- # @param String name the name of the command
72
+ # @param String/Regex match the thing that triggers this command
61
73
  # @param String description the description to appear in {help}
62
74
  # @param Hash options behavioural options (@see {Pry::CommandSet#command})
63
75
  # @param Module helpers a module of helper functions to be included.
@@ -65,10 +77,10 @@ class Pry
65
77
  #
66
78
  # @return Class (a subclass of Pry::Command)
67
79
  #
68
- def subclass(name, description, options, helpers, &block)
80
+ def subclass(match, description, options, helpers, &block)
69
81
  klass = Class.new(self)
70
82
  klass.send(:include, helpers)
71
- klass.name = name
83
+ klass.match = match
72
84
  klass.description = description
73
85
  klass.command_options = options
74
86
  klass.block = block
@@ -115,10 +127,11 @@ class Pry
115
127
  end
116
128
 
117
129
  def command_regex
118
- prefix = convert_to_regex(Pry.config.command_prefix)
130
+ pr = defined?(Pry.config.command_prefix) ? Pry.config.command_prefix : ""
131
+ prefix = convert_to_regex(pr)
119
132
  prefix = "(?:#{prefix})?" unless options[:use_prefix]
120
133
 
121
- /^#{prefix}#{convert_to_regex(name)}(?!\S)/
134
+ /^#{prefix}#{convert_to_regex(match)}(?!\S)/
122
135
  end
123
136
 
124
137
  def convert_to_regex(obj)
@@ -180,7 +193,7 @@ class Pry
180
193
  # @example
181
194
  # run "amend-line", "5", 'puts "hello world"'
182
195
  def run(command_string, *args)
183
- complete_string = "#{command_string} #{args.join(" ")}"
196
+ complete_string = "#{command_string} #{args.join(" ")}".rstrip
184
197
  command_set.process_line(complete_string, context)
185
198
  end
186
199
 
@@ -233,12 +246,12 @@ class Pry
233
246
  # the current scope.
234
247
  # @param [String] command_name_match The name of the colliding command.
235
248
  # @param [Binding] target The current binding context.
236
- def check_for_command_name_collision(command_name_match, arg_string)
237
- collision_type = target.eval("defined?(#{command_name_match})")
249
+ def check_for_command_collision(command_match, arg_string)
250
+ collision_type = target.eval("defined?(#{command_match})")
238
251
  collision_type ||= 'local-variable' if arg_string.match(%r{\A\s*[-+*/%&|^]*=})
239
252
 
240
253
  if collision_type
241
- output.puts "#{Pry::Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_name_match}'," +
254
+ output.puts "#{Pry::Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_match}'," +
242
255
  "which conflicts with a #{collision_type}.\n\n"
243
256
  end
244
257
  rescue Pry::RescuableException
@@ -248,8 +261,8 @@ class Pry
248
261
  #
249
262
  # @param String the line of input
250
263
  # @return [
251
- # String the command name used, or portion of line that matched the command_regex
252
- # String a string of all the arguments (i.e. everything but the name)
264
+ # String the portion of the line that matched with the Command match
265
+ # String a string of all the arguments (i.e. everything but the match)
253
266
  # Array the captures caught by the command_regex
254
267
  # Array args the arguments got by splitting the arg_string
255
268
  # ]
@@ -285,9 +298,9 @@ class Pry
285
298
  # @param String the line to process
286
299
  # @return Object or Command::VOID_VALUE
287
300
  def process_line(line)
288
- command_name, arg_string, captures, args = tokenize(line)
301
+ command_match, arg_string, captures, args = tokenize(line)
289
302
 
290
- check_for_command_name_collision(command_name, arg_string) if Pry.config.collision_warning
303
+ check_for_command_collision(command_match, arg_string) if Pry.config.collision_warning
291
304
 
292
305
  self.arg_string = arg_string
293
306
  self.captures = captures
@@ -310,7 +323,7 @@ class Pry
310
323
  block_init_string = arg_string.slice!(block_index..-1)[1..-1]
311
324
  prime_string = "proc #{block_init_string}\n"
312
325
 
313
- if !_pry_.complete_expression?(prime_string)
326
+ if !Pry::Code.complete_expression?(prime_string)
314
327
  block_string = _pry_.r(target, prime_string)
315
328
  else
316
329
  block_string = prime_string
@@ -335,14 +348,14 @@ class Pry
335
348
  unless dependencies_met?
336
349
  gems_needed = Array(command_options[:requires_gem])
337
350
  gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
338
- output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
351
+ output.puts "\nThe command '#{command_name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
339
352
  output.puts "-"
340
- output.puts "Type `install-command #{name}` to install the required gems and activate this command."
353
+ output.puts "Type `install-command #{command_name}` to install the required gems and activate this command."
341
354
  return void
342
355
  end
343
356
 
344
357
  if command_options[:argument_required] && args.empty?
345
- raise CommandError, "The command '#{name}' requires an argument."
358
+ raise CommandError, "The command '#{command_name}' requires an argument."
346
359
  end
347
360
 
348
361
  ret = call_with_hooks(*args)
@@ -507,6 +520,6 @@ class Pry
507
520
  # gist_method
508
521
  # end
509
522
  # end
510
- def process; raise CommandError, "command '#{name}' not implemented" end
523
+ def process; raise CommandError, "command '#{command_name}' not implemented" end
511
524
  end
512
525
  end
@@ -1,7 +1,7 @@
1
1
  class Pry
2
2
  class NoCommandError < StandardError
3
- def initialize(name, owner)
4
- super "Command '#{name}' not found in command set #{owner}"
3
+ def initialize(match, owner)
4
+ super "Command '#{match}' not found in command set #{owner}"
5
5
  end
6
6
  end
7
7
 
@@ -27,8 +27,7 @@ class Pry
27
27
  end
28
28
 
29
29
  # Defines a new Pry command.
30
- # @param [String, Regexp] name The name of the command. Can be
31
- # Regexp as well as String.
30
+ # @param [String, Regexp] match The start of invocations of this command.
32
31
  # @param [String] description A description of the command.
33
32
  # @param [Hash] options The optional configuration parameters.
34
33
  # @option options [Boolean] :keep_retval Whether or not to use return value
@@ -43,7 +42,7 @@ class Pry
43
42
  # executing the command. Defaults to true.
44
43
  # @option options [String] :listing The listing name of the
45
44
  # command. That is the name by which the command is looked up by
46
- # help and by show-command. Necessary for regex based commands.
45
+ # help and by show-command. Necessary for commands with regex matches.
47
46
  # @option options [Boolean] :use_prefix Whether the command uses
48
47
  # `Pry.config.command_prefix` prefix (if one is defined). Defaults
49
48
  # to true.
@@ -80,18 +79,17 @@ class Pry
80
79
  # # hello john, nice number: 10
81
80
  # # pry(main)> help number
82
81
  # # number-N regex command
83
- def block_command(name, description="No description.", options={}, &block)
82
+ def block_command(match, description="No description.", options={}, &block)
84
83
  description, options = ["No description.", description] if description.is_a?(Hash)
85
- options = default_options(name).merge!(options)
84
+ options = default_options(match).merge!(options)
86
85
 
87
- commands[name] = Pry::BlockCommand.subclass(name, description, options, helper_module, &block)
86
+ commands[match] = Pry::BlockCommand.subclass(match, description, options, helper_module, &block)
88
87
  end
89
88
  alias_method :command, :block_command
90
89
 
91
90
  # Defines a new Pry command class.
92
91
  #
93
- # @param [String, Regexp] name The name of the command. Can be
94
- # Regexp as well as String.
92
+ # @param [String, Regexp] match The start of invocations of this command.
95
93
  # @param [String] description A description of the command.
96
94
  # @param [Hash] options The optional configuration parameters, see {#command}
97
95
  # @param &Block The class body's definition.
@@ -113,40 +111,40 @@ class Pry
113
111
  # end
114
112
  # end
115
113
  #
116
- def create_command(name, description="No description.", options={}, &block)
114
+ def create_command(match, description="No description.", options={}, &block)
117
115
  description, options = ["No description.", description] if description.is_a?(Hash)
118
- options = default_options(name).merge!(options)
116
+ options = default_options(match).merge!(options)
119
117
 
120
- commands[name] = Pry::ClassCommand.subclass(name, description, options, helper_module, &block)
121
- commands[name].class_eval(&block)
122
- commands[name]
118
+ commands[match] = Pry::ClassCommand.subclass(match, description, options, helper_module, &block)
119
+ commands[match].class_eval(&block)
120
+ commands[match]
123
121
  end
124
122
 
125
123
  # Execute a block of code before a command is invoked. The block also
126
124
  # gets access to parameters that will be passed to the command and
127
125
  # is evaluated in the same context.
128
- # @param [String, Regexp] name The name of the command.
126
+ # @param [String, Regexp] search The match or listing of the command.
129
127
  # @yield The block to be run before the command.
130
128
  # @example Display parameter before invoking command
131
129
  # Pry.commands.before_command("whereami") do |n|
132
130
  # output.puts "parameter passed was #{n}"
133
131
  # end
134
- def before_command(name, &block)
135
- cmd = find_command_by_name_or_listing(name)
132
+ def before_command(search, &block)
133
+ cmd = find_command_by_match_or_listing(search)
136
134
  cmd.hooks[:before].unshift block
137
135
  end
138
136
 
139
137
  # Execute a block of code after a command is invoked. The block also
140
138
  # gets access to parameters that will be passed to the command and
141
139
  # is evaluated in the same context.
142
- # @param [String, Regexp] name The name of the command.
140
+ # @param [String, Regexp] search The match or listing of the command.
143
141
  # @yield The block to be run after the command.
144
142
  # @example Display text 'command complete' after invoking command
145
143
  # Pry.commands.after_command("whereami") do |n|
146
144
  # output.puts "command complete!"
147
145
  # end
148
- def after_command(name, &block)
149
- cmd = find_command_by_name_or_listing(name)
146
+ def after_command(search, &block)
147
+ cmd = find_command_by_match_or_listing(search)
150
148
  cmd.hooks[:after] << block
151
149
  end
152
150
 
@@ -154,91 +152,122 @@ class Pry
154
152
  @commands.each(&block)
155
153
  end
156
154
 
155
+ # Add a given command object to this set.
156
+ # @param Command the subclass of Pry::Command you wish to add.
157
+ def add_command(command)
158
+ commands[command.match] = command
159
+ end
160
+
157
161
  # Removes some commands from the set
158
- # @param [Array<String>] names name of the commands to remove
159
- def delete(*names)
160
- names.each do |name|
161
- cmd = find_command_by_name_or_listing(name)
162
- commands.delete cmd.name
162
+ # @param [Array<String>] searches the matches or listings of the commands to remove
163
+ def delete(*searches)
164
+ searches.each do |search|
165
+ cmd = find_command_by_match_or_listing(search)
166
+ commands.delete cmd.match
163
167
  end
164
168
  end
165
169
 
166
170
  # Imports all the commands from one or more sets.
167
171
  # @param [Array<CommandSet>] sets Command sets, all of the commands of which
168
172
  # will be imported.
173
+ # @return [Pry::CommandSet] Returns the reciever (a command set).
169
174
  def import(*sets)
170
175
  sets.each do |set|
171
176
  commands.merge! set.commands
172
177
  helper_module.send :include, set.helper_module
173
178
  end
179
+ self
174
180
  end
175
181
 
176
182
  # Imports some commands from a set
177
183
  # @param [CommandSet] set Set to import commands from
178
- # @param [Array<String>] names Commands to import
179
- def import_from(set, *names)
184
+ # @param [Array<String>] matches Commands to import
185
+ # @return [Pry::CommandSet] Returns the reciever (a command set).
186
+ def import_from(set, *matches)
180
187
  helper_module.send :include, set.helper_module
181
- names.each do |name|
182
- cmd = set.find_command_by_name_or_listing(name)
183
- commands[cmd.name] = cmd
188
+ matches.each do |match|
189
+ cmd = set.find_command_by_match_or_listing(match)
190
+ commands[cmd.match] = cmd
184
191
  end
192
+ self
185
193
  end
186
194
 
187
- # @param [String, Regexp] name_or_listing The name or listing name
195
+ # @param [String, Regexp] match_or_listing The match or listing of a command.
188
196
  # of the command to retrieve.
189
197
  # @return [Command] The command object matched.
190
- def find_command_by_name_or_listing(name_or_listing)
191
- if commands[name_or_listing]
192
- cmd = commands[name_or_listing]
198
+ def find_command_by_match_or_listing(match_or_listing)
199
+ if commands[match_or_listing]
200
+ cmd = commands[match_or_listing]
193
201
  else
194
- _, cmd = commands.find { |name, command| command.options[:listing] == name_or_listing }
202
+ _, cmd = commands.find { |match, command| command.options[:listing] == match_or_listing }
195
203
  end
196
204
 
197
- raise ArgumentError, "Cannot find a command with name: '#{name_or_listing}'!" if !cmd
205
+ raise ArgumentError, "Cannot find a command: '#{match_or_listing}'!" if !cmd
198
206
  cmd
199
207
  end
200
- protected :find_command_by_name_or_listing
208
+ protected :find_command_by_match_or_listing
201
209
 
202
210
  # Aliases a command
203
- # @param [String] new_name New name of the command.
204
- # @param [String] old_name Old name of the command.
205
- # @param [String, nil] desc New description of the command.
206
- def alias_command(new_name, old_name, desc="")
207
- orig_command = find_command_by_name_or_listing(old_name)
208
- commands[new_name] = orig_command.dup
209
- commands[new_name].name = new_name
210
- commands[new_name].description = desc
211
+ # Note that if `desc` parameter is `nil` then the default
212
+ # description is used.
213
+ # @param [String, Regex] match The match of the alias (can be a regex).
214
+ # @param [String] action The action to be performed (typically
215
+ # another command).
216
+ # @param [Hash] options The optional configuration parameters,
217
+ # accepts the same as the `command` method, but also allows the
218
+ # command description to be passed this way too as `:desc`
219
+ # @example Creating an alias for `ls -M`
220
+ # Pry.config.commands.alias_command "lM", "ls -M"
221
+ # @example Pass explicit description (overriding default).
222
+ # Pry.config.commands.alias_command "lM", "ls -M", :desc => "cutiepie"
223
+ def alias_command(match, action, options={})
224
+ original_options = find_command(action).options.dup
225
+
226
+ options = original_options.merge!({
227
+ :desc => "Alias for `#{action}`",
228
+ :listing => match
229
+ }).merge!(options)
230
+
231
+ # ensure default description is used if desc is nil
232
+ desc = options.delete(:desc).to_s
233
+
234
+ c = block_command match, desc, options do |*args|
235
+ run action, *args
236
+ end
237
+
238
+ c.group "Aliases"
239
+
240
+ c
211
241
  end
212
242
 
213
- # Rename a command. Accepts either actual name or listing name for
214
- # the `old_name`.
215
- # `new_name` must be the actual name of the new command.
216
- # @param [String, Regexp] new_name The new name for the command.
217
- # @param [String, Regexp] old_name The command's current name.
243
+ # Rename a command. Accepts either match or listing for the search.
244
+ #
245
+ # @param [String, Regexp] new_name The new match for the command.
246
+ # @param [String, Regexp] search The command's current match or listing.
218
247
  # @param [Hash] options The optional configuration parameters,
219
248
  # accepts the same as the `command` method, but also allows the
220
249
  # command description to be passed this way too.
221
250
  # @example Renaming the `ls` command and changing its description.
222
251
  # Pry.config.commands.rename "dir", "ls", :description => "DOS friendly ls"
223
- def rename_command(new_name, old_name, options={})
224
- cmd = find_command_by_name_or_listing(old_name)
252
+ def rename_command(new_match, search, options={})
253
+ cmd = find_command_by_match_or_listing(search)
225
254
 
226
255
  options = {
227
- :listing => new_name,
256
+ :listing => new_match,
228
257
  :description => cmd.description
229
258
  }.merge!(options)
230
259
 
231
- commands[new_name] = cmd.dup
232
- commands[new_name].name = new_name
233
- commands[new_name].description = options.delete(:description)
234
- commands[new_name].options.merge!(options)
235
- commands.delete(cmd.name)
260
+ commands[new_match] = cmd.dup
261
+ commands[new_match].match = new_match
262
+ commands[new_match].description = options.delete(:description)
263
+ commands[new_match].options.merge!(options)
264
+ commands.delete(cmd.match)
236
265
  end
237
266
 
238
267
  # Sets or gets the description for a command (replacing the old
239
268
  # description). Returns current description if no description
240
269
  # parameter provided.
241
- # @param [String, Regexp] name The command name.
270
+ # @param [String, Regexp] match The command match.
242
271
  # @param [String] description The command description.
243
272
  # @example Setting
244
273
  # MyCommands = Pry::CommandSet.new do
@@ -246,8 +275,8 @@ class Pry
246
275
  # end
247
276
  # @example Getting
248
277
  # Pry.config.commands.desc "amend-line"
249
- def desc(name, description=nil)
250
- cmd = find_command_by_name_or_listing(name)
278
+ def desc(search, description=nil)
279
+ cmd = find_command_by_match_or_listing(search)
251
280
  return cmd.description if !description
252
281
 
253
282
  cmd.description = description
@@ -282,6 +311,7 @@ class Pry
282
311
  def find_command(val)
283
312
  commands.values.select{ |c| c.matches?(val) }.sort_by{ |c| c.match_score(val) }.last
284
313
  end
314
+ alias_method :[], :find_command
285
315
 
286
316
  # Find the command that the user might be trying to refer to.
287
317
  #
@@ -289,7 +319,7 @@ class Pry
289
319
  # @return [Pry::Command, nil]
290
320
  def find_command_for_help(search)
291
321
  find_command(search) || (begin
292
- find_command_by_name_or_listing(search)
322
+ find_command_by_match_or_listing(search)
293
323
  rescue ArgumentError
294
324
  nil
295
325
  end)
@@ -320,21 +350,21 @@ class Pry
320
350
  end
321
351
 
322
352
  # @nodoc used for testing
323
- def run_command(context, name, *args)
324
- command = commands[name] or raise NoCommandError.new(name, self)
353
+ def run_command(context, match, *args)
354
+ command = commands[match] or raise NoCommandError.new(match, self)
325
355
  command.new(context).call_safely(*args)
326
356
  end
327
357
 
328
358
  private
329
359
 
330
- def default_options(name)
360
+ def default_options(match)
331
361
  {
332
362
  :requires_gem => [],
333
363
  :keep_retval => false,
334
364
  :argument_required => false,
335
365
  :interpolate => true,
336
366
  :shellwords => true,
337
- :listing => name,
367
+ :listing => (String === match ? match : match.inspect),
338
368
  :use_prefix => true,
339
369
  :takes_block => false
340
370
  }