pry 0.9.0pre3-java → 0.9.4pre2-java

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 (47) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG +84 -6
  3. data/CONTRIBUTORS +13 -0
  4. data/README.markdown +23 -183
  5. data/Rakefile +22 -19
  6. data/TODO +36 -6
  7. data/bin/pry +12 -1
  8. data/lib/pry.rb +60 -12
  9. data/lib/pry/command_context.rb +21 -0
  10. data/lib/pry/command_processor.rb +62 -16
  11. data/lib/pry/command_set.rb +25 -11
  12. data/lib/pry/commands.rb +0 -3
  13. data/lib/pry/completion.rb +6 -6
  14. data/lib/pry/config.rb +25 -5
  15. data/lib/pry/default_commands/basic.rb +27 -6
  16. data/lib/pry/default_commands/context.rb +84 -35
  17. data/lib/pry/default_commands/documentation.rb +69 -31
  18. data/lib/pry/default_commands/easter_eggs.rb +5 -0
  19. data/lib/pry/default_commands/input.rb +193 -56
  20. data/lib/pry/default_commands/introspection.rb +98 -50
  21. data/lib/pry/default_commands/ls.rb +51 -21
  22. data/lib/pry/default_commands/shell.rb +57 -13
  23. data/lib/pry/extended_commands/experimental.rb +0 -32
  24. data/lib/pry/extended_commands/user_command_api.rb +33 -2
  25. data/lib/pry/helpers/base_helpers.rb +30 -10
  26. data/lib/pry/helpers/command_helpers.rb +75 -16
  27. data/lib/pry/helpers/text.rb +12 -11
  28. data/lib/pry/history.rb +61 -0
  29. data/lib/pry/plugins.rb +23 -12
  30. data/lib/pry/pry_class.rb +51 -50
  31. data/lib/pry/pry_instance.rb +129 -119
  32. data/lib/pry/version.rb +1 -1
  33. data/pry.gemspec +46 -0
  34. data/test/helper.rb +37 -3
  35. data/test/test_command_processor.rb +62 -19
  36. data/test/test_command_set.rb +40 -2
  37. data/test/test_completion.rb +27 -0
  38. data/test/test_default_commands/test_context.rb +185 -1
  39. data/test/test_default_commands/test_documentation.rb +10 -0
  40. data/test/test_default_commands/test_input.rb +207 -11
  41. data/test/test_default_commands/test_introspection.rb +20 -1
  42. data/test/test_default_commands/test_shell.rb +18 -0
  43. data/test/test_pry.rb +261 -45
  44. data/test/test_pry_history.rb +82 -0
  45. data/test/test_pry_output.rb +44 -0
  46. data/test/test_special_locals.rb +35 -0
  47. metadata +185 -159
data/TODO CHANGED
@@ -1,10 +1,40 @@
1
+ 0.9.4
2
+ * include method visiblity in show-doc and stat output
3
+ * tempfile should end in .rb (for edit -t)
4
+ * ls output should not be in array format
5
+ * exceptions should allow access to previous items in the backtrace
6
+ * input should allow multiple objects which are switched to automatically when EOF is reached on the preceding one
7
+ * pry -r should happen in pry
8
+ * more plugin-related commands in pry - see installed ones, see activated ones, see available on rubygems
9
+ * should also allow plugins be explicitly activated as a command line option
10
+ * should not raise if plugin activation fails (should show warning instead)
11
+ * more documentation on CommandContext, etc and also command helpers
12
+ * fix history saving (should not save all of Readline::HISTORY, but only what changed)
13
+ * prevent blank lines going to Readline::HISTORY
14
+ * ensure that cat --ex emulates the `whereami` format - includes line numbers and formatted the same, etc
15
+ * rename inp and out to _inp_ and _out_ otherwise than can overwrite locals by those names when debugging (not good)
16
+ * add source file to stat command
17
+ * make plugins use hash instead of array
18
+ * ensure edit -t has 'edit' alias (no parameters) and dumps eval_string into buffer
19
+ * whitelist exceptions
20
+ * hooks system
21
+ * jruby shell command support
22
+ *
1
23
 
2
- ROADMAP
3
-
4
- FUTURE
5
- --------
6
- * Pry server and Pry client for SLIME style remote repl connectinos.
7
- * i18n support
24
+ 0.9.3
25
+ * hist command now excludes last line of input (the command invocation itself)
26
+ * hist now has `history` alias
27
+ * `pry -r` requires now happen after plugin loading (so as not to interfere with
28
+ * new Pry.config.disable_auto_reload option, for turning off auto reloading by edit-method and related
29
+ * add better error messages for `cd` command
30
+ * add command_prefix
31
+ * change some command names to include hyphen, e.g version => pry-version, install => install-command
32
+ * do cat --ex and edit --ex
33
+ * add reload-method
34
+ * fixed exotic object regression - BasicObject.new etc now return "=> unknown"
35
+ * converted: import => import-set, version => pry-version, install => install-command
36
+ * fix show-doc bug for ruby 1.8 and Kernel.fork
37
+ * edit -t (opens a temporary file and evals it in current context when closed)
8
38
 
9
39
  0.9.0
10
40
  Major features
data/bin/pry CHANGED
@@ -39,12 +39,14 @@ See: `https://github.com/banister` for more information.
39
39
  Pry.config.plugins.enabled = false
40
40
  end
41
41
 
42
+ on "installed-plugins", "List installed plugins."
43
+
42
44
  on "simple-prompt", "Enable simple prompt mode" do
43
45
  Pry.prompt = Pry::SIMPLE_PROMPT
44
46
  end
45
47
 
46
48
  on :r, :require, "`require` a Ruby script at startup", true do |file|
47
- require file
49
+ Pry.config.requires << file
48
50
  end
49
51
 
50
52
  on :I, "Add a path to the $LOAD_PATH", true do |path|
@@ -63,6 +65,15 @@ See: `https://github.com/banister` for more information.
63
65
  )
64
66
  end
65
67
 
68
+ if opts["installed-plugins"]
69
+ puts "Installed Plugins:"
70
+ puts "--"
71
+ Pry.locate_plugins.each do |plugin|
72
+ puts "#{plugin.name}".ljust(18) + plugin.spec.summary
73
+ end
74
+ exit
75
+ end
76
+
66
77
  # invoked via cli
67
78
  Pry.cli = true
68
79
 
data/lib/pry.rb CHANGED
@@ -2,13 +2,12 @@
2
2
  # MIT License
3
3
 
4
4
  require 'pp'
5
-
5
+ require 'pry/helpers/base_helpers'
6
6
  class Pry
7
7
  # The default hooks - display messages when beginning and ending Pry sessions.
8
8
  DEFAULT_HOOKS = {
9
9
  :before_session => proc do |out, target|
10
10
  # ensure we're actually in a method
11
- meth_name = target.eval('__method__')
12
11
  file = target.eval('__FILE__')
13
12
 
14
13
  # /unknown/ for rbx
@@ -20,11 +19,20 @@ class Pry
20
19
 
21
20
  # The default prints
22
21
  DEFAULT_PRINT = proc do |output, value|
23
- if Pry.color
24
- output.puts "=> #{CodeRay.scan(value.pretty_inspect, :ruby).term}"
25
- else
26
- output.puts "=> #{Pry.view(value)}"
22
+ stringified = begin
23
+ value.pretty_inspect
24
+ rescue RescuableException => ex
25
+ nil
26
+ end
27
+
28
+ unless String === stringified
29
+ # Read the class name off of the singleton class to provide a default inspect.
30
+ klass = (class << value; self; end).ancestors.first
31
+ stringified = "#<#{klass}:0x#{value.__id__.to_s(16)}>"
32
+ Helpers::BaseHelpers.stagger_output("output error: #{ex.inspect}", output) if ex
27
33
  end
34
+
35
+ Helpers::BaseHelpers.stagger_output("=> #{Helpers::BaseHelpers.colorize_code(stringified)}", output)
28
36
  end
29
37
 
30
38
  # Will only show the first line of the backtrace
@@ -35,7 +43,7 @@ class Pry
35
43
 
36
44
  # The default prompt; includes the target and nesting level
37
45
  DEFAULT_PROMPT = [
38
- proc { |target_self, nest_level|
46
+ proc { |target_self, nest_level, _|
39
47
  if nest_level == 0
40
48
  "pry(#{Pry.view_clip(target_self)})> "
41
49
  else
@@ -43,23 +51,62 @@ class Pry
43
51
  end
44
52
  },
45
53
 
46
- proc { |target_self, nest_level|
54
+ proc { |target_self, nest_level, _|
47
55
  if nest_level == 0
48
56
  "pry(#{Pry.view_clip(target_self)})* "
49
57
  else
50
58
  "pry(#{Pry.view_clip(target_self)}):#{Pry.view_clip(nest_level)}* "
51
59
  end
52
60
  }
53
- ]
61
+ ]
62
+ # Deal with the ^D key being pressed, different behaviour in
63
+ # different cases:
64
+ # 1) In an expression - behave like `!` command (clear input buffer)
65
+ # 2) At top-level session - behave like `exit command (break out of repl loop)
66
+ # 3) In a nested session - behave like `cd ..` (pop a binding)
67
+ DEFAULT_CONTROL_D_HANDLER = proc do |eval_string, _pry_|
68
+ if !eval_string.empty?
69
+ # clear input buffer
70
+ eval_string.replace("")
71
+ elsif _pry_.binding_stack.one?
72
+ # ^D at top-level breaks out of loop
73
+ _pry_.binding_stack.clear
74
+ throw(:breakout)
75
+ else
76
+ # otherwise just pops a binding
77
+ _pry_.binding_stack.pop
78
+ end
79
+ end
54
80
 
55
81
  # A simple prompt - doesn't display target or nesting level
56
- SIMPLE_PROMPT = [proc { ">> " }, proc { ">* " }]
82
+ SIMPLE_PROMPT = [proc { ">> " }, proc { " | " }]
57
83
 
58
84
  SHELL_PROMPT = [
59
- proc { |target_self, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} $ " },
60
- proc { |target_self, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} * " }
85
+ proc { |target_self, _, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} $ " },
86
+ proc { |target_self, _, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} * " }
61
87
  ]
62
88
 
89
+ # As a REPL, we often want to catch any unexpected exceptions that may have
90
+ # been raised; however we don't want to go overboard and prevent the user
91
+ # from exiting Pry when they want to.
92
+ module RescuableException
93
+ def self.===(exception)
94
+ case exception
95
+ # Catch when the user hits ^C (Interrupt < SignalException), and assume
96
+ # that they just wanted to stop the in-progress command (just like bash etc.)
97
+ when Interrupt
98
+ true
99
+ # Don't catch signals (particularly not SIGTERM) as these are unlikely to be
100
+ # intended for pry itself. We should also make sure that Kernel#exit works.
101
+ when SystemExit, SignalException
102
+ false
103
+ # All other exceptions will be caught.
104
+ else
105
+ true
106
+ end
107
+ end
108
+ end
109
+
63
110
  end
64
111
 
65
112
  require "method_source"
@@ -83,6 +130,7 @@ end
83
130
  require "pry/version"
84
131
  require "pry/history_array"
85
132
  require "pry/helpers"
133
+ require "pry/history"
86
134
  require "pry/command_set"
87
135
  require "pry/commands"
88
136
  require "pry/command_context"
@@ -2,6 +2,13 @@ class Pry
2
2
  # Command contexts are the objects runing each command.
3
3
  # Helper modules can be mixed into this class.
4
4
  class CommandContext
5
+
6
+ # represents a void return value for a command
7
+ VOID_VALUE = Object.new
8
+
9
+ # give it a nice inspect
10
+ def VOID_VALUE.inspect() "void" end
11
+
5
12
  attr_accessor :output
6
13
  attr_accessor :target
7
14
  attr_accessor :captures
@@ -10,7 +17,17 @@ class Pry
10
17
  attr_accessor :opts
11
18
  attr_accessor :command_set
12
19
  attr_accessor :command_processor
20
+ attr_accessor :_pry_
13
21
 
22
+ # Run a command from another command.
23
+ # @param [String] command_string The string that invokes the command
24
+ # @param [Array] args Further arguments to pass to the command
25
+ # @example
26
+ # run "show-input"
27
+ # @example
28
+ # run ".ls"
29
+ # @example
30
+ # run "amend-line", "5", 'puts "hello world"'
14
31
  def run(command_string, *args)
15
32
  complete_string = "#{command_string} #{args.join(" ")}"
16
33
  command_processor.process_commands(complete_string, eval_string, target)
@@ -24,6 +41,10 @@ class Pry
24
41
  Pry::Helpers::Text
25
42
  end
26
43
 
44
+ def void
45
+ VOID_VALUE
46
+ end
47
+
27
48
  include Pry::Helpers::BaseHelpers
28
49
  include Pry::Helpers::CommandHelpers
29
50
  end
@@ -2,6 +2,36 @@ require 'forwardable'
2
2
 
3
3
  class Pry
4
4
  class CommandProcessor
5
+
6
+ # Wraps the return result of process_commands, indicates if the
7
+ # result IS a command and what kind of command (e.g void)
8
+ class Result
9
+ attr_reader :retval
10
+
11
+ def initialize(is_command, keep_retval = false, retval = nil)
12
+ @is_command, @keep_retval, @retval = is_command, keep_retval, retval
13
+ end
14
+
15
+ # Is the result a command?
16
+ # @return [Boolean]
17
+ def command?
18
+ @is_command
19
+ end
20
+
21
+ # Is the result a command and if it is, is it a void command?
22
+ # (one that does not return a value)
23
+ # @return [Boolean]
24
+ def void_command?
25
+ (command? && !keep_retval?) || retval == CommandContext::VOID_VALUE
26
+ end
27
+
28
+ # Is the return value kept for this command? (i.e :keep_retval => true)
29
+ # @return [Boolean]
30
+ def keep_retval?
31
+ @keep_retval
32
+ end
33
+ end
34
+
5
35
  extend Forwardable
6
36
 
7
37
  attr_accessor :pry_instance
@@ -10,13 +40,15 @@ class Pry
10
40
  @pry_instance = pry_instance
11
41
  end
12
42
 
13
- def_delegators :@pry_instance, :commands, :nesting, :output
43
+ def_delegators :@pry_instance, :commands, :output
14
44
 
15
45
  # Is the string a valid command?
16
46
  # @param [String] val The string passed in from the Pry prompt.
47
+ # @param [Binding] target The context where the string should be
48
+ # interpolated in.
17
49
  # @return [Boolean] Whether the string is a valid command.
18
- def valid_command?(val)
19
- !!(command_matched(val, binding)[0])
50
+ def valid_command?(val, target=binding)
51
+ !!(command_matched(val, target)[0])
20
52
  end
21
53
 
22
54
  # Convert the object to a form that can be interpolated into a
@@ -34,7 +66,7 @@ class Pry
34
66
  # Revaluate the string (str) and perform interpolation.
35
67
  # @param [String] str The string to reevaluate with interpolation.
36
68
  # @param [Binding] target The context where the string should be
37
- # reevaluated in.
69
+ # interpolated in.
38
70
  # @return [String] The reevaluated string with interpolations
39
71
  # applied (if any).
40
72
  def interpolate_string(str, target)
@@ -52,14 +84,17 @@ class Pry
52
84
  # @return [Array] The command data and arg string pair
53
85
  def command_matched(val, target)
54
86
  _, cmd_data = commands.commands.find do |name, data|
87
+ prefix = convert_to_regex(Pry.config.command_prefix)
88
+ prefix = "(?:#{prefix})?" unless data.options[:use_prefix]
55
89
 
56
- interp_val = interpolate_string(val, target)
57
- command_regex = /^#{convert_to_regex(name)}(?!\S)/
90
+ command_regex = /^#{prefix}#{convert_to_regex(name)}(?!\S)/
58
91
 
59
- if data.options[:interpolate] && (command_regex =~ interp_val)
60
- val.replace interp_val
61
- else
62
- command_regex =~ val
92
+ if command_regex =~ val
93
+ if data.options[:interpolate]
94
+ val.replace(interpolate_string(val, target))
95
+ command_regex =~ val # re-match with the interpolated string
96
+ end
97
+ true
63
98
  end
64
99
  end
65
100
 
@@ -75,12 +110,21 @@ class Pry
75
110
  # @param [String] eval_string The cumulative lines of input for
76
111
  # multi-line input.
77
112
  # @param [Binding] target The receiver of the commands.
113
+ # @return [Pry::CommandProcessor::Result] A wrapper object
114
+ # containing info about the result of the command processing
115
+ # (indicating whether it is a command and if it is what kind of
116
+ # command it is.
78
117
  def process_commands(val, eval_string, target)
79
118
 
80
- # no command was matched, so return to caller
81
119
  command, captures, pos = command_matched(val, target)
82
- return if !command
83
- arg_string = val[pos..-1].strip
120
+
121
+ # no command was matched, so return to caller
122
+ return Result.new(false) if !command
123
+
124
+ arg_string = val[pos..-1]
125
+
126
+ # remove the one leading space if it exists
127
+ arg_string.slice!(0) if arg_string.start_with?(" ")
84
128
 
85
129
  args = arg_string ? Shellwords.shellwords(arg_string) : []
86
130
 
@@ -88,12 +132,13 @@ class Pry
88
132
  :val => val,
89
133
  :arg_string => arg_string,
90
134
  :eval_string => eval_string,
91
- :nesting => nesting,
92
135
  :commands => commands.commands,
93
136
  :captures => captures
94
137
  }
95
138
 
96
- execute_command(target, command.name, options, *(captures + args))
139
+ ret = execute_command(target, command.name, options, *(captures + args))
140
+
141
+ Result.new(true, command.options[:keep_retval], ret)
97
142
  end
98
143
 
99
144
  # Execute a Pry command.
@@ -102,6 +147,7 @@ class Pry
102
147
  # @param [String] command The name of the command to be run.
103
148
  # @param [Hash] options The options to set on the Commands object.
104
149
  # @param [Array] args The command arguments.
150
+ # @return [Object] The value returned by the command
105
151
  def execute_command(target, command, options, *args)
106
152
  context = CommandContext.new
107
153
 
@@ -113,12 +159,12 @@ class Pry
113
159
  context.eval_string = options[:eval_string]
114
160
  context.arg_string = options[:arg_string]
115
161
  context.command_set = commands
162
+ context._pry_ = @pry_instance
116
163
 
117
164
  context.command_processor = self
118
165
 
119
166
  ret = commands.run_command(context, command, *args)
120
167
 
121
- # Tick, tock, im getting rid of this shit soon.
122
168
  options[:val].replace("")
123
169
 
124
170
  ret
@@ -15,7 +15,11 @@ class Pry
15
15
  context.instance_eval(&stub_block)
16
16
  else
17
17
  ret = context.instance_exec(*correct_arg_arity(block.arity, args), &block)
18
- ret if options[:keep_retval]
18
+ if options[:keep_retval]
19
+ ret
20
+ else
21
+ Pry::CommandContext::VOID_VALUE
22
+ end
19
23
  end
20
24
  end
21
25
 
@@ -24,9 +28,15 @@ class Pry
24
28
  case arity <=> 0
25
29
  when -1
26
30
  args
27
- when 1, 0
28
- # Keep 1.8 happy
29
- args.values_at 0..(arity - 1)
31
+ when 0
32
+ []
33
+ when 1
34
+ # another jruby hack
35
+ if Pry::Helpers::BaseHelpers.jruby?
36
+ args[0..(arity - 1)]
37
+ else
38
+ args.values_at 0..(arity - 1)
39
+ end
30
40
  end
31
41
  end
32
42
  end
@@ -68,6 +78,9 @@ class Pry
68
78
  # @option options [String] :listing The listing name of the
69
79
  # command. That is the name by which the command is looked up by
70
80
  # help and by show-command. Necessary for regex based commands.
81
+ # @option options [Boolean] :use_prefix Whether the command uses
82
+ # `Pry.config.command_prefix` prefix (if one is defined). Defaults
83
+ # to true.
71
84
  # @yield The action to perform. The parameters in the block
72
85
  # determines the parameters the command will receive. All
73
86
  # parameters passed into the block will be strings. Successive
@@ -105,7 +118,8 @@ class Pry
105
118
  :keep_retval => false,
106
119
  :argument_required => false,
107
120
  :interpolate => true,
108
- :listing => name
121
+ :listing => name,
122
+ :use_prefix => true
109
123
  }.merge!(options)
110
124
 
111
125
  unless command_dependencies_met? options
@@ -115,7 +129,7 @@ class Pry
115
129
  options[:stub_info] = proc do
116
130
  output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
117
131
  output.puts "-"
118
- output.puts "Type `install #{name}` to install the required gems and activate this command."
132
+ output.puts "Type `install-command #{name}` to install the required gems and activate this command."
119
133
  end
120
134
  end
121
135
 
@@ -123,7 +137,7 @@ class Pry
123
137
  end
124
138
 
125
139
  def each &block
126
- @commands.each(&block)
140
+ @commands.each(&block)
127
141
  end
128
142
 
129
143
  # Removes some commands from the set
@@ -223,11 +237,11 @@ class Pry
223
237
  output.puts
224
238
  help_text = heading("Command List: ") + "\n"
225
239
 
226
- commands.each do |key, command|
240
+ help_text << commands.map do |key, command|
227
241
  if command.description && !command.description.empty?
228
- help_text << "#{command.options[:listing]}".ljust(18) + command.description + "\n"
242
+ "#{command.options[:listing]}".ljust(18) + command.description
229
243
  end
230
- end
244
+ end.compact.sort.join("\n")
231
245
 
232
246
  stagger_output(help_text)
233
247
  else
@@ -239,7 +253,7 @@ class Pry
239
253
  end
240
254
  end
241
255
 
242
- command "install", "Install a disabled command." do |name|
256
+ command "install-command", "Install a disabled command." do |name|
243
257
  command = find_command(name)
244
258
  stub_info = command.options[:stub_info]
245
259