irb 1.7.0 → 1.7.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.
- checksums.yaml +4 -4
- data/irb.gemspec +1 -1
- data/lib/irb/cmd/irb_info.rb +14 -18
- data/lib/irb/cmd/nop.rb +4 -8
- data/lib/irb/cmd/show_cmds.rb +1 -1
- data/lib/irb/cmd/show_source.rb +3 -3
- data/lib/irb/completion.rb +2 -2
- data/lib/irb/context.rb +47 -16
- data/lib/irb/ext/{history.rb → eval_history.rb} +4 -4
- data/lib/irb/ext/loader.rb +2 -0
- data/lib/irb/extend-command.rb +2 -4
- data/lib/irb/{ext/save-history.rb → history.rb} +0 -51
- data/lib/irb/input-method.rb +6 -15
- data/lib/irb/nesting_parser.rb +227 -0
- data/lib/irb/ruby-lex.rb +220 -495
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +24 -30
- metadata +7 -8
- data/lib/irb/cmd/fork.rb +0 -34
- data/lib/irb/src_encoding.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9400febd023df0efde88c58ff524d4261ffe727404faf5cc719036e8691b7804
|
4
|
+
data.tar.gz: c46f543dc01f54f1ef6eaa37c2fdad212e06ffeecec0775e65f47423b68f8f7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ecca8c833a94435b5d4b2abfea2669b9e6d688976d6010cff13f8440651c3379616b202e2be101bf78ac706ca108abe2b98871984e02f8a3f295522b6e820c0e
|
7
|
+
data.tar.gz: 7877a1a4857f5b9163745057d8a9fdf6440f40272b71699fc481c889520c40cf77f07e3f48488fec7d8ef086d89cf0463900bc8257ba72447bf3164595081f55
|
data/irb.gemspec
CHANGED
data/lib/irb/cmd/irb_info.rb
CHANGED
@@ -11,24 +11,20 @@ module IRB
|
|
11
11
|
description "Show information about IRB."
|
12
12
|
|
13
13
|
def execute
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
str
|
29
|
-
end
|
30
|
-
alias_method :to_s, :inspect
|
31
|
-
}.new
|
14
|
+
str = "Ruby version: #{RUBY_VERSION}\n"
|
15
|
+
str += "IRB version: #{IRB.version}\n"
|
16
|
+
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
17
|
+
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
|
18
|
+
str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
|
19
|
+
str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
|
20
|
+
str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
|
21
|
+
str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
|
22
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
23
|
+
codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
|
24
|
+
str += "Code page: #{codepage}\n"
|
25
|
+
end
|
26
|
+
puts str
|
27
|
+
nil
|
32
28
|
end
|
33
29
|
end
|
34
30
|
end
|
data/lib/irb/cmd/nop.rb
CHANGED
@@ -30,23 +30,19 @@ module IRB
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def self.execute(
|
34
|
-
command = new(
|
33
|
+
def self.execute(irb_context, *opts, **kwargs, &block)
|
34
|
+
command = new(irb_context)
|
35
35
|
command.execute(*opts, **kwargs, &block)
|
36
36
|
rescue CommandArgumentError => e
|
37
37
|
puts e.message
|
38
38
|
end
|
39
39
|
|
40
|
-
def initialize(
|
41
|
-
@irb_context =
|
40
|
+
def initialize(irb_context)
|
41
|
+
@irb_context = irb_context
|
42
42
|
end
|
43
43
|
|
44
44
|
attr_reader :irb_context
|
45
45
|
|
46
|
-
def irb
|
47
|
-
@irb_context.irb
|
48
|
-
end
|
49
|
-
|
50
46
|
def execute(*opts)
|
51
47
|
#nop
|
52
48
|
end
|
data/lib/irb/cmd/show_cmds.rb
CHANGED
@@ -14,7 +14,7 @@ module IRB
|
|
14
14
|
def execute(*args)
|
15
15
|
commands_info = IRB::ExtendCommandBundle.all_commands_info
|
16
16
|
commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
|
17
|
-
longest_cmd_name_length = commands_info.map { |c| c[:display_name]
|
17
|
+
longest_cmd_name_length = commands_info.map { |c| c[:display_name].length }.max
|
18
18
|
|
19
19
|
output = StringIO.new
|
20
20
|
|
data/lib/irb/cmd/show_source.rb
CHANGED
@@ -58,9 +58,9 @@ module IRB
|
|
58
58
|
tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
|
59
59
|
code = lines[0..lnum].join
|
60
60
|
prev_tokens.concat chunk
|
61
|
-
continue = lex.
|
62
|
-
|
63
|
-
if !continue &&
|
61
|
+
continue = lex.should_continue?(prev_tokens)
|
62
|
+
syntax = lex.check_code_syntax(code)
|
63
|
+
if !continue && syntax == :valid
|
64
64
|
return first_line + lnum
|
65
65
|
end
|
66
66
|
end
|
data/lib/irb/completion.rb
CHANGED
@@ -218,7 +218,7 @@ module IRB
|
|
218
218
|
else
|
219
219
|
sym = $1
|
220
220
|
candidates = Symbol.all_symbols.collect do |s|
|
221
|
-
|
221
|
+
s.inspect
|
222
222
|
rescue EncodingError
|
223
223
|
# ignore
|
224
224
|
end
|
@@ -233,7 +233,7 @@ module IRB
|
|
233
233
|
if doc_namespace
|
234
234
|
candidates.find { |i| i == receiver }
|
235
235
|
else
|
236
|
-
candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
|
236
|
+
candidates.grep(/^#{Regexp.quote(receiver)}/).collect{|e| "::" + e}
|
237
237
|
end
|
238
238
|
|
239
239
|
when /^([A-Z].*)::([^:.]*)$/
|
data/lib/irb/context.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative "workspace"
|
|
8
8
|
require_relative "inspector"
|
9
9
|
require_relative "input-method"
|
10
10
|
require_relative "output-method"
|
11
|
+
require_relative "history"
|
11
12
|
|
12
13
|
module IRB
|
13
14
|
# A class that wraps the current state of the irb session, including the
|
@@ -151,6 +152,27 @@ module IRB
|
|
151
152
|
@command_aliases = IRB.conf[:COMMAND_ALIASES]
|
152
153
|
end
|
153
154
|
|
155
|
+
def save_history=(val)
|
156
|
+
IRB.conf[:SAVE_HISTORY] = val
|
157
|
+
if val
|
158
|
+
(IRB.conf[:MAIN_CONTEXT] || self).init_save_history
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def save_history
|
163
|
+
IRB.conf[:SAVE_HISTORY]
|
164
|
+
end
|
165
|
+
|
166
|
+
# A copy of the default <code>IRB.conf[:HISTORY_FILE]</code>
|
167
|
+
def history_file
|
168
|
+
IRB.conf[:HISTORY_FILE]
|
169
|
+
end
|
170
|
+
|
171
|
+
# Set <code>IRB.conf[:HISTORY_FILE]</code> to the given +hist+.
|
172
|
+
def history_file=(hist)
|
173
|
+
IRB.conf[:HISTORY_FILE] = hist
|
174
|
+
end
|
175
|
+
|
154
176
|
# The top-level workspace, see WorkSpace#main
|
155
177
|
def main
|
156
178
|
@workspace.main
|
@@ -473,28 +495,31 @@ module IRB
|
|
473
495
|
@inspect_mode
|
474
496
|
end
|
475
497
|
|
476
|
-
def evaluate(line, line_no
|
498
|
+
def evaluate(line, line_no) # :nodoc:
|
477
499
|
@line_no = line_no
|
478
|
-
|
479
|
-
line_no -= 1
|
480
|
-
line = "begin ::Kernel.raise _; rescue _.class\n#{line}\n""end"
|
481
|
-
@workspace.local_variable_set(:_, exception)
|
482
|
-
end
|
500
|
+
result = nil
|
483
501
|
|
484
|
-
|
485
|
-
|
486
|
-
if original = command_aliases[command.to_sym]
|
487
|
-
line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
|
488
|
-
command = original
|
502
|
+
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
|
503
|
+
IRB.set_measure_callback
|
489
504
|
end
|
490
505
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
506
|
+
if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
|
507
|
+
last_proc = proc do
|
508
|
+
result = @workspace.evaluate(line, irb_path, line_no)
|
509
|
+
end
|
510
|
+
IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item|
|
511
|
+
_name, callback, arg = item
|
512
|
+
proc do
|
513
|
+
callback.(self, line, line_no, arg) do
|
514
|
+
chain.call
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end.call
|
518
|
+
else
|
519
|
+
result = @workspace.evaluate(line, irb_path, line_no)
|
495
520
|
end
|
496
521
|
|
497
|
-
set_last_value(
|
522
|
+
set_last_value(result)
|
498
523
|
end
|
499
524
|
|
500
525
|
def inspect_last_value # :nodoc:
|
@@ -551,5 +576,11 @@ module IRB
|
|
551
576
|
command = command_aliases.fetch(command.to_sym, command)
|
552
577
|
ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
|
553
578
|
end
|
579
|
+
|
580
|
+
def init_save_history# :nodoc:
|
581
|
+
unless (class<<@io;self;end).include?(HistorySavingAbility)
|
582
|
+
@io.extend(HistorySavingAbility)
|
583
|
+
end
|
584
|
+
end
|
554
585
|
end
|
555
586
|
end
|
@@ -40,14 +40,14 @@ module IRB # :nodoc:
|
|
40
40
|
#
|
41
41
|
# If +no+ is +nil+, execution result history isn't used (default).
|
42
42
|
#
|
43
|
-
#
|
44
|
-
# IRB::
|
43
|
+
# EvalHistory values are available via <code>__</code> variable, see
|
44
|
+
# IRB::EvalHistory.
|
45
45
|
def eval_history=(no)
|
46
46
|
if no
|
47
47
|
if defined?(@eval_history) && @eval_history
|
48
48
|
@eval_history_values.size(no)
|
49
49
|
else
|
50
|
-
@eval_history_values =
|
50
|
+
@eval_history_values = EvalHistory.new(no)
|
51
51
|
IRB.conf[:__TMP__EHV__] = @eval_history_values
|
52
52
|
@workspace.evaluate("__ = IRB.conf[:__TMP__EHV__]")
|
53
53
|
IRB.conf.delete(:__TMP_EHV__)
|
@@ -89,7 +89,7 @@ module IRB # :nodoc:
|
|
89
89
|
# __[1]
|
90
90
|
# # => 10
|
91
91
|
#
|
92
|
-
class
|
92
|
+
class EvalHistory
|
93
93
|
|
94
94
|
def initialize(size = 16) # :nodoc:
|
95
95
|
@size = size
|
data/lib/irb/ext/loader.rb
CHANGED
@@ -42,6 +42,7 @@ module IRB # :nodoc:
|
|
42
42
|
#
|
43
43
|
# See Irb#suspend_input_method for more information.
|
44
44
|
def source_file(path)
|
45
|
+
irb = irb_context.irb
|
45
46
|
irb.suspend_name(path, File.basename(path)) do
|
46
47
|
FileInputMethod.open(path) do |io|
|
47
48
|
irb.suspend_input_method(io) do
|
@@ -66,6 +67,7 @@ module IRB # :nodoc:
|
|
66
67
|
#
|
67
68
|
# See Irb#suspend_input_method for more information.
|
68
69
|
def load_file(path, priv = nil)
|
70
|
+
irb = irb_context.irb
|
69
71
|
irb.suspend_name(path, File.basename(path)) do
|
70
72
|
|
71
73
|
if priv
|
data/lib/irb/extend-command.rb
CHANGED
@@ -289,7 +289,7 @@ module IRB # :nodoc:
|
|
289
289
|
alias_method to, from
|
290
290
|
}
|
291
291
|
else
|
292
|
-
Kernel.
|
292
|
+
Kernel.warn "irb: warn: can't alias #{to} from #{from}.\n"
|
293
293
|
end
|
294
294
|
end
|
295
295
|
|
@@ -316,10 +316,9 @@ module IRB # :nodoc:
|
|
316
316
|
CE = ContextExtender # :nodoc:
|
317
317
|
|
318
318
|
@EXTEND_COMMANDS = [
|
319
|
-
[:eval_history=, "ext/
|
319
|
+
[:eval_history=, "ext/eval_history.rb"],
|
320
320
|
[:use_tracer=, "ext/tracer.rb"],
|
321
321
|
[:use_loader=, "ext/use-loader.rb"],
|
322
|
-
[:save_history=, "ext/save-history.rb"],
|
323
322
|
]
|
324
323
|
|
325
324
|
# Installs the default context extensions as irb commands:
|
@@ -327,7 +326,6 @@ module IRB # :nodoc:
|
|
327
326
|
# Context#eval_history=:: +irb/ext/history.rb+
|
328
327
|
# Context#use_tracer=:: +irb/ext/tracer.rb+
|
329
328
|
# Context#use_loader=:: +irb/ext/use-loader.rb+
|
330
|
-
# Context#save_history=:: +irb/ext/save-history.rb+
|
331
329
|
def self.install_extend_commands
|
332
330
|
for args in @EXTEND_COMMANDS
|
333
331
|
def_extend_command(*args)
|
@@ -1,55 +1,4 @@
|
|
1
|
-
# frozen_string_literal: false
|
2
|
-
#
|
3
|
-
# save-history.rb -
|
4
|
-
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
5
|
-
#
|
6
|
-
|
7
1
|
module IRB
|
8
|
-
module HistorySavingAbility # :nodoc:
|
9
|
-
end
|
10
|
-
|
11
|
-
class Context
|
12
|
-
def init_save_history# :nodoc:
|
13
|
-
unless (class<<@io;self;end).include?(HistorySavingAbility)
|
14
|
-
@io.extend(HistorySavingAbility)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# A copy of the default <code>IRB.conf[:SAVE_HISTORY]</code>
|
19
|
-
def save_history
|
20
|
-
IRB.conf[:SAVE_HISTORY]
|
21
|
-
end
|
22
|
-
|
23
|
-
remove_method(:save_history=) if method_defined?(:save_history=)
|
24
|
-
# Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
|
25
|
-
# #init_save_history with this context.
|
26
|
-
#
|
27
|
-
# Will store the number of +val+ entries of history in the #history_file
|
28
|
-
#
|
29
|
-
# Add the following to your +.irbrc+ to change the number of history
|
30
|
-
# entries stored to 1000:
|
31
|
-
#
|
32
|
-
# IRB.conf[:SAVE_HISTORY] = 1000
|
33
|
-
def save_history=(val)
|
34
|
-
IRB.conf[:SAVE_HISTORY] = val
|
35
|
-
if val
|
36
|
-
main_context = IRB.conf[:MAIN_CONTEXT]
|
37
|
-
main_context = self unless main_context
|
38
|
-
main_context.init_save_history
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# A copy of the default <code>IRB.conf[:HISTORY_FILE]</code>
|
43
|
-
def history_file
|
44
|
-
IRB.conf[:HISTORY_FILE]
|
45
|
-
end
|
46
|
-
|
47
|
-
# Set <code>IRB.conf[:HISTORY_FILE]</code> to the given +hist+.
|
48
|
-
def history_file=(hist)
|
49
|
-
IRB.conf[:HISTORY_FILE] = hist
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
2
|
module HistorySavingAbility # :nodoc:
|
54
3
|
def HistorySavingAbility.extended(obj)
|
55
4
|
IRB.conf[:AT_EXIT].push proc{obj.save_history}
|
data/lib/irb/input-method.rb
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
5
5
|
#
|
6
6
|
|
7
|
-
require_relative 'src_encoding'
|
8
7
|
require_relative 'completion'
|
9
8
|
require 'io/console'
|
10
9
|
require 'reline'
|
@@ -256,8 +255,6 @@ module IRB
|
|
256
255
|
end
|
257
256
|
|
258
257
|
class RelineInputMethod < InputMethod
|
259
|
-
include Reline
|
260
|
-
|
261
258
|
# Creates a new input method object using Reline
|
262
259
|
def initialize
|
263
260
|
IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)
|
@@ -270,9 +267,7 @@ module IRB
|
|
270
267
|
@stdin = ::IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
|
271
268
|
@stdout = ::IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
|
272
269
|
|
273
|
-
|
274
|
-
Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
|
275
|
-
end
|
270
|
+
Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
|
276
271
|
Reline.completion_append_character = nil
|
277
272
|
Reline.completer_quote_characters = ''
|
278
273
|
Reline.completion_proc = IRB::InputCompletor::CompletionProc
|
@@ -401,10 +396,10 @@ module IRB
|
|
401
396
|
mod_key = RUBY_PLATFORM.match?(/darwin/) ? "Option" : "Alt"
|
402
397
|
message = "Press #{mod_key}+d to read the full document"
|
403
398
|
contents = [message] + doc.accept(formatter).split("\n")
|
404
|
-
contents = contents.take(preferred_dialog_height)
|
399
|
+
contents = contents.take(Reline.preferred_dialog_height)
|
405
400
|
|
406
401
|
y = cursor_pos_to_render.y
|
407
|
-
DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
|
402
|
+
Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
|
408
403
|
}
|
409
404
|
|
410
405
|
# Reads the next line from this input method.
|
@@ -415,8 +410,8 @@ module IRB
|
|
415
410
|
Reline.output = @stdout
|
416
411
|
Reline.prompt_proc = @prompt_proc
|
417
412
|
Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc
|
418
|
-
if l = readmultiline(@prompt, false, &@check_termination_proc)
|
419
|
-
HISTORY.push(l) if !l.empty?
|
413
|
+
if l = Reline.readmultiline(@prompt, false, &@check_termination_proc)
|
414
|
+
Reline::HISTORY.push(l) if !l.empty?
|
420
415
|
@line[@line_no += 1] = l + "\n"
|
421
416
|
else
|
422
417
|
@eof = true
|
@@ -458,11 +453,7 @@ module IRB
|
|
458
453
|
def inspect
|
459
454
|
config = Reline::Config.new
|
460
455
|
str = "RelineInputMethod with Reline #{Reline::VERSION}"
|
461
|
-
|
462
|
-
inputrc_path = File.expand_path(config.inputrc_path)
|
463
|
-
else
|
464
|
-
inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
|
465
|
-
end
|
456
|
+
inputrc_path = File.expand_path(config.inputrc_path)
|
466
457
|
str += " and #{inputrc_path}" if File.exist?(inputrc_path)
|
467
458
|
str
|
468
459
|
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module IRB
|
3
|
+
module NestingParser
|
4
|
+
IGNORE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
|
5
|
+
|
6
|
+
# Scan each token and call the given block with array of token and other information for parsing
|
7
|
+
def self.scan_opens(tokens)
|
8
|
+
opens = []
|
9
|
+
pending_heredocs = []
|
10
|
+
first_token_on_line = true
|
11
|
+
tokens.each do |t|
|
12
|
+
skip = false
|
13
|
+
last_tok, state, args = opens.last
|
14
|
+
case state
|
15
|
+
when :in_unquoted_symbol
|
16
|
+
unless IGNORE_TOKENS.include?(t.event)
|
17
|
+
opens.pop
|
18
|
+
skip = true
|
19
|
+
end
|
20
|
+
when :in_lambda_head
|
21
|
+
opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
|
22
|
+
when :in_method_head
|
23
|
+
unless IGNORE_TOKENS.include?(t.event)
|
24
|
+
next_args = []
|
25
|
+
body = nil
|
26
|
+
if args.include?(:receiver)
|
27
|
+
case t.event
|
28
|
+
when :on_lparen, :on_ivar, :on_gvar, :on_cvar
|
29
|
+
# def (receiver). | def @ivar. | def $gvar. | def @@cvar.
|
30
|
+
next_args << :dot
|
31
|
+
when :on_kw
|
32
|
+
case t.tok
|
33
|
+
when 'self', 'true', 'false', 'nil'
|
34
|
+
# def self(arg) | def self.
|
35
|
+
next_args.push(:arg, :dot)
|
36
|
+
else
|
37
|
+
# def if(arg)
|
38
|
+
skip = true
|
39
|
+
next_args << :arg
|
40
|
+
end
|
41
|
+
when :on_op, :on_backtick
|
42
|
+
# def +(arg)
|
43
|
+
skip = true
|
44
|
+
next_args << :arg
|
45
|
+
when :on_ident, :on_const
|
46
|
+
# def a(arg) | def a.
|
47
|
+
next_args.push(:arg, :dot)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
if args.include?(:dot)
|
51
|
+
# def receiver.name
|
52
|
+
next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::')
|
53
|
+
end
|
54
|
+
if args.include?(:name)
|
55
|
+
if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event)
|
56
|
+
# def name(arg) | def receiver.name(arg)
|
57
|
+
next_args << :arg
|
58
|
+
skip = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
if args.include?(:arg)
|
62
|
+
case t.event
|
63
|
+
when :on_nl, :on_semicolon
|
64
|
+
# def recever.f;
|
65
|
+
body = :normal
|
66
|
+
when :on_lparen
|
67
|
+
# def recever.f()
|
68
|
+
next_args << :eq
|
69
|
+
else
|
70
|
+
if t.event == :on_op && t.tok == '='
|
71
|
+
# def receiver.f =
|
72
|
+
body = :oneliner
|
73
|
+
else
|
74
|
+
# def recever.f arg
|
75
|
+
next_args << :arg_without_paren
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if args.include?(:eq)
|
80
|
+
if t.event == :on_op && t.tok == '='
|
81
|
+
body = :oneliner
|
82
|
+
else
|
83
|
+
body = :normal
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if args.include?(:arg_without_paren)
|
87
|
+
if %i[on_semicolon on_nl].include?(t.event)
|
88
|
+
# def f a;
|
89
|
+
body = :normal
|
90
|
+
else
|
91
|
+
# def f a, b
|
92
|
+
next_args << :arg_without_paren
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if body == :oneliner
|
96
|
+
opens.pop
|
97
|
+
elsif body
|
98
|
+
opens[-1] = [last_tok, nil]
|
99
|
+
else
|
100
|
+
opens[-1] = [last_tok, :in_method_head, next_args]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
when :in_for_while_until_condition
|
104
|
+
if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do')
|
105
|
+
skip = true if t.event == :on_kw && t.tok == 'do'
|
106
|
+
opens[-1] = [last_tok, nil]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
unless skip
|
111
|
+
case t.event
|
112
|
+
when :on_kw
|
113
|
+
case t.tok
|
114
|
+
when 'begin', 'class', 'module', 'do', 'case'
|
115
|
+
opens << [t, nil]
|
116
|
+
when 'end'
|
117
|
+
opens.pop
|
118
|
+
when 'def'
|
119
|
+
opens << [t, :in_method_head, [:receiver, :name]]
|
120
|
+
when 'if', 'unless'
|
121
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
122
|
+
opens << [t, nil]
|
123
|
+
end
|
124
|
+
when 'while', 'until'
|
125
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
126
|
+
opens << [t, :in_for_while_until_condition]
|
127
|
+
end
|
128
|
+
when 'ensure', 'rescue'
|
129
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
130
|
+
opens.pop
|
131
|
+
opens << [t, nil]
|
132
|
+
end
|
133
|
+
when 'elsif', 'else', 'when'
|
134
|
+
opens.pop
|
135
|
+
opens << [t, nil]
|
136
|
+
when 'for'
|
137
|
+
opens << [t, :in_for_while_until_condition]
|
138
|
+
when 'in'
|
139
|
+
if last_tok&.event == :on_kw && %w[case in].include?(last_tok.tok) && first_token_on_line
|
140
|
+
opens.pop
|
141
|
+
opens << [t, nil]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
when :on_tlambda
|
145
|
+
opens << [t, :in_lambda_head]
|
146
|
+
when :on_lparen, :on_lbracket, :on_lbrace, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
|
147
|
+
opens << [t, nil]
|
148
|
+
when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
|
149
|
+
opens.pop
|
150
|
+
when :on_heredoc_beg
|
151
|
+
pending_heredocs << t
|
152
|
+
when :on_heredoc_end
|
153
|
+
opens.pop
|
154
|
+
when :on_backtick
|
155
|
+
opens << [t, nil] if t.state.allbits?(Ripper::EXPR_BEG)
|
156
|
+
when :on_tstring_beg, :on_words_beg, :on_qwords_beg, :on_symbols_beg, :on_qsymbols_beg, :on_regexp_beg
|
157
|
+
opens << [t, nil]
|
158
|
+
when :on_tstring_end, :on_regexp_end, :on_label_end
|
159
|
+
opens.pop
|
160
|
+
when :on_symbeg
|
161
|
+
if t.tok == ':'
|
162
|
+
opens << [t, :in_unquoted_symbol]
|
163
|
+
else
|
164
|
+
opens << [t, nil]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
if t.event == :on_nl || t.event == :on_semicolon
|
169
|
+
first_token_on_line = true
|
170
|
+
elsif t.event != :on_sp
|
171
|
+
first_token_on_line = false
|
172
|
+
end
|
173
|
+
if pending_heredocs.any? && t.tok.include?("\n")
|
174
|
+
pending_heredocs.reverse_each { |t| opens << [t, nil] }
|
175
|
+
pending_heredocs = []
|
176
|
+
end
|
177
|
+
yield t, opens if block_given?
|
178
|
+
end
|
179
|
+
opens.map(&:first) + pending_heredocs.reverse
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.open_tokens(tokens)
|
183
|
+
# scan_opens without block will return a list of open tokens at last token position
|
184
|
+
scan_opens(tokens)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Calculates token information [line_tokens, prev_opens, next_opens, min_depth] for each line.
|
188
|
+
# Example code
|
189
|
+
# ["hello
|
190
|
+
# world"+(
|
191
|
+
# First line
|
192
|
+
# line_tokens: [[lbracket, '['], [tstring_beg, '"'], [tstring_content("hello\nworld"), "hello\n"]]
|
193
|
+
# prev_opens: []
|
194
|
+
# next_tokens: [lbracket, tstring_beg]
|
195
|
+
# min_depth: 0 (minimum at beginning of line)
|
196
|
+
# Second line
|
197
|
+
# line_tokens: [[tstring_content("hello\nworld"), "world"], [tstring_end, '"'], [op, '+'], [lparen, '(']]
|
198
|
+
# prev_opens: [lbracket, tstring_beg]
|
199
|
+
# next_tokens: [lbracket, lparen]
|
200
|
+
# min_depth: 1 (minimum just after tstring_end)
|
201
|
+
def self.parse_by_line(tokens)
|
202
|
+
line_tokens = []
|
203
|
+
prev_opens = []
|
204
|
+
min_depth = 0
|
205
|
+
output = []
|
206
|
+
last_opens = scan_opens(tokens) do |t, opens|
|
207
|
+
depth = t == opens.last&.first ? opens.size - 1 : opens.size
|
208
|
+
min_depth = depth if depth < min_depth
|
209
|
+
if t.tok.include?("\n")
|
210
|
+
t.tok.each_line do |line|
|
211
|
+
line_tokens << [t, line]
|
212
|
+
next if line[-1] != "\n"
|
213
|
+
next_opens = opens.map(&:first)
|
214
|
+
output << [line_tokens, prev_opens, next_opens, min_depth]
|
215
|
+
prev_opens = next_opens
|
216
|
+
min_depth = prev_opens.size
|
217
|
+
line_tokens = []
|
218
|
+
end
|
219
|
+
else
|
220
|
+
line_tokens << [t, t.tok]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
output << [line_tokens, prev_opens, last_opens, min_depth] if line_tokens.any?
|
224
|
+
output
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|