pry 0.9.3pre1-i386-mswin32 → 0.9.4-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/CHANGELOG +53 -0
  2. data/CONTRIBUTORS +13 -0
  3. data/README.markdown +4 -2
  4. data/Rakefile +17 -3
  5. data/TODO +22 -0
  6. data/lib/pry.rb +102 -24
  7. data/lib/pry/command_context.rb +12 -0
  8. data/lib/pry/command_processor.rb +50 -19
  9. data/lib/pry/command_set.rb +17 -7
  10. data/lib/pry/completion.rb +6 -6
  11. data/lib/pry/config.rb +6 -2
  12. data/lib/pry/default_commands/basic.rb +8 -4
  13. data/lib/pry/default_commands/context.rb +84 -36
  14. data/lib/pry/default_commands/documentation.rb +50 -30
  15. data/lib/pry/default_commands/easter_eggs.rb +5 -0
  16. data/lib/pry/default_commands/input.rb +20 -16
  17. data/lib/pry/default_commands/introspection.rb +61 -77
  18. data/lib/pry/default_commands/ls.rb +22 -14
  19. data/lib/pry/default_commands/shell.rb +32 -17
  20. data/lib/pry/extended_commands/user_command_api.rb +32 -1
  21. data/lib/pry/helpers/base_helpers.rb +21 -9
  22. data/lib/pry/helpers/command_helpers.rb +99 -17
  23. data/lib/pry/helpers/text.rb +12 -11
  24. data/lib/pry/history.rb +61 -0
  25. data/lib/pry/plugins.rb +19 -8
  26. data/lib/pry/pry_class.rb +49 -60
  27. data/lib/pry/pry_instance.rb +122 -119
  28. data/lib/pry/version.rb +1 -1
  29. data/pry.gemspec +15 -14
  30. data/test/helper.rb +31 -0
  31. data/test/test_command_processor.rb +8 -87
  32. data/test/test_command_set.rb +40 -2
  33. data/test/test_completion.rb +26 -0
  34. data/test/test_default_commands/test_context.rb +185 -1
  35. data/test/test_default_commands/test_documentation.rb +10 -0
  36. data/test/test_default_commands/test_input.rb +39 -13
  37. data/test/test_default_commands/test_introspection.rb +11 -1
  38. data/test/test_default_commands/test_shell.rb +18 -0
  39. data/test/test_pry.rb +217 -47
  40. data/test/test_pry_history.rb +84 -0
  41. data/test/test_pry_output.rb +44 -0
  42. data/test/test_special_locals.rb +35 -0
  43. metadata +83 -77
@@ -9,7 +9,7 @@ class Pry
9
9
  target = target()
10
10
 
11
11
  opts = Slop.parse!(args) do |opt|
12
- opt.banner "Usage: show-method [OPTIONS] [METH]\n" \
12
+ opt.banner "Usage: show-method [OPTIONS] [METH 1] [METH 2] [METH N]\n" \
13
13
  "Show the source for method METH. Tries instance methods first and then methods by default.\n" \
14
14
  "e.g: show-method hello_method"
15
15
 
@@ -29,30 +29,33 @@ class Pry
29
29
 
30
30
  next if opts.help?
31
31
 
32
- meth_name = args.shift
33
- if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
34
- output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help"
35
- next
36
- end
32
+ args = [nil] if args.empty?
33
+ args.each do |method_name|
34
+ meth_name = method_name
35
+ if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
36
+ output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help"
37
+ next
38
+ end
37
39
 
38
- code, code_type = code_and_code_type_for(meth)
39
- next if !code
40
+ code, code_type = code_and_code_type_for(meth)
41
+ next if !code
40
42
 
41
- output.puts make_header(meth, code_type, code)
42
- if Pry.color
43
- code = CodeRay.scan(code, code_type).term
44
- end
43
+ output.puts make_header(meth, code_type, code)
44
+ if Pry.color
45
+ code = CodeRay.scan(code, code_type).term
46
+ end
45
47
 
46
- start_line = false
47
- if opts.l?
48
- start_line = meth.source_location ? meth.source_location.last : 1
49
- end
48
+ start_line = false
49
+ if opts.l?
50
+ start_line = meth.source_location ? meth.source_location.last : 1
51
+ end
50
52
 
51
- start_line = opts.b? ? 1 : start_line
53
+ start_line = opts.b? ? 1 : start_line
52
54
 
53
55
 
54
- render_output(opts.flood?, start_line, code)
55
- code
56
+ render_output(opts.flood?, start_line, code)
57
+ code
58
+ end
56
59
  end
57
60
 
58
61
  alias_command "show-source", "show-method", ""
@@ -108,13 +111,14 @@ class Pry
108
111
  command "edit", "Invoke the default editor on a file. Type `edit --help` for more info" do |*args|
109
112
  opts = Slop.parse!(args) do |opt|
110
113
  opt.banner "Usage: edit [OPTIONS] [FILE]\n" \
111
- "Edit the method FILE in an editor.\n" \
112
- "Ensure #{text.bold("Pry.editor")} is set to your editor of choice.\n" \
114
+ "Edit the method FILE in an editor.\nWhen no file given, opens editor with contents of input buffer and evals after closing." \
115
+ "\nEnsure #{text.bold("Pry.config.editor")} is set to your editor of choice.\n" \
113
116
  "e.g: edit sample.rb"
114
117
 
115
118
  opt.on :r, "reload", "Eval file content after editing (evals at top level)"
116
- opt.on :ex, "Open an editor at the line and file that generated the most recent Exception."
117
- opt.on :t, "temp", "Open a temporary file in an editor and eval it in current context after closing."
119
+ opt.on :n, "no-reload", "Do not automatically reload the file after editing (only applies to --ex and -t)."
120
+ opt.on :ex, "Open an editor at the line and file that generated the most recent Exception, reloads file after editing."
121
+ opt.on :t, "temp", "Open a temporary file in an editor with contents of input buffer and eval it in current context after closing (same as `edit` with no args)"
118
122
  opt.on :p, "play", "Use the pry `play` command to eval the file content after editing."
119
123
  opt.on :l, "line", "Specify line number to jump to in file", true, :as => Integer
120
124
  opt.on :h, :help, "This message." do
@@ -123,26 +127,37 @@ class Pry
123
127
  end
124
128
  next if opts.h?
125
129
 
126
- # the context the file will be eval'd in after closing
127
- context = TOPLEVEL_BINDING
128
- should_reload = opts[:r]
130
+ should_reload_at_top_level = opts[:r]
131
+ should_reload_locally = false
129
132
 
130
133
  if opts.ex?
131
- next output.puts "No Exception found." if Pry.last_exception.nil?
134
+ next output.puts "No Exception found." if _pry_.last_exception.nil?
135
+
136
+ if is_core_rbx_path?(_pry_.last_exception.file)
137
+ file_name = rbx_convert_path_to_full(_pry_.last_exception.file)
138
+ else
139
+ file_name = _pry_.last_exception.file
140
+ end
132
141
 
133
- file_name = Pry.last_exception.file
134
- line = Pry.last_exception.line
142
+ line = _pry_.last_exception.line
135
143
  next output.puts "Exception has no associated file." if file_name.nil?
136
144
  next output.puts "Cannot edit exceptions raised in REPL." if Pry.eval_path == file_name
137
- elsif opts.t?
138
- file_name = Tempfile.new("tmp").tap(&:close).path
139
- line = 0
140
- should_reload = true
141
- context = target
145
+
146
+ should_reload_at_top_level = opts[:n] ? false : true
147
+
148
+ elsif opts.t? || args.first.nil?
149
+ file_name = temp_file do |f|
150
+ f.puts eval_string if !eval_string.empty?
151
+ end
152
+ line = eval_string.lines.count + 1
153
+ should_reload_locally = opts[:n] ? false : true
142
154
  else
143
- next output.puts("Need to specify a file.") if !args.first
144
- file_name = File.expand_path(args.first)
145
- line = opts[:l].to_i
155
+ # break up into file:line
156
+ /(:(\d+))?$/ =~ File.expand_path(args.first)
157
+
158
+ # $` is pre-match
159
+ file_name, line = [$`, $2]
160
+ line = line ? line.to_i : opts[:l].to_i
146
161
  end
147
162
 
148
163
  invoke_editor(file_name, line)
@@ -150,11 +165,15 @@ class Pry
150
165
 
151
166
  if opts[:p]
152
167
  silence_warnings do
153
- Pry.active_instance.input = StringIO.new(File.readlines(file_name).join)
168
+ _pry_.input = StringIO.new(File.readlines(file_name).join)
154
169
  end
155
- elsif should_reload
170
+ elsif should_reload_locally
156
171
  silence_warnings do
157
- context.eval(File.read(file_name))
172
+ eval_string.replace(File.read(file_name))
173
+ end
174
+ elsif should_reload_at_top_level
175
+ silence_warnings do
176
+ TOPLEVEL_BINDING.eval(File.read(file_name), file_name)
158
177
  end
159
178
  end
160
179
  end
@@ -165,7 +184,7 @@ class Pry
165
184
  opts = Slop.parse!(args) do |opt|
166
185
  opt.banner "Usage: edit-method [OPTIONS] [METH]\n" \
167
186
  "Edit the method METH in an editor.\n" \
168
- "Ensure #{text.bold("Pry.editor")} is set to your editor of choice.\n" \
187
+ "Ensure #{text.bold("Pry.config.editor")} is set to your editor of choice.\n" \
169
188
  "e.g: edit-method hello_method"
170
189
 
171
190
  opt.on :M, "instance-methods", "Operate on instance methods."
@@ -188,7 +207,7 @@ class Pry
188
207
  next
189
208
  end
190
209
 
191
- next output.puts "Error: No editor set!\nEnsure that #{text.bold("Pry.editor")} is set to your editor of choice." if !Pry.editor
210
+ next output.puts "Error: No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice." if !Pry.config.editor
192
211
 
193
212
  if is_a_c_method?(meth)
194
213
  output.puts "Error: Can't edit a C method."
@@ -207,41 +226,6 @@ class Pry
207
226
  end
208
227
  end
209
228
 
210
- helpers do
211
-
212
- def invoke_editor(file, line)
213
- if Pry.editor.respond_to?(:call)
214
- editor_invocation = Pry.editor.call(file, line)
215
- else
216
- editor_invocation = "#{Pry.editor} #{start_line_syntax_for_editor(file, line)}"
217
- end
218
-
219
- run ".#{editor_invocation}"
220
- end
221
-
222
- def start_line_syntax_for_editor(file_name, line_number)
223
- file_name = file_name.gsub(/\//, '\\') if RUBY_PLATFORM =~ /mswin|mingw/
224
-
225
- case Pry.editor
226
- when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
227
- "+#{line_number} #{file_name}"
228
- when /^mate/, /^geany/
229
- "-l #{line_number} #{file_name}"
230
- when /^uedit32/
231
- "#{file_name}/#{line_number}"
232
- when /^jedit/
233
- "#{file_name} +line:#{line_number}"
234
- else
235
- if RUBY_PLATFORM =~ /mswin|mingw/
236
- "#{file_name}"
237
- else
238
- "+#{line_number} #{file_name}"
239
- end
240
- end
241
- end
242
-
243
- end
244
-
245
229
  end
246
230
  end
247
231
  end
@@ -19,6 +19,23 @@ class Pry
19
19
  Object.send("#{visibility}_instance_methods")
20
20
  end
21
21
  end
22
+
23
+ def ls_color_map
24
+ {
25
+ "local variables" => Pry.config.ls.local_var_color,
26
+ "instance variables" => Pry.config.ls.instance_var_color,
27
+ "class variables" => Pry.config.ls.class_var_color,
28
+ "global variables" => Pry.config.ls.global_var_color,
29
+ "just singleton methods" => Pry.config.ls.method_color,
30
+ "public methods" => Pry.config.ls.method_color,
31
+ "private methods" => Pry.config.ls.method_color,
32
+ "protected methods" => Pry.config.ls.method_color,
33
+ "public instance methods" => Pry.config.ls.instance_method_color,
34
+ "private instance methods" => Pry.config.ls.instance_method_color,
35
+ "protected instance methods" => Pry.config.ls.instance_method_color,
36
+ "constants" => Pry.config.ls.constant_color
37
+ }
38
+ end
22
39
  end
23
40
 
24
41
  command "ls", "Show the list of vars and methods in the current scope. Type `ls --help` for more info." do |*args|
@@ -154,7 +171,7 @@ Shows local and instance variables by default.
154
171
 
155
172
  info["private methods"] = [Array(target.eval("private_methods(#{options[:s]})")).sort - trim_methods(target, options, :private), i += 1] if (options[:m] && options[:p]) || options[:a]
156
173
 
157
- info["just singleton methods"] = [Array(target.eval("methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:j]) || options[:a]
174
+ info["just singleton methods"] = [Array(target.eval("methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:j]) && !options[:a]
158
175
 
159
176
  info["public instance methods"] = [Array(target.eval("public_instance_methods(#{options[:s]})")).uniq.sort - trim_methods(target, options, :public), i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:P]) || options[:a])
160
177
 
@@ -181,11 +198,7 @@ Shows local and instance variables by default.
181
198
  if !v.first.empty?
182
199
  text << "#{k}:\n--\n"
183
200
  filtered_list = v.first.grep options[:grep]
184
- if Pry.color
185
- text << CodeRay.scan(Pry.view(filtered_list), :ruby).term + "\n"
186
- else
187
- text << Pry.view(filtered_list) + "\n"
188
- end
201
+ text << text().send(ls_color_map[k], (filtered_list.join(Pry.config.ls.separator)))
189
202
  text << "\n\n"
190
203
  end
191
204
  end
@@ -198,14 +211,9 @@ Shows local and instance variables by default.
198
211
 
199
212
  # plain
200
213
  else
201
- list = info.values.sort_by(&:last).map(&:first).inject(&:+)
202
- list = list.grep(options[:grep]) if list
203
- list.uniq! if list
204
- if Pry.color
205
- text << CodeRay.scan(list.inspect, :ruby).term + "\n"
206
- else
207
- text << list.inspect + "\n"
208
- end
214
+ list = info.sort_by { |k, v| v.last }.map { |k, v| [k, [v.first.grep(options[:grep])], v.last] }
215
+ list = list.each { |k, v| text << text().send(ls_color_map[k], v.first.join(Pry.config.ls.separator)); text << Pry.config.ls.separator }
216
+
209
217
  if !options[:f]
210
218
  stagger_output(text)
211
219
  else
@@ -20,15 +20,15 @@ class Pry
20
20
  end
21
21
 
22
22
  command "shell-mode", "Toggle shell mode. Bring in pwd prompt and file completion." do
23
- case Pry.active_instance.prompt
23
+ case _pry_.prompt
24
24
  when Pry::SHELL_PROMPT
25
- Pry.active_instance.pop_prompt
26
- Pry.active_instance.custom_completions = Pry::DEFAULT_CUSTOM_COMPLETIONS
25
+ _pry_.pop_prompt
26
+ _pry_.custom_completions = Pry::DEFAULT_CUSTOM_COMPLETIONS
27
27
  else
28
- Pry.active_instance.push_prompt Pry::SHELL_PROMPT
29
- Pry.active_instance.custom_completions = Pry::FILE_COMPLETIONS
28
+ _pry_.push_prompt Pry::SHELL_PROMPT
29
+ _pry_.custom_completions = Pry::FILE_COMPLETIONS
30
30
  Readline.completion_proc = Pry::InputCompleter.build_completion_proc target,
31
- Pry.active_instance.instance_eval(&Pry::FILE_COMPLETIONS)
31
+ _pry_.instance_eval(&Pry::FILE_COMPLETIONS)
32
32
  end
33
33
  end
34
34
 
@@ -48,14 +48,18 @@ class Pry
48
48
  end_line = line - 1
49
49
  end
50
50
 
51
- opt.on :ex, "Show a window of N lines around last exception (defaults to 5).", :optional => true, :as => Integer do |window_size|
51
+ opt.on :ex, "Show a window of N lines either side of the last exception (defaults to 5).", :optional => true, :as => Integer do |window_size|
52
52
  window_size ||= 5
53
- ex = Pry.last_exception
53
+ ex = _pry_.last_exception
54
54
  next if !ex
55
55
  start_line = (ex.line - 1) - window_size
56
56
  start_line = start_line < 0 ? 0 : start_line
57
57
  end_line = (ex.line - 1) + window_size
58
- file_name = ex.file
58
+ if is_core_rbx_path?(ex.file)
59
+ file_name = rbx_convert_path_to_full(ex.file)
60
+ else
61
+ file_name = ex.file
62
+ end
59
63
  end
60
64
 
61
65
  opt.on :l, "line-numbers", "Show line numbers."
@@ -80,27 +84,38 @@ class Pry
80
84
  next
81
85
  end
82
86
 
83
- contents, normalized_start_line, _ = read_between_the_lines(file_name, start_line, end_line)
87
+ contents, _, _ = read_between_the_lines(file_name, start_line, end_line)
88
+ contents = syntax_highlight_by_file_type_or_specified(contents, file_name, opts[:type])
89
+
90
+ if opts.l?
91
+ contents = text.with_line_numbers contents, start_line + 1
92
+ end
84
93
 
85
94
  # add the arrow pointing to line that caused the exception
86
95
  if opts.ex?
96
+ contents = text.with_line_numbers contents, start_line + 1, :bright_red
97
+
87
98
  contents = contents.lines.each_with_index.map do |line, idx|
88
99
  l = idx + start_line
89
- if l == (Pry.last_exception.line - 1)
90
- "=> #{line}"
100
+ if l == (_pry_.last_exception.line - 1)
101
+ " =>#{line}"
91
102
  else
92
103
  " #{line}"
93
104
  end
94
105
  end.join
95
- end
96
106
 
97
- if Pry.color
98
- contents = syntax_highlight_by_file_type_or_specified(contents, file_name, opts[:type])
107
+ # header for exceptions
108
+ output.puts "\n#{Pry::Helpers::Text.bold('Exception:')} #{_pry_.last_exception.class}: #{_pry_.last_exception.message}\n--"
109
+ output.puts "#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{_pry_.last_exception.line}\n\n"
99
110
  end
100
111
 
101
112
  set_file_and_dir_locals(file_name)
102
- render_output(opts.flood?, opts.l? ? normalized_start_line + 1 : false, contents)
103
- contents
113
+
114
+ if opts.f?
115
+ output.puts contents
116
+ else
117
+ stagger_output(contents)
118
+ end
104
119
  end
105
120
  end
106
121
 
@@ -7,7 +7,7 @@ class Pry
7
7
  next output.puts("Provide an arg!") if arg.nil?
8
8
 
9
9
  prime_string = "command #{arg_string}\n"
10
- command_string = Pry.active_instance.r(target, prime_string)
10
+ command_string = _pry_.r(target, prime_string)
11
11
 
12
12
  eval_string.replace <<-HERE
13
13
  _pry_.commands.instance_eval do
@@ -17,6 +17,37 @@ class Pry
17
17
 
18
18
  end
19
19
 
20
+ command "reload-command", "Reload a command. reload-command CMD_NAME CMD_SET" do |command_name, set_name|
21
+ next output.puts "Must provide command name" if command_name.nil?
22
+ next output.puts "Must provide command set name" if set_name.nil?
23
+
24
+ cmd = Pry.config.commands.commands[command_name]
25
+ file_name = cmd.block.source_location.first
26
+
27
+ silence_warnings do
28
+ load file_name
29
+ end
30
+ Pry.config.commands.import target.eval(set_name)
31
+ _pry_.commands.import target.eval(set_name)
32
+ set_file_and_dir_locals(file_name)
33
+ end
34
+
35
+ command "edit-command", "Edit a command. edit-command CMD_NAME CMD_SET" do |command_name, set_name|
36
+ next output.puts "Must provide command name" if command_name.nil?
37
+ next output.puts "Must provide a command set name" if set_name.nil?
38
+
39
+ cmd = Pry.config.commands.commands[command_name]
40
+ file_name = cmd.block.source_location.first
41
+
42
+ invoke_editor(*cmd.block.source_location)
43
+ silence_warnings do
44
+ load file_name
45
+ end
46
+ Pry.config.commands.import target.eval(set_name)
47
+ _pry_.commands.import target.eval(set_name)
48
+ set_file_and_dir_locals(file_name)
49
+ end
50
+
20
51
  end
21
52
  end
22
53
  end
@@ -2,6 +2,7 @@ class Pry
2
2
  module Helpers
3
3
 
4
4
  module BaseHelpers
5
+
5
6
  module_function
6
7
 
7
8
  def silence_warnings
@@ -35,10 +36,11 @@ class Pry
35
36
 
36
37
  def set_file_and_dir_locals(file_name)
37
38
  return if !target
38
- $_file_temp = File.expand_path(file_name)
39
- $_dir_temp = File.dirname($_file_temp)
40
- target.eval("_file_ = $_file_temp")
41
- target.eval("_dir_ = $_dir_temp")
39
+ _pry_.last_file = File.expand_path(file_name)
40
+ _pry_.inject_local("_file_", _pry_.last_file, target)
41
+
42
+ _pry_.last_dir = File.dirname(_pry_.last_file)
43
+ _pry_.inject_local("_dir_", _pry_.last_dir, target)
42
44
  end
43
45
 
44
46
  def stub_proc(name, options)
@@ -72,7 +74,7 @@ class Pry
72
74
  end
73
75
 
74
76
  def highlight(string, regexp, highlight_color=:bright_yellow)
75
- highlighted = string.gsub(regexp) { |match| "<#{highlight_color}>#{match}</#{highlight_color}>" }
77
+ string.gsub(regexp) { |match| "<#{highlight_color}>#{match}</#{highlight_color}>" }
76
78
  end
77
79
 
78
80
  # formatting
@@ -85,8 +87,18 @@ class Pry
85
87
  27
86
88
  end
87
89
 
90
+ # are we on Jruby platform?
91
+ def jruby?
92
+ defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/
93
+ end
94
+
95
+ # are we on rbx platform?
96
+ def rbx?
97
+ defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
98
+ end
99
+
88
100
  # a simple pager for systems without `less`. A la windows.
89
- def simple_pager(text)
101
+ def simple_pager(text, output=output())
90
102
  text_array = text.lines.to_a
91
103
  text_array.each_slice(page_size) do |chunk|
92
104
  output.puts chunk.join
@@ -108,13 +120,13 @@ class Pry
108
120
  end
109
121
 
110
122
  # FIXME! Another JRuby hack
111
- if Object.const_defined?(:RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/
112
- simple_pager(text)
123
+ if jruby?
124
+ simple_pager(text, output)
113
125
  else
114
126
  lesspipe { |less| less.puts text }
115
127
  end
116
128
  rescue Errno::ENOENT
117
- simple_pager(text)
129
+ simple_pager(text, output)
118
130
  rescue Errno::EPIPE
119
131
  end
120
132