pry 0.9.7.4-i386-mswin32 → 0.9.8-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.
- 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
data/lib/pry/pry_instance.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require "pry/command_processor.rb"
|
2
1
|
require "pry/indent"
|
3
2
|
|
4
3
|
class Pry
|
@@ -8,7 +7,6 @@ class Pry
|
|
8
7
|
attr_accessor :commands
|
9
8
|
attr_accessor :print
|
10
9
|
attr_accessor :exception_handler
|
11
|
-
attr_accessor :hooks
|
12
10
|
attr_accessor :input_stack
|
13
11
|
|
14
12
|
attr_accessor :custom_completions
|
@@ -16,13 +14,32 @@ class Pry
|
|
16
14
|
attr_accessor :binding_stack
|
17
15
|
|
18
16
|
attr_accessor :last_result
|
19
|
-
attr_accessor :last_exception
|
20
17
|
attr_accessor :last_file
|
21
18
|
attr_accessor :last_dir
|
22
19
|
|
20
|
+
attr_reader :last_exception
|
21
|
+
|
23
22
|
attr_reader :input_array
|
24
23
|
attr_reader :output_array
|
25
24
|
|
25
|
+
attr_accessor :backtrace
|
26
|
+
|
27
|
+
# Special treatment for hooks as we want to alert people of the
|
28
|
+
# changed API
|
29
|
+
attr_reader :hooks
|
30
|
+
|
31
|
+
# FIXME:
|
32
|
+
# This is a hack to alert people of the new API.
|
33
|
+
# @param [Pry::Hooks] v Only accept `Pry::Hooks` now!
|
34
|
+
def hooks=(v)
|
35
|
+
if v.is_a?(Hash)
|
36
|
+
warn "Hash-based hooks are now deprecated! Use a `Pry::Hooks` object instead! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"
|
37
|
+
@hooks = Pry::Hooks.from_hash(v)
|
38
|
+
else
|
39
|
+
@hooks = v
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
26
43
|
# Create a new `Pry` object.
|
27
44
|
# @param [Hash] options The optional configuration parameters.
|
28
45
|
# @option options [#readline] :input The object to use for input.
|
@@ -35,7 +52,6 @@ class Pry
|
|
35
52
|
def initialize(options={})
|
36
53
|
refresh(options)
|
37
54
|
|
38
|
-
@command_processor = CommandProcessor.new(self)
|
39
55
|
@binding_stack = []
|
40
56
|
@indent = Pry::Indent.new
|
41
57
|
end
|
@@ -57,7 +73,7 @@ class Pry
|
|
57
73
|
end
|
58
74
|
|
59
75
|
defaults.merge!(options).each do |key, value|
|
60
|
-
send
|
76
|
+
send("#{key}=", value) if respond_to?("#{key}=")
|
61
77
|
end
|
62
78
|
|
63
79
|
true
|
@@ -106,21 +122,14 @@ class Pry
|
|
106
122
|
@output_array = Pry::HistoryArray.new(size)
|
107
123
|
end
|
108
124
|
|
109
|
-
# Execute the hook `hook_name`, if it is defined.
|
110
|
-
# @param [Symbol] hook_name The hook to execute
|
111
|
-
# @param [Array] args The arguments to pass to the hook.
|
112
|
-
def exec_hook(hook_name, *args, &block)
|
113
|
-
hooks[hook_name].call(*args, &block) if hooks[hook_name]
|
114
|
-
end
|
115
|
-
|
116
125
|
# Make sure special locals exist at start of session
|
117
126
|
def initialize_special_locals(target)
|
118
127
|
inject_local("_in_", @input_array, target)
|
119
128
|
inject_local("_out_", @output_array, target)
|
120
129
|
inject_local("_pry_", self, target)
|
121
|
-
inject_local("_ex_",
|
122
|
-
inject_local("_file_",
|
123
|
-
inject_local("_dir_",
|
130
|
+
inject_local("_ex_", last_exception, target)
|
131
|
+
inject_local("_file_", last_file, target)
|
132
|
+
inject_local("_dir_", last_dir, target)
|
124
133
|
|
125
134
|
# without this line we get 1 test failure, ask Mon_Ouie
|
126
135
|
set_last_result(nil, target)
|
@@ -136,13 +145,13 @@ class Pry
|
|
136
145
|
|
137
146
|
def special_locals
|
138
147
|
{
|
139
|
-
:_in_
|
140
|
-
:_out_
|
141
|
-
:_pry_
|
142
|
-
:_ex_
|
148
|
+
:_in_ => @input_array,
|
149
|
+
:_out_ => @output_array,
|
150
|
+
:_pry_ => self,
|
151
|
+
:_ex_ => last_exception,
|
143
152
|
:_file_ => last_file,
|
144
|
-
:_dir_
|
145
|
-
:_
|
153
|
+
:_dir_ => last_dir,
|
154
|
+
:_ => last_result
|
146
155
|
}
|
147
156
|
end
|
148
157
|
|
@@ -188,8 +197,9 @@ class Pry
|
|
188
197
|
end
|
189
198
|
end
|
190
199
|
|
200
|
+
break_data || nil
|
201
|
+
ensure
|
191
202
|
repl_epilogue(target)
|
192
|
-
break_data || target_self
|
193
203
|
end
|
194
204
|
|
195
205
|
# Perform a read-eval-print.
|
@@ -232,15 +242,16 @@ class Pry
|
|
232
242
|
|
233
243
|
code = r(target)
|
234
244
|
|
235
|
-
result =
|
245
|
+
result = target.eval(code, Pry.eval_path, Pry.current_line)
|
246
|
+
set_last_result(result, target, code)
|
247
|
+
|
236
248
|
result
|
237
|
-
rescue CommandError, Slop::InvalidOptionError => e
|
238
|
-
output.puts "Error: #{e.message}"
|
239
|
-
@suppress_output = true
|
240
249
|
rescue RescuableException => e
|
241
|
-
|
250
|
+
self.last_exception = e
|
251
|
+
e
|
242
252
|
ensure
|
243
253
|
update_input_history(code)
|
254
|
+
exec_hook :after_eval, result, self
|
244
255
|
end
|
245
256
|
|
246
257
|
# Perform a read.
|
@@ -259,16 +270,24 @@ class Pry
|
|
259
270
|
|
260
271
|
val = ""
|
261
272
|
loop do
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
273
|
+
begin
|
274
|
+
# eval_string will probably be mutated by this method
|
275
|
+
retrieve_line(eval_string, target)
|
276
|
+
rescue CommandError, Slop::InvalidOptionError => e
|
277
|
+
output.puts "Error: #{e.message}"
|
278
|
+
end
|
266
279
|
|
267
|
-
|
280
|
+
begin
|
281
|
+
break if complete_expression?(eval_string)
|
282
|
+
rescue SyntaxError => e
|
283
|
+
output.puts "SyntaxError: #{e.message.sub(/.*syntax error, */m, '')}"
|
284
|
+
eval_string = ""
|
285
|
+
end
|
268
286
|
end
|
269
287
|
|
270
288
|
@suppress_output = true if eval_string =~ /;\Z/ || eval_string.empty?
|
271
289
|
|
290
|
+
exec_hook :after_read, eval_string, self
|
272
291
|
eval_string
|
273
292
|
end
|
274
293
|
|
@@ -294,10 +313,15 @@ class Pry
|
|
294
313
|
end
|
295
314
|
end
|
296
315
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
316
|
+
def should_force_encoding?(eval_string, val)
|
317
|
+
eval_string.empty? && val.respond_to?(:encoding) && val.encoding != eval_string.encoding
|
318
|
+
end
|
319
|
+
private :should_force_encoding?
|
320
|
+
|
321
|
+
# Read and process a line of input -- check for ^D, determine which prompt to
|
322
|
+
# use, rewrite the indentation if `Pry.config.auto_indent` is enabled, and,
|
323
|
+
# if the line is a command, process it and alter the eval_string accordingly.
|
324
|
+
# This method should not need to be invoked directly.
|
301
325
|
#
|
302
326
|
# @param [String] eval_string The cumulative lines of input.
|
303
327
|
# @param [Binding] target The target of the session.
|
@@ -305,45 +329,60 @@ class Pry
|
|
305
329
|
def retrieve_line(eval_string, target)
|
306
330
|
@indent.reset if eval_string.empty?
|
307
331
|
|
308
|
-
current_prompt = select_prompt(eval_string
|
332
|
+
current_prompt = select_prompt(eval_string, target)
|
309
333
|
indentation = Pry.config.auto_indent ? @indent.indent_level : ''
|
310
334
|
|
311
|
-
val = readline(current_prompt
|
335
|
+
val = readline("#{current_prompt}#{indentation}")
|
312
336
|
|
313
337
|
# invoke handler if we receive EOF character (^D)
|
314
338
|
if !val
|
315
339
|
output.puts ""
|
316
340
|
Pry.config.control_d_handler.call(eval_string, self)
|
317
|
-
|
318
|
-
|
319
|
-
# Change the eval_string into the input encoding (Issue 284)
|
320
|
-
# TODO: This wouldn't be necessary if the eval_string was constructed from
|
321
|
-
# input strings only.
|
322
|
-
if eval_string.empty? && val.respond_to?(:encoding) && val.encoding != eval_string.encoding
|
323
|
-
eval_string.force_encoding(val.encoding)
|
324
|
-
end
|
341
|
+
return
|
342
|
+
end
|
325
343
|
|
326
|
-
|
327
|
-
|
328
|
-
|
344
|
+
# Change the eval_string into the input encoding (Issue 284)
|
345
|
+
# TODO: This wouldn't be necessary if the eval_string was constructed from
|
346
|
+
# input strings only.
|
347
|
+
if should_force_encoding?(eval_string, val)
|
348
|
+
eval_string.force_encoding(val.encoding)
|
349
|
+
end
|
329
350
|
|
330
|
-
|
331
|
-
|
332
|
-
|
351
|
+
if Pry.config.auto_indent && !input.is_a?(StringIO)
|
352
|
+
original_val = "#{indentation}#{val}"
|
353
|
+
indented_val = @indent.indent(val)
|
354
|
+
|
355
|
+
if original_val != indented_val && output.tty? && Pry::Helpers::BaseHelpers.use_ansi_codes? && Pry.config.correct_indent
|
356
|
+
output.print @indent.correct_indentation(current_prompt + indented_val, original_val.length - indented_val.length)
|
357
|
+
output.flush
|
333
358
|
end
|
359
|
+
else
|
360
|
+
indented_val = val
|
361
|
+
end
|
334
362
|
|
335
|
-
|
336
|
-
val
|
363
|
+
begin
|
364
|
+
if !process_command(val, eval_string, target)
|
365
|
+
eval_string << "#{indented_val.rstrip}\n" unless val.empty?
|
366
|
+
end
|
367
|
+
ensure
|
368
|
+
Pry.history << indented_val unless input.is_a?(StringIO)
|
337
369
|
end
|
338
370
|
end
|
339
371
|
|
340
|
-
#
|
372
|
+
# If the given line is a valid command, process it in the context of the
|
373
|
+
# current `eval_string` and context.
|
341
374
|
# This method should not need to be invoked directly.
|
342
375
|
# @param [String] val The line to process.
|
343
376
|
# @param [String] eval_string The cumulative lines of input.
|
344
377
|
# @param [Binding] target The target of the Pry session.
|
345
|
-
|
346
|
-
|
378
|
+
# @return [Boolean] `true` if `val` is a command, `false` otherwise
|
379
|
+
def process_command(val, eval_string, target)
|
380
|
+
result = commands.process_line(val, {
|
381
|
+
:target => target,
|
382
|
+
:output => output,
|
383
|
+
:eval_string => eval_string,
|
384
|
+
:pry_instance => self
|
385
|
+
})
|
347
386
|
|
348
387
|
# set a temporary (just so we can inject the value we want into eval_string)
|
349
388
|
Thread.current[:__pry_cmd_result__] = result
|
@@ -351,16 +390,16 @@ class Pry
|
|
351
390
|
# note that `result` wraps the result of command processing; if a
|
352
391
|
# command was matched and invoked then `result.command?` returns true,
|
353
392
|
# otherwise it returns false.
|
354
|
-
if result.command?
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
393
|
+
if result.command?
|
394
|
+
if !result.void_command?
|
395
|
+
# the command that was invoked was non-void (had a return value) and so we make
|
396
|
+
# the value of the current expression equal to the return value
|
397
|
+
# of the command.
|
398
|
+
eval_string.replace "Thread.current[:__pry_cmd_result__].retval\n"
|
399
|
+
end
|
400
|
+
true
|
360
401
|
else
|
361
|
-
|
362
|
-
# so this ignores their result
|
363
|
-
eval_string << "#{val.rstrip}\n" if !val.empty?
|
402
|
+
false
|
364
403
|
end
|
365
404
|
end
|
366
405
|
|
@@ -368,36 +407,63 @@ class Pry
|
|
368
407
|
# @param [String] val The command (and its params) to execute.
|
369
408
|
# @param [String] eval_string The current input buffer.
|
370
409
|
# @param [Binding] target The binding to use..
|
371
|
-
# @return [Pry::
|
410
|
+
# @return [Pry::Command::VOID_VALUE]
|
372
411
|
# @example
|
373
412
|
# pry_instance.run_command("ls -m")
|
374
413
|
def run_command(val, eval_string = "", target = binding_stack.last)
|
375
|
-
process_line(val,
|
376
|
-
|
414
|
+
commands.process_line(val,
|
415
|
+
:eval_string => eval_string,
|
416
|
+
:target => target,
|
417
|
+
:pry_instance => self,
|
418
|
+
:output => output
|
419
|
+
)
|
420
|
+
Pry::Command::VOID_VALUE
|
421
|
+
end
|
422
|
+
|
423
|
+
# Execute the specified hook.
|
424
|
+
# @param [Symbol] name The hook name to execute
|
425
|
+
# @param [*Object] args The arguments to pass to the hook
|
426
|
+
# @return [Object, Exception] The return value of the hook or the exception raised
|
427
|
+
#
|
428
|
+
# If executing a hook raises an exception, we log that and then continue sucessfully.
|
429
|
+
# To debug such errors, use the global variable $pry_hook_error, which is set as a
|
430
|
+
# result.
|
431
|
+
def exec_hook(name, *args, &block)
|
432
|
+
e_before = hooks.errors.size
|
433
|
+
hooks.exec_hook(name, *args, &block).tap do
|
434
|
+
hooks.errors[e_before..-1].each do |e|
|
435
|
+
output.puts "#{name} hook failed: #{e.class}: #{e.message}"
|
436
|
+
output.puts "#{e.backtrace.first}"
|
437
|
+
output.puts "(see _pry_.hooks.errors to debug)"
|
438
|
+
end
|
439
|
+
end
|
377
440
|
end
|
378
441
|
|
379
442
|
# Set the last result of an eval.
|
380
443
|
# This method should not need to be invoked directly.
|
381
444
|
# @param [Object] result The result.
|
382
445
|
# @param [Binding] target The binding to set `_` on.
|
383
|
-
|
446
|
+
# @param [String] code The code that was run.
|
447
|
+
def set_last_result(result, target, code="")
|
384
448
|
@last_result_is_exception = false
|
385
449
|
@output_array << result
|
386
450
|
|
387
|
-
self.last_result = result
|
451
|
+
self.last_result = result unless code =~ /\A\s*\z/
|
388
452
|
end
|
389
453
|
|
390
454
|
# Set the last exception for a session.
|
391
|
-
#
|
392
|
-
|
393
|
-
# @param [Binding] target The binding to set `_ex_` on.
|
394
|
-
def set_last_exception(ex, target)
|
455
|
+
# @param [Exception] ex
|
456
|
+
def last_exception=(ex)
|
395
457
|
class << ex
|
396
458
|
attr_accessor :file, :line, :bt_index
|
397
459
|
def bt_source_location_for(index)
|
398
460
|
backtrace[index] =~ /(.*):(\d+)/
|
399
461
|
[$1, $2.to_i]
|
400
462
|
end
|
463
|
+
|
464
|
+
def inc_bt_index
|
465
|
+
@bt_index = (@bt_index + 1) % backtrace.size
|
466
|
+
end
|
401
467
|
end
|
402
468
|
|
403
469
|
ex.bt_index = 0
|
@@ -405,8 +471,7 @@ class Pry
|
|
405
471
|
|
406
472
|
@last_result_is_exception = true
|
407
473
|
@output_array << ex
|
408
|
-
|
409
|
-
self.last_exception = ex
|
474
|
+
@last_exception = ex
|
410
475
|
end
|
411
476
|
|
412
477
|
# Update Pry's internal state after evalling code.
|
@@ -480,14 +545,17 @@ class Pry
|
|
480
545
|
|
481
546
|
# Returns the appropriate prompt to use.
|
482
547
|
# This method should not need to be invoked directly.
|
483
|
-
# @param [
|
484
|
-
#
|
485
|
-
# @param [Object] target_self The receiver of the Pry session.
|
548
|
+
# @param [String] eval_string The current input buffer.
|
549
|
+
# @param [Binding] target The target Binding of the Pry session.
|
486
550
|
# @return [String] The prompt.
|
487
|
-
def select_prompt(
|
551
|
+
def select_prompt(eval_string, target)
|
552
|
+
target_self = target.eval('self')
|
488
553
|
|
489
|
-
|
554
|
+
# If input buffer is empty then use normal prompt
|
555
|
+
if eval_string.empty?
|
490
556
|
Array(prompt).first.call(target_self, binding_stack.size - 1, self)
|
557
|
+
|
558
|
+
# Otherwise use the wait prompt (indicating multi-line expression)
|
491
559
|
else
|
492
560
|
Array(prompt).last.call(target_self, binding_stack.size - 1, self)
|
493
561
|
end
|
@@ -526,45 +594,49 @@ class Pry
|
|
526
594
|
prompt_stack.size > 1 ? prompt_stack.pop : prompt
|
527
595
|
end
|
528
596
|
|
529
|
-
if
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
597
|
+
# Determine if a string of code is a complete Ruby expression.
|
598
|
+
# @param [String] code The code to validate.
|
599
|
+
# @return [Boolean] Whether or not the code is a complete Ruby expression.
|
600
|
+
# @raise [SyntaxError] Any SyntaxError that does not represent incompleteness.
|
601
|
+
# @example
|
602
|
+
# complete_expression?("class Hello") #=> false
|
603
|
+
# complete_expression?("class Hello; end") #=> true
|
604
|
+
def complete_expression?(str)
|
605
|
+
if defined?(Rubinius::Melbourne19) && RUBY_VERSION =~ /^1\.9/
|
606
|
+
Rubinius::Melbourne19.parse_string(str, Pry.eval_path)
|
607
|
+
elsif defined?(Rubinius::Melbourne)
|
608
|
+
Rubinius::Melbourne.parse_string(str, Pry.eval_path)
|
609
|
+
else
|
610
|
+
catch(:valid) do
|
611
|
+
Helpers::BaseHelpers.silence_warnings do
|
612
|
+
eval("BEGIN{throw :valid}\n#{str}", binding, Pry.eval_path)
|
613
|
+
end
|
614
|
+
end
|
541
615
|
end
|
542
616
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
JRuby.parse(code)
|
548
|
-
true
|
549
|
-
rescue SyntaxError
|
617
|
+
# Assert that a line which ends with a , is incomplete.
|
618
|
+
str !~ /[,]\z/
|
619
|
+
rescue SyntaxError => e
|
620
|
+
if incomplete_user_input_exception?(e)
|
550
621
|
false
|
622
|
+
else
|
623
|
+
raise e
|
551
624
|
end
|
625
|
+
end
|
552
626
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
# NOTE: we're using .dup because RubyParser mutates the input
|
565
|
-
RubyParser.new.parse(code.dup)
|
627
|
+
# Check whether the exception indicates that the user should input more.
|
628
|
+
#
|
629
|
+
# @param [SyntaxError] the exception object that was raised.
|
630
|
+
# @param [Array<String>] The stack frame of the function that executed eval.
|
631
|
+
# @return [Boolean]
|
632
|
+
#
|
633
|
+
def incomplete_user_input_exception?(ex)
|
634
|
+
case ex.message
|
635
|
+
when /unexpected (\$end|end-of-file|END_OF_FILE)/, # mri, jruby, ironruby
|
636
|
+
/unterminated (quoted string|string|regexp) meets end of file/, # "quoted string" is ironruby
|
637
|
+
/missing 'end' for/, /: expecting '[})\]]'$/, /can't find string ".*" anywhere before EOF/, /expecting keyword_end/ # rbx
|
566
638
|
true
|
567
|
-
|
639
|
+
else
|
568
640
|
false
|
569
641
|
end
|
570
642
|
end
|