pry 0.9.10pre1-i386-mswin32 → 0.9.11-i386-mswin32

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 (194) hide show
  1. data/.travis.yml +3 -1
  2. data/CHANGELOG +63 -2
  3. data/CONTRIBUTORS +43 -25
  4. data/Gemfile +7 -0
  5. data/Guardfile +62 -0
  6. data/README.markdown +4 -4
  7. data/Rakefile +34 -35
  8. data/lib/pry.rb +107 -54
  9. data/lib/pry/cli.rb +34 -11
  10. data/lib/pry/code.rb +165 -182
  11. data/lib/pry/code/code_range.rb +70 -0
  12. data/lib/pry/code/loc.rb +92 -0
  13. data/lib/pry/code_object.rb +153 -0
  14. data/lib/pry/command.rb +160 -22
  15. data/lib/pry/command_set.rb +37 -26
  16. data/lib/pry/commands.rb +4 -27
  17. data/lib/pry/commands/amend_line.rb +99 -0
  18. data/lib/pry/commands/bang.rb +20 -0
  19. data/lib/pry/commands/bang_pry.rb +17 -0
  20. data/lib/pry/commands/cat.rb +53 -0
  21. data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
  22. data/lib/pry/commands/cat/exception_formatter.rb +78 -0
  23. data/lib/pry/commands/cat/file_formatter.rb +84 -0
  24. data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
  25. data/lib/pry/commands/cd.rb +30 -0
  26. data/lib/pry/commands/code_collector.rb +165 -0
  27. data/lib/pry/commands/deprecated_commands.rb +2 -0
  28. data/lib/pry/commands/disable_pry.rb +27 -0
  29. data/lib/pry/commands/easter_eggs.rb +112 -0
  30. data/lib/pry/commands/edit.rb +206 -0
  31. data/lib/pry/commands/edit/exception_patcher.rb +25 -0
  32. data/lib/pry/commands/edit/file_and_line_locator.rb +38 -0
  33. data/lib/pry/commands/edit/method_patcher.rb +122 -0
  34. data/lib/pry/commands/exit.rb +42 -0
  35. data/lib/pry/commands/exit_all.rb +29 -0
  36. data/lib/pry/commands/exit_program.rb +24 -0
  37. data/lib/pry/commands/find_method.rb +199 -0
  38. data/lib/pry/commands/fix_indent.rb +19 -0
  39. data/lib/pry/commands/gem_cd.rb +26 -0
  40. data/lib/pry/commands/gem_install.rb +29 -0
  41. data/lib/pry/commands/gem_list.rb +33 -0
  42. data/lib/pry/commands/gem_open.rb +29 -0
  43. data/lib/pry/commands/gist.rb +95 -0
  44. data/lib/pry/commands/help.rb +164 -0
  45. data/lib/pry/commands/hist.rb +161 -0
  46. data/lib/pry/commands/import_set.rb +22 -0
  47. data/lib/pry/commands/install_command.rb +51 -0
  48. data/lib/pry/commands/jump_to.rb +29 -0
  49. data/lib/pry/commands/ls.rb +339 -0
  50. data/lib/pry/commands/nesting.rb +25 -0
  51. data/lib/pry/commands/play.rb +69 -0
  52. data/lib/pry/commands/pry_backtrace.rb +26 -0
  53. data/lib/pry/commands/pry_version.rb +17 -0
  54. data/lib/pry/commands/raise_up.rb +32 -0
  55. data/lib/pry/commands/reload_code.rb +39 -0
  56. data/lib/pry/commands/reset.rb +18 -0
  57. data/lib/pry/commands/ri.rb +56 -0
  58. data/lib/pry/commands/save_file.rb +61 -0
  59. data/lib/pry/commands/shell_command.rb +43 -0
  60. data/lib/pry/commands/shell_mode.rb +27 -0
  61. data/lib/pry/commands/show_doc.rb +78 -0
  62. data/lib/pry/commands/show_info.rb +139 -0
  63. data/lib/pry/commands/show_input.rb +17 -0
  64. data/lib/pry/commands/show_source.rb +37 -0
  65. data/lib/pry/commands/simple_prompt.rb +22 -0
  66. data/lib/pry/commands/stat.rb +40 -0
  67. data/lib/pry/commands/switch_to.rb +23 -0
  68. data/lib/pry/commands/toggle_color.rb +20 -0
  69. data/lib/pry/commands/whereami.rb +114 -0
  70. data/lib/pry/commands/wtf.rb +57 -0
  71. data/lib/pry/completion.rb +120 -46
  72. data/lib/pry/config.rb +11 -0
  73. data/lib/pry/core_extensions.rb +30 -19
  74. data/lib/pry/editor.rb +129 -0
  75. data/lib/pry/helpers.rb +1 -0
  76. data/lib/pry/helpers/base_helpers.rb +89 -119
  77. data/lib/pry/helpers/command_helpers.rb +7 -122
  78. data/lib/pry/helpers/table.rb +100 -0
  79. data/lib/pry/helpers/text.rb +4 -4
  80. data/lib/pry/history_array.rb +5 -0
  81. data/lib/pry/hooks.rb +1 -3
  82. data/lib/pry/indent.rb +104 -30
  83. data/lib/pry/method.rb +66 -22
  84. data/lib/pry/module_candidate.rb +26 -15
  85. data/lib/pry/pager.rb +70 -0
  86. data/lib/pry/plugins.rb +1 -2
  87. data/lib/pry/pry_class.rb +63 -22
  88. data/lib/pry/pry_instance.rb +58 -37
  89. data/lib/pry/rubygem.rb +74 -0
  90. data/lib/pry/terminal_info.rb +43 -0
  91. data/lib/pry/test/helper.rb +185 -0
  92. data/lib/pry/version.rb +1 -1
  93. data/lib/pry/wrapped_module.rb +58 -24
  94. data/pry.gemspec +21 -37
  95. data/{test/test_cli.rb → spec/cli_spec.rb} +0 -0
  96. data/spec/code_object_spec.rb +277 -0
  97. data/{test/test_code.rb → spec/code_spec.rb} +19 -1
  98. data/{test/test_command_helpers.rb → spec/command_helpers_spec.rb} +0 -0
  99. data/{test/test_command_integration.rb → spec/command_integration_spec.rb} +38 -46
  100. data/{test/test_command_set.rb → spec/command_set_spec.rb} +18 -1
  101. data/{test/test_command.rb → spec/command_spec.rb} +250 -149
  102. data/spec/commands/amend_line_spec.rb +247 -0
  103. data/spec/commands/bang_spec.rb +19 -0
  104. data/spec/commands/cat_spec.rb +164 -0
  105. data/spec/commands/cd_spec.rb +250 -0
  106. data/spec/commands/disable_pry_spec.rb +25 -0
  107. data/spec/commands/edit_spec.rb +727 -0
  108. data/spec/commands/exit_all_spec.rb +34 -0
  109. data/spec/commands/exit_program_spec.rb +19 -0
  110. data/spec/commands/exit_spec.rb +34 -0
  111. data/{test/test_default_commands/test_find_method.rb → spec/commands/find_method_spec.rb} +27 -7
  112. data/spec/commands/gem_list_spec.rb +26 -0
  113. data/spec/commands/gist_spec.rb +75 -0
  114. data/{test/test_default_commands/test_help.rb → spec/commands/help_spec.rb} +8 -9
  115. data/spec/commands/hist_spec.rb +181 -0
  116. data/spec/commands/jump_to_spec.rb +15 -0
  117. data/spec/commands/ls_spec.rb +177 -0
  118. data/spec/commands/play_spec.rb +140 -0
  119. data/spec/commands/raise_up_spec.rb +56 -0
  120. data/spec/commands/save_file_spec.rb +177 -0
  121. data/spec/commands/show_doc_spec.rb +378 -0
  122. data/spec/commands/show_input_spec.rb +17 -0
  123. data/spec/commands/show_source_spec.rb +597 -0
  124. data/spec/commands/whereami_spec.rb +154 -0
  125. data/spec/completion_spec.rb +233 -0
  126. data/spec/control_d_handler_spec.rb +58 -0
  127. data/spec/editor_spec.rb +79 -0
  128. data/{test/test_exception_whitelist.rb → spec/exception_whitelist_spec.rb} +0 -0
  129. data/{test → spec/fixtures}/candidate_helper1.rb +0 -0
  130. data/{test → spec/fixtures}/candidate_helper2.rb +0 -0
  131. data/{test/test_default_commands → spec/fixtures}/example.erb +0 -0
  132. data/spec/fixtures/example_nesting.rb +33 -0
  133. data/spec/fixtures/show_source_doc_examples.rb +15 -0
  134. data/{test → spec/fixtures}/testrc +0 -0
  135. data/{test → spec/fixtures}/testrcbad +0 -0
  136. data/spec/helper.rb +34 -0
  137. data/spec/helpers/bacon.rb +86 -0
  138. data/spec/helpers/mock_pry.rb +43 -0
  139. data/spec/helpers/table_spec.rb +83 -0
  140. data/{test/test_history_array.rb → spec/history_array_spec.rb} +21 -19
  141. data/{test/test_hooks.rb → spec/hooks_spec.rb} +0 -0
  142. data/{test/test_indent.rb → spec/indent_spec.rb} +24 -0
  143. data/{test/test_input_stack.rb → spec/input_stack_spec.rb} +4 -0
  144. data/{test/test_method.rb → spec/method_spec.rb} +65 -1
  145. data/{test/test_prompt.rb → spec/prompt_spec.rb} +0 -0
  146. data/{test/test_pry_defaults.rb → spec/pry_defaults_spec.rb} +14 -14
  147. data/{test/test_pry_history.rb → spec/pry_history_spec.rb} +15 -0
  148. data/spec/pry_output_spec.rb +95 -0
  149. data/{test/test_pry.rb → spec/pry_spec.rb} +74 -32
  150. data/{test/test_sticky_locals.rb → spec/sticky_locals_spec.rb} +27 -25
  151. data/{test/test_syntax_checking.rb → spec/syntax_checking_spec.rb} +17 -1
  152. data/{test/test_wrapped_module.rb → spec/wrapped_module_spec.rb} +92 -5
  153. metadata +239 -115
  154. data/examples/example_basic.rb +0 -15
  155. data/examples/example_command_override.rb +0 -32
  156. data/examples/example_commands.rb +0 -36
  157. data/examples/example_hooks.rb +0 -9
  158. data/examples/example_image_edit.rb +0 -67
  159. data/examples/example_input.rb +0 -7
  160. data/examples/example_input2.rb +0 -29
  161. data/examples/example_output.rb +0 -11
  162. data/examples/example_print.rb +0 -6
  163. data/examples/example_prompt.rb +0 -9
  164. data/examples/helper.rb +0 -6
  165. data/lib/pry/default_commands/cd.rb +0 -81
  166. data/lib/pry/default_commands/commands.rb +0 -62
  167. data/lib/pry/default_commands/context.rb +0 -98
  168. data/lib/pry/default_commands/easter_eggs.rb +0 -95
  169. data/lib/pry/default_commands/editing.rb +0 -420
  170. data/lib/pry/default_commands/find_method.rb +0 -169
  171. data/lib/pry/default_commands/gems.rb +0 -84
  172. data/lib/pry/default_commands/gist.rb +0 -187
  173. data/lib/pry/default_commands/help.rb +0 -127
  174. data/lib/pry/default_commands/hist.rb +0 -120
  175. data/lib/pry/default_commands/input_and_output.rb +0 -306
  176. data/lib/pry/default_commands/introspection.rb +0 -410
  177. data/lib/pry/default_commands/ls.rb +0 -272
  178. data/lib/pry/default_commands/misc.rb +0 -38
  179. data/lib/pry/default_commands/navigating_pry.rb +0 -110
  180. data/lib/pry/default_commands/whereami.rb +0 -92
  181. data/lib/pry/extended_commands/experimental.rb +0 -7
  182. data/test/helper.rb +0 -223
  183. data/test/test_completion.rb +0 -62
  184. data/test/test_control_d_handler.rb +0 -45
  185. data/test/test_default_commands/test_cd.rb +0 -321
  186. data/test/test_default_commands/test_context.rb +0 -288
  187. data/test/test_default_commands/test_documentation.rb +0 -315
  188. data/test/test_default_commands/test_gems.rb +0 -18
  189. data/test/test_default_commands/test_input.rb +0 -428
  190. data/test/test_default_commands/test_introspection.rb +0 -511
  191. data/test/test_default_commands/test_ls.rb +0 -151
  192. data/test/test_default_commands/test_shell.rb +0 -343
  193. data/test/test_default_commands/test_show_source.rb +0 -432
  194. data/test/test_pry_output.rb +0 -41
@@ -0,0 +1,206 @@
1
+ class Pry
2
+ class Command::Edit < Pry::ClassCommand
3
+ require 'pry/commands/edit/method_patcher'
4
+ require 'pry/commands/edit/exception_patcher'
5
+ require 'pry/commands/edit/file_and_line_locator'
6
+
7
+ match 'edit'
8
+ group 'Editing'
9
+ description 'Invoke the default editor on a file.'
10
+
11
+ banner <<-'BANNER'
12
+ Usage: edit [--no-reload|--reload|--patch] [--line LINE] [--temp|--ex|FILE[:LINE]|OBJECT|--in N]
13
+
14
+ Open a text editor. When no FILE is given, edits the pry input buffer. Ensure
15
+ `Pry.config.editor` is set to your editor of choice.
16
+
17
+ edit sample.rb edit -p MyClass#my_method
18
+ edit sample.rb --line 105 edit YourClass
19
+ edit MyClass#my_method edit --ex
20
+ edit --method edit --ex -p
21
+
22
+ https://github.com/pry/pry/wiki/Editor-integration#wiki-Edit_command
23
+ BANNER
24
+
25
+ def options(opt)
26
+ opt.on :e, :ex, "Open the file that raised the most recent exception (_ex_.file)",
27
+ :optional_argument => true, :as => Integer
28
+ opt.on :i, :in, "Open a temporary file containing the Nth input expression. N may be a range",
29
+ :optional_argument => true, :as => Range, :default => -1..-1
30
+ opt.on :t, :temp, "Open an empty temporary file"
31
+ opt.on :l, :line, "Jump to this line in the opened file",
32
+ :argument => true, :as => Integer
33
+ opt.on :n, :"no-reload", "Don't automatically reload the edited code"
34
+ opt.on :c, :current, "Open the current __FILE__ and at __LINE__ (as returned by `whereami`)"
35
+ opt.on :r, :reload, "Reload the edited code immediately (default for ruby files)"
36
+ opt.on :p, :patch, "Instead of editing the object's file, try to edit in a tempfile and apply as a monkey patch"
37
+ opt.on :m, :method, "Explicitly edit the _current_ method (when inside a method context)."
38
+ end
39
+
40
+ def process
41
+ if bad_option_combination?
42
+ raise CommandError, "Only one of --ex, --temp, --in, --method and FILE may be specified."
43
+ end
44
+
45
+ if repl_edit?
46
+ # code defined in pry, eval'd within pry.
47
+ repl_edit
48
+ elsif runtime_patch?
49
+ # patch code without persisting changes
50
+ apply_runtime_patch
51
+ else
52
+ # code stored in actual files, eval'd at top-level
53
+ file_edit
54
+ end
55
+ end
56
+
57
+ def repl_edit?
58
+ !opts.present?(:ex) && !opts.present?(:current) && !opts.present?(:method) &&
59
+ filename_argument.empty?
60
+ end
61
+
62
+ def repl_edit
63
+ content = Pry::Editor.edit_tempfile_with_content(initial_temp_file_content,
64
+ initial_temp_file_content.lines.count)
65
+ if repl_reload?
66
+ silence_warnings do
67
+ eval_string.replace content
68
+ end
69
+ end
70
+ end
71
+
72
+ def file_based_exception?
73
+ opts.present?(:ex) && !opts.present?(:patch)
74
+ end
75
+
76
+ def runtime_patch?
77
+ !file_based_exception? && (opts.present?(:patch) || pry_method?(code_object))
78
+ end
79
+
80
+ def apply_runtime_patch
81
+ if patch_exception?
82
+ ExceptionPatcher.new(_pry_, state, file_and_line_for_current_exception).perform_patch
83
+ else
84
+ if code_object.is_a?(Pry::Method)
85
+ MethodPatcher.new(_pry_, code_object).perform_patch
86
+ else
87
+ raise NotImplementedError, "Cannot yet patch #{code_object} objects!"
88
+ end
89
+ end
90
+ end
91
+
92
+ def ensure_file_name_is_valid(file_name)
93
+ raise CommandError, "Cannot find a valid file for #{filename_argument}" if !file_name
94
+ raise CommandError, "#{file_name} is not a valid file name, cannot edit!" if not_a_real_file?(file_name)
95
+ end
96
+
97
+ def file_and_line_for_current_exception
98
+ FileAndLineLocator.from_exception(_pry_.last_exception, opts[:ex].to_i)
99
+ end
100
+
101
+ def file_and_line
102
+ file_name, line = if opts.present?(:current)
103
+ FileAndLineLocator.from_binding(target)
104
+ elsif opts.present?(:ex)
105
+ file_and_line_for_current_exception
106
+ elsif code_object
107
+ FileAndLineLocator.from_code_object(code_object, filename_argument)
108
+ else
109
+ # when file and line are passed as a single arg, e.g my_file.rb:30
110
+ FileAndLineLocator.from_filename_argument(filename_argument)
111
+ end
112
+
113
+ [file_name, opts.present?(:line) ? opts[:l].to_i : line]
114
+ end
115
+
116
+ def file_edit
117
+ file_name, line = file_and_line
118
+
119
+ ensure_file_name_is_valid(file_name)
120
+
121
+ Pry::Editor.invoke_editor(file_name, line, reload?(file_name))
122
+ set_file_and_dir_locals(file_name)
123
+
124
+ if reload?(file_name)
125
+ silence_warnings do
126
+ TOPLEVEL_BINDING.eval(File.read(file_name), file_name)
127
+ end
128
+ end
129
+ end
130
+
131
+ def filename_argument
132
+ args.join(' ')
133
+ end
134
+
135
+ def code_object
136
+ @code_object ||= !probably_a_file?(filename_argument) &&
137
+ Pry::CodeObject.lookup(filename_argument, _pry_)
138
+ end
139
+
140
+ def pry_method?(code_object)
141
+ code_object.is_a?(Pry::Method) &&
142
+ code_object.pry_method?
143
+ end
144
+
145
+ def patch_exception?
146
+ opts.present?(:ex) && opts.present?(:patch)
147
+ end
148
+
149
+ def bad_option_combination?
150
+ [opts.present?(:ex), opts.present?(:temp),
151
+ opts.present?(:in), opts.present?(:method), !filename_argument.empty?].count(true) > 1
152
+ end
153
+
154
+ def input_expression
155
+ case opts[:i]
156
+ when Range
157
+ (_pry_.input_array[opts[:i]] || []).join
158
+ when Fixnum
159
+ _pry_.input_array[opts[:i]] || ""
160
+ else
161
+ raise Pry::CommandError, "Not a valid range: #{opts[:i]}"
162
+ end
163
+ end
164
+
165
+ def reloadable?
166
+ opts.present?(:reload) || opts.present?(:ex)
167
+ end
168
+
169
+ def never_reload?
170
+ opts.present?(:'no-reload') || Pry.config.disable_auto_reload
171
+ end
172
+
173
+ # conditions much less strict than for reload? (which is for file-based reloads)
174
+ def repl_reload?
175
+ !never_reload?
176
+ end
177
+
178
+ def reload?(file_name="")
179
+ (reloadable? || file_name.end_with?(".rb")) && !never_reload?
180
+ end
181
+
182
+ def initial_temp_file_content
183
+ case
184
+ when opts.present?(:temp)
185
+ ""
186
+ when opts.present?(:in)
187
+ input_expression
188
+ when eval_string.strip != ""
189
+ eval_string
190
+ else
191
+ _pry_.input_array.reverse_each.find { |x| x && x.strip != "" } || ""
192
+ end
193
+ end
194
+
195
+ def probably_a_file?(str)
196
+ [".rb", ".c", ".py", ".yml", ".gemspec"].include? File.extname(str) ||
197
+ str =~ /\/|\\/
198
+ end
199
+
200
+ def complete(search)
201
+ super + Bond::Rc.files(search.split(" ").last || '')
202
+ end
203
+ end
204
+
205
+ Pry::Commands.add_command(Pry::Command::Edit)
206
+ end
@@ -0,0 +1,25 @@
1
+ class Pry
2
+ class Command::Edit
3
+ class ExceptionPatcher
4
+ attr_accessor :_pry_
5
+ attr_accessor :state
6
+ attr_accessor :file_and_line
7
+
8
+ def initialize(_pry_, state, exception_file_and_line)
9
+ @_pry_ = _pry_
10
+ @state = state
11
+ @file_and_line = exception_file_and_line
12
+ end
13
+
14
+ # perform the patch
15
+ def perform_patch
16
+ file_name, line = file_and_line
17
+ lines = state.dynamical_ex_file || File.read(file_name)
18
+
19
+ source = Pry::Editor.edit_tempfile_with_content(lines)
20
+ _pry_.evaluate_ruby source
21
+ state.dynamical_ex_file = source.split("\n")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ class Pry
2
+ class Command::Edit
3
+ module FileAndLineLocator
4
+ class << self
5
+ def from_binding(target)
6
+ [target.eval("__FILE__"), target.eval("__LINE__")]
7
+ end
8
+
9
+ def from_code_object(code_object, filename_argument)
10
+ if File.exists?(code_object.source_file.to_s)
11
+ [code_object.source_file, code_object.source_line]
12
+ else
13
+ raise CommandError, "Cannot find a file for #{filename_argument}!"
14
+ end
15
+ end
16
+
17
+ def from_exception(exception, backtrace_level)
18
+ raise CommandError, "No exception found." if exception.nil?
19
+
20
+ file_name, line = exception.bt_source_location_for(backtrace_level)
21
+ raise CommandError, "Exception has no associated file." if file_name.nil?
22
+ raise CommandError, "Cannot edit exceptions raised in REPL." if Pry.eval_path == file_name
23
+
24
+ file_name = RbxPath.convert_path_to_full(file_name) if RbxPath.is_core_path?(file_name)
25
+
26
+ [file_name, line]
27
+ end
28
+
29
+ # when file and line are passed as a single arg, e.g my_file.rb:30
30
+ def from_filename_argument(filename_argument)
31
+ f = File.expand_path(filename_argument)
32
+ l = f.sub!(/:(\d+)$/, "") ? $1.to_i : 1
33
+ [f, l]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,122 @@
1
+ class Pry
2
+ class Command::Edit
3
+ class MethodPatcher
4
+ attr_accessor :_pry_
5
+ attr_accessor :code_object
6
+
7
+ def initialize(_pry_, code_object)
8
+ @_pry_ = _pry_
9
+ @code_object = code_object
10
+ end
11
+
12
+ # perform the patch
13
+ def perform_patch
14
+ if code_object.alias?
15
+ with_method_transaction do
16
+ _pry_.evaluate_ruby patched_code
17
+ end
18
+ else
19
+ _pry_.evaluate_ruby patched_code
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def patched_code
26
+ @patched_code ||= wrap(Pry::Editor.edit_tempfile_with_content(adjusted_lines))
27
+ end
28
+
29
+ # The method code adjusted so that the first line is rewritten
30
+ # so that def self.foo --> def foo
31
+ def adjusted_lines
32
+ lines = code_object.source.lines.to_a
33
+ lines[0] = definition_line_for_owner(lines.first)
34
+ lines
35
+ end
36
+
37
+ # Run some code ensuring that at the end target#meth_name will not have changed.
38
+ #
39
+ # When we're redefining aliased methods we will overwrite the method at the
40
+ # unaliased name (so that super continues to work). By wrapping that code in a
41
+ # transation we make that not happen, which means that alias_method_chains, etc.
42
+ # continue to work.
43
+ #
44
+ # @param [String] meth_name The method name before aliasing
45
+ # @param [Module] target The owner of the method
46
+
47
+ def with_method_transaction
48
+ temp_name = "__pry_#{code_object.original_name}__"
49
+ co = code_object
50
+ code_object.owner.class_eval do
51
+ alias_method temp_name, co.original_name
52
+ yield
53
+ alias_method co.name, co.original_name
54
+ alias_method co.original_name, temp_name
55
+ end
56
+
57
+ ensure
58
+ co.send(:remove_method, temp_name) rescue nil
59
+ end
60
+
61
+ # Update the definition line so that it can be eval'd directly on the Method's
62
+ # owner instead of from the original context.
63
+ #
64
+ # In particular this takes `def self.foo` and turns it into `def foo` so that we
65
+ # don't end up creating the method on the singleton class of the singleton class
66
+ # by accident.
67
+ #
68
+ # This is necessarily done by String manipulation because we can't find out what
69
+ # syntax is needed for the argument list by ruby-level introspection.
70
+ #
71
+ # @param String The original definition line. e.g. def self.foo(bar, baz=1)
72
+ # @return String The new definition line. e.g. def foo(bar, baz=1)
73
+ def definition_line_for_owner(line)
74
+ if line =~ /^def (?:.*?\.)?#{Regexp.escape(code_object.original_name)}(?=[\(\s;]|$)/
75
+ "def #{code_object.original_name}#{$'}"
76
+ else
77
+ raise CommandError, "Could not find original `def #{code_object.original_name}` line to patch."
78
+ end
79
+ end
80
+
81
+ # Apply wrap_for_owner and wrap_for_nesting successively to `source`
82
+ # @param [String] source
83
+ # @return [String] The wrapped source.
84
+ def wrap(source)
85
+ wrap_for_nesting(wrap_for_owner(source))
86
+ end
87
+
88
+ # Update the source code so that when it has the right owner when eval'd.
89
+ #
90
+ # This (combined with definition_line_for_owner) is backup for the case that
91
+ # wrap_for_nesting fails, to ensure that the method will stil be defined in
92
+ # the correct place.
93
+ #
94
+ # @param [String] source The source to wrap
95
+ # @return [String]
96
+ def wrap_for_owner(source)
97
+ Pry.current[:pry_owner] = code_object.owner
98
+ "Pry.current[:pry_owner].class_eval do\n#{source}\nend"
99
+ end
100
+
101
+ # Update the new source code to have the correct Module.nesting.
102
+ #
103
+ # This method uses syntactic analysis of the original source file to determine
104
+ # the new nesting, so that we can tell the difference between:
105
+ #
106
+ # class A; def self.b; end; end
107
+ # class << A; def b; end; end
108
+ #
109
+ # The resulting code should be evaluated in the TOPLEVEL_BINDING.
110
+ #
111
+ # @param [String] source The source to wrap.
112
+ # @return [String]
113
+ def wrap_for_nesting(source)
114
+ nesting = Pry::Code.from_file(code_object.source_file).nesting_at(code_object.source_line)
115
+
116
+ (nesting + [source] + nesting.map{ "end" } + [""]).join("\n")
117
+ rescue Pry::Indent::UnparseableNestingError => e
118
+ source
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,42 @@
1
+ class Pry
2
+ class Command::Exit < Pry::ClassCommand
3
+ match 'exit'
4
+ group 'Navigating Pry'
5
+ description 'Pop the previous binding.'
6
+ command_options :keep_retval => true
7
+
8
+ banner <<-'BANNER'
9
+ Usage: exit [OPTIONS] [--help]
10
+ Aliases: quit
11
+
12
+ Pop the previous binding (does NOT exit program). It can be useful to exit a
13
+ context with a user-provided value. For instance an exit value can be used to
14
+ determine program flow.
15
+
16
+ exit "pry this"
17
+ exit
18
+
19
+ https://github.com/pry/pry/wiki/State-navigation#wiki-Exit_with_value
20
+ BANNER
21
+
22
+ def process
23
+ if _pry_.binding_stack.one?
24
+ _pry_.run_command "exit-all #{arg_string}"
25
+ else
26
+ # otherwise just pop a binding and return user supplied value
27
+ process_pop_and_return
28
+ end
29
+ end
30
+
31
+ def process_pop_and_return
32
+ popped_object = _pry_.binding_stack.pop.eval('self')
33
+
34
+ # return a user-specified value if given otherwise return the object
35
+ return target.eval(arg_string) unless arg_string.empty?
36
+ popped_object
37
+ end
38
+ end
39
+
40
+ Pry::Commands.add_command(Pry::Command::Exit)
41
+ Pry::Commands.alias_command 'quit', 'exit'
42
+ end
@@ -0,0 +1,29 @@
1
+ class Pry
2
+ class Command::ExitAll < Pry::ClassCommand
3
+ match 'exit-all'
4
+ group 'Navigating Pry'
5
+ description 'End the current Pry session.'
6
+
7
+ banner <<-'BANNER'
8
+ Usage: exit-all [--help]
9
+ Aliases: !!@
10
+
11
+ End the current Pry session (popping all bindings and returning to caller).
12
+ Accepts optional return value.
13
+ BANNER
14
+
15
+ def process
16
+ # calculate user-given value
17
+ exit_value = target.eval(arg_string)
18
+
19
+ # clear the binding stack
20
+ _pry_.binding_stack.clear
21
+
22
+ # break out of the repl loop
23
+ throw(:breakout, exit_value)
24
+ end
25
+ end
26
+
27
+ Pry::Commands.add_command(Pry::Command::ExitAll)
28
+ Pry::Commands.alias_command '!!@', 'exit-all'
29
+ end