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
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
2
4
  # @return [Array] Code of the method used when implementing Pry's
3
5
  # __binding__, along with line indication to be used with instance_eval (and
4
6
  # friends).
5
7
  #
6
8
  # @see Object#__binding__
7
- BINDING_METHOD_IMPL = [<<-METHOD, __FILE__, __LINE__ + 1]
9
+ BINDING_METHOD_IMPL = [<<-METHOD, __FILE__, __LINE__ + 1].freeze
8
10
  # Get a binding with 'self' set to self, and no locals.
9
11
  #
10
12
  # The default definee is determined by the context in which the
@@ -38,8 +40,8 @@ class Object
38
40
  # end
39
41
  # my_method()
40
42
  # @see Pry.start
41
- def pry(object=nil, hash={})
42
- if object.nil? || Hash === object
43
+ def pry(object = nil, hash = {})
44
+ if object.nil? || Hash === object # rubocop:disable Style/CaseEquality
43
45
  Pry.start(self, object || {})
44
46
  else
45
47
  Pry.start(object, hash)
@@ -68,15 +70,26 @@ class Object
68
70
  def __binding__
69
71
  # If you ever feel like changing this method, be careful about variables
70
72
  # that you use. They shouldn't be inserted into the binding that will
71
- # eventually be returning.
73
+ # eventually be returned.
72
74
 
73
75
  # When you're cd'd into a class, methods you define should be added to it.
74
76
  if is_a?(Module)
77
+ # A special case, for JRuby.
78
+ # Module.new.class_eval("binding") has different behaviour than CRuby,
79
+ # where this is not needed: class_eval("binding") vs class_eval{binding}.
80
+ # Using a block works around the difference of behaviour on JRuby.
81
+ # The scope is clear of local variables. Don't add any.
82
+ #
83
+ # This fixes the following two spec failures, at https://travis-ci.org/pry/pry/jobs/274470002
84
+ # 1) ./spec/pry_spec.rb:360:in `block in (root)'
85
+ # 2) ./spec/pry_spec.rb:366:in `block in (root)'
86
+ return class_eval { binding } if Pry::Helpers::Platform.jruby? && name.nil?
87
+
75
88
  # class_eval sets both self and the default definee to this class.
76
- return class_eval "binding"
89
+ return class_eval("binding", __FILE__, __LINE__)
77
90
  end
78
91
 
79
- unless respond_to?(:__pry__)
92
+ unless self.class.method_defined?(:__pry__)
80
93
  # The easiest way to check whether an object has a working singleton class
81
94
  # is to try and define a method on it. (just checking for the presence of
82
95
  # the singleton class gives false positives for `true` and `false`).
@@ -84,14 +97,14 @@ class Object
84
97
  # it has the nice property that we can memoize this check.
85
98
  begin
86
99
  # instance_eval sets the default definee to the object's singleton class
87
- instance_eval *Pry::BINDING_METHOD_IMPL
100
+ instance_eval(*Pry::BINDING_METHOD_IMPL)
88
101
 
89
102
  # If we can't define methods on the Object's singleton_class. Then we fall
90
103
  # back to setting the default definee to be the Object's class. That seems
91
104
  # nicer than having a REPL in which you can't define methods.
92
- rescue TypeError
105
+ rescue TypeError, Pry::FrozenObjectException
93
106
  # class_eval sets the default definee to self.class
94
- self.class.class_eval *Pry::BINDING_METHOD_IMPL
107
+ self.class.class_eval(*Pry::BINDING_METHOD_IMPL)
95
108
  end
96
109
  end
97
110
 
@@ -99,23 +112,33 @@ class Object
99
112
  end
100
113
  end
101
114
 
102
- # There's a splat bug on jruby in 1.9 emulation mode, which breaks the
103
- # pp library.
104
- #
105
- # * http://jira.codehaus.org/browse/JRUBY-6687
106
- # * https://github.com/pry/pry/issues/568
107
- #
108
- # Until that gets fixed upstream, let's monkey-patch here:
109
- if [[1, 2]].pretty_inspect == "[1]\n"
110
- class Array
111
- def pretty_print(q)
112
- q.group(1, '[', ']') {
113
- i = 0
114
- q.seplist(self) { |*|
115
- q.pp self[i]
116
- i += 1
117
- }
118
- }
119
- end
115
+ class BasicObject
116
+ # Return a binding object for the receiver.
117
+ #
118
+ # The `self` of the binding is set to the current object, and it contains no
119
+ # local variables.
120
+ #
121
+ # The default definee (http://yugui.jp/articles/846) is set such that new
122
+ # methods defined will be added to the singleton class of the BasicObject.
123
+ #
124
+ # @return [Binding]
125
+ def __binding__
126
+ # BasicObjects don't have respond_to?, so we just define the method
127
+ # every time. As they also don't have `.freeze`, this call won't
128
+ # fail as it can for normal Objects.
129
+ (class << self; self; end).class_eval(<<-METHOD, __FILE__, __LINE__ + 1)
130
+ # Get a binding with 'self' set to self, and no locals.
131
+ #
132
+ # The default definee is determined by the context in which the
133
+ # definition is eval'd.
134
+ #
135
+ # Please don't call this method directly, see {__binding__}.
136
+ #
137
+ # @return [Binding]
138
+ def __pry__
139
+ ::Kernel.binding
140
+ end
141
+ METHOD
142
+ __pry__
120
143
  end
121
144
  end
data/lib/pry/editor.rb CHANGED
@@ -1,129 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
4
+
1
5
  class Pry
2
6
  class Editor
3
- extend Pry::Helpers::BaseHelpers
4
- extend Pry::Helpers::CommandHelpers
5
-
6
- class << self
7
- def edit_tempfile_with_content(initial_content, line=1)
8
- temp_file do |f|
9
- f.puts(initial_content)
10
- f.flush
11
- f.close(false)
12
- invoke_editor(f.path, line, true)
13
- File.read(f.path)
14
- end
7
+ def self.default
8
+ if (visual = Pry::Env['VISUAL'])
9
+ return visual
15
10
  end
16
11
 
17
- def invoke_editor(file, line, blocking=true)
18
- raise CommandError, "Please set Pry.config.editor or export $VISUAL or $EDITOR" unless Pry.config.editor
12
+ if (editor = Pry::Env['EDITOR'])
13
+ return editor
14
+ end
19
15
 
20
- editor_invocation = build_editor_invocation_string(file, line, blocking)
21
- return nil unless editor_invocation
16
+ return 'notepad' if Helpers::Platform.windows?
22
17
 
23
- if jruby?
24
- open_editor_on_jruby(editor_invocation)
25
- else
26
- open_editor(editor_invocation)
27
- end
18
+ %w[editor nano vi].find do |editor_exe|
19
+ Kernel.system("which #{editor_exe} > /dev/null 2>&1")
28
20
  end
21
+ end
29
22
 
30
- private
23
+ include Pry::Helpers::CommandHelpers
31
24
 
32
- # Generate the string that's used to start the editor. This includes
33
- # all the flags we want as well as the file and line number we
34
- # want to open at.
35
- def build_editor_invocation_string(file, line, blocking)
25
+ attr_reader :pry_instance
36
26
 
37
- if Pry.config.editor.respond_to?(:call)
38
- args = [file, line, blocking][0...(Pry.config.editor.arity)]
39
- Pry.config.editor.call(*args)
40
- else
41
- sanitized_file = if windows?
42
- file.gsub(/\//, '\\')
43
- else
44
- Shellwords.escape(file)
45
- end
27
+ def initialize(pry_instance)
28
+ @pry_instance = pry_instance
29
+ end
46
30
 
47
- "#{Pry.config.editor} #{blocking_flag_for_editor(blocking)} #{start_line_syntax_for_editor(sanitized_file, line)}"
48
- end
31
+ def edit_tempfile_with_content(initial_content, line = 1)
32
+ temp_file do |f|
33
+ f.puts(initial_content)
34
+ f.flush
35
+ f.close(false)
36
+ invoke_editor(f.path, line, true)
37
+ File.read(f.path)
49
38
  end
39
+ end
50
40
 
51
- # Start the editor running, using the calculated invocation string
52
- def open_editor(editor_invocation)
53
- # Note we dont want to use Pry.config.system here as that
54
- # may be invoked non-interactively (i.e via Open4), whereas we want to
55
- # ensure the editor is always interactive
56
- system(editor_invocation) or raise CommandError, "`#{editor_invocation}` gave exit status: #{$?.exitstatus}"
41
+ def invoke_editor(file, line, blocking = true)
42
+ unless pry_instance.config.editor
43
+ raise CommandError,
44
+ "Please set Pry.config.editor or export $VISUAL or $EDITOR"
57
45
  end
58
46
 
59
- # We need JRuby specific code here cos just shelling out using
60
- # system() appears to be pretty broken :/
61
- def open_editor_on_jruby(editor_invocation)
62
- begin
63
- require 'spoon'
64
- pid = Spoon.spawnp(*editor_invocation.split)
65
- Process.waitpid(pid)
66
- rescue FFI::NotFoundError
67
- system(editor_invocation)
68
- end
47
+ editor_invocation = build_editor_invocation_string(file, line, blocking)
48
+ return nil unless editor_invocation
49
+
50
+ if Helpers::Platform.jruby?
51
+ open_editor_on_jruby(editor_invocation)
52
+ else
53
+ open_editor(editor_invocation)
69
54
  end
55
+ end
70
56
 
71
- # Some editors that run outside the terminal allow you to control whether or
72
- # not to block the process from which they were launched (in this case, Pry).
73
- # For those editors, return the flag that produces the desired behavior.
74
- def blocking_flag_for_editor(blocking)
75
- case editor_name
76
- when /^emacsclient/
77
- '--no-wait' unless blocking
78
- when /^[gm]vim/
79
- '--nofork' if blocking
80
- when /^jedit/
81
- '-wait' if blocking
82
- when /^mate/, /^subl/
83
- '-w' if blocking
84
- end
57
+ # Generate the string that's used to start the editor. This includes
58
+ # all the flags we want as well as the file and line number we
59
+ # want to open at.
60
+ def build_editor_invocation_string(file, line, blocking)
61
+ if pry_instance.config.editor.respond_to?(:call)
62
+ args = [file, line, blocking][0...(pry_instance.config.editor.arity)]
63
+ pry_instance.config.editor.call(*args)
64
+ else
65
+ sanitized_file = Helpers::Platform.windows? ? file : Shellwords.escape(file)
66
+ editor = pry_instance.config.editor
67
+ flag = blocking_flag_for_editor(blocking)
68
+ start_line = start_line_syntax_for_editor(sanitized_file, line)
69
+ "#{editor} #{flag} #{start_line}"
85
70
  end
71
+ end
86
72
 
87
- # Return the syntax for a given editor for starting the editor
88
- # and moving to a particular line within that file
89
- def start_line_syntax_for_editor(file_name, line_number)
90
- # special case for 1st line
91
- return file_name if line_number <= 1
73
+ private
92
74
 
93
- case editor_name
94
- when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
95
- "+#{line_number} #{file_name}"
96
- when /^mate/, /^geany/
97
- "-l #{line_number} #{file_name}"
98
- when /^subl/
99
- "#{file_name}:#{line_number}"
100
- when /^uedit32/
101
- "#{file_name}/#{line_number}"
102
- when /^jedit/
103
- "#{file_name} +line:#{line_number}"
104
- else
105
- if windows?
106
- "#{file_name}"
107
- else
108
- "+#{line_number} #{file_name}"
109
- end
110
- end
75
+ # Start the editor running, using the calculated invocation string
76
+ def open_editor(editor_invocation)
77
+ # Note we dont want to use Pry.config.system here as that
78
+ # may be invoked non-interactively (i.e via Open4), whereas we want to
79
+ # ensure the editor is always interactive
80
+ system(*Shellwords.split(editor_invocation)) ||
81
+ raise(
82
+ CommandError,
83
+ "`#{editor_invocation}` gave exit status: #{$CHILD_STATUS.exitstatus}"
84
+ )
85
+ end
86
+
87
+ # We need JRuby specific code here cos just shelling out using
88
+ # system() appears to be pretty broken :/
89
+ def open_editor_on_jruby(editor_invocation)
90
+ require 'spoon'
91
+ pid = Spoon.spawnp(*Shellwords.split(editor_invocation))
92
+ Process.waitpid(pid)
93
+ rescue FFI::NotFoundError
94
+ system(editor_invocation)
95
+ end
96
+
97
+ # Some editors that run outside the terminal allow you to control whether or
98
+ # not to block the process from which they were launched (in this case, Pry).
99
+ # For those editors, return the flag that produces the desired behavior.
100
+ def blocking_flag_for_editor(blocking)
101
+ case editor_name
102
+ when /^emacsclient/
103
+ '--no-wait' unless blocking
104
+ when /^[gm]vim/
105
+ '--nofork' if blocking
106
+ when /^jedit/
107
+ '-wait' if blocking
108
+ when /^mate/, /^subl/, /^redcar/, /^code/
109
+ '-w' if blocking
111
110
  end
111
+ end
112
112
 
113
- # Get the name of the binary that Pry.config.editor points to.
114
- #
115
- # This is useful for deciding which flags we pass to the editor as
116
- # we can just use the program's name and ignore any absolute paths.
117
- #
118
- # @example
119
- # Pry.config.editor="/home/conrad/bin/textmate -w"
120
- # editor_name
121
- # # => textmate
122
- #
123
- def editor_name
124
- File.basename(Pry.config.editor).split(" ").first
113
+ # Return the syntax for a given editor for starting the editor
114
+ # and moving to a particular line within that file
115
+ def start_line_syntax_for_editor(file_name, line_number)
116
+ # special case for 1st line
117
+ return file_name if line_number <= 1
118
+
119
+ case editor_name
120
+ when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
121
+ "+#{line_number} #{file_name}"
122
+ when /^mate/, /^geany/
123
+ "-l #{line_number} #{file_name}"
124
+ when /^code/
125
+ "-g #{file_name}:#{line_number}"
126
+ when /^subl/
127
+ "#{file_name}:#{line_number}"
128
+ when /^uedit32/
129
+ "#{file_name}/#{line_number}"
130
+ when /^jedit/
131
+ "#{file_name} +line:#{line_number}"
132
+ when /^redcar/
133
+ "-l#{line_number} #{file_name}"
134
+ else
135
+ if Helpers::Platform.windows?
136
+ file_name.to_s
137
+ else
138
+ "+#{line_number} #{file_name}"
139
+ end
125
140
  end
141
+ end
126
142
 
143
+ # Get the name of the binary that Pry.config.editor points to.
144
+ #
145
+ # This is useful for deciding which flags we pass to the editor as
146
+ # we can just use the program's name and ignore any absolute paths.
147
+ #
148
+ # @example
149
+ # Pry.config.editor="/home/conrad/bin/textmate -w"
150
+ # editor_name
151
+ # # => textmate
152
+ #
153
+ def editor_name
154
+ File.basename(pry_instance.config.editor).split(" ").first
127
155
  end
128
156
  end
129
157
  end
data/lib/pry/env.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ # Env is a helper module to work with environment variables.
5
+ #
6
+ # @since v0.13.0
7
+ # @api private
8
+ module Env
9
+ def self.[](key)
10
+ return unless ENV.key?(key)
11
+
12
+ value = ENV[key]
13
+ return if value == ''
14
+
15
+ value
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ # @api private
5
+ # @since v0.13.0
6
+ module ExceptionHandler
7
+ class << self
8
+ # Will only show the first line of the backtrace.
9
+ def handle_exception(output, exception, _pry_instance)
10
+ if exception.is_a?(UserError) && exception.is_a?(SyntaxError)
11
+ output.puts "SyntaxError: #{exception.message.sub(/.*syntax error, */m, '')}"
12
+ else
13
+ output.puts standard_error_text_for(exception)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def standard_error_text_for(exception)
20
+ text = exception_text(exception)
21
+ return text unless exception.respond_to?(:cause)
22
+
23
+ cause = exception.cause
24
+ while cause
25
+ text += cause_text(cause)
26
+ cause = cause.cause
27
+ end
28
+
29
+ text
30
+ end
31
+
32
+ def exception_text(exception)
33
+ "#{exception.class}: #{exception.message}\n" \
34
+ "from #{exception.backtrace.first}\n"
35
+ end
36
+
37
+ def cause_text(cause)
38
+ "Caused by #{cause.class}: #{cause}\n" \
39
+ "from #{cause.backtrace.first}\n"
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ # As a REPL, we often want to catch any unexpected exceptions that may have
5
+ # been raised; however we don't want to go overboard and prevent the user
6
+ # from exiting Pry when they want to.
7
+ module RescuableException
8
+ def self.===(exception)
9
+ case exception
10
+ # Catch when the user hits ^C (Interrupt < SignalException), and assume
11
+ # that they just wanted to stop the in-progress command (just like bash
12
+ # etc.)
13
+ when Interrupt
14
+ true
15
+ # Don't catch signals (particularly not SIGTERM) as these are unlikely
16
+ # to be intended for pry itself. We should also make sure that
17
+ # Kernel#exit works.
18
+ when *Pry.config.unrescued_exceptions
19
+ false
20
+ # All other exceptions will be caught.
21
+ else
22
+ true
23
+ end
24
+ end
25
+ end
26
+
27
+ # Catches SecurityErrors if $SAFE is set
28
+ module TooSafeException
29
+ def self.===(exception)
30
+ if Pry::HAS_SAFE_LEVEL
31
+ $SAFE > 0 && exception.is_a?(SecurityError)
32
+ else
33
+ exception.is_a?(SecurityError)
34
+ end
35
+ end
36
+ end
37
+
38
+ # An Exception Tag (cf. Exceptional Ruby) that instructs Pry to show the error
39
+ # in a more user-friendly manner. This should be used when the exception
40
+ # happens within Pry itself as a direct consequence of the user typing
41
+ # something wrong.
42
+ #
43
+ # This allows us to distinguish between the user typing:
44
+ #
45
+ # pry(main)> def )
46
+ # SyntaxError: unexpected )
47
+ #
48
+ # pry(main)> method_that_evals("def )")
49
+ # SyntaxError: (eval):1: syntax error, unexpected ')'
50
+ # from ./a.rb:2 in `eval'
51
+ module UserError; end
52
+
53
+ # When we try to get a binding for an object, we try to define a method on
54
+ # that Object's singleton class. This doesn't work for "frozen" Object's, and
55
+ # the exception is just a vanilla RuntimeError.
56
+ module FrozenObjectException
57
+ def self.===(exception)
58
+ [
59
+ "can't modify frozen class/module",
60
+ "can't modify frozen Class",
61
+ "can't modify frozen object"
62
+ ].include?(exception.message)
63
+ end
64
+ end
65
+
66
+ # CommandErrors are caught by the REPL loop and displayed to the user. They
67
+ # indicate an exceptional condition that's fatal to the current command.
68
+ class CommandError < StandardError; end
69
+ class MethodNotFound < CommandError; end
70
+
71
+ # indicates obsolete API
72
+ class ObsoleteError < StandardError; end
73
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ module Forwardable
5
+ require 'forwardable'
6
+ include ::Forwardable
7
+
8
+ #
9
+ # Since Ruby 2.4, Forwardable will print a warning when
10
+ # calling a method that is private on a delegate, and
11
+ # in the future it could be an error: https://bugs.ruby-lang.org/issues/12782#note-3
12
+ #
13
+ # That's why we revert to a custom implementation for delegating one
14
+ # private method to another.
15
+ #
16
+ def def_private_delegators(target, *private_delegates)
17
+ private_delegates.each do |private_delegate|
18
+ define_method(private_delegate) do |*a, &b|
19
+ instance_variable_get(target).__send__(private_delegate, *a, &b)
20
+ end
21
+ end
22
+ class_eval do
23
+ private(*private_delegates) # rubocop:disable Style/AccessModifierDeclarations
24
+ end
25
+ end
26
+ end
27
+ end