pry 0.9.7.4-i386-mingw32 → 0.9.8-i386-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -3
- data/CHANGELOG +43 -0
- data/README.markdown +3 -1
- data/Rakefile +51 -32
- data/bin/pry +2 -80
- data/lib/pry.rb +33 -26
- data/lib/pry/cli.rb +152 -0
- data/lib/pry/code.rb +351 -0
- data/lib/pry/command.rb +422 -0
- data/lib/pry/command_set.rb +259 -129
- data/lib/pry/commands.rb +0 -1
- data/lib/pry/config.rb +43 -9
- data/lib/pry/default_commands/context.rb +109 -92
- data/lib/pry/default_commands/documentation.rb +174 -63
- data/lib/pry/default_commands/easter_eggs.rb +26 -2
- data/lib/pry/default_commands/gems.rb +65 -37
- data/lib/pry/default_commands/input.rb +175 -243
- data/lib/pry/default_commands/introspection.rb +173 -112
- data/lib/pry/default_commands/ls.rb +96 -114
- data/lib/pry/default_commands/shell.rb +175 -70
- data/lib/pry/helpers/base_helpers.rb +7 -2
- data/lib/pry/helpers/command_helpers.rb +71 -77
- data/lib/pry/helpers/options_helpers.rb +10 -41
- data/lib/pry/helpers/text.rb +24 -4
- data/lib/pry/history.rb +55 -17
- data/lib/pry/history_array.rb +2 -0
- data/lib/pry/hooks.rb +252 -0
- data/lib/pry/indent.rb +9 -5
- data/lib/pry/method.rb +149 -50
- data/lib/pry/plugins.rb +12 -4
- data/lib/pry/pry_class.rb +69 -26
- data/lib/pry/pry_instance.rb +187 -115
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +73 -0
- data/man/pry.1 +195 -0
- data/man/pry.1.html +204 -0
- data/man/pry.1.ronn +141 -0
- data/pry.gemspec +29 -32
- data/test/helper.rb +32 -36
- data/test/test_cli.rb +78 -0
- data/test/test_code.rb +201 -0
- data/test/test_command.rb +327 -0
- data/test/test_command_integration.rb +512 -0
- data/test/test_command_set.rb +338 -12
- data/test/test_completion.rb +1 -1
- data/test/test_default_commands.rb +1 -2
- data/test/test_default_commands/test_context.rb +27 -5
- data/test/test_default_commands/test_documentation.rb +20 -8
- data/test/test_default_commands/test_input.rb +84 -45
- data/test/test_default_commands/test_introspection.rb +74 -17
- data/test/test_default_commands/test_ls.rb +9 -36
- data/test/test_default_commands/test_shell.rb +240 -13
- data/test/test_hooks.rb +490 -0
- data/test/test_indent.rb +2 -0
- data/test/test_method.rb +60 -0
- data/test/test_pry.rb +29 -904
- data/test/test_pry_defaults.rb +380 -0
- data/test/test_pry_history.rb +24 -24
- data/test/test_syntax_checking.rb +63 -0
- data/test/test_wrapped_module.rb +71 -0
- metadata +50 -39
- data/lib/pry/command_context.rb +0 -53
- data/lib/pry/command_processor.rb +0 -181
- data/lib/pry/extended_commands/user_command_api.rb +0 -65
- data/test/test_command_processor.rb +0 -176
@@ -28,104 +28,209 @@ class Pry
|
|
28
28
|
_pry_.instance_eval(&Pry::FILE_COMPLETIONS)
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
32
31
|
alias_command "file-mode", "shell-mode"
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
create_command "save-file", "Export to a file using content from the REPL." do
|
34
|
+
banner <<-USAGE
|
35
|
+
Usage: save-file [OPTIONS] [FILE]
|
36
|
+
Save REPL content to a file.
|
37
|
+
e.g: save-file -m my_method -m my_method2 ./hello.rb
|
38
|
+
e.g: save-file -i 1..10 ./hello.rb --append
|
39
|
+
e.g: save-file -c show-method ./my_command.rb
|
40
|
+
e.g: save-file -f sample_file --lines 2..10 ./output_file.rb
|
41
|
+
USAGE
|
42
|
+
|
43
|
+
attr_accessor :content
|
44
|
+
attr_accessor :file_name
|
45
|
+
|
46
|
+
def setup
|
47
|
+
self.content = ""
|
48
|
+
end
|
39
49
|
|
40
|
-
|
41
|
-
opt.on :
|
42
|
-
|
50
|
+
def options(opt)
|
51
|
+
opt.on :m, :method, "Save a method's source.", true do |meth_name|
|
52
|
+
meth = get_method_or_raise(meth_name, target, {})
|
53
|
+
self.content << meth.source
|
54
|
+
end
|
55
|
+
opt.on :c, :command, "Save a command's source.", true do |command_name|
|
56
|
+
command = find_command(command_name)
|
57
|
+
block = Pry::Method.new(find_command(command_name).block)
|
58
|
+
self.content << block.source
|
59
|
+
end
|
60
|
+
opt.on :f, :file, "Save a file.", true do |file|
|
61
|
+
self.content << File.read(File.expand_path(file))
|
43
62
|
end
|
63
|
+
opt.on :l, :lines, "Only save a subset of lines.", :optional => true, :as => Range, :default => 1..-1
|
64
|
+
opt.on :i, :in, "Save entries from Pry's input expression history. Takes an index or range.", :optional => true,
|
65
|
+
:as => Range, :default => -5..-1 do |range|
|
66
|
+
input_expressions = _pry_.input_array[range] || []
|
67
|
+
Array(input_expressions).each { |v| self.content << v }
|
68
|
+
end
|
69
|
+
opt.on :a, :append, "Append to the given file instead of overwriting it."
|
70
|
+
end
|
44
71
|
|
45
|
-
|
46
|
-
|
72
|
+
def process
|
73
|
+
if args.empty?
|
74
|
+
raise CommandError, "Must specify a file name."
|
47
75
|
end
|
48
76
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
start_line = start_line < 0 ? 0 : start_line
|
63
|
-
end_line = (ex_line - 1) + window_size
|
64
|
-
if ex_file && RbxPath.is_core_path?(ex_file)
|
65
|
-
file_name = RbxPath.convert_path_to_full(ex_file)
|
77
|
+
self.file_name = File.expand_path(args.first)
|
78
|
+
|
79
|
+
save_file
|
80
|
+
end
|
81
|
+
|
82
|
+
def save_file
|
83
|
+
if self.content.empty?
|
84
|
+
raise CommandError, "Found no code to save."
|
85
|
+
end
|
86
|
+
|
87
|
+
File.open(file_name, mode) do |f|
|
88
|
+
if opts.present?(:lines)
|
89
|
+
f.puts restrict_to_lines(content, opts[:l])
|
66
90
|
else
|
67
|
-
|
91
|
+
f.puts content
|
68
92
|
end
|
69
93
|
end
|
94
|
+
end
|
70
95
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
96
|
+
def mode
|
97
|
+
if opts.present?(:append)
|
98
|
+
"a"
|
99
|
+
else
|
100
|
+
"w"
|
76
101
|
end
|
77
102
|
end
|
103
|
+
end
|
78
104
|
|
79
|
-
|
105
|
+
create_command "cat", "Show code from a file, Pry's input buffer, or the last exception." do
|
106
|
+
banner <<-USAGE
|
107
|
+
Usage: cat FILE
|
108
|
+
cat --ex [STACK_INDEX]
|
109
|
+
cat --in [INPUT_INDEX_OR_RANGE]
|
80
110
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
111
|
+
cat is capable of showing part or all of a source file, the context of the
|
112
|
+
last exception, or an expression from Pry's input history.
|
113
|
+
|
114
|
+
cat --ex defaults to showing the lines surrounding the location of the last
|
115
|
+
exception. Invoking it more than once travels up the exception's backtrace,
|
116
|
+
and providing a number shows the context of the given index of the backtrace.
|
117
|
+
USAGE
|
88
118
|
|
89
|
-
|
90
|
-
|
119
|
+
def options(opt)
|
120
|
+
opt.on :ex, "Show the context of the last exception.", :optional => true, :as => Integer
|
121
|
+
opt.on :i, :in, "Show one or more entries from Pry's expression history.", :optional => true, :as => Range, :default => -5..-1
|
122
|
+
|
123
|
+
opt.on :s, :start, "Starting line (defaults to the first line).", :optional => true, :as => Integer
|
124
|
+
opt.on :e, :end, "Ending line (defaults to the last line).", :optional => true, :as => Integer
|
125
|
+
opt.on :l, :'line-numbers', "Show line numbers."
|
126
|
+
opt.on :t, :type, "The file type for syntax highlighting (e.g., 'ruby' or 'python').", true, :as => Symbol
|
127
|
+
|
128
|
+
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
|
91
129
|
end
|
92
130
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
131
|
+
def process
|
132
|
+
handler = case
|
133
|
+
when opts.present?(:ex)
|
134
|
+
method :process_ex
|
135
|
+
when opts.present?(:in)
|
136
|
+
method :process_in
|
137
|
+
else
|
138
|
+
method :process_file
|
139
|
+
end
|
140
|
+
|
141
|
+
output = handler.call do |code|
|
142
|
+
code.code_type = opts[:type] || :ruby
|
143
|
+
|
144
|
+
code.between(opts[:start] || 1, opts[:end] || -1).
|
145
|
+
with_line_numbers(opts.present?(:'line-numbers') || opts.present?(:ex))
|
146
|
+
end
|
147
|
+
|
148
|
+
render_output(output, opts)
|
98
149
|
end
|
99
150
|
|
100
|
-
|
101
|
-
|
151
|
+
def process_ex
|
152
|
+
window_size = Pry.config.default_window_size || 5
|
153
|
+
ex = _pry_.last_exception
|
154
|
+
|
155
|
+
raise CommandError, "No exception found." unless ex
|
156
|
+
|
157
|
+
if opts[:ex].nil?
|
158
|
+
bt_index = ex.bt_index
|
159
|
+
ex.inc_bt_index
|
160
|
+
else
|
161
|
+
bt_index = opts[:ex]
|
162
|
+
end
|
163
|
+
|
164
|
+
ex_file, ex_line = ex.bt_source_location_for(bt_index)
|
165
|
+
|
166
|
+
raise CommandError, "The given backtrace level is out of bounds." unless ex_file
|
167
|
+
|
168
|
+
if RbxPath.is_core_path?(ex_file)
|
169
|
+
ex_file = RbxPath.convert_path_to_full(ex_file)
|
170
|
+
end
|
171
|
+
|
172
|
+
set_file_and_dir_locals(ex_file)
|
173
|
+
|
174
|
+
start_line = ex_line - window_size
|
175
|
+
start_line = 1 if start_line < 1
|
176
|
+
end_line = ex_line + window_size
|
177
|
+
|
178
|
+
header = unindent <<-HEADER
|
179
|
+
#{text.bold 'Exception:'} #{ex.class}: #{ex.message}
|
180
|
+
--
|
181
|
+
#{text.bold('From:')} #{ex_file} @ line #{ex_line} @ #{text.bold("level: #{bt_index}")} of backtrace (of #{ex.backtrace.size - 1}).
|
182
|
+
|
183
|
+
HEADER
|
184
|
+
|
185
|
+
code = yield(Pry::Code.from_file(ex_file).
|
186
|
+
between(start_line, end_line).
|
187
|
+
with_marker(ex_line))
|
188
|
+
|
189
|
+
"#{header}#{code}"
|
102
190
|
end
|
103
191
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
contents = text.with_line_numbers contents, start_line + 1, :bright_red
|
192
|
+
def process_in
|
193
|
+
normalized_range = absolute_index_range(opts[:i], _pry_.input_array.length)
|
194
|
+
input_items = _pry_.input_array[normalized_range] || []
|
108
195
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
196
|
+
zipped_items = normalized_range.zip(input_items).reject { |_, s| s.nil? || s == "" }
|
197
|
+
|
198
|
+
unless zipped_items.length > 0
|
199
|
+
raise CommandError, "No expressions found."
|
200
|
+
end
|
201
|
+
|
202
|
+
if zipped_items.length > 1
|
203
|
+
contents = ""
|
204
|
+
zipped_items.each do |i, s|
|
205
|
+
contents << "#{text.bold(i.to_s)}:\n"
|
206
|
+
contents << yield(Pry::Code(s).with_indentation(2)).to_s
|
115
207
|
end
|
116
|
-
|
208
|
+
else
|
209
|
+
contents = yield(Pry::Code(zipped_items.first.last))
|
210
|
+
end
|
117
211
|
|
118
|
-
|
119
|
-
output.puts "\n#{Pry::Helpers::Text.bold('Exception:')} #{_pry_.last_exception.class}: #{_pry_.last_exception.message}\n--"
|
120
|
-
output.puts "#{Pry::Helpers::Text.bold('From:')} #{ex_file} @ line #{ex_line} @ #{text.bold('level: ')} #{bt_index} of backtrace (of #{_pry_.last_exception.backtrace.size - 1}).\n\n"
|
212
|
+
contents
|
121
213
|
end
|
122
214
|
|
123
|
-
|
215
|
+
def process_file
|
216
|
+
file_name = args.shift
|
217
|
+
|
218
|
+
unless file_name
|
219
|
+
raise CommandError, "Must provide a filename, --in, or --ex."
|
220
|
+
end
|
221
|
+
|
222
|
+
file_name, line_num = file_name.split(':')
|
223
|
+
file_name = File.expand_path(file_name)
|
224
|
+
set_file_and_dir_locals(file_name)
|
124
225
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
226
|
+
code = yield(Pry::Code.from_file(file_name))
|
227
|
+
|
228
|
+
if line_num
|
229
|
+
code = code.around(line_num.to_i,
|
230
|
+
Pry.config.default_window_size || 7)
|
231
|
+
end
|
232
|
+
|
233
|
+
code
|
129
234
|
end
|
130
235
|
end
|
131
236
|
end
|
@@ -91,14 +91,19 @@ class Pry
|
|
91
91
|
27
|
92
92
|
end
|
93
93
|
|
94
|
+
# have fun on the Windows platform.
|
95
|
+
def windows?
|
96
|
+
RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
97
|
+
end
|
98
|
+
|
94
99
|
# are we on Jruby platform?
|
95
100
|
def jruby?
|
96
|
-
|
101
|
+
RbConfig::CONFIG['ruby_install_name'] == 'jruby'
|
97
102
|
end
|
98
103
|
|
99
104
|
# are we on rbx platform?
|
100
105
|
def rbx?
|
101
|
-
|
106
|
+
RbConfig::CONFIG['ruby_install_name'] == 'rbx'
|
102
107
|
end
|
103
108
|
|
104
109
|
# a simple pager for systems without `less`. A la windows.
|
@@ -6,26 +6,21 @@ class Pry
|
|
6
6
|
|
7
7
|
module_function
|
8
8
|
|
9
|
-
# if start_line is not false then add line numbers starting with start_line
|
10
|
-
def render_output(should_flood, start_line, text, color=:blue)
|
11
|
-
if start_line
|
12
|
-
text = Pry::Helpers::Text.with_line_numbers text, start_line, color
|
13
|
-
end
|
14
|
-
|
15
|
-
if should_flood
|
16
|
-
output.puts text
|
17
|
-
else
|
18
|
-
stagger_output(text)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
9
|
# Open a temp file and yield it to the block, closing it after
|
23
10
|
# @return [String] The path of the temp file
|
24
|
-
def temp_file
|
25
|
-
file = Tempfile.new([
|
11
|
+
def temp_file(ext='.rb')
|
12
|
+
file = Tempfile.new(['pry', ext])
|
26
13
|
yield file
|
27
14
|
ensure
|
28
|
-
file.close
|
15
|
+
file.close(true) if file
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_output(str, opts={})
|
19
|
+
if opts[:flood]
|
20
|
+
output.puts str
|
21
|
+
else
|
22
|
+
stagger_output str
|
23
|
+
end
|
29
24
|
end
|
30
25
|
|
31
26
|
def get_method_or_raise(name, target, opts={}, omit_help=false)
|
@@ -34,14 +29,14 @@ class Pry
|
|
34
29
|
if name && !meth
|
35
30
|
command_error("The method '#{name}' could not be found.", omit_help)
|
36
31
|
elsif !meth
|
37
|
-
command_error("No method name given, and context is not a method.", omit_help)
|
32
|
+
command_error("No method name given, and context is not a method.", omit_help, NonMethodContextError)
|
38
33
|
end
|
39
34
|
|
40
35
|
(opts[:super] || 0).times do
|
41
36
|
if meth.super
|
42
37
|
meth = meth.super
|
43
38
|
else
|
44
|
-
command_error("
|
39
|
+
command_error("'#{meth.name_with_owner}' has no super method.", omit_help)
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
@@ -49,9 +44,9 @@ class Pry
|
|
49
44
|
meth
|
50
45
|
end
|
51
46
|
|
52
|
-
def command_error(message, omit_help)
|
47
|
+
def command_error(message, omit_help, klass=CommandError)
|
53
48
|
message += " Type `#{command_name} --help` for help." unless omit_help
|
54
|
-
raise
|
49
|
+
raise klass, message
|
55
50
|
end
|
56
51
|
|
57
52
|
def make_header(meth, content=meth.source)
|
@@ -66,60 +61,6 @@ class Pry
|
|
66
61
|
header << "#{Pry::Helpers::Text.bold("Number of lines:")} #{content.each_line.count.to_s}\n"
|
67
62
|
end
|
68
63
|
|
69
|
-
def file_map
|
70
|
-
{
|
71
|
-
[".c", ".h"] => :c,
|
72
|
-
[".cpp", ".hpp", ".cc", ".h", "cxx"] => :cpp,
|
73
|
-
[".rb", "Rakefile", ".irbrc", ".gemspec", ".pryrc"] => :ruby,
|
74
|
-
".py" => :python,
|
75
|
-
".diff" => :diff,
|
76
|
-
".css" => :css,
|
77
|
-
".html" => :html,
|
78
|
-
[".yaml", ".yml"] => :yaml,
|
79
|
-
".xml" => :xml,
|
80
|
-
".php" => :php,
|
81
|
-
".js" => :javascript,
|
82
|
-
".java" => :java,
|
83
|
-
".rhtml" => :rhtml,
|
84
|
-
".json" => :json
|
85
|
-
}
|
86
|
-
end
|
87
|
-
|
88
|
-
def syntax_highlight_by_file_type_or_specified(contents, file_name, file_type)
|
89
|
-
_, language_detected = file_map.find do |k, v|
|
90
|
-
Array(k).any? do |matcher|
|
91
|
-
matcher == File.extname(file_name) || matcher == File.basename(file_name)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
language_detected = file_type if file_type
|
96
|
-
if Pry.color
|
97
|
-
CodeRay.scan(contents, language_detected).term
|
98
|
-
else
|
99
|
-
contents
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# convert negative line numbers to positive by wrapping around
|
104
|
-
# last line (as per array indexing with negative numbers)
|
105
|
-
def normalized_line_number(line_number, total_lines)
|
106
|
-
line_number < 0 ? line_number + total_lines : line_number
|
107
|
-
end
|
108
|
-
|
109
|
-
# returns the file content between the lines and the normalized
|
110
|
-
# start and end line numbers.
|
111
|
-
def read_between_the_lines(file_name, start_line, end_line)
|
112
|
-
if file_name == Pry.eval_path
|
113
|
-
content = Pry.line_buffer.drop(1).join
|
114
|
-
else
|
115
|
-
content = File.read(File.expand_path(file_name))
|
116
|
-
end
|
117
|
-
lines_array = content.each_line.to_a
|
118
|
-
|
119
|
-
[lines_array[start_line..end_line].join, normalized_line_number(start_line, lines_array.size),
|
120
|
-
normalized_line_number(end_line, lines_array.size)]
|
121
|
-
end
|
122
|
-
|
123
64
|
def process_rdoc(comment, code_type)
|
124
65
|
comment = comment.dup
|
125
66
|
comment.gsub(/<code>(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }.
|
@@ -157,6 +98,7 @@ class Pry
|
|
157
98
|
end
|
158
99
|
|
159
100
|
def invoke_editor(file, line)
|
101
|
+
raise CommandError, "Please set Pry.config.editor or export $EDITOR" unless Pry.config.editor
|
160
102
|
if Pry.config.editor.respond_to?(:call)
|
161
103
|
editor_invocation = Pry.config.editor.call(file, line)
|
162
104
|
else
|
@@ -176,14 +118,16 @@ class Pry
|
|
176
118
|
# Note we dont want to use Pry.config.system here as that
|
177
119
|
# may be invoked non-interactively (i.e via Open4), whereas we want to
|
178
120
|
# ensure the editor is always interactive
|
179
|
-
system(editor_invocation)
|
121
|
+
system(editor_invocation) or raise CommandError, "`#{editor_invocation}` gave exit status: #{$?.exitstatus}"
|
180
122
|
end
|
181
123
|
end
|
182
124
|
|
183
125
|
# Return the syntax for a given editor for starting the editor
|
184
126
|
# and moving to a particular line within that file
|
185
127
|
def start_line_syntax_for_editor(file_name, line_number)
|
186
|
-
|
128
|
+
if windows?
|
129
|
+
file_name = file_name.gsub(/\//, '\\')
|
130
|
+
end
|
187
131
|
|
188
132
|
# special case for 1st line
|
189
133
|
return file_name if line_number <= 1
|
@@ -198,7 +142,7 @@ class Pry
|
|
198
142
|
when /^jedit/
|
199
143
|
"#{file_name} +line:#{line_number}"
|
200
144
|
else
|
201
|
-
if
|
145
|
+
if windows?
|
202
146
|
"#{file_name}"
|
203
147
|
else
|
204
148
|
"+#{line_number} #{file_name}"
|
@@ -247,6 +191,56 @@ class Pry
|
|
247
191
|
text.gsub(/^#{margin}/, '')
|
248
192
|
end
|
249
193
|
|
194
|
+
# Restrict a string to the given range of lines (1-indexed)
|
195
|
+
# @param [String] content The string.
|
196
|
+
# @param [Range, Fixnum] lines The line(s) to restrict it to.
|
197
|
+
# @return [String] The resulting string.
|
198
|
+
def restrict_to_lines(content, lines)
|
199
|
+
line_range = one_index_range_or_number(lines)
|
200
|
+
Array(content.lines.to_a[line_range]).join
|
201
|
+
end
|
202
|
+
|
203
|
+
def one_index_number(line_number)
|
204
|
+
if line_number > 0
|
205
|
+
line_number - 1
|
206
|
+
else
|
207
|
+
line_number
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# convert a 1-index range to a 0-indexed one
|
212
|
+
def one_index_range(range)
|
213
|
+
Range.new(one_index_number(range.begin), one_index_number(range.end))
|
214
|
+
end
|
215
|
+
|
216
|
+
def one_index_range_or_number(range_or_number)
|
217
|
+
case range_or_number
|
218
|
+
when Range
|
219
|
+
one_index_range(range_or_number)
|
220
|
+
else
|
221
|
+
one_index_number(range_or_number)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def absolute_index_number(line_number, array_length)
|
226
|
+
if line_number >= 0
|
227
|
+
line_number
|
228
|
+
else
|
229
|
+
[array_length + line_number, 0].max
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def absolute_index_range(range_or_number, array_length)
|
234
|
+
case range_or_number
|
235
|
+
when Range
|
236
|
+
a = absolute_index_number(range_or_number.begin, array_length)
|
237
|
+
b = absolute_index_number(range_or_number.end, array_length)
|
238
|
+
else
|
239
|
+
a = b = absolute_index_number(range_or_number, array_length)
|
240
|
+
end
|
241
|
+
|
242
|
+
Range.new(a, b)
|
243
|
+
end
|
250
244
|
end
|
251
245
|
|
252
246
|
end
|