pry 0.9.12.2 → 0.14.2

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 (237) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1141 -0
  3. data/LICENSE +2 -2
  4. data/README.md +466 -0
  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 +97 -92
  10. data/lib/pry/code/code_file.rb +114 -0
  11. data/lib/pry/code/code_range.rb +7 -4
  12. data/lib/pry/code/loc.rb +27 -14
  13. data/lib/pry/code.rb +62 -90
  14. data/lib/pry/code_object.rb +83 -39
  15. data/lib/pry/color_printer.rb +66 -0
  16. data/lib/pry/command.rb +202 -371
  17. data/lib/pry/command_set.rb +151 -133
  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 -73
  24. data/lib/pry/commands/cat/file_formatter.rb +56 -63
  25. data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
  26. data/lib/pry/commands/cat.rb +64 -47
  27. data/lib/pry/commands/cd.rb +42 -26
  28. data/lib/pry/commands/change_inspector.rb +34 -0
  29. data/lib/pry/commands/change_prompt.rb +51 -0
  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 +33 -24
  36. data/lib/pry/commands/edit.rb +183 -167
  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 -17
  40. data/lib/pry/commands/find_method.rb +167 -167
  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 +153 -132
  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 +42 -0
  47. data/lib/pry/commands/ls/constants.rb +75 -0
  48. data/lib/pry/commands/ls/formatter.rb +55 -0
  49. data/lib/pry/commands/ls/globals.rb +50 -0
  50. data/lib/pry/commands/ls/grep.rb +23 -0
  51. data/lib/pry/commands/ls/instance_vars.rb +40 -0
  52. data/lib/pry/commands/ls/interrogatable.rb +24 -0
  53. data/lib/pry/commands/ls/jruby_hacks.rb +55 -0
  54. data/lib/pry/commands/ls/local_names.rb +37 -0
  55. data/lib/pry/commands/ls/local_vars.rb +47 -0
  56. data/lib/pry/commands/ls/ls_entity.rb +65 -0
  57. data/lib/pry/commands/ls/methods.rb +55 -0
  58. data/lib/pry/commands/ls/methods_helper.rb +50 -0
  59. data/lib/pry/commands/ls/self_methods.rb +34 -0
  60. data/lib/pry/commands/ls.rb +100 -303
  61. data/lib/pry/commands/nesting.rb +21 -17
  62. data/lib/pry/commands/play.rb +93 -49
  63. data/lib/pry/commands/pry_backtrace.rb +22 -18
  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 +57 -48
  67. data/lib/pry/commands/reset.rb +16 -12
  68. data/lib/pry/commands/ri.rb +57 -38
  69. data/lib/pry/commands/save_file.rb +45 -43
  70. data/lib/pry/commands/shell_command.rb +66 -34
  71. data/lib/pry/commands/shell_mode.rb +22 -20
  72. data/lib/pry/commands/show_doc.rb +80 -65
  73. data/lib/pry/commands/show_info.rb +193 -159
  74. data/lib/pry/commands/show_input.rb +16 -11
  75. data/lib/pry/commands/show_source.rb +113 -33
  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 +21 -13
  79. data/lib/pry/commands/watch_expression/expression.rb +43 -0
  80. data/lib/pry/commands/watch_expression.rb +110 -0
  81. data/lib/pry/commands/whereami.rb +157 -134
  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 +290 -220
  88. data/lib/pry/control_d_handler.rb +28 -0
  89. data/lib/pry/core_extensions.rb +50 -27
  90. data/lib/pry/editor.rb +130 -102
  91. data/lib/pry/env.rb +18 -0
  92. data/lib/pry/exception_handler.rb +43 -0
  93. data/lib/pry/exceptions.rb +73 -0
  94. data/lib/pry/forwardable.rb +27 -0
  95. data/lib/pry/helpers/base_helpers.rb +22 -151
  96. data/lib/pry/helpers/command_helpers.rb +55 -63
  97. data/lib/pry/helpers/documentation_helpers.rb +21 -13
  98. data/lib/pry/helpers/options_helpers.rb +15 -8
  99. data/lib/pry/helpers/platform.rb +55 -0
  100. data/lib/pry/helpers/table.rb +44 -32
  101. data/lib/pry/helpers/text.rb +96 -86
  102. data/lib/pry/helpers.rb +3 -0
  103. data/lib/pry/history.rb +101 -70
  104. data/lib/pry/hooks.rb +67 -137
  105. data/lib/pry/indent.rb +79 -73
  106. data/lib/pry/input_completer.rb +283 -0
  107. data/lib/pry/input_lock.rb +129 -0
  108. data/lib/pry/inspector.rb +39 -0
  109. data/lib/pry/last_exception.rb +61 -0
  110. data/lib/pry/method/disowned.rb +19 -5
  111. data/lib/pry/{commands/edit/method_patcher.rb → method/patcher.rb} +51 -42
  112. data/lib/pry/method/weird_method_locator.rb +80 -44
  113. data/lib/pry/method.rb +225 -176
  114. data/lib/pry/object_path.rb +91 -0
  115. data/lib/pry/output.rb +136 -0
  116. data/lib/pry/pager.rb +227 -68
  117. data/lib/pry/prompt.rb +214 -0
  118. data/lib/pry/pry_class.rb +216 -289
  119. data/lib/pry/pry_instance.rb +438 -500
  120. data/lib/pry/repl.rb +256 -0
  121. data/lib/pry/repl_file_loader.rb +34 -35
  122. data/lib/pry/ring.rb +89 -0
  123. data/lib/pry/slop/LICENSE +20 -0
  124. data/lib/pry/slop/commands.rb +190 -0
  125. data/lib/pry/slop/option.rb +210 -0
  126. data/lib/pry/slop.rb +672 -0
  127. data/lib/pry/syntax_highlighter.rb +26 -0
  128. data/lib/pry/system_command_handler.rb +17 -0
  129. data/lib/pry/testable/evalable.rb +24 -0
  130. data/lib/pry/testable/mockable.rb +22 -0
  131. data/lib/pry/testable/pry_tester.rb +88 -0
  132. data/lib/pry/testable/utility.rb +34 -0
  133. data/lib/pry/testable/variables.rb +52 -0
  134. data/lib/pry/testable.rb +68 -0
  135. data/lib/pry/version.rb +3 -1
  136. data/lib/pry/warning.rb +20 -0
  137. data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +36 -43
  138. data/lib/pry/wrapped_module.rb +102 -103
  139. data/lib/pry.rb +135 -261
  140. metadata +94 -283
  141. data/.document +0 -2
  142. data/.gitignore +0 -16
  143. data/.travis.yml +0 -21
  144. data/.yardopts +0 -1
  145. data/CHANGELOG +0 -534
  146. data/CONTRIBUTORS +0 -55
  147. data/Gemfile +0 -9
  148. data/Guardfile +0 -62
  149. data/README.markdown +0 -400
  150. data/Rakefile +0 -140
  151. data/TODO +0 -117
  152. data/lib/pry/commands/disabled_commands.rb +0 -2
  153. data/lib/pry/commands/gem_cd.rb +0 -26
  154. data/lib/pry/commands/gem_install.rb +0 -29
  155. data/lib/pry/commands/gem_list.rb +0 -33
  156. data/lib/pry/commands/gem_open.rb +0 -29
  157. data/lib/pry/commands/gist.rb +0 -102
  158. data/lib/pry/commands/install_command.rb +0 -51
  159. data/lib/pry/commands/simple_prompt.rb +0 -22
  160. data/lib/pry/commands.rb +0 -6
  161. data/lib/pry/completion.rb +0 -304
  162. data/lib/pry/custom_completions.rb +0 -6
  163. data/lib/pry/history_array.rb +0 -116
  164. data/lib/pry/plugins.rb +0 -103
  165. data/lib/pry/rbx_method.rb +0 -13
  166. data/lib/pry/rbx_path.rb +0 -22
  167. data/lib/pry/rubygem.rb +0 -74
  168. data/lib/pry/terminal.rb +0 -78
  169. data/lib/pry/test/helper.rb +0 -185
  170. data/man/pry.1 +0 -195
  171. data/man/pry.1.html +0 -204
  172. data/man/pry.1.ronn +0 -141
  173. data/pry.gemspec +0 -30
  174. data/spec/Procfile +0 -3
  175. data/spec/cli_spec.rb +0 -78
  176. data/spec/code_object_spec.rb +0 -277
  177. data/spec/code_spec.rb +0 -219
  178. data/spec/command_helpers_spec.rb +0 -29
  179. data/spec/command_integration_spec.rb +0 -644
  180. data/spec/command_set_spec.rb +0 -627
  181. data/spec/command_spec.rb +0 -821
  182. data/spec/commands/amend_line_spec.rb +0 -247
  183. data/spec/commands/bang_spec.rb +0 -19
  184. data/spec/commands/cat_spec.rb +0 -164
  185. data/spec/commands/cd_spec.rb +0 -250
  186. data/spec/commands/disable_pry_spec.rb +0 -25
  187. data/spec/commands/edit_spec.rb +0 -727
  188. data/spec/commands/exit_all_spec.rb +0 -34
  189. data/spec/commands/exit_program_spec.rb +0 -19
  190. data/spec/commands/exit_spec.rb +0 -34
  191. data/spec/commands/find_method_spec.rb +0 -70
  192. data/spec/commands/gem_list_spec.rb +0 -26
  193. data/spec/commands/gist_spec.rb +0 -79
  194. data/spec/commands/help_spec.rb +0 -56
  195. data/spec/commands/hist_spec.rb +0 -181
  196. data/spec/commands/jump_to_spec.rb +0 -15
  197. data/spec/commands/ls_spec.rb +0 -181
  198. data/spec/commands/play_spec.rb +0 -140
  199. data/spec/commands/raise_up_spec.rb +0 -56
  200. data/spec/commands/save_file_spec.rb +0 -177
  201. data/spec/commands/show_doc_spec.rb +0 -510
  202. data/spec/commands/show_input_spec.rb +0 -17
  203. data/spec/commands/show_source_spec.rb +0 -782
  204. data/spec/commands/whereami_spec.rb +0 -203
  205. data/spec/completion_spec.rb +0 -239
  206. data/spec/control_d_handler_spec.rb +0 -58
  207. data/spec/documentation_helper_spec.rb +0 -73
  208. data/spec/editor_spec.rb +0 -79
  209. data/spec/exception_whitelist_spec.rb +0 -21
  210. data/spec/fixtures/candidate_helper1.rb +0 -11
  211. data/spec/fixtures/candidate_helper2.rb +0 -8
  212. data/spec/fixtures/example.erb +0 -5
  213. data/spec/fixtures/example_nesting.rb +0 -33
  214. data/spec/fixtures/show_source_doc_examples.rb +0 -15
  215. data/spec/fixtures/testrc +0 -2
  216. data/spec/fixtures/testrcbad +0 -2
  217. data/spec/fixtures/whereami_helper.rb +0 -6
  218. data/spec/helper.rb +0 -34
  219. data/spec/helpers/bacon.rb +0 -86
  220. data/spec/helpers/mock_pry.rb +0 -43
  221. data/spec/helpers/table_spec.rb +0 -105
  222. data/spec/history_array_spec.rb +0 -67
  223. data/spec/hooks_spec.rb +0 -522
  224. data/spec/indent_spec.rb +0 -301
  225. data/spec/input_stack_spec.rb +0 -90
  226. data/spec/method_spec.rb +0 -482
  227. data/spec/prompt_spec.rb +0 -60
  228. data/spec/pry_defaults_spec.rb +0 -419
  229. data/spec/pry_history_spec.rb +0 -99
  230. data/spec/pry_output_spec.rb +0 -95
  231. data/spec/pry_spec.rb +0 -504
  232. data/spec/run_command_spec.rb +0 -25
  233. data/spec/sticky_locals_spec.rb +0 -157
  234. data/spec/syntax_checking_spec.rb +0 -81
  235. data/spec/wrapped_module_spec.rb +0 -261
  236. data/wiki/Customizing-pry.md +0 -397
  237. data/wiki/Home.md +0 -4
data/lib/pry/code/loc.rb CHANGED
@@ -1,10 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
2
4
  class Code
3
-
4
- # Represents a line of code. A line of code is a tuple, which consists of a
5
- # line and a line number. A `LOC` object's state (namely, the line
6
- # parameter) can be changed via instance methods. `Pry::Code` heavily uses
7
- # this class.
5
+ # Represents a line of code (which may, in fact, contain multiple lines if
6
+ # the entirety was eval'd as a single unit following the `edit` command).
7
+ #
8
+ # A line of code is a tuple, which consists of a line and a line number. A
9
+ # `LOC` object's state (namely, the line parameter) can be changed via
10
+ # instance methods. `Pry::Code` heavily uses this class.
8
11
  #
9
12
  # @api private
10
13
  # @example
@@ -18,7 +21,6 @@ class Pry
18
21
  # loc.indent(3)
19
22
  # loc.line #=> " def example\n :example\nend"
20
23
  class LOC
21
-
22
24
  # @return [Array<String, Integer>]
23
25
  attr_reader :tuple
24
26
 
@@ -52,17 +54,23 @@ class Pry
52
54
  # @param [Symbol] code_type
53
55
  # @return [void]
54
56
  def colorize(code_type)
55
- tuple[0] = CodeRay.scan(line, code_type).term
57
+ tuple[0] = SyntaxHighlighter.highlight(line, code_type)
56
58
  end
57
59
 
58
60
  # Prepends the line number `lineno` to the `line`.
59
61
  #
60
62
  # @param [Integer] max_width
61
63
  # @return [void]
62
- def add_line_number(max_width = 0)
64
+ def add_line_number(max_width = 0, color = false)
63
65
  padded = lineno.to_s.rjust(max_width)
64
- colorized_lineno = Pry::Helpers::BaseHelpers.colorize_code(padded)
65
- tuple[0] = "#{ colorized_lineno }: #{ line }"
66
+ colorized_lineno =
67
+ if color
68
+ Pry::Helpers::BaseHelpers.colorize_code(padded)
69
+ else
70
+ padded
71
+ end
72
+ properly_padded_line = handle_multiline_entries_from_edit_command(line, max_width)
73
+ tuple[0] = "#{colorized_lineno}: #{properly_padded_line}"
66
74
  end
67
75
 
68
76
  # Prepends a marker "=>" or an empty marker to the +line+.
@@ -73,9 +81,9 @@ class Pry
73
81
  def add_marker(marker_lineno)
74
82
  tuple[0] =
75
83
  if lineno == marker_lineno
76
- " => #{ line }"
84
+ " => #{line}"
77
85
  else
78
- " #{ line }"
86
+ " #{line}"
79
87
  end
80
88
  end
81
89
 
@@ -84,9 +92,14 @@ class Pry
84
92
  # @param [Integer] distance
85
93
  # @return [void]
86
94
  def indent(distance)
87
- tuple[0] = "#{ ' ' * distance }#{ line }"
95
+ tuple[0] = "#{' ' * distance}#{line}"
88
96
  end
89
- end
90
97
 
98
+ def handle_multiline_entries_from_edit_command(line, max_width)
99
+ line.split("\n").map.with_index do |inner_line, i|
100
+ i.zero? ? inner_line : "#{' ' * (max_width + 2)}#{inner_line}"
101
+ end.join("\n")
102
+ end
103
+ end
91
104
  end
92
105
  end
data/lib/pry/code.rb CHANGED
@@ -1,5 +1,6 @@
1
- require 'pry/code/loc'
2
- require 'pry/code/code_range'
1
+ # frozen_string_literal: true
2
+
3
+ require 'method_source'
3
4
 
4
5
  class Pry
5
6
  class << self
@@ -29,26 +30,6 @@ class Pry
29
30
  # arbitrary chaining of formatting methods without mutating the original
30
31
  # object.
31
32
  class Code
32
-
33
- # List of all supported languages.
34
- # @return [Hash]
35
- EXTENSIONS = {
36
- %w(.py) => :python,
37
- %w(.js) => :javascript,
38
- %w(.css) => :css,
39
- %w(.xml) => :xml,
40
- %w(.php) => :php,
41
- %w(.html) => :html,
42
- %w(.diff) => :diff,
43
- %w(.java) => :java,
44
- %w(.json) => :json,
45
- %w(.c .h) => :c,
46
- %w(.rhtml) => :rhtml,
47
- %w(.yaml .yml) => :yaml,
48
- %w(.cpp .hpp .cc .h cxx) => :cpp,
49
- %w(.rb .ru .irbrc .gemspec .pryrc) => :ruby,
50
- }
51
-
52
33
  class << self
53
34
  include MethodSource::CodeHelpers
54
35
 
@@ -58,13 +39,9 @@ class Pry
58
39
  # @param [String] filename The name of a file, or "(pry)".
59
40
  # @param [Symbol] code_type The type of code the file contains.
60
41
  # @return [Code]
61
- def from_file(filename, code_type = type_from_filename(filename))
62
- code = if filename == Pry.eval_path
63
- Pry.line_buffer.drop(1)
64
- else
65
- File.read(abs_path(filename))
66
- end
67
- new(code, 1, code_type)
42
+ def from_file(filename, code_type = nil)
43
+ code_file = CodeFile.new(filename, code_type)
44
+ new(code_file.code, 1, code_file.code_type)
68
45
  end
69
46
 
70
47
  # Instantiate a `Code` object containing code extracted from a
@@ -89,40 +66,11 @@ class Pry
89
66
  # @param [Integer, nil] start_line The line number to start on, or nil to
90
67
  # use the method's original line numbers.
91
68
  # @return [Code]
92
- def from_module(mod, candidate_rank = 0, start_line=nil)
69
+ def from_module(mod, candidate_rank = 0, start_line = nil)
93
70
  candidate = Pry::WrappedModule(mod).candidate(candidate_rank)
94
71
  start_line ||= candidate.line
95
72
  new(candidate.source, start_line, :ruby)
96
73
  end
97
-
98
- protected
99
-
100
- # Guess the CodeRay type of a file from its extension, or nil if
101
- # unknown.
102
- #
103
- # @param [String] filename
104
- # @param [Symbol] default (:ruby) the file type to assume if none could be
105
- # detected.
106
- # @return [Symbol, nil]
107
- def type_from_filename(filename, default = :ruby)
108
- _, type = Pry::Code::EXTENSIONS.find do |k, _|
109
- k.any? { |ext| ext == File.extname(filename) }
110
- end
111
-
112
- type || default
113
- end
114
-
115
- # @param [String] filename
116
- # @raise [MethodSource::SourceNotFoundError] if the +filename+ is not
117
- # readable for some reason.
118
- # @return [String] absolute path for the given +filename+.
119
- def abs_path(filename)
120
- abs_path = [File.expand_path(filename, Dir.pwd),
121
- File.expand_path(filename, Pry::INITIAL_PWD)
122
- ].detect { |abs_path| File.readable?(abs_path) }
123
- abs_path or raise MethodSource::SourceNotFoundError,
124
- "Cannot open #{filename.inspect} for reading."
125
- end
126
74
  end
127
75
 
128
76
  # @return [Symbol] The type of code stored in this wrapper.
@@ -137,26 +85,23 @@ class Pry
137
85
  # @param [Integer?] start_line
138
86
  # @param [Symbol?] code_type
139
87
  def initialize(lines = [], start_line = 1, code_type = :ruby)
140
- if lines.is_a? String
141
- lines = lines.lines
88
+ lines = lines.lines if lines.is_a? String
89
+ @lines = lines.each_with_index.map do |line, lineno|
90
+ LOC.new(line, lineno + start_line.to_i)
142
91
  end
143
- @lines = lines.each_with_index.map { |line, lineno|
144
- LOC.new(line, lineno + start_line.to_i) }
145
92
  @code_type = code_type
93
+
94
+ @with_marker = @with_indentation = @with_line_numbers = nil
146
95
  end
147
96
 
148
97
  # Append the given line. +lineno+ is one more than the last existing
149
98
  # line, unless specified otherwise.
150
99
  #
151
100
  # @param [String] line
152
- # @param [Integer?] lineno
153
- # @return [String] The inserted line.
154
- def push(line, lineno = nil)
155
- if lineno.nil?
156
- lineno = @lines.last.lineno + 1
157
- end
158
- @lines.push(LOC.new(line, lineno))
159
- line
101
+ # @return [void]
102
+ def push(line)
103
+ line_number = @lines.any? ? @lines.last.lineno + 1 : 1
104
+ @lines.push(LOC.new(line, line_number))
160
105
  end
161
106
  alias << push
162
107
 
@@ -170,6 +115,16 @@ class Pry
170
115
  end
171
116
  end
172
117
 
118
+ # Filter the lines using the given block.
119
+ #
120
+ # @yield [LOC]
121
+ # @return [Code]
122
+ def reject(&block)
123
+ alter do
124
+ @lines = @lines.reject(&block)
125
+ end
126
+ end
127
+
173
128
  # Remove all lines that aren't in the given range, expressed either as a
174
129
  # `Range` object or a first and last line number (inclusive). Negative
175
130
  # indices count from the end of the array of lines.
@@ -197,7 +152,7 @@ class Pry
197
152
  if start_line >= 0
198
153
  @lines.index { |loc| loc.lineno >= start_line } || @lines.length
199
154
  else
200
- @lines.length + start_line
155
+ [@lines.length + start_line, 0].max
201
156
  end
202
157
 
203
158
  alter do
@@ -251,6 +206,7 @@ class Pry
251
206
  # @return [Code]
252
207
  def grep(pattern)
253
208
  return self unless pattern
209
+
254
210
  pattern = Regexp.new(pattern)
255
211
 
256
212
  select do |loc|
@@ -292,27 +248,35 @@ class Pry
292
248
  end
293
249
  end
294
250
 
295
- # @return [String]
296
- def inspect
297
- Object.instance_method(:to_s).bind(self).call
298
- end
299
-
300
251
  # @return [Integer] the number of digits in the last line.
301
252
  def max_lineno_width
302
- @lines.length > 0 ? @lines.last.lineno.to_s.length : 0
253
+ !@lines.empty? ? @lines.last.lineno.to_s.length : 0
303
254
  end
304
255
 
305
256
  # @return [String] a formatted representation (based on the configuration of
306
257
  # the object).
307
258
  def to_s
308
- @lines.map { |loc|
259
+ print_to_output(''.dup, false)
260
+ end
261
+
262
+ # @return [String] a (possibly highlighted) copy of the source code.
263
+ def highlighted
264
+ print_to_output(''.dup, true)
265
+ end
266
+
267
+ # Writes a formatted representation (based on the configuration of the
268
+ # object) to the given output, which must respond to `#<<`.
269
+ def print_to_output(output, color = false)
270
+ @lines.each do |loc|
309
271
  loc = loc.dup
310
- loc.colorize(@code_type) if Pry.color
311
- loc.add_line_number(max_lineno_width) if @with_line_numbers
272
+ loc.colorize(@code_type) if color
273
+ loc.add_line_number(max_lineno_width, color) if @with_line_numbers
312
274
  loc.add_marker(@marker_lineno) if @with_marker
313
275
  loc.indent(@indentation_num) if @with_indentation
314
- loc.line
315
- }.join("\n") + "\n"
276
+ output << loc.line
277
+ output << "\n"
278
+ end
279
+ output
316
280
  end
317
281
 
318
282
  # Get the comment that describes the expression on the given line number.
@@ -328,15 +292,14 @@ class Pry
328
292
  # @param [Integer] line_number (1-based)
329
293
  # @return [String] the code.
330
294
  def expression_at(line_number, consume = 0)
331
- self.class.expression_at(raw, line_number, :consume => consume)
295
+ self.class.expression_at(raw, line_number, consume: consume)
332
296
  end
333
297
 
334
298
  # Get the (approximate) Module.nesting at the give line number.
335
299
  #
336
300
  # @param [Integer] line_number line number starting from 1
337
- # @param [Module] top_module the module in which this code exists
338
301
  # @return [Array<Module>] a list of open modules.
339
- def nesting_at(line_number, top_module = Object)
302
+ def nesting_at(line_number)
340
303
  Pry::Indent.nesting_at(raw, line_number)
341
304
  end
342
305
 
@@ -344,7 +307,7 @@ class Pry
344
307
  #
345
308
  # @return [String]
346
309
  def raw
347
- @lines.map(&:line).join("\n") + "\n"
310
+ @lines.map(&:line).join("\n") << "\n"
348
311
  end
349
312
 
350
313
  # Return the number of lines stored.
@@ -369,10 +332,19 @@ class Pry
369
332
  end
370
333
 
371
334
  # Forward any missing methods to the output of `#to_s`.
372
- def method_missing(name, *args, &block)
373
- to_s.send(name, *args, &block)
335
+ def method_missing(method_name, *args, &block)
336
+ if (string = to_s).respond_to?(method_name)
337
+ string.__send__(method_name, *args, &block)
338
+ else
339
+ super
340
+ end
341
+ end
342
+ undef =~ if method_defined?(:=~)
343
+
344
+ # Check whether String responds to missing methods.
345
+ def respond_to_missing?(method_name, include_private = false)
346
+ ''.respond_to?(method_name, include_private) || super
374
347
  end
375
- undef =~
376
348
 
377
349
  protected
378
350
 
@@ -1,4 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
4
+ # This class is responsible for taking a string (identifying a
5
+ # command/class/method/etc) and returning the relevant type of object.
6
+ # For example, if the user looks up "show-source" then a
7
+ # `Pry::Command` will be returned. Alternatively, if the user passes in "Pry#repl" then
8
+ # a `Pry::Method` object will be returned.
9
+ #
10
+ # The `CodeObject.lookup` method is responsible for 1. figuring out what kind of
11
+ # object the user wants (applying precedence rules in doing so -- i.e methods
12
+ # get precedence over commands with the same name) and 2. Returning
13
+ # the appropriate object. If the user fails to provide a string
14
+ # identifer for the object (i.e they pass in `nil` or "") then the
15
+ # object looked up will be the 'current method' or 'current class'
16
+ # associated with the Binding.
17
+ #
18
+ # TODO: This class is a clusterfuck. We need a much more robust
19
+ # concept of what a "Code Object" really is. Currently
20
+ # commands/classes/candidates/methods and so on just share a very
21
+ # ill-defined interface.
2
22
  class CodeObject
3
23
  module Helpers
4
24
  # we need this helper as some Pry::Method objects can wrap Procs
@@ -18,13 +38,36 @@ class Pry
18
38
  def command?
19
39
  is_a?(Module) && self <= Pry::Command
20
40
  end
41
+
42
+ # @return [Boolean] `true` if this module was defined by means of the C API,
43
+ # `false` if it's a Ruby module.
44
+ # @note If a module defined by C was extended with a lot of methods written
45
+ # in Ruby, this method would fail.
46
+ def c_module?
47
+ return unless is_a?(WrappedModule)
48
+
49
+ method_locations = wrapped.methods(false).map do |m|
50
+ wrapped.method(m).source_location
51
+ end
52
+
53
+ method_locations.concat(
54
+ wrapped.instance_methods(false).map do |m|
55
+ wrapped.instance_method(m).source_location
56
+ end
57
+ )
58
+
59
+ c_methods = method_locations.grep(nil).count
60
+ ruby_methods = method_locations.count - c_methods
61
+
62
+ c_methods > ruby_methods
63
+ end
21
64
  end
22
65
 
23
66
  include Pry::Helpers::CommandHelpers
24
67
 
25
68
  class << self
26
- def lookup(str, _pry_, options={})
27
- co = new(str, _pry_, options)
69
+ def lookup(str, pry_instance, options = {})
70
+ co = new(str, pry_instance, options)
28
71
 
29
72
  co.default_lookup || co.method_or_class_lookup ||
30
73
  co.command_lookup || co.empty_lookup
@@ -33,41 +76,48 @@ class Pry
33
76
 
34
77
  attr_accessor :str
35
78
  attr_accessor :target
36
- attr_accessor :pry
79
+ attr_accessor :pry_instance
37
80
  attr_accessor :super_level
38
81
 
39
- def initialize(str, _pry_, options={})
82
+ def initialize(str, pry_instance, options = {})
40
83
  options = {
41
- :super => 0,
84
+ super: 0
42
85
  }.merge!(options)
43
86
 
44
87
  @str = str
45
- @pry = _pry_
46
- @target = _pry_.current_context
88
+ @pry_instance = pry_instance
89
+ @target = pry_instance.current_context
47
90
  @super_level = options[:super]
48
91
  end
49
92
 
93
+ # TODO: just make it so find_command_by_match_or_listing doesn't raise?
50
94
  def command_lookup
51
- # TODO: just make it so find_command_by_match_or_listing doesn't
52
- # raise?
53
- pry.commands.find_command_by_match_or_listing(str) rescue nil
95
+ pry_instance.commands.find_command_by_match_or_listing(str)
96
+ rescue StandardError
97
+ nil
54
98
  end
55
99
 
100
+ # when no paramter is given (i.e CodeObject.lookup(nil)), then we
101
+ # lookup the 'current object' from the binding.
56
102
  def empty_lookup
57
103
  return nil if str && !str.empty?
58
104
 
59
- if internal_binding?(target)
60
- mod = target_self.is_a?(Module) ? target_self : target_self.class
61
- Pry::WrappedModule(mod)
62
- else
63
- Pry::Method.from_binding(target)
64
- end
105
+ obj = if internal_binding?(target)
106
+ mod = target_self.is_a?(Module) ? target_self : target_self.class
107
+ Pry::WrappedModule(mod)
108
+ else
109
+ Pry::Method.from_binding(target)
110
+ end
111
+
112
+ # respect the super level (i.e user might have specified a
113
+ # --super flag to show-source)
114
+ lookup_super(obj, super_level)
65
115
  end
66
116
 
67
117
  # lookup variables and constants and `self` that are not modules
68
118
  def default_lookup
69
-
70
- # we skip instance methods as we want those to fall through to method_or_class_lookup()
119
+ # we skip instance methods as we want those to fall through to
120
+ # method_or_class_lookup()
71
121
  if safe_to_evaluate?(str) && !looks_like_an_instance_method?(str)
72
122
  obj = target.eval(str)
73
123
 
@@ -77,27 +127,22 @@ class Pry
77
127
  Pry::Method(obj)
78
128
  elsif !obj.is_a?(Module)
79
129
  Pry::WrappedModule(obj.class)
80
- else
81
- nil
82
130
  end
83
131
  end
84
-
85
132
  rescue Pry::RescuableException
86
133
  nil
87
134
  end
88
135
 
89
136
  def method_or_class_lookup
90
- # we need this here because stupid Pry::Method.from_str() does a
91
- # Pry::Method.from_binding when str is nil.
92
- # Once we refactor Pry::Method.from_str() so it doesnt lookup
93
- # from bindings, we can get rid of this check
94
- return nil if str.to_s.empty?
95
-
96
- obj = if str =~ /::(?:\S+)\Z/
97
- Pry::WrappedModule.from_str(str,target) || Pry::Method.from_str(str, target)
98
- else
99
- Pry::Method.from_str(str,target) || Pry::WrappedModule.from_str(str, target)
100
- end
137
+ obj =
138
+ case str
139
+ when /\S+\(\)\z/
140
+ Pry::Method.from_str(str.sub(/\(\)\z/, ''), target) ||
141
+ Pry::WrappedModule.from_str(str, target)
142
+ else
143
+ Pry::WrappedModule.from_str(str, target) ||
144
+ Pry::Method.from_str(str, target)
145
+ end
101
146
 
102
147
  lookup_super(obj, super_level)
103
148
  end
@@ -108,7 +153,6 @@ class Pry
108
153
  [::Proc, ::Method, ::UnboundMethod].any? { |o| obj.is_a?(o) }
109
154
  end
110
155
 
111
-
112
156
  # Returns true if `str` looks like a method, i.e Klass#method
113
157
  # We need to consider this case because method lookups should fall
114
158
  # through to the `method_or_class_lookup()` method but a
@@ -128,6 +172,8 @@ class Pry
128
172
  # @return [Boolean]
129
173
  def safe_to_evaluate?(str)
130
174
  return true if str.strip == "self"
175
+ return false if str =~ /%/
176
+
131
177
  kind = target.eval("defined?(#{str})")
132
178
  kind =~ /variable|constant/
133
179
  end
@@ -140,14 +186,12 @@ class Pry
140
186
  # @param [Object] obj
141
187
  # @param [Fixnum] super_level How far up the super chain to ascend.
142
188
  def lookup_super(obj, super_level)
143
- return nil if !obj
189
+ return unless obj
144
190
 
145
191
  sup = obj.super(super_level)
146
- if !sup
147
- raise Pry::CommandError, "No superclass found for #{obj.wrapped}"
148
- else
149
- sup
150
- end
192
+ raise Pry::CommandError, "No superclass found for #{obj.wrapped}" unless sup
193
+
194
+ sup
151
195
  end
152
196
  end
153
197
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pp'
4
+ require 'English'
5
+
6
+ class Pry
7
+ # PP subclass for streaming inspect output in color.
8
+ class ColorPrinter < ::PP
9
+ Pry::SyntaxHighlighter.overwrite_coderay_comment_token!
10
+
11
+ def self.default(_output, value, pry_instance)
12
+ pry_instance.pager.open do |pager|
13
+ pager.print pry_instance.config.output_prefix
14
+ pp(value, pager, pry_instance.output.width - 1)
15
+ end
16
+ end
17
+
18
+ def self.pp(obj, output = $DEFAULT_OUTPUT, max_width = 79)
19
+ queue = ColorPrinter.new(output, max_width, "\n")
20
+ queue.guard_inspect_key { queue.pp(obj) }
21
+ queue.flush
22
+ output << "\n"
23
+ end
24
+
25
+ def pp(object)
26
+ return super unless object.is_a?(String)
27
+
28
+ # Avoid calling Ruby 2.4+ String#pretty_print that prints multiline
29
+ # Strings prettier
30
+ text(object.inspect)
31
+ rescue StandardError => exception
32
+ raise if exception.is_a?(Pry::Pager::StopPaging)
33
+
34
+ text(highlight_object_literal(inspect_object(object)))
35
+ end
36
+
37
+ def text(str, max_width = str.length)
38
+ if str.include?("\e[")
39
+ super("#{str}\e[0m", max_width)
40
+ elsif str.start_with?('#<') || %w[= >].include?(str)
41
+ super(highlight_object_literal(str), max_width)
42
+ else
43
+ super(SyntaxHighlighter.highlight(str), max_width)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def highlight_object_literal(object_literal)
50
+ code = Pry::SyntaxHighlighter.keyword_token_color
51
+ obj_color = code.start_with?("\e") ? code : "\e[0m\e[0;#{code}m"
52
+ "#{obj_color}#{object_literal}\e[0m"
53
+ end
54
+
55
+ def inspect_object(object)
56
+ object.inspect
57
+ rescue StandardError
58
+ # Read the class name off of the singleton class to provide a default
59
+ # inspect.
60
+ singleton = class << object; self; end
61
+ ancestors = Pry::Method.safe_send(singleton, :ancestors)
62
+ klass = ancestors.find { |k| k != singleton }
63
+ "#<#{klass}:0x#{object.__id__.to_s(16)}>"
64
+ end
65
+ end
66
+ end