pry 0.10.1 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +378 -11
  3. data/LICENSE +1 -1
  4. data/README.md +352 -306
  5. data/bin/pry +4 -7
  6. data/lib/pry/basic_object.rb +10 -0
  7. data/lib/pry/block_command.rb +22 -0
  8. data/lib/pry/class_command.rb +194 -0
  9. data/lib/pry/cli.rb +81 -74
  10. data/lib/pry/code/code_file.rb +37 -26
  11. data/lib/pry/code/code_range.rb +7 -5
  12. data/lib/pry/code/loc.rb +26 -13
  13. data/lib/pry/code.rb +49 -30
  14. data/lib/pry/code_object.rb +53 -28
  15. data/lib/pry/color_printer.rb +46 -35
  16. data/lib/pry/command.rb +197 -369
  17. data/lib/pry/command_set.rb +89 -114
  18. data/lib/pry/command_state.rb +31 -0
  19. data/lib/pry/commands/amend_line.rb +86 -82
  20. data/lib/pry/commands/bang.rb +18 -14
  21. data/lib/pry/commands/bang_pry.rb +15 -11
  22. data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
  23. data/lib/pry/commands/cat/exception_formatter.rb +85 -72
  24. data/lib/pry/commands/cat/file_formatter.rb +56 -46
  25. data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
  26. data/lib/pry/commands/cat.rb +62 -54
  27. data/lib/pry/commands/cd.rb +40 -35
  28. data/lib/pry/commands/change_inspector.rb +29 -22
  29. data/lib/pry/commands/change_prompt.rb +48 -23
  30. data/lib/pry/commands/clear_screen.rb +20 -0
  31. data/lib/pry/commands/code_collector.rb +148 -131
  32. data/lib/pry/commands/disable_pry.rb +23 -19
  33. data/lib/pry/commands/easter_eggs.rb +23 -34
  34. data/lib/pry/commands/edit/exception_patcher.rb +21 -17
  35. data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
  36. data/lib/pry/commands/edit.rb +185 -157
  37. data/lib/pry/commands/exit.rb +40 -35
  38. data/lib/pry/commands/exit_all.rb +24 -20
  39. data/lib/pry/commands/exit_program.rb +20 -16
  40. data/lib/pry/commands/find_method.rb +168 -162
  41. data/lib/pry/commands/fix_indent.rb +16 -12
  42. data/lib/pry/commands/help.rb +140 -133
  43. data/lib/pry/commands/hist.rb +151 -149
  44. data/lib/pry/commands/import_set.rb +20 -15
  45. data/lib/pry/commands/jump_to.rb +25 -21
  46. data/lib/pry/commands/list_inspectors.rb +35 -28
  47. data/lib/pry/commands/ls/constants.rb +59 -31
  48. data/lib/pry/commands/ls/formatter.rb +42 -36
  49. data/lib/pry/commands/ls/globals.rb +38 -36
  50. data/lib/pry/commands/ls/grep.rb +17 -15
  51. data/lib/pry/commands/ls/instance_vars.rb +29 -28
  52. data/lib/pry/commands/ls/interrogatable.rb +18 -12
  53. data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
  54. data/lib/pry/commands/ls/local_names.rb +26 -24
  55. data/lib/pry/commands/ls/local_vars.rb +38 -30
  56. data/lib/pry/commands/ls/ls_entity.rb +47 -52
  57. data/lib/pry/commands/ls/methods.rb +49 -51
  58. data/lib/pry/commands/ls/methods_helper.rb +46 -42
  59. data/lib/pry/commands/ls/self_methods.rb +23 -21
  60. data/lib/pry/commands/ls.rb +124 -103
  61. data/lib/pry/commands/nesting.rb +21 -17
  62. data/lib/pry/commands/play.rb +92 -82
  63. data/lib/pry/commands/pry_backtrace.rb +22 -17
  64. data/lib/pry/commands/pry_version.rb +15 -11
  65. data/lib/pry/commands/raise_up.rb +33 -27
  66. data/lib/pry/commands/reload_code.rb +60 -48
  67. data/lib/pry/commands/reset.rb +16 -12
  68. data/lib/pry/commands/ri.rb +57 -42
  69. data/lib/pry/commands/save_file.rb +45 -43
  70. data/lib/pry/commands/shell_command.rb +56 -29
  71. data/lib/pry/commands/shell_mode.rb +22 -18
  72. data/lib/pry/commands/show_doc.rb +81 -70
  73. data/lib/pry/commands/show_info.rb +194 -155
  74. data/lib/pry/commands/show_input.rb +16 -11
  75. data/lib/pry/commands/show_source.rb +109 -42
  76. data/lib/pry/commands/stat.rb +35 -31
  77. data/lib/pry/commands/switch_to.rb +21 -15
  78. data/lib/pry/commands/toggle_color.rb +20 -16
  79. data/lib/pry/commands/watch_expression/expression.rb +32 -27
  80. data/lib/pry/commands/watch_expression.rb +89 -84
  81. data/lib/pry/commands/whereami.rb +156 -141
  82. data/lib/pry/commands/wtf.rb +78 -40
  83. data/lib/pry/config/attributable.rb +22 -0
  84. data/lib/pry/config/lazy_value.rb +29 -0
  85. data/lib/pry/config/memoized_value.rb +34 -0
  86. data/lib/pry/config/value.rb +24 -0
  87. data/lib/pry/config.rb +317 -20
  88. data/lib/pry/control_d_handler.rb +28 -0
  89. data/lib/pry/core_extensions.rb +22 -9
  90. data/lib/pry/editor.rb +53 -33
  91. data/lib/pry/env.rb +18 -0
  92. data/lib/pry/exception_handler.rb +43 -0
  93. data/lib/pry/exceptions.rb +13 -17
  94. data/lib/pry/forwardable.rb +27 -0
  95. data/lib/pry/helpers/base_helpers.rb +20 -62
  96. data/lib/pry/helpers/command_helpers.rb +52 -62
  97. data/lib/pry/helpers/documentation_helpers.rb +20 -12
  98. data/lib/pry/helpers/options_helpers.rb +15 -8
  99. data/lib/pry/helpers/platform.rb +60 -0
  100. data/lib/pry/helpers/table.rb +44 -32
  101. data/lib/pry/helpers/text.rb +96 -85
  102. data/lib/pry/helpers.rb +3 -0
  103. data/lib/pry/history.rb +81 -55
  104. data/lib/pry/hooks.rb +60 -110
  105. data/lib/pry/indent.rb +72 -66
  106. data/lib/pry/input_completer.rb +199 -158
  107. data/lib/pry/input_lock.rb +7 -10
  108. data/lib/pry/inspector.rb +36 -24
  109. data/lib/pry/last_exception.rb +45 -45
  110. data/lib/pry/method/disowned.rb +19 -5
  111. data/lib/pry/method/patcher.rb +14 -8
  112. data/lib/pry/method/weird_method_locator.rb +79 -43
  113. data/lib/pry/method.rb +177 -124
  114. data/lib/pry/object_path.rb +37 -28
  115. data/lib/pry/output.rb +102 -16
  116. data/lib/pry/pager.rb +187 -174
  117. data/lib/pry/plugins.rb +49 -13
  118. data/lib/pry/prompt.rb +213 -25
  119. data/lib/pry/pry_class.rb +106 -93
  120. data/lib/pry/pry_instance.rb +261 -224
  121. data/lib/pry/repl.rb +82 -27
  122. data/lib/pry/repl_file_loader.rb +27 -22
  123. data/lib/pry/ring.rb +89 -0
  124. data/lib/pry/slop/LICENSE +20 -0
  125. data/lib/pry/slop/commands.rb +190 -0
  126. data/lib/pry/slop/option.rb +210 -0
  127. data/lib/pry/slop.rb +672 -0
  128. data/lib/pry/syntax_highlighter.rb +26 -0
  129. data/lib/pry/system_command_handler.rb +17 -0
  130. data/lib/pry/testable/evalable.rb +24 -0
  131. data/lib/pry/testable/mockable.rb +22 -0
  132. data/lib/pry/testable/pry_tester.rb +88 -0
  133. data/lib/pry/testable/utility.rb +34 -0
  134. data/lib/pry/testable/variables.rb +52 -0
  135. data/lib/pry/testable.rb +68 -0
  136. data/lib/pry/version.rb +3 -1
  137. data/lib/pry/warning.rb +27 -0
  138. data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +29 -27
  139. data/lib/pry/wrapped_module.rb +67 -57
  140. data/lib/pry.rb +134 -149
  141. metadata +49 -59
  142. data/lib/pry/commands/disabled_commands.rb +0 -2
  143. data/lib/pry/commands/gem_cd.rb +0 -26
  144. data/lib/pry/commands/gem_install.rb +0 -32
  145. data/lib/pry/commands/gem_list.rb +0 -33
  146. data/lib/pry/commands/gem_open.rb +0 -29
  147. data/lib/pry/commands/gist.rb +0 -101
  148. data/lib/pry/commands/install_command.rb +0 -53
  149. data/lib/pry/commands/list_prompts.rb +0 -35
  150. data/lib/pry/commands/simple_prompt.rb +0 -22
  151. data/lib/pry/commands.rb +0 -6
  152. data/lib/pry/config/behavior.rb +0 -139
  153. data/lib/pry/config/convenience.rb +0 -25
  154. data/lib/pry/config/default.rb +0 -161
  155. data/lib/pry/history_array.rb +0 -121
  156. data/lib/pry/rbx_path.rb +0 -22
  157. data/lib/pry/rubygem.rb +0 -82
  158. data/lib/pry/terminal.rb +0 -79
  159. data/lib/pry/test/helper.rb +0 -170
@@ -1,190 +1,205 @@
1
- class Pry
2
- class Command::Whereami < Pry::ClassCommand
1
+ # frozen_string_literal: true
3
2
 
4
- class << self
5
- attr_accessor :method_size_cutoff
6
- end
3
+ require 'method_source'
7
4
 
8
- @method_size_cutoff = 30
5
+ class Pry
6
+ class Command
7
+ class Whereami < Pry::ClassCommand
8
+ def initialize(*)
9
+ super
9
10
 
10
- match 'whereami'
11
- description 'Show code surrounding the current context.'
12
- group 'Context'
11
+ @method_code = nil
12
+ end
13
13
 
14
- banner <<-'BANNER'
15
- Usage: whereami [-qn] [LINES]
14
+ class << self
15
+ attr_accessor :method_size_cutoff
16
+ end
16
17
 
17
- Describe the current location. If you use `binding.pry` inside a method then
18
- whereami will print out the source for that method.
18
+ @method_size_cutoff = 30
19
19
 
20
- If a number is passed, then LINES lines before and after the current line will be
21
- shown instead of the method itself.
20
+ match 'whereami'
21
+ description 'Show code surrounding the current context.'
22
+ group 'Context'
22
23
 
23
- The `-q` flag can be used to suppress error messages in the case that there's
24
- no code to show. This is used by pry in the default before_session hook to show
25
- you when you arrive at a `binding.pry`.
24
+ banner <<-'BANNER'
25
+ Usage: whereami [-qn] [LINES]
26
26
 
27
- The `-n` flag can be used to hide line numbers so that code can be copy/pasted
28
- effectively.
27
+ Describe the current location. If you use `binding.pry` inside a method then
28
+ whereami will print out the source for that method.
29
29
 
30
- When pry was started on an Object and there is no associated method, whereami
31
- will instead output a brief description of the current object.
32
- BANNER
30
+ If a number is passed, then LINES lines before and after the current line will be
31
+ shown instead of the method itself.
33
32
 
34
- def setup
35
- @file = expand_path(target.eval('__FILE__'))
36
- @line = target.eval('__LINE__')
37
- @method = Pry::Method.from_binding(target)
38
- end
33
+ The `-q` flag can be used to suppress error messages in the case that there's
34
+ no code to show. This is used by pry in the default before_session hook to show
35
+ you when you arrive at a `binding.pry`.
39
36
 
40
- def options(opt)
41
- opt.on :q, :quiet, "Don't display anything in case of an error"
42
- opt.on :n, :"no-line-numbers", "Do not display line numbers"
43
- opt.on :m, :"method", "Show the complete source for the current method."
44
- opt.on :c, :"class", "Show the complete source for the current class or module."
45
- opt.on :f, :"file", "Show the complete source for the current file."
46
- end
37
+ The `-n` flag can be used to hide line numbers so that code can be copy/pasted
38
+ effectively.
47
39
 
48
- def code
49
- @code ||= if opts.present?(:m)
50
- method_code or raise CommandError, "Cannot find method code."
51
- elsif opts.present?(:c)
52
- class_code or raise CommandError, "Cannot find class code."
53
- elsif opts.present?(:f)
54
- Pry::Code.from_file(@file)
55
- elsif args.any?
56
- code_window
57
- else
58
- default_code
59
- end
60
- end
40
+ When pry was started on an Object and there is no associated method, whereami
41
+ will instead output a brief description of the current object.
42
+ BANNER
61
43
 
62
- def code?
63
- !!code
64
- rescue MethodSource::SourceNotFoundError
65
- false
66
- end
44
+ def setup
45
+ if target.respond_to?(:source_location)
46
+ file, @line = target.source_location
47
+ @file = expand_path(file)
48
+ else
49
+ @file = expand_path(target.eval('__FILE__'))
50
+ @line = target.eval('__LINE__')
51
+ end
52
+ @method = Pry::Method.from_binding(target)
53
+ end
67
54
 
68
- def bad_option_combination?
69
- [opts.present?(:m), opts.present?(:f),
70
- opts.present?(:c), args.any?].count(true) > 1
71
- end
55
+ def options(opt)
56
+ opt.on :q, :quiet, "Don't display anything in case of an error"
57
+ opt.on :n, :"no-line-numbers", "Do not display line numbers"
58
+ opt.on :m, :method, "Show the complete source for the current method."
59
+ opt.on :c, :class, "Show the complete source for the current class or module."
60
+ opt.on :f, :file, "Show the complete source for the current file."
61
+ end
72
62
 
73
- def location
74
- "#{@file} @ line #{@line} #{@method && @method.name_with_owner}"
75
- end
63
+ def code
64
+ @code ||= if opts.present?(:m)
65
+ method_code || raise(CommandError, "Cannot find method code.")
66
+ elsif opts.present?(:c)
67
+ class_code || raise(CommandError, "Cannot find class code.")
68
+ elsif opts.present?(:f)
69
+ Pry::Code.from_file(@file)
70
+ elsif args.any?
71
+ code_window
72
+ else
73
+ default_code
74
+ end
75
+ end
76
76
 
77
- def process
78
- if bad_option_combination?
79
- raise CommandError, "Only one of -m, -c, -f, and LINES may be specified."
77
+ def code?
78
+ !!code
79
+ rescue MethodSource::SourceNotFoundError
80
+ false
80
81
  end
81
82
 
82
- if nothing_to_do?
83
- return
84
- elsif internal_binding?(target)
85
- handle_internal_binding
86
- return
83
+ def bad_option_combination?
84
+ [opts.present?(:m), opts.present?(:f),
85
+ opts.present?(:c), args.any?].count(true) > 1
87
86
  end
88
87
 
89
- set_file_and_dir_locals(@file)
88
+ def location
89
+ "#{@file}:#{@line} #{@method && @method.name_with_owner}"
90
+ end
90
91
 
91
- out = "\n#{text.bold('From:')} #{location}:\n\n" <<
92
- code.with_line_numbers(use_line_numbers?).with_marker(marker).highlighted << "\n"
92
+ def process
93
+ if bad_option_combination?
94
+ raise CommandError, "Only one of -m, -c, -f, and LINES may be specified."
95
+ end
93
96
 
94
- _pry_.pager.page out
95
- end
97
+ return if nothing_to_do?
96
98
 
97
- private
99
+ if internal_binding?(target)
100
+ handle_internal_binding
101
+ return
102
+ end
98
103
 
99
- def nothing_to_do?
100
- opts.quiet? && (internal_binding?(target) || !code?)
101
- end
104
+ set_file_and_dir_locals(@file)
102
105
 
103
- def use_line_numbers?
104
- !opts.present?(:n)
105
- end
106
+ pretty_code = code.with_line_numbers(use_line_numbers?)
107
+ .with_marker(marker)
108
+ .highlighted
109
+ pry_instance.pager.page(
110
+ "\n#{bold('From:')} #{location}:\n\n" + pretty_code + "\n"
111
+ )
112
+ end
106
113
 
107
- def marker
108
- !opts.present?(:n) && @line
109
- end
114
+ private
110
115
 
111
- def top_level?
112
- target_self == Pry.main
113
- end
116
+ def nothing_to_do?
117
+ opts.quiet? && (internal_binding?(target) || !code?)
118
+ end
114
119
 
115
- def handle_internal_binding
116
- if top_level?
117
- output.puts "At the top level."
118
- else
119
- output.puts "Inside #{Pry.view_clip(target_self)}."
120
+ def use_line_numbers?
121
+ !opts.present?(:n)
120
122
  end
121
- end
122
123
 
123
- def small_method?
124
- @method.source_range.count < self.class.method_size_cutoff
125
- end
124
+ def marker
125
+ !opts.present?(:n) && @line
126
+ end
126
127
 
127
- def default_code
128
- if method_code && small_method?
129
- method_code
130
- else
131
- code_window
128
+ def top_level?
129
+ target_self == Pry.main
132
130
  end
133
- end
134
131
 
135
- def code_window
136
- Pry::Code.from_file(@file).around(@line, window_size)
137
- end
132
+ def handle_internal_binding
133
+ if top_level?
134
+ output.puts "At the top level."
135
+ else
136
+ output.puts "Inside #{Pry.view_clip(target_self)}."
137
+ end
138
+ end
138
139
 
139
- def method_code
140
- return @method_code if @method_code
140
+ def small_method?
141
+ @method.source_range.count < self.class.method_size_cutoff
142
+ end
141
143
 
142
- if valid_method?
143
- @method_code = Pry::Code.from_method(@method)
144
+ def default_code
145
+ if method_code && small_method?
146
+ method_code
147
+ else
148
+ code_window
149
+ end
144
150
  end
145
- end
146
151
 
147
- # This either returns the `target_self`
148
- # or it returns the class of `target_self` if `target_self` is not a class.
149
- # @return [Pry::WrappedModule]
150
- def target_class
151
- target_self.is_a?(Module) ? Pry::WrappedModule(target_self) :
152
- Pry::WrappedModule(target_self.class)
153
- end
152
+ def code_window
153
+ Pry::Code.from_file(@file).around(@line, window_size)
154
+ end
155
+
156
+ def method_code
157
+ return @method_code if @method_code
154
158
 
155
- def class_code
156
- return @class_code if @class_code
159
+ @method_code = Pry::Code.from_method(@method) if valid_method?
160
+ end
157
161
 
158
- mod = @method ? Pry::WrappedModule(@method.owner) : target_class
162
+ # This either returns the `target_self`
163
+ # or it returns the class of `target_self` if `target_self` is not a class.
164
+ # @return [Pry::WrappedModule]
165
+ def target_class
166
+ return Pry::WrappedModule(target_self) if target_self.is_a?(Module)
159
167
 
160
- idx = mod.candidates.find_index { |v| expand_path(v.source_file) == @file }
161
- @class_code = idx && Pry::Code.from_module(mod, idx)
162
- end
168
+ Pry::WrappedModule(target_self.class)
169
+ end
163
170
 
164
- def valid_method?
165
- @method && @method.source? && expand_path(@method.source_file) == @file &&
166
- @method.source_range.include?(@line)
167
- end
171
+ def class_code
172
+ @class_code ||=
173
+ begin
174
+ mod = @method ? Pry::WrappedModule(@method.owner) : target_class
175
+ idx = mod.candidates.find_index { |v| expand_path(v.source_file) == @file }
176
+ idx && Pry::Code.from_module(mod, idx)
177
+ end
178
+ end
168
179
 
169
- def expand_path(f)
170
- return if !f
180
+ def valid_method?
181
+ @method && @method.source? && expand_path(@method.source_file) == @file &&
182
+ @method.source_range.include?(@line)
183
+ end
184
+
185
+ def expand_path(filename)
186
+ return unless filename
187
+ return filename if Pry.eval_path == filename
171
188
 
172
- if Pry.eval_path == f
173
- f
174
- else
175
- File.expand_path(f)
189
+ File.expand_path(filename)
176
190
  end
177
- end
178
191
 
179
- def window_size
180
- if args.empty?
181
- _pry_.config.default_window_size
182
- else
183
- args.first.to_i
192
+ def window_size
193
+ if args.empty?
194
+ pry_instance.config.default_window_size
195
+ else
196
+ args.first.to_i
197
+ end
184
198
  end
185
199
  end
186
- end
187
200
 
188
- Pry::Commands.add_command(Pry::Command::Whereami)
189
- Pry::Commands.alias_command '@', 'whereami'
201
+ Pry::Commands.add_command(Pry::Command::Whereami)
202
+ Pry::Commands.alias_command '@', 'whereami'
203
+ Pry::Commands.alias_command(/whereami[!?]+/, 'whereami')
204
+ end
190
205
  end
@@ -1,57 +1,95 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
2
- class Command::Wtf < Pry::ClassCommand
3
- match(/wtf([?!]*)/)
4
- group 'Context'
5
- description 'Show the backtrace of the most recent exception.'
6
- options :listing => 'wtf?'
4
+ class Command
5
+ class Wtf < Pry::ClassCommand
6
+ match(/wtf([?!]*)/)
7
+ group 'Context'
8
+ description 'Show the backtrace of the most recent exception.'
9
+ options listing: 'wtf?'
7
10
 
8
- banner <<-'BANNER'
9
- Usage: wtf[?|!]
11
+ banner <<-'BANNER'
12
+ Usage: wtf[?|!]
10
13
 
11
- Show's a few lines of the backtrace of the most recent exception (also available
12
- as `_ex_.backtrace`). If you want to see more lines, add more question marks or
13
- exclamation marks.
14
+ Shows a few lines of the backtrace of the most recent exception (also available
15
+ as `_ex_.backtrace`). If you want to see more lines, add more question marks or
16
+ exclamation marks.
14
17
 
15
- wtf?
16
- wtf?!???!?!?
18
+ wtf?
19
+ wtf?!???!?!?
17
20
 
18
- # To see the entire backtrace, pass the `-v` or `--verbose` flag.
19
- wtf -v
20
- BANNER
21
+ # To see the entire backtrace, pass the `-v` or `--verbose` flag.
22
+ wtf -v
23
+ BANNER
21
24
 
22
- def options(opt)
23
- opt.on :v, :verbose, "Show the full backtrace"
24
- end
25
+ RUBY_FRAME_PATTERN = /\A(?<file>(.+)):(?<line>(\d+))/.freeze
26
+
27
+ def options(opt)
28
+ opt.on :v, :verbose, "Show the full backtrace"
29
+ opt.on :c, :code, "Show code corresponding to the backtrace frame"
30
+ end
25
31
 
26
- def process
27
- raise Pry::CommandError, "No most-recent exception" unless exception
32
+ def process
33
+ unless pry_instance.last_exception
34
+ raise Pry::CommandError, "No most-recent exception"
35
+ end
28
36
 
29
- output.puts "#{text.bold('Exception:')} #{exception.class}: #{exception}\n--"
30
- if opts.verbose?
31
- output.puts with_line_numbers(backtrace)
32
- else
33
- output.puts with_line_numbers(backtrace.first(size_of_backtrace))
37
+ text = ''.dup
38
+ unwind_exceptions.each_with_index do |exception, i|
39
+ title = (i == 0 ? 'Exception' : 'Caused by')
40
+ text << format_header(title, exception)
41
+ text << format_backtrace(exception.backtrace)
42
+ end
43
+ output.puts(text)
34
44
  end
35
- end
36
45
 
37
- private
46
+ private
38
47
 
39
- def exception
40
- _pry_.last_exception
41
- end
48
+ def unwind_exceptions
49
+ exception_list = []
50
+ exception = pry_instance.last_exception
42
51
 
43
- def with_line_numbers(bt)
44
- Pry::Code.new(bt, 0, :text).with_line_numbers.to_s
45
- end
52
+ while exception
53
+ exception_list << exception
54
+ exception = (exception.cause if exception.respond_to?(:cause))
55
+ end
46
56
 
47
- def backtrace
48
- exception.backtrace
49
- end
57
+ exception_list
58
+ end
59
+
60
+ def format_header(title, exception)
61
+ "#{bold(title + ':')} #{exception.class}: #{exception}\n--\n"
62
+ end
50
63
 
51
- def size_of_backtrace
52
- [captures[0].size, 0.5].max * 10
64
+ def format_backtrace(backtrace)
65
+ lines = trim_backtrace(backtrace).map do |frame|
66
+ next frame unless opts.code?
67
+
68
+ match = frame.match(RUBY_FRAME_PATTERN)
69
+ code = read_line(match[:file], match[:line].to_i)
70
+ [bold(frame), code].join("\n")
71
+ end
72
+
73
+ Pry::Code.new(lines.compact, 0, :text).with_line_numbers.to_s
74
+ end
75
+
76
+ def trim_backtrace(backtrace)
77
+ return backtrace if opts.verbose?
78
+
79
+ size_of_backtrace = [captures[0].size, 0.5].max * 10
80
+ backtrace.first(size_of_backtrace)
81
+ end
82
+
83
+ def read_line(file, line)
84
+ File.open(file, 'r') do |f|
85
+ (line - 1).times { f.gets }
86
+ f.gets
87
+ end
88
+ rescue Errno::ENOENT
89
+ nil
90
+ end
53
91
  end
54
- end
55
92
 
56
- Pry::Commands.add_command(Pry::Command::Wtf)
93
+ Pry::Commands.add_command(Pry::Command::Wtf)
94
+ end
57
95
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Config
5
+ # Attributable provides the ability to create "attribute"
6
+ # accessors. Attribute accessors create a standard "attr_writer" and a
7
+ # customised "attr_reader". This reader is Proc-aware (lazy).
8
+ #
9
+ # @since v0.13.0
10
+ # @api private
11
+ module Attributable
12
+ def attribute(attr_name)
13
+ define_method(attr_name) do
14
+ value = Config::Value.new(instance_variable_get("@#{attr_name}"))
15
+ value.call
16
+ end
17
+
18
+ attr_writer(attr_name)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Config
5
+ # LazyValue is a Proc (block) wrapper. It is meant to be used as a
6
+ # configuration value. Subsequent `#call` calls always evaluate the given
7
+ # block.
8
+ #
9
+ # @example
10
+ # num = 19
11
+ # value = Pry::Config::LazyValue.new { num += 1 }
12
+ # value.foo # => 20
13
+ # value.foo # => 21
14
+ # value.foo # => 22
15
+ #
16
+ # @api private
17
+ # @since v0.13.0
18
+ # @see Pry::Config::MemoizedValue
19
+ class LazyValue
20
+ def initialize(&block)
21
+ @block = block
22
+ end
23
+
24
+ def call
25
+ @block.call
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Config
5
+ # MemoizedValue is a Proc (block) wrapper. It is meant to be used as a
6
+ # configuration value. Subsequent `#call` calls return the same memoized
7
+ # result.
8
+ #
9
+ # @example
10
+ # num = 19
11
+ # value = Pry::Config::MemoizedValue.new { num += 1 }
12
+ # value.call # => 20
13
+ # value.call # => 20
14
+ # value.call # => 20
15
+ #
16
+ # @api private
17
+ # @since v0.13.0
18
+ # @see Pry::Config::LazyValue
19
+ class MemoizedValue
20
+ def initialize(&block)
21
+ @block = block
22
+ @called = false
23
+ @call = nil
24
+ end
25
+
26
+ def call
27
+ return @call if @called
28
+
29
+ @called = true
30
+ @call = @block.call
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Config
5
+ # Value holds a value for the given attribute and decides how it should
6
+ # be read. Procs get called, other values are returned as is.
7
+ #
8
+ # @since v0.13.0
9
+ # @api private
10
+ class Value
11
+ def initialize(value)
12
+ @value = value
13
+ end
14
+
15
+ def call
16
+ unless [Config::MemoizedValue, Config::LazyValue].include?(@value.class)
17
+ return @value
18
+ end
19
+
20
+ @value.call
21
+ end
22
+ end
23
+ end
24
+ end