pry 0.10.0.pre2-universal-mingw32

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 (131) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +702 -0
  3. data/LICENSE +25 -0
  4. data/README.md +406 -0
  5. data/bin/pry +16 -0
  6. data/lib/pry.rb +161 -0
  7. data/lib/pry/cli.rb +220 -0
  8. data/lib/pry/code.rb +346 -0
  9. data/lib/pry/code/code_file.rb +103 -0
  10. data/lib/pry/code/code_range.rb +71 -0
  11. data/lib/pry/code/loc.rb +92 -0
  12. data/lib/pry/code_object.rb +172 -0
  13. data/lib/pry/color_printer.rb +55 -0
  14. data/lib/pry/command.rb +692 -0
  15. data/lib/pry/command_set.rb +443 -0
  16. data/lib/pry/commands.rb +6 -0
  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 +62 -0
  21. data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
  22. data/lib/pry/commands/cat/exception_formatter.rb +77 -0
  23. data/lib/pry/commands/cat/file_formatter.rb +67 -0
  24. data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
  25. data/lib/pry/commands/cd.rb +41 -0
  26. data/lib/pry/commands/change_inspector.rb +27 -0
  27. data/lib/pry/commands/change_prompt.rb +26 -0
  28. data/lib/pry/commands/code_collector.rb +165 -0
  29. data/lib/pry/commands/disable_pry.rb +27 -0
  30. data/lib/pry/commands/disabled_commands.rb +2 -0
  31. data/lib/pry/commands/easter_eggs.rb +112 -0
  32. data/lib/pry/commands/edit.rb +195 -0
  33. data/lib/pry/commands/edit/exception_patcher.rb +25 -0
  34. data/lib/pry/commands/edit/file_and_line_locator.rb +36 -0
  35. data/lib/pry/commands/exit.rb +42 -0
  36. data/lib/pry/commands/exit_all.rb +29 -0
  37. data/lib/pry/commands/exit_program.rb +23 -0
  38. data/lib/pry/commands/find_method.rb +193 -0
  39. data/lib/pry/commands/fix_indent.rb +19 -0
  40. data/lib/pry/commands/gem_cd.rb +26 -0
  41. data/lib/pry/commands/gem_install.rb +32 -0
  42. data/lib/pry/commands/gem_list.rb +33 -0
  43. data/lib/pry/commands/gem_open.rb +29 -0
  44. data/lib/pry/commands/gist.rb +101 -0
  45. data/lib/pry/commands/help.rb +164 -0
  46. data/lib/pry/commands/hist.rb +180 -0
  47. data/lib/pry/commands/import_set.rb +22 -0
  48. data/lib/pry/commands/install_command.rb +53 -0
  49. data/lib/pry/commands/jump_to.rb +29 -0
  50. data/lib/pry/commands/list_inspectors.rb +35 -0
  51. data/lib/pry/commands/list_prompts.rb +35 -0
  52. data/lib/pry/commands/ls.rb +114 -0
  53. data/lib/pry/commands/ls/constants.rb +47 -0
  54. data/lib/pry/commands/ls/formatter.rb +49 -0
  55. data/lib/pry/commands/ls/globals.rb +48 -0
  56. data/lib/pry/commands/ls/grep.rb +21 -0
  57. data/lib/pry/commands/ls/instance_vars.rb +39 -0
  58. data/lib/pry/commands/ls/interrogatable.rb +18 -0
  59. data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
  60. data/lib/pry/commands/ls/local_names.rb +35 -0
  61. data/lib/pry/commands/ls/local_vars.rb +39 -0
  62. data/lib/pry/commands/ls/ls_entity.rb +70 -0
  63. data/lib/pry/commands/ls/methods.rb +57 -0
  64. data/lib/pry/commands/ls/methods_helper.rb +46 -0
  65. data/lib/pry/commands/ls/self_methods.rb +32 -0
  66. data/lib/pry/commands/nesting.rb +25 -0
  67. data/lib/pry/commands/play.rb +103 -0
  68. data/lib/pry/commands/pry_backtrace.rb +25 -0
  69. data/lib/pry/commands/pry_version.rb +17 -0
  70. data/lib/pry/commands/raise_up.rb +32 -0
  71. data/lib/pry/commands/reload_code.rb +62 -0
  72. data/lib/pry/commands/reset.rb +18 -0
  73. data/lib/pry/commands/ri.rb +60 -0
  74. data/lib/pry/commands/save_file.rb +61 -0
  75. data/lib/pry/commands/shell_command.rb +48 -0
  76. data/lib/pry/commands/shell_mode.rb +25 -0
  77. data/lib/pry/commands/show_doc.rb +83 -0
  78. data/lib/pry/commands/show_info.rb +195 -0
  79. data/lib/pry/commands/show_input.rb +17 -0
  80. data/lib/pry/commands/show_source.rb +50 -0
  81. data/lib/pry/commands/simple_prompt.rb +22 -0
  82. data/lib/pry/commands/stat.rb +40 -0
  83. data/lib/pry/commands/switch_to.rb +23 -0
  84. data/lib/pry/commands/toggle_color.rb +24 -0
  85. data/lib/pry/commands/watch_expression.rb +105 -0
  86. data/lib/pry/commands/watch_expression/expression.rb +38 -0
  87. data/lib/pry/commands/whereami.rb +190 -0
  88. data/lib/pry/commands/wtf.rb +57 -0
  89. data/lib/pry/config.rb +24 -0
  90. data/lib/pry/config/behavior.rb +139 -0
  91. data/lib/pry/config/convenience.rb +26 -0
  92. data/lib/pry/config/default.rb +165 -0
  93. data/lib/pry/core_extensions.rb +131 -0
  94. data/lib/pry/editor.rb +133 -0
  95. data/lib/pry/exceptions.rb +77 -0
  96. data/lib/pry/helpers.rb +5 -0
  97. data/lib/pry/helpers/base_helpers.rb +113 -0
  98. data/lib/pry/helpers/command_helpers.rb +156 -0
  99. data/lib/pry/helpers/documentation_helpers.rb +75 -0
  100. data/lib/pry/helpers/options_helpers.rb +27 -0
  101. data/lib/pry/helpers/table.rb +109 -0
  102. data/lib/pry/helpers/text.rb +107 -0
  103. data/lib/pry/history.rb +125 -0
  104. data/lib/pry/history_array.rb +121 -0
  105. data/lib/pry/hooks.rb +230 -0
  106. data/lib/pry/indent.rb +406 -0
  107. data/lib/pry/input_completer.rb +242 -0
  108. data/lib/pry/input_lock.rb +132 -0
  109. data/lib/pry/inspector.rb +27 -0
  110. data/lib/pry/last_exception.rb +61 -0
  111. data/lib/pry/method.rb +546 -0
  112. data/lib/pry/method/disowned.rb +53 -0
  113. data/lib/pry/method/patcher.rb +125 -0
  114. data/lib/pry/method/weird_method_locator.rb +186 -0
  115. data/lib/pry/module_candidate.rb +136 -0
  116. data/lib/pry/object_path.rb +82 -0
  117. data/lib/pry/output.rb +50 -0
  118. data/lib/pry/pager.rb +234 -0
  119. data/lib/pry/plugins.rb +103 -0
  120. data/lib/pry/prompt.rb +26 -0
  121. data/lib/pry/pry_class.rb +375 -0
  122. data/lib/pry/pry_instance.rb +654 -0
  123. data/lib/pry/rbx_path.rb +22 -0
  124. data/lib/pry/repl.rb +202 -0
  125. data/lib/pry/repl_file_loader.rb +74 -0
  126. data/lib/pry/rubygem.rb +82 -0
  127. data/lib/pry/terminal.rb +79 -0
  128. data/lib/pry/test/helper.rb +170 -0
  129. data/lib/pry/version.rb +3 -0
  130. data/lib/pry/wrapped_module.rb +373 -0
  131. metadata +248 -0
data/lib/pry/editor.rb ADDED
@@ -0,0 +1,133 @@
1
+ class Pry
2
+ class Editor
3
+ include Pry::Helpers::BaseHelpers
4
+ include Pry::Helpers::CommandHelpers
5
+
6
+ attr_reader :_pry_
7
+
8
+ def initialize(_pry_)
9
+ @_pry_ = _pry_
10
+ end
11
+
12
+ def edit_tempfile_with_content(initial_content, line=1)
13
+ temp_file do |f|
14
+ f.puts(initial_content)
15
+ f.flush
16
+ f.close(false)
17
+ invoke_editor(f.path, line, true)
18
+ File.read(f.path)
19
+ end
20
+ end
21
+
22
+ def invoke_editor(file, line, blocking=true)
23
+ raise CommandError, "Please set Pry.config.editor or export $VISUAL or $EDITOR" unless _pry_.config.editor
24
+
25
+ editor_invocation = build_editor_invocation_string(file, line, blocking)
26
+ return nil unless editor_invocation
27
+
28
+ if jruby?
29
+ open_editor_on_jruby(editor_invocation)
30
+ else
31
+ open_editor(editor_invocation)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ # Generate the string that's used to start the editor. This includes
38
+ # all the flags we want as well as the file and line number we
39
+ # want to open at.
40
+ def build_editor_invocation_string(file, line, blocking)
41
+
42
+ if _pry_.config.editor.respond_to?(:call)
43
+ args = [file, line, blocking][0...(_pry_.config.editor.arity)]
44
+ _pry_.config.editor.call(*args)
45
+ else
46
+ sanitized_file = if windows?
47
+ file.gsub(/\//, '\\')
48
+ else
49
+ Shellwords.escape(file)
50
+ end
51
+
52
+ "#{_pry_.config.editor} #{blocking_flag_for_editor(blocking)} #{start_line_syntax_for_editor(sanitized_file, line)}"
53
+ end
54
+ end
55
+
56
+ # Start the editor running, using the calculated invocation string
57
+ def open_editor(editor_invocation)
58
+ # Note we dont want to use Pry.config.system here as that
59
+ # may be invoked non-interactively (i.e via Open4), whereas we want to
60
+ # ensure the editor is always interactive
61
+ system(*Shellwords.split(editor_invocation)) or raise CommandError, "`#{editor_invocation}` gave exit status: #{$?.exitstatus}"
62
+ end
63
+
64
+ # We need JRuby specific code here cos just shelling out using
65
+ # system() appears to be pretty broken :/
66
+ def open_editor_on_jruby(editor_invocation)
67
+ begin
68
+ require 'spoon'
69
+ pid = Spoon.spawnp(*Shellwords.split(editor_invocation))
70
+ Process.waitpid(pid)
71
+ rescue FFI::NotFoundError
72
+ system(editor_invocation)
73
+ end
74
+ end
75
+
76
+ # Some editors that run outside the terminal allow you to control whether or
77
+ # not to block the process from which they were launched (in this case, Pry).
78
+ # For those editors, return the flag that produces the desired behavior.
79
+ def blocking_flag_for_editor(blocking)
80
+ case editor_name
81
+ when /^emacsclient/
82
+ '--no-wait' unless blocking
83
+ when /^[gm]vim/
84
+ '--nofork' if blocking
85
+ when /^jedit/
86
+ '-wait' if blocking
87
+ when /^mate/, /^subl/
88
+ '-w' if blocking
89
+ end
90
+ end
91
+
92
+ # Return the syntax for a given editor for starting the editor
93
+ # and moving to a particular line within that file
94
+ def start_line_syntax_for_editor(file_name, line_number)
95
+ # special case for 1st line
96
+ return file_name if line_number <= 1
97
+
98
+ case editor_name
99
+ when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
100
+ "+#{line_number} #{file_name}"
101
+ when /^mate/, /^geany/
102
+ "-l #{line_number} #{file_name}"
103
+ when /^subl/
104
+ "#{file_name}:#{line_number}"
105
+ when /^uedit32/
106
+ "#{file_name}/#{line_number}"
107
+ when /^jedit/
108
+ "#{file_name} +line:#{line_number}"
109
+ else
110
+ if windows?
111
+ "#{file_name}"
112
+ else
113
+ "+#{line_number} #{file_name}"
114
+ end
115
+ end
116
+ end
117
+
118
+ # Get the name of the binary that Pry.config.editor points to.
119
+ #
120
+ # This is useful for deciding which flags we pass to the editor as
121
+ # we can just use the program's name and ignore any absolute paths.
122
+ #
123
+ # @example
124
+ # Pry.config.editor="/home/conrad/bin/textmate -w"
125
+ # editor_name
126
+ # # => textmate
127
+ #
128
+ def editor_name
129
+ File.basename(_pry_.config.editor).split(" ").first
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,77 @@
1
+ class Pry
2
+
3
+ # As a REPL, we often want to catch any unexpected exceptions that may have
4
+ # been raised; however we don't want to go overboard and prevent the user
5
+ # from exiting Pry when they want to.
6
+ module RescuableException
7
+ def self.===(exception)
8
+ case exception
9
+ # Catch when the user hits ^C (Interrupt < SignalException), and assume
10
+ # that they just wanted to stop the in-progress command (just like bash
11
+ # etc.)
12
+ when Interrupt
13
+ true
14
+ # Don't catch signals (particularly not SIGTERM) as these are unlikely
15
+ # to be intended for pry itself. We should also make sure that
16
+ # Kernel#exit works.
17
+ when *Pry.config.exception_whitelist
18
+ false
19
+ # All other exceptions will be caught.
20
+ else
21
+ true
22
+ end
23
+ end
24
+ end
25
+
26
+ # Catches SecurityErrors if $SAFE is set
27
+ module Pry::TooSafeException
28
+ def self.===(exception)
29
+ $SAFE > 0 && SecurityError === exception
30
+ end
31
+ end
32
+
33
+ # An Exception Tag (cf. Exceptional Ruby) that instructs Pry to show the error
34
+ # in a more user-friendly manner. This should be used when the exception
35
+ # happens within Pry itself as a direct consequence of the user typing
36
+ # something wrong.
37
+ #
38
+ # This allows us to distinguish between the user typing:
39
+ #
40
+ # pry(main)> def )
41
+ # SyntaxError: unexpected )
42
+ #
43
+ # pry(main)> method_that_evals("def )")
44
+ # SyntaxError: (eval):1: syntax error, unexpected ')'
45
+ # from ./a.rb:2 in `eval'
46
+ module UserError; end
47
+
48
+ # When we try to get a binding for an object, we try to define a method on
49
+ # that Object's singleton class. This doesn't work for "frozen" Object's, and
50
+ # the exception is just a vanilla RuntimeError.
51
+ module FrozenObjectException
52
+ def self.===(exception)
53
+ ["can't modify frozen class/module",
54
+ "can't modify frozen Class",
55
+ ].include?(exception.message)
56
+ end
57
+ end
58
+
59
+ # Don't catch these exceptions
60
+ DEFAULT_EXCEPTION_WHITELIST = [SystemExit,
61
+ SignalException,
62
+ Pry::TooSafeException]
63
+
64
+ # CommandErrors are caught by the REPL loop and displayed to the user. They
65
+ # indicate an exceptional condition that's fatal to the current command.
66
+ class CommandError < StandardError; end
67
+ class MethodNotFound < CommandError; end
68
+
69
+ # indicates obsolete API
70
+ class ObsoleteError < StandardError; end
71
+
72
+ # This is to keep from breaking under Rails 3.2 for people who are doing that
73
+ # IRB = Pry thing.
74
+ module ExtendCommandBundle
75
+ end
76
+
77
+ end
@@ -0,0 +1,5 @@
1
+ require "pry/helpers/base_helpers"
2
+ require "pry/helpers/options_helpers"
3
+ require "pry/helpers/command_helpers"
4
+ require "pry/helpers/text"
5
+ require "pry/helpers/table"
@@ -0,0 +1,113 @@
1
+ class Pry
2
+ module Helpers
3
+
4
+ module BaseHelpers
5
+
6
+ module_function
7
+
8
+ def silence_warnings
9
+ old_verbose = $VERBOSE
10
+ $VERBOSE = nil
11
+ begin
12
+ yield
13
+ ensure
14
+ $VERBOSE = old_verbose
15
+ end
16
+ end
17
+
18
+ # Acts like send but ignores any methods defined below Object or Class in the
19
+ # inheritance hierarchy.
20
+ # This is required to introspect methods on objects like Net::HTTP::Get that
21
+ # have overridden the `method` method.
22
+ def safe_send(obj, method, *args, &block)
23
+ (Module === obj ? Module : Object).instance_method(method).bind(obj).call(*args, &block)
24
+ end
25
+ public :safe_send
26
+
27
+ def find_command(name, set = Pry::Commands)
28
+ command_match = set.find do |_, command|
29
+ (listing = command.options[:listing]) == name && listing != nil
30
+ end
31
+ command_match.last if command_match
32
+ end
33
+
34
+ def not_a_real_file?(file)
35
+ file =~ /(\(.*\))|<.*>/ || file =~ /__unknown__/ || file == "" || file == "-e"
36
+ end
37
+
38
+ def command_dependencies_met?(options)
39
+ return true if !options[:requires_gem]
40
+ Array(options[:requires_gem]).all? do |g|
41
+ Rubygem.installed?(g)
42
+ end
43
+ end
44
+
45
+ def use_ansi_codes?
46
+ windows_ansi? || ENV['TERM'] && ENV['TERM'] != "dumb"
47
+ end
48
+
49
+ def colorize_code(code)
50
+ CodeRay.scan(code, :ruby).term
51
+ end
52
+
53
+ def highlight(string, regexp, highlight_color=:bright_yellow)
54
+ string.gsub(regexp) { |match| "<#{highlight_color}>#{match}</#{highlight_color}>" }
55
+ end
56
+
57
+ # formatting
58
+ def heading(text)
59
+ text = "#{text}\n--"
60
+ "\e[1m#{text}\e[0m"
61
+ end
62
+
63
+ # have fun on the Windows platform.
64
+ def windows?
65
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
66
+ end
67
+
68
+ # are we able to use ansi on windows?
69
+ def windows_ansi?
70
+ defined?(Win32::Console) || ENV['ANSICON'] || (windows? && mri_2?)
71
+ end
72
+
73
+ def jruby?
74
+ RbConfig::CONFIG['ruby_install_name'] == 'jruby'
75
+ end
76
+
77
+ def jruby_19?
78
+ jruby? && RbConfig::CONFIG['ruby_version'] == '1.9'
79
+ end
80
+
81
+ def rbx?
82
+ RbConfig::CONFIG['ruby_install_name'] == 'rbx'
83
+ end
84
+
85
+ def mri?
86
+ RbConfig::CONFIG['ruby_install_name'] == 'ruby'
87
+ end
88
+
89
+ def mri_19?
90
+ mri? && RUBY_VERSION =~ /^1\.9/
91
+ end
92
+
93
+ def mri_2?
94
+ mri? && RUBY_VERSION =~ /^2/
95
+ end
96
+
97
+ def mri_20?
98
+ mri? && RUBY_VERSION =~ /^2\.0/
99
+ end
100
+
101
+ def mri_21?
102
+ mri? && RUBY_VERSION =~ /^2\.1/
103
+ end
104
+
105
+ # Send the given text through the best available pager (if Pry.config.pager is
106
+ # enabled). Infers where to send the output if used as a mixin.
107
+ # DEPRECATED.
108
+ def stagger_output(text, out = nil)
109
+ Pry.new.pager.page text
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,156 @@
1
+ class Pry
2
+ module Helpers
3
+
4
+ module CommandHelpers
5
+ include OptionsHelpers
6
+
7
+ module_function
8
+
9
+ # Open a temp file and yield it to the block, closing it after
10
+ # @return [String] The path of the temp file
11
+ def temp_file(ext='.rb')
12
+ file = Tempfile.new(['pry', ext])
13
+ yield file
14
+ ensure
15
+ file.close(true) if file
16
+ end
17
+
18
+ def internal_binding?(target)
19
+ m = target.eval("::Kernel.__method__").to_s
20
+ # class_eval is here because of http://jira.codehaus.org/browse/JRUBY-6753
21
+ ["__binding__", "__pry__", "class_eval"].include?(m)
22
+ end
23
+
24
+ def get_method_or_raise(name, target, opts={}, omit_help=false)
25
+ meth = Pry::Method.from_str(name, target, opts)
26
+
27
+ if name && !meth
28
+ command_error("The method '#{name}' could not be found.", omit_help, MethodNotFound)
29
+ end
30
+
31
+ (opts[:super] || 0).times do
32
+ if meth.super
33
+ meth = meth.super
34
+ else
35
+ command_error("'#{meth.name_with_owner}' has no super method.", omit_help, MethodNotFound)
36
+ end
37
+ end
38
+
39
+ if !meth || (!name && internal_binding?(target))
40
+ command_error("No method name given, and context is not a method.", omit_help, MethodNotFound)
41
+ end
42
+
43
+ set_file_and_dir_locals(meth.source_file)
44
+ meth
45
+ end
46
+
47
+ def command_error(message, omit_help, klass=CommandError)
48
+ message += " Type `#{command_name} --help` for help." unless omit_help
49
+ raise klass, message
50
+ end
51
+
52
+ # Remove any common leading whitespace from every line in `text`.
53
+ #
54
+ # This can be used to make a HEREDOC line up with the left margin, without
55
+ # sacrificing the indentation level of the source code.
56
+ #
57
+ # e.g.
58
+ # opt.banner unindent <<-USAGE
59
+ # Lorem ipsum dolor sit amet, consectetur adipisicing elit,
60
+ # sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
61
+ # "Ut enim ad minim veniam."
62
+ # USAGE
63
+ #
64
+ # Heavily based on textwrap.dedent from Python, which is:
65
+ # Copyright (C) 1999-2001 Gregory P. Ward.
66
+ # Copyright (C) 2002, 2003 Python Software Foundation.
67
+ # Written by Greg Ward <gward@python.net>
68
+ #
69
+ # Licensed under <http://docs.python.org/license.html>
70
+ # From <http://hg.python.org/cpython/file/6b9f0a6efaeb/Lib/textwrap.py>
71
+ #
72
+ # @param [String] text The text from which to remove indentation
73
+ # @return [String] The text with indentation stripped.
74
+ def unindent(text, left_padding = 0)
75
+ # Empty blank lines
76
+ text = text.sub(/^[ \t]+$/, '')
77
+
78
+ # Find the longest common whitespace to all indented lines
79
+ # Ignore lines containing just -- or ++ as these seem to be used by
80
+ # comment authors as delimeters.
81
+ margin = text.scan(/^[ \t]*(?!--\n|\+\+\n)(?=[^ \t\n])/).inject do |current_margin, next_indent|
82
+ if next_indent.start_with?(current_margin)
83
+ current_margin
84
+ elsif current_margin.start_with?(next_indent)
85
+ next_indent
86
+ else
87
+ ""
88
+ end
89
+ end
90
+
91
+ text.gsub(/^#{margin}/, ' ' * left_padding)
92
+ end
93
+
94
+ # Restrict a string to the given range of lines (1-indexed)
95
+ # @param [String] content The string.
96
+ # @param [Range, Fixnum] lines The line(s) to restrict it to.
97
+ # @return [String] The resulting string.
98
+ def restrict_to_lines(content, lines)
99
+ line_range = one_index_range_or_number(lines)
100
+ Array(content.lines.to_a[line_range]).join
101
+ end
102
+
103
+ def one_index_number(line_number)
104
+ if line_number > 0
105
+ line_number - 1
106
+ else
107
+ line_number
108
+ end
109
+ end
110
+
111
+ # convert a 1-index range to a 0-indexed one
112
+ def one_index_range(range)
113
+ Range.new(one_index_number(range.begin), one_index_number(range.end))
114
+ end
115
+
116
+ def one_index_range_or_number(range_or_number)
117
+ case range_or_number
118
+ when Range
119
+ one_index_range(range_or_number)
120
+ else
121
+ one_index_number(range_or_number)
122
+ end
123
+ end
124
+
125
+ def absolute_index_number(line_number, array_length)
126
+ if line_number >= 0
127
+ line_number
128
+ else
129
+ [array_length + line_number, 0].max
130
+ end
131
+ end
132
+
133
+ def absolute_index_range(range_or_number, array_length)
134
+ case range_or_number
135
+ when Range
136
+ a = absolute_index_number(range_or_number.begin, array_length)
137
+ b = absolute_index_number(range_or_number.end, array_length)
138
+ else
139
+ a = b = absolute_index_number(range_or_number, array_length)
140
+ end
141
+
142
+ Range.new(a, b)
143
+ end
144
+
145
+ def set_file_and_dir_locals(file_name, _pry_=_pry_(), target=target())
146
+ return if !target or !file_name
147
+ _pry_.last_file = File.expand_path(file_name)
148
+ _pry_.inject_local("_file_", _pry_.last_file, target)
149
+
150
+ _pry_.last_dir = File.dirname(_pry_.last_file)
151
+ _pry_.inject_local("_dir_", _pry_.last_dir, target)
152
+ end
153
+ end
154
+
155
+ end
156
+ end