katakata_irb 0.1.3 → 0.1.5
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/Gemfile.lock +8 -2
- data/README.md +16 -26
- data/bin/console +2 -7
- data/katakata_irb.gemspec +2 -1
- data/lib/katakata_irb/completor.rb +128 -14
- data/lib/katakata_irb/{trex.rb → nesting_parser.rb} +47 -11
- data/lib/katakata_irb/scope.rb +248 -0
- data/lib/katakata_irb/type_simulator.rb +148 -332
- data/lib/katakata_irb/types.rb +96 -22
- data/lib/katakata_irb/version.rb +1 -1
- data/lib/katakata_irb.rb +5 -7
- metadata +21 -15
- data/exe/kirb +0 -11
- data/lib/katakata_irb/reline_patch.rb +0 -43
- data/lib/katakata_irb/reline_patches/escapeseq.patch +0 -45
- data/lib/katakata_irb/reline_patches/indent.patch +0 -25
- data/lib/katakata_irb/reline_patches/raw.patch +0 -95
- data/lib/katakata_irb/reline_patches/scrollbar.patch +0 -34
- data/lib/katakata_irb/reline_patches/wholelines.patch +0 -102
- data/lib/katakata_irb/ruby_lex_patch.rb +0 -221
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 882c0834b6d52916911b26b82083e1100491dd24cafdb1c948c4c1795fe03d7e
|
4
|
+
data.tar.gz: 2250eaec5d0b1cabc236f238249e132206b62e70ada1c16429567b680ace2093
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60f3c4de13636f2948e740b3a57b6091c1f193ae7fa259d665c69a404833ef413b90aca3da7360f97be2d7a669e9a0d5fc101ff172890c4f0714c9eb63db8dd4
|
7
|
+
data.tar.gz: eb496c54819de4f1e035e261a6afffcc13d2809b316428602567614dbc5671df5ead97fb4a0696afbb34a7ade9ce8a2b3e9579ebad4ddd006d9a32b120b3e05d
|
data/Gemfile.lock
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
katakata_irb (0.1.
|
4
|
+
katakata_irb (0.1.5)
|
5
|
+
irb (>= 1.4.0)
|
5
6
|
rbs
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
11
|
+
io-console (0.6.0)
|
12
|
+
irb (1.6.2)
|
13
|
+
reline (>= 0.3.0)
|
10
14
|
minitest (5.16.3)
|
11
15
|
rake (13.0.6)
|
12
16
|
rbs (2.7.0)
|
17
|
+
reline (0.3.2)
|
18
|
+
io-console (~> 0.5)
|
13
19
|
|
14
20
|
PLATFORMS
|
15
21
|
x86_64-darwin-20
|
@@ -20,4 +26,4 @@ DEPENDENCIES
|
|
20
26
|
rake (~> 13.0)
|
21
27
|
|
22
28
|
BUNDLED WITH
|
23
|
-
2.4.
|
29
|
+
2.4.5
|
data/README.md
CHANGED
@@ -9,9 +9,15 @@ gem install katakata_irb
|
|
9
9
|
```
|
10
10
|
## Usage
|
11
11
|
|
12
|
+
Just require katakata_irb or write it to your `.irbrc` file.
|
13
|
+
```ruby
|
14
|
+
require 'katakata_irb'
|
15
|
+
```
|
16
|
+
|
12
17
|
```
|
13
|
-
|
14
|
-
|
18
|
+
irb(main):001:0> require 'katakata_irb'
|
19
|
+
=> true
|
20
|
+
irb(main):002:0> [1,'a'].sample.a█
|
15
21
|
|[1,'a'].sample.abs |
|
16
22
|
|[1,'a'].sample.abs2 |
|
17
23
|
|[1,'a'].sample.allbits? |
|
@@ -22,30 +28,14 @@ irb(main):001:0> [1,'a'].sample.a█
|
|
22
28
|
```
|
23
29
|
|
24
30
|
```
|
25
|
-
|
26
|
-
|
31
|
+
irb(main):001:0> require 'katakata_irb'
|
32
|
+
=> true
|
33
|
+
irb(main):002:0> a = 10
|
27
34
|
=> 10
|
28
|
-
irb(main):
|
29
|
-
irb(main):
|
30
|
-
irb(main):
|
31
|
-
irb(main):
|
32
|
-
irb(main):
|
35
|
+
irb(main):003:1* if true
|
36
|
+
irb(main):004:2* b = a.times.map do
|
37
|
+
irb(main):005:2* _1.to_s
|
38
|
+
irb(main):006:1* end
|
39
|
+
irb(main):007:1* b[0].a█
|
33
40
|
|b[0].ascii_only?|
|
34
41
|
```
|
35
|
-
|
36
|
-
```ruby
|
37
|
-
require 'katakata_irb/completor'
|
38
|
-
KatakataIrb::Completor.setup
|
39
|
-
10.times do |i|
|
40
|
-
binding.irb
|
41
|
-
end
|
42
|
-
```
|
43
|
-
|
44
|
-
## Options
|
45
|
-
|
46
|
-
### `kirb --debug-output`
|
47
|
-
Show debug output if it meets unimplemented syntax or something
|
48
|
-
|
49
|
-
### `kirb --without-patch`
|
50
|
-
`kirb` will apply some patches to reline and irb/ruby-lex.rb by default. This option will disable it.
|
51
|
-
See `lib/katakata_irb/ruby_lex_patch.rb` and `lib/katakata_irb/reline_patches/*.patch`
|
data/bin/console
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require_relative '../lib/katakata_irb'
|
3
|
-
require_relative '../lib/katakata_irb/reline_patch'
|
4
|
-
KatakataIrb.log_output = STDERR
|
5
|
-
KatakataIrb::RelinePatch.require_patched_reline
|
6
2
|
require 'bundler/setup'
|
7
3
|
require 'katakata_irb'
|
8
|
-
|
9
|
-
|
10
|
-
KatakataIrb.repl
|
4
|
+
KatakataIrb.log_output = STDERR
|
5
|
+
IRB.start(__FILE__)
|
data/katakata_irb.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = "IRB with Typed Completion"
|
13
13
|
spec.homepage = "http://github.com/tompng/katakata_irb"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 3.1.0
|
15
|
+
spec.required_ruby_version = ">= 3.0.0" # recommend >= 3.1.0
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = "http://github.com/tompng/katakata_irb"
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.require_paths = ["lib"]
|
30
30
|
|
31
31
|
# Uncomment to register a new dependency of your gem
|
32
|
+
spec.add_dependency 'irb', '>= 1.4.0'
|
32
33
|
spec.add_dependency 'rbs'
|
33
34
|
|
34
35
|
# For more information and examples about making a new gem, check out our
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'nesting_parser'
|
2
2
|
require_relative 'type_simulator'
|
3
3
|
require 'rbs'
|
4
4
|
require 'rbs/cli'
|
@@ -6,15 +6,17 @@ require 'irb'
|
|
6
6
|
|
7
7
|
module KatakataIrb::Completor
|
8
8
|
using KatakataIrb::TypeSimulator::LexerElemMatcher
|
9
|
-
|
10
9
|
HIDDEN_METHODS = %w[Namespace TypeName] # defined by rbs, should be hidden
|
10
|
+
singleton_class.attr_accessor :prev_analyze_result
|
11
11
|
|
12
12
|
def self.setup
|
13
13
|
completion_proc = ->(target, preposing = nil, postposing = nil) do
|
14
14
|
code = "#{preposing}#{target}"
|
15
15
|
irb_context = IRB.conf[:MAIN_CONTEXT]
|
16
16
|
binding = irb_context.workspace.binding
|
17
|
-
|
17
|
+
result = analyze code, binding
|
18
|
+
KatakataIrb::Completor.prev_analyze_result = result
|
19
|
+
candidates = case result
|
18
20
|
in [:require | :require_relative => method, name]
|
19
21
|
if method == :require
|
20
22
|
IRB::InputCompletor.retrieve_files_to_require_from_load_path
|
@@ -25,18 +27,18 @@ module KatakataIrb::Completor
|
|
25
27
|
((self_call ? type.all_methods: type.methods).map(&:to_s) - HIDDEN_METHODS) | type.constants
|
26
28
|
in [:const, type, name]
|
27
29
|
type.constants
|
28
|
-
in [:ivar, name, _scope]
|
30
|
+
in [:ivar, name, *_scope]
|
29
31
|
# TODO: scope
|
30
32
|
ivars = binding.eval('self').instance_variables rescue []
|
31
33
|
cvars = (binding.eval('self').class_variables rescue nil) if name == '@'
|
32
34
|
ivars | (cvars || [])
|
33
|
-
in [:cvar, name, _scope]
|
35
|
+
in [:cvar, name, *_scope]
|
34
36
|
# TODO: scope
|
35
37
|
binding.eval('self').class_variables rescue []
|
36
38
|
in [:gvar, name]
|
37
39
|
global_variables
|
38
40
|
in [:symbol, name]
|
39
|
-
Symbol.all_symbols
|
41
|
+
Symbol.all_symbols.map { _1.inspect[1..] }
|
40
42
|
in [:call, type, name, self_call]
|
41
43
|
(self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
|
42
44
|
in [:lvar_or_method, name, scope]
|
@@ -57,16 +59,95 @@ module KatakataIrb::Completor
|
|
57
59
|
KatakataIrb.log_puts "#{e.inspect} stored to $error"
|
58
60
|
KatakataIrb.log_puts
|
59
61
|
end
|
62
|
+
|
63
|
+
IRB::InputCompletor.singleton_class.prepend Module.new{
|
64
|
+
def retrieve_completion_data(input, _bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
|
65
|
+
return super unless doc_namespace
|
66
|
+
name = input[/[a-zA-Z_0-9]+[!?=]?\z/]
|
67
|
+
method_doc = -> type do
|
68
|
+
type = type.types.find { _1.all_methods.include? name.to_sym }
|
69
|
+
if type in KatakataIrb::Types::SingletonType
|
70
|
+
"#{KatakataIrb::Types.class_name_of(type.module_or_class)}.#{name}"
|
71
|
+
elsif type in KatakataIrb::Types::InstanceType
|
72
|
+
"#{KatakataIrb::Types.class_name_of(type.klass)}##{name}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
call_or_const_doc = -> type do
|
76
|
+
if name =~ /\A[A-Z]/
|
77
|
+
type = type.types.grep(KatakataIrb::Types::SingletonType).find { _1.module_or_class.const_defined?(name) }
|
78
|
+
type.module_or_class == Object ? name : "#{KatakataIrb::Types.class_name_of(type.module_or_class)}::#{name}" if type
|
79
|
+
else
|
80
|
+
method_doc.call(type)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
case KatakataIrb::Completor.prev_analyze_result
|
85
|
+
in [:call_or_const, type, _name, _self_call]
|
86
|
+
call_or_const_doc.call type
|
87
|
+
in [:const, type, _name]
|
88
|
+
# when prev_analyze_result is const, current analyze result might be call
|
89
|
+
call_or_const_doc.call type
|
90
|
+
in [:gvar, _name]
|
91
|
+
name
|
92
|
+
in [:call, type, _name, _self_call]
|
93
|
+
method_doc.call type
|
94
|
+
in [:lvar_or_method, _name, scope]
|
95
|
+
method_doc.call scope.self_type unless scope.local_variables.include?(name)
|
96
|
+
else
|
97
|
+
end
|
98
|
+
end
|
99
|
+
}
|
100
|
+
setup_type_dialog
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.setup_type_dialog
|
104
|
+
type_dialog_proc = -> {
|
105
|
+
return if just_cursor_moving && completion_journey_data
|
106
|
+
cursor_pos_to_render, _result, pointer, autocomplete_dialog = context.last(4)
|
107
|
+
return unless cursor_pos_to_render && autocomplete_dialog&.width && pointer.nil?
|
108
|
+
receiver_type = (
|
109
|
+
case KatakataIrb::Completor.prev_analyze_result
|
110
|
+
in [:call_or_const, type, name, _self_call] if name.empty?
|
111
|
+
type
|
112
|
+
in [:call, type, name, _self_call] if name.empty?
|
113
|
+
type
|
114
|
+
else
|
115
|
+
return
|
116
|
+
end
|
117
|
+
)
|
118
|
+
return unless receiver_type
|
119
|
+
types = type.types
|
120
|
+
contents = types.filter_map do |type|
|
121
|
+
case type
|
122
|
+
when KatakataIrb::Types::InstanceType
|
123
|
+
KatakataIrb::Types.class_name_of type.klass
|
124
|
+
when KatakataIrb::Types::SingletonType
|
125
|
+
module_name = KatakataIrb::Types.class_name_of type.module_or_class
|
126
|
+
"#{module_name}.itself" if module_name
|
127
|
+
end
|
128
|
+
end.uniq
|
129
|
+
return if contents.empty?
|
130
|
+
|
131
|
+
width = contents.map { Reline::Unicode.calculate_width _1 }.max
|
132
|
+
x = cursor_pos_to_render.x + autocomplete_dialog.width
|
133
|
+
y = cursor_pos_to_render.y
|
134
|
+
Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: 44, fg_color: 37)
|
135
|
+
}
|
136
|
+
Reline.add_dialog_proc(:show_type, type_dialog_proc, Reline::DEFAULT_DIALOG_CONTEXT)
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.empty_binding()
|
140
|
+
Kernel.binding
|
60
141
|
end
|
61
142
|
|
62
|
-
def self.analyze(code, binding =
|
143
|
+
def self.analyze(code, binding = empty_binding)
|
63
144
|
lvars_code = binding.local_variables.map do |name|
|
64
145
|
"#{name}="
|
65
146
|
end.join + "nil;\n"
|
66
147
|
code = lvars_code + code
|
67
148
|
tokens = RubyLex.ripper_lex_without_warning code
|
68
|
-
tokens = KatakataIrb::
|
69
|
-
last_opens = KatakataIrb::
|
149
|
+
tokens = KatakataIrb::NestingParser.interpolate_ripper_ignored_tokens code, tokens
|
150
|
+
last_opens = KatakataIrb::NestingParser.parse(tokens)
|
70
151
|
closings = last_opens.map do |t|
|
71
152
|
case t.tok
|
72
153
|
when /\A%.[<>]\z/
|
@@ -84,12 +165,21 @@ module KatakataIrb::Completor
|
|
84
165
|
t.tok
|
85
166
|
when /\A<<[~-]?(?:"(?<s>.+)"|'(?<s>.+)'|(?<s>.+))/
|
86
167
|
$/ + ($1 || $2 || $3) + $/
|
168
|
+
when ':"', ":'", ':'
|
169
|
+
t.tok[1]
|
170
|
+
when '?'
|
171
|
+
# ternary operator
|
172
|
+
' : value'
|
173
|
+
when '|'
|
174
|
+
# block args
|
175
|
+
'|'
|
87
176
|
else
|
88
177
|
$/ + 'end'
|
89
178
|
end
|
90
179
|
end
|
180
|
+
# remove error tokens
|
181
|
+
tokens.pop while tokens&.last&.tok&.empty?
|
91
182
|
|
92
|
-
return if code =~ /[!?]\z/
|
93
183
|
case tokens.last
|
94
184
|
in { event: :on_ignored_by_ripper, tok: '.' }
|
95
185
|
suffix = 'method'
|
@@ -97,6 +187,9 @@ module KatakataIrb::Completor
|
|
97
187
|
in { dot: true }
|
98
188
|
suffix = 'method'
|
99
189
|
name = ''
|
190
|
+
in { event: :on_symbeg }
|
191
|
+
suffix = 'symbol'
|
192
|
+
name = ''
|
100
193
|
in { event: :on_ident | :on_kw, tok: }
|
101
194
|
return unless code.delete_suffix! tok
|
102
195
|
suffix = 'method'
|
@@ -109,10 +202,21 @@ module KatakataIrb::Completor
|
|
109
202
|
return unless code.delete_suffix! tok
|
110
203
|
suffix = 'string'
|
111
204
|
name = tok.rstrip
|
205
|
+
in { event: :on_gvar, tok: }
|
206
|
+
return unless code.delete_suffix! tok
|
207
|
+
suffix = '$gvar'
|
208
|
+
name = tok
|
209
|
+
in { event: :on_ivar, tok: }
|
210
|
+
return unless code.delete_suffix! tok
|
211
|
+
suffix = '@ivar'
|
212
|
+
name = tok
|
213
|
+
in { event: :on_cvar, tok: }
|
214
|
+
return unless code.delete_suffix! tok
|
215
|
+
suffix = '@@cvar'
|
216
|
+
name = tok
|
112
217
|
else
|
113
218
|
return
|
114
219
|
end
|
115
|
-
|
116
220
|
sexp = Ripper.sexp code + suffix + closings.reverse.join
|
117
221
|
lines = code.lines
|
118
222
|
line_no = lines.size
|
@@ -136,16 +240,26 @@ module KatakataIrb::Completor
|
|
136
240
|
return [:cvar, name] if icvar_available
|
137
241
|
end
|
138
242
|
return unless expression
|
243
|
+
calculate_scope = -> { KatakataIrb::TypeSimulator.calculate_binding_scope binding, parents, expression }
|
244
|
+
calculate_receiver = -> receiver { KatakataIrb::TypeSimulator.calculate_receiver binding, parents, receiver }
|
245
|
+
|
139
246
|
if (target in [:@tstring_content,]) && (parents[-4] in [:command, [:@ident, 'require' | 'require_relative' => require_method,],])
|
247
|
+
# `require 'target'`
|
140
248
|
return [require_method.to_sym, name.rstrip]
|
141
249
|
end
|
142
|
-
|
143
|
-
|
250
|
+
if (target in [:@ident,]) && (expression in [:symbol,]) && (parents[-2] in [:args_add_block, Array => args, [:symbol_literal, ^expression]])
|
251
|
+
# `method(&:target)`
|
252
|
+
receiver_ref = [:var_ref, [:@ident, '_1', [0, 0]]]
|
253
|
+
block_statements = [receiver_ref]
|
254
|
+
parents[-1] = parents[-2][-1] = [:brace_block, nil, block_statements]
|
255
|
+
parents << block_statements
|
256
|
+
return [:call, calculate_receiver.call(receiver_ref), name, false]
|
257
|
+
end
|
144
258
|
case expression
|
145
259
|
in [:vcall | :var_ref, [:@ident,]]
|
146
260
|
[:lvar_or_method, name, calculate_scope.call]
|
147
261
|
in [:symbol, [:@ident | :@const | :@op | :@kw,]]
|
148
|
-
[:symbol, name]
|
262
|
+
[:symbol, name] unless name.empty?
|
149
263
|
in [:var_ref | :const_ref, [:@const,]]
|
150
264
|
# TODO
|
151
265
|
[:const, KatakataIrb::Types::SingletonType.new(Object), name]
|
@@ -1,5 +1,4 @@
|
|
1
|
-
module KatakataIrb
|
2
|
-
module KatakataIrb::TRex
|
1
|
+
module KatakataIrb::NestingParser
|
3
2
|
def self.interpolate_ripper_ignored_tokens(code, tokens)
|
4
3
|
line_positions = code.lines.reduce([0]) { _1 << _1.last + _2.bytesize }
|
5
4
|
prev_byte_pos = 0
|
@@ -27,19 +26,25 @@ module KatakataIrb::TRex
|
|
27
26
|
interpolated
|
28
27
|
end
|
29
28
|
|
29
|
+
IGNOREABLE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
|
30
|
+
|
30
31
|
def self.parse(tokens)
|
31
32
|
opens = []
|
32
33
|
pending_heredocs = []
|
33
34
|
first_token_on_line = true
|
34
|
-
tokens.
|
35
|
+
tokens.each do |t|
|
35
36
|
skip = false
|
36
37
|
last_tok, state, args = opens.last
|
37
38
|
case state
|
38
39
|
when :in_unquoted_symbol
|
39
|
-
|
40
|
-
|
40
|
+
unless t.event == :on_sp
|
41
|
+
opens.pop
|
42
|
+
skip = true
|
43
|
+
end
|
44
|
+
when :in_lambda_head
|
45
|
+
opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
|
41
46
|
when :in_method_head
|
42
|
-
unless
|
47
|
+
unless IGNOREABLE_TOKENS.include?(t.event)
|
43
48
|
next_args = []
|
44
49
|
body = nil
|
45
50
|
if args.include?(:receiver)
|
@@ -124,13 +129,27 @@ module KatakataIrb::TRex
|
|
124
129
|
skip = true if t.event == :on_kw && t.tok == 'do'
|
125
130
|
opens[-1] = [last_tok, nil]
|
126
131
|
end
|
132
|
+
when :in_block_head
|
133
|
+
if t.event == :on_op && t.tok == '|'
|
134
|
+
opens[-1] = [last_tok, nil]
|
135
|
+
opens << [t, :in_block_args]
|
136
|
+
elsif !IGNOREABLE_TOKENS.include?(t.event)
|
137
|
+
opens[-1] = [last_tok, nil]
|
138
|
+
end
|
139
|
+
when :in_block_args
|
140
|
+
if t.event == :on_op && t.tok == '|' && t.state.allbits?(Ripper::EXPR_BEG)
|
141
|
+
opens.pop
|
142
|
+
skip = true
|
143
|
+
end
|
127
144
|
end
|
128
145
|
|
129
146
|
unless skip
|
130
147
|
case t.event
|
131
148
|
when :on_kw
|
132
149
|
case t.tok
|
133
|
-
when '
|
150
|
+
when 'do'
|
151
|
+
opens << [t, :in_block_head]
|
152
|
+
when 'begin', 'class', 'module', 'case'
|
134
153
|
opens << [t, nil]
|
135
154
|
when 'end'
|
136
155
|
opens.pop
|
@@ -160,7 +179,15 @@ module KatakataIrb::TRex
|
|
160
179
|
opens << [t, nil]
|
161
180
|
end
|
162
181
|
end
|
163
|
-
when :
|
182
|
+
when :on_lbrace
|
183
|
+
if t.state.allbits?(Ripper::EXPR_LABEL)
|
184
|
+
opens << [t, nil]
|
185
|
+
else
|
186
|
+
opens << [t, :in_block_head]
|
187
|
+
end
|
188
|
+
when :on_tlambda
|
189
|
+
opens << [t, :in_lambda_head]
|
190
|
+
when :on_lparen, :on_lbracket, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
|
164
191
|
opens << [t, nil]
|
165
192
|
when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
|
166
193
|
opens.pop
|
@@ -174,6 +201,15 @@ module KatakataIrb::TRex
|
|
174
201
|
opens << [t, nil]
|
175
202
|
when :on_tstring_end, :on_regexp_end, :on_label_end
|
176
203
|
opens.pop
|
204
|
+
when :on_op
|
205
|
+
case t.tok
|
206
|
+
when '?'
|
207
|
+
# opening of `cond ? value : value``
|
208
|
+
opens << [t, nil]
|
209
|
+
when ':'
|
210
|
+
# closing of `cond ? value : value``
|
211
|
+
opens.pop
|
212
|
+
end
|
177
213
|
when :on_symbeg
|
178
214
|
if t.tok == ':'
|
179
215
|
opens << [t, :in_unquoted_symbol]
|
@@ -188,10 +224,10 @@ module KatakataIrb::TRex
|
|
188
224
|
first_token_on_line = false
|
189
225
|
end
|
190
226
|
if pending_heredocs.any? && t.tok.include?("\n")
|
191
|
-
pending_heredocs.reverse_each { opens << [
|
227
|
+
pending_heredocs.reverse_each { |t| opens << [t, nil] }
|
192
228
|
pending_heredocs = []
|
193
229
|
end
|
194
|
-
yield t,
|
230
|
+
yield t, opens if block_given?
|
195
231
|
end
|
196
232
|
opens.map(&:first) + pending_heredocs.reverse
|
197
233
|
end
|
@@ -201,7 +237,7 @@ module KatakataIrb::TRex
|
|
201
237
|
prev_opens = []
|
202
238
|
min_depth = 0
|
203
239
|
output = []
|
204
|
-
last_opens = parse(tokens) do |t,
|
240
|
+
last_opens = parse(tokens) do |t, opens|
|
205
241
|
depth = t == opens.last&.first ? opens.size - 1 : opens.size
|
206
242
|
min_depth = depth if depth < min_depth
|
207
243
|
if t.tok.include?("\n")
|