pry 0.9.0pre3-java → 0.9.4pre2-java

Sign up to get free protection for your applications and to get access to all the features.
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