pry 0.9.8pre5-i386-mswin32 → 0.9.8pre6-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,67 +28,94 @@ class Pry
28
28
  _pry_.instance_eval(&Pry::FILE_COMPLETIONS)
29
29
  end
30
30
  end
31
-
32
31
  alias_command "file-mode", "shell-mode"
33
32
 
34
- command "cat", "Show code from a file or Pry's input buffer. Type `cat --help` for more information." do |*args|
35
- start_line = 0
36
- end_line = -1
37
- file_name = nil
38
- bt_index = 0
33
+ command_class "cat", "Show code from a file, Pry's input buffer, or the last exception." do
34
+ banner <<-USAGE
35
+ Usage: cat FILE
36
+ cat --ex [STACK_INDEX]
37
+ cat --in [INPUT_INDEX_OR_RANGE]
39
38
 
40
- opts = Slop.parse!(args) do |opt|
41
- opt.on :s, :start, "Start line (defaults to start of file)Line 1 is the first line.", true, :as => Integer do |line|
42
- start_line = line - 1
43
- end
39
+ cat is capable of showing part or all of a source file, the context of the
40
+ last exception, or an expression from Pry's input history.
44
41
 
45
- opt.on :e, :end, "End line (defaults to end of file). Line -1 is the last line", true, :as => Integer do |line|
46
- end_line = line - 1
47
- end
42
+ cat --ex defaults to showing the lines surrounding the location of the last
43
+ exception. Invoking it more than once travels up the exception's backtrace,
44
+ and providing a number shows the context of the given index of the backtrace.
45
+ USAGE
48
46
 
49
- opt.on :ex, "Show a window of N lines either side of the last exception (defaults to 5).", :optional => true, :as => Integer do |bt_index_arg|
50
- window_size = Pry.config.exception_window_size || 5
51
- ex = _pry_.last_exception
52
- next if !ex
53
- if bt_index_arg
54
- bt_index = bt_index_arg
55
- else
56
- bt_index = ex.bt_index
57
- end
58
- ex.bt_index = (bt_index + 1) % ex.backtrace.size
59
-
60
- ex_file, ex_line = ex.bt_source_location_for(bt_index)
61
- start_line = (ex_line - 1) - window_size
62
- start_line = start_line < 0 ? 0 : start_line
63
- end_line = (ex_line - 1) + window_size
64
- if ex_file && RbxPath.is_core_path?(ex_file)
65
- file_name = RbxPath.convert_path_to_full(ex_file)
47
+ def options(opt)
48
+ opt.on :ex, "Show the context of the last exception.", :optional => true, :as => Integer
49
+ opt.on :i, :in, "Show one or more entries from Pry's expression history.", :optional => true, :as => Range, :default => -5..-1
50
+
51
+ opt.on :s, :start, "Starting line (defaults to the first line).", :optional => true, :as => Integer
52
+ opt.on :e, :end, "Ending line (defaults to the last line).", :optional => true, :as => Integer
53
+ opt.on :l, :'line-numbers', "Show line numbers."
54
+ opt.on :t, :type, "The file type for syntax highlighting (e.g., 'ruby' or 'python').", true, :as => Symbol
55
+
56
+ opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
57
+ end
58
+
59
+ def process
60
+ handler = case
61
+ when opts.present?(:ex)
62
+ method :process_ex
63
+ when opts.present?(:in)
64
+ method :process_in
66
65
  else
67
- file_name = ex_file
66
+ method :process_file
68
67
  end
69
- end
70
68
 
71
- opt.on :i, :in, "Show entries from Pry's input expression history. Takes an index or range.", :optional => true, :as => Range, :default => -5..-1
69
+ output = handler.call do |code|
70
+ code.code_type = opts[:type] || :ruby
72
71
 
73
- opt.on :l, "line-numbers", "Show line numbers."
74
- opt.on :t, :type, "The specific file type for syntax higlighting (e.g ruby, python)", true, :as => Symbol
75
- opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
76
- opt.on :h, :help, "This message." do
77
- output.puts opt.help
72
+ code.between(opts[:start] || 1, opts[:end] || -1).
73
+ with_line_numbers(opts.present?(:'line-numbers') || opts.present?(:ex))
78
74
  end
75
+
76
+ render_output(output, opts)
79
77
  end
80
78
 
81
- next if opts.present?(:help)
79
+ def process_ex
80
+ window_size = Pry.config.default_window_size || 5
81
+ ex = _pry_.last_exception
82
+
83
+ raise CommandError, "No exception found." unless ex
82
84
 
83
- if opts.present?(:ex)
84
- if file_name.nil?
85
- raise CommandError, "No Exception or Exception has no associated file."
85
+ if opts[:ex].nil?
86
+ bt_index = ex.bt_index
87
+ ex.inc_bt_index
88
+ else
89
+ bt_index = opts[:ex]
86
90
  end
87
- else
88
- file_name = args.shift
91
+
92
+ ex_file, ex_line = ex.bt_source_location_for(bt_index)
93
+
94
+ raise CommandError, "The given backtrace level is out of bounds." unless ex_file
95
+
96
+ if RbxPath.is_core_path?(ex_file)
97
+ ex_file = RbxPath.convert_path_to_full(ex_file)
98
+ end
99
+
100
+ start_line = ex_line - window_size
101
+ start_line = 1 if start_line < 1
102
+ end_line = ex_line + window_size
103
+
104
+ header = unindent <<-HEADER
105
+ #{text.bold 'Exception:'} #{ex.class}: #{ex.message}
106
+ --
107
+ #{text.bold('From:')} #{ex_file} @ line #{ex_line} @ #{text.bold("level: #{bt_index}")} of backtrace (of #{ex.backtrace.size - 1}).
108
+
109
+ HEADER
110
+
111
+ code = yield(Pry::Code.from_file(ex_file).
112
+ between(start_line, end_line).
113
+ with_marker(ex_line))
114
+
115
+ "#{header}#{code}"
89
116
  end
90
117
 
91
- if opts.present?(:in)
118
+ def process_in
92
119
  normalized_range = absolute_index_range(opts[:i], _pry_.input_array.length)
93
120
  input_items = _pry_.input_array[normalized_range] || []
94
121
 
@@ -98,66 +125,37 @@ class Pry
98
125
  raise CommandError, "No expressions found."
99
126
  end
100
127
 
101
- if opts[:i].is_a?(Range)
128
+ if zipped_items.length > 1
102
129
  contents = ""
103
-
104
130
  zipped_items.each do |i, s|
105
131
  contents << "#{text.bold(i.to_s)}:\n"
106
-
107
- code = syntax_highlight_by_file_type_or_specified(s, nil, :ruby)
108
-
109
- if opts.present?(:'line-numbers')
110
- contents << text.indent(text.with_line_numbers(code, 1), 2)
111
- else
112
- contents << text.indent(code, 2)
113
- end
132
+ contents << yield(Pry::Code(s).with_indentation(2)).to_s
114
133
  end
115
134
  else
116
- contents = syntax_highlight_by_file_type_or_specified(zipped_items.first.last, nil, :ruby)
117
- end
118
- else
119
- unless file_name
120
- raise CommandError, "Must provide a file name."
135
+ contents = yield(Pry::Code(zipped_items.first.last))
121
136
  end
122
137
 
123
- begin
124
- contents, _, _ = read_between_the_lines(file_name, start_line, end_line)
125
- rescue Errno::ENOENT
126
- raise CommandError, "Could not find file: #{file_name}"
127
- end
138
+ contents
139
+ end
128
140
 
129
- contents = syntax_highlight_by_file_type_or_specified(contents, file_name, opts[:type])
141
+ def process_file
142
+ file_name = args.shift
130
143
 
131
- if opts.present?(:'line-numbers')
132
- contents = text.with_line_numbers contents, start_line + 1
144
+ unless file_name
145
+ raise CommandError, "Must provide a filename, --in, or --ex."
133
146
  end
134
- end
135
147
 
136
- # add the arrow pointing to line that caused the exception
137
- if opts.present?(:ex)
138
- ex_file, ex_line = _pry_.last_exception.bt_source_location_for(bt_index)
139
- contents = text.with_line_numbers contents, start_line + 1, :bright_red
148
+ file_name, line_num = file_name.split(':')
149
+ set_file_and_dir_locals(file_name)
140
150
 
141
- contents = contents.lines.each_with_index.map do |line, idx|
142
- l = idx + start_line
143
- if l == (ex_line - 1)
144
- " =>#{line}"
145
- else
146
- " #{line}"
147
- end
148
- end.join
149
-
150
- # header for exceptions
151
- output.puts "\n#{Pry::Helpers::Text.bold('Exception:')} #{_pry_.last_exception.class}: #{_pry_.last_exception.message}\n--"
152
- output.puts "#{Pry::Helpers::Text.bold('From:')} #{ex_file} @ line #{ex_line} @ #{text.bold('level: ')} #{bt_index} of backtrace (of #{_pry_.last_exception.backtrace.size - 1}).\n\n"
153
- end
151
+ code = yield(Pry::Code.from_file(file_name))
154
152
 
155
- set_file_and_dir_locals(file_name)
153
+ if line_num
154
+ code = code.around(line_num.to_i,
155
+ Pry.config.default_window_size || 7)
156
+ end
156
157
 
157
- if opts.present?(:flood)
158
- output.puts contents
159
- else
160
- stagger_output(contents)
158
+ code
161
159
  end
162
160
  end
163
161
  end
@@ -6,26 +6,21 @@ class Pry
6
6
 
7
7
  module_function
8
8
 
9
- # if start_line is not false then add line numbers starting with start_line
10
- def render_output(should_flood, start_line, text, color=:blue)
11
- if start_line
12
- text = Pry::Helpers::Text.with_line_numbers text, start_line, color
13
- end
14
-
15
- if should_flood
16
- output.puts text
17
- else
18
- stagger_output(text)
19
- end
20
- end
21
-
22
9
  # Open a temp file and yield it to the block, closing it after
23
10
  # @return [String] The path of the temp file
24
- def temp_file
25
- file = Tempfile.new(['pry', '.rb'])
11
+ def temp_file(ext='.rb')
12
+ file = Tempfile.new(['pry', ext])
26
13
  yield file
27
14
  ensure
28
- file.close(true)
15
+ file.close(true) if file
16
+ end
17
+
18
+ def render_output(str, opts={})
19
+ if opts[:flood]
20
+ output.puts str
21
+ else
22
+ stagger_output str
23
+ end
29
24
  end
30
25
 
31
26
  def get_method_or_raise(name, target, opts={}, omit_help=false)
@@ -34,7 +29,7 @@ class Pry
34
29
  if name && !meth
35
30
  command_error("The method '#{name}' could not be found.", omit_help)
36
31
  elsif !meth
37
- command_error("No method name given, and context is not a method.", omit_help)
32
+ command_error("No method name given, and context is not a method.", omit_help, NonMethodContextError)
38
33
  end
39
34
 
40
35
  (opts[:super] || 0).times do
@@ -49,9 +44,9 @@ class Pry
49
44
  meth
50
45
  end
51
46
 
52
- def command_error(message, omit_help)
47
+ def command_error(message, omit_help, klass=CommandError)
53
48
  message += " Type `#{command_name} --help` for help." unless omit_help
54
- raise CommandError, message
49
+ raise klass, message
55
50
  end
56
51
 
57
52
  def make_header(meth, content=meth.source)
@@ -66,63 +61,6 @@ class Pry
66
61
  header << "#{Pry::Helpers::Text.bold("Number of lines:")} #{content.each_line.count.to_s}\n"
67
62
  end
68
63
 
69
- def file_map
70
- {
71
- [".c", ".h"] => :c,
72
- [".cpp", ".hpp", ".cc", ".h", "cxx"] => :cpp,
73
- [".rb", "Rakefile", ".irbrc", ".gemspec", ".pryrc"] => :ruby,
74
- ".py" => :python,
75
- ".diff" => :diff,
76
- ".css" => :css,
77
- ".html" => :html,
78
- [".yaml", ".yml"] => :yaml,
79
- ".xml" => :xml,
80
- ".php" => :php,
81
- ".js" => :javascript,
82
- ".java" => :java,
83
- ".rhtml" => :rhtml,
84
- ".json" => :json
85
- }
86
- end
87
-
88
- def syntax_highlight_by_file_type_or_specified(contents, file_name, file_type)
89
- if file_type
90
- language_detected = file_type
91
- else
92
- _, language_detected = file_map.find do |k, v|
93
- Array(k).any? do |matcher|
94
- matcher == File.extname(file_name) || matcher == File.basename(file_name)
95
- end
96
- end
97
- end
98
-
99
- if Pry.color
100
- CodeRay.scan(contents, language_detected).term
101
- else
102
- contents
103
- end
104
- end
105
-
106
- # convert negative line numbers to positive by wrapping around
107
- # last line (as per array indexing with negative numbers)
108
- def normalized_line_number(line_number, total_lines)
109
- line_number < 0 ? line_number + total_lines : line_number
110
- end
111
-
112
- # returns the file content between the lines and the normalized
113
- # start and end line numbers.
114
- def read_between_the_lines(file_name, start_line, end_line)
115
- if file_name == Pry.eval_path
116
- content = Pry.line_buffer.drop(1).join
117
- else
118
- content = File.read(File.expand_path(file_name))
119
- end
120
- lines_array = content.each_line.to_a
121
-
122
- [lines_array[start_line..end_line].join, normalized_line_number(start_line, lines_array.size),
123
- normalized_line_number(end_line, lines_array.size)]
124
- end
125
-
126
64
  def process_rdoc(comment, code_type)
127
65
  comment = comment.dup
128
66
  comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
data/lib/pry/hooks.rb CHANGED
@@ -20,6 +20,10 @@ class Pry
20
20
  end
21
21
  protected :hooks
22
22
 
23
+ def errors
24
+ @errors ||= []
25
+ end
26
+
23
27
  # Destructively merge the contents of two `Pry:Hooks` instances.
24
28
  # @param [Pry::Hooks] other The `Pry::Hooks` instance to merge
25
29
 
@@ -89,7 +93,14 @@ class Pry
89
93
  # silence warnings to get rid of 1.8's "warning: multiple values
90
94
  # for a block parameter" warnings
91
95
  Pry::Helpers::BaseHelpers.silence_warnings do
92
- @hooks[event_name].map { |hook_name, callable| callable.call(*args, &block) }.last
96
+ @hooks[event_name].map do |hook_name, callable|
97
+ begin
98
+ callable.call(*args, &block)
99
+ rescue RescuableException => e
100
+ errors << e
101
+ e
102
+ end
103
+ end.last
93
104
  end
94
105
  end
95
106
 
data/lib/pry/pry_class.rb CHANGED
@@ -116,7 +116,7 @@ class Pry
116
116
  pry_instance.backtrace = caller.tap(&:shift)
117
117
 
118
118
  # yield the binding_stack to the hook for modification
119
- Pry.config.hooks.exec_hook(
119
+ pry_instance.exec_hook(
120
120
  :when_started,
121
121
  binding_stack = [target],
122
122
  options,
@@ -220,8 +220,8 @@ class Pry
220
220
  config.prompt = DEFAULT_PROMPT
221
221
  config.print = DEFAULT_PRINT
222
222
  config.exception_handler = DEFAULT_EXCEPTION_HANDLER
223
- config.exception_window_size = 5
224
223
  config.exception_whitelist = DEFAULT_EXCEPTION_WHITELIST
224
+ config.default_window_size = 5
225
225
  config.hooks = DEFAULT_HOOKS
226
226
  config.input_stack = []
227
227
  config.color = Helpers::BaseHelpers.use_ansi_codes?
@@ -237,7 +237,7 @@ class Pry
237
237
  config.collision_warning = false
238
238
 
239
239
  config.gist ||= OpenStruct.new
240
- config.gist.inspecter = proc &:pretty_inspect
240
+ config.gist.inspecter = proc(&:pretty_inspect)
241
241
 
242
242
  config.plugins ||= OpenStruct.new
243
243
  config.plugins.enabled = true
@@ -15,10 +15,11 @@ class Pry
15
15
  attr_accessor :binding_stack
16
16
 
17
17
  attr_accessor :last_result
18
- attr_accessor :last_exception
19
18
  attr_accessor :last_file
20
19
  attr_accessor :last_dir
21
20
 
21
+ attr_reader :last_exception
22
+
22
23
  attr_reader :input_array
23
24
  attr_reader :output_array
24
25
 
@@ -142,7 +143,7 @@ class Pry
142
143
  # Initialize the repl session.
143
144
  # @param [Binding] target The target binding for the session.
144
145
  def repl_prologue(target)
145
- hooks.exec_hook :before_session, output, target, self
146
+ exec_hook :before_session, output, target, self
146
147
  initialize_special_locals(target)
147
148
 
148
149
  @input_array << nil # add empty input so _in_ and _out_ match
@@ -154,7 +155,7 @@ class Pry
154
155
  # Clean-up after the repl session.
155
156
  # @param [Binding] target The target binding for the session.
156
157
  def repl_epilogue(target)
157
- hooks.exec_hook :after_session, output, target, self
158
+ exec_hook :after_session, output, target, self
158
159
 
159
160
  Pry.active_sessions -= 1
160
161
  binding_stack.pop
@@ -231,10 +232,11 @@ class Pry
231
232
 
232
233
  result
233
234
  rescue RescuableException => e
234
- result = set_last_exception(e, target)
235
+ self.last_exception = e
236
+ e
235
237
  ensure
236
238
  update_input_history(code)
237
- hooks.exec_hook :after_eval, result, self
239
+ exec_hook :after_eval, result, self
238
240
  end
239
241
 
240
242
  # Perform a read.
@@ -270,7 +272,7 @@ class Pry
270
272
 
271
273
  @suppress_output = true if eval_string =~ /;\Z/ || eval_string.empty?
272
274
 
273
- hooks.exec_hook :after_read, eval_string, self
275
+ exec_hook :after_read, eval_string, self
274
276
  eval_string
275
277
  end
276
278
 
@@ -337,6 +339,7 @@ class Pry
337
339
 
338
340
  if original_val != indented_val && output.tty? && Pry::Helpers::BaseHelpers.use_ansi_codes? && Pry.config.correct_indent
339
341
  output.print @indent.correct_indentation(current_prompt + indented_val, original_val.length - indented_val.length)
342
+ output.flush
340
343
  end
341
344
  else
342
345
  indented_val = val
@@ -402,6 +405,25 @@ class Pry
402
405
  Pry::Command::VOID_VALUE
403
406
  end
404
407
 
408
+ # Execute the specified hook.
409
+ # @param [Symbol] name The hook name to execute
410
+ # @param [*Object] args The arguments to pass to the hook
411
+ # @return [Object, Exception] The return value of the hook or the exception raised
412
+ #
413
+ # If executing a hook raises an exception, we log that and then continue sucessfully.
414
+ # To debug such errors, use the global variable $pry_hook_error, which is set as a
415
+ # result.
416
+ def exec_hook(name, *args, &block)
417
+ e_before = hooks.errors.size
418
+ hooks.exec_hook(name, *args, &block).tap do
419
+ hooks.errors[e_before..-1].each do |e|
420
+ output.puts "#{name} hook failed: #{e.class}: #{e.message}"
421
+ output.puts "#{e.backtrace.first}"
422
+ output.puts "(see _pry_.hooks.errors to debug)"
423
+ end
424
+ end
425
+ end
426
+
405
427
  # Set the last result of an eval.
406
428
  # This method should not need to be invoked directly.
407
429
  # @param [Object] result The result.
@@ -415,16 +437,18 @@ class Pry
415
437
  end
416
438
 
417
439
  # Set the last exception for a session.
418
- # This method should not need to be invoked directly.
419
- # @param [Exception] ex The exception.
420
- # @param [Binding] target The binding to set `_ex_` on.
421
- def set_last_exception(ex, target)
440
+ # @param [Exception] ex
441
+ def last_exception=(ex)
422
442
  class << ex
423
443
  attr_accessor :file, :line, :bt_index
424
444
  def bt_source_location_for(index)
425
445
  backtrace[index] =~ /(.*):(\d+)/
426
446
  [$1, $2.to_i]
427
447
  end
448
+
449
+ def inc_bt_index
450
+ @bt_index = (@bt_index + 1) % backtrace.size
451
+ end
428
452
  end
429
453
 
430
454
  ex.bt_index = 0
@@ -432,8 +456,7 @@ class Pry
432
456
 
433
457
  @last_result_is_exception = true
434
458
  @output_array << ex
435
-
436
- self.last_exception = ex
459
+ @last_exception = ex
437
460
  end
438
461
 
439
462
  # Update Pry's internal state after evalling code.
@@ -569,9 +592,11 @@ class Pry
569
592
  elsif defined?(Rubinius::Melbourne)
570
593
  Rubinius::Melbourne.parse_string(str, Pry.eval_path)
571
594
  else
572
- catch(:valid) {
573
- eval("BEGIN{throw :valid}\n#{str}", binding, Pry.eval_path)
574
- }
595
+ catch(:valid) do
596
+ Helpers::BaseHelpers.silence_warnings do
597
+ eval("BEGIN{throw :valid}\n#{str}", binding, Pry.eval_path)
598
+ end
599
+ end
575
600
  end
576
601
 
577
602
  # Assert that a line which ends with a , is incomplete.