katakata_irb 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,216 +0,0 @@
1
- require 'irb'
2
- require_relative 'trex'
3
-
4
- module KatakataIrb::RubyLexPatch
5
- def self.patch_to_ruby_lex
6
- (RubyLex.instance_methods(false) - [:set_prompt, :process_continue, :check_code_block]).each { RubyLex.remove_method _1 }
7
- RubyLex.prepend self
8
- end
9
-
10
- def self.complete_tokens(code, context: nil)
11
- incomplete_tokens = RubyLex.ripper_lex_without_warning(code, context: context)
12
- KatakataIrb::TRex.interpolate_ripper_ignored_tokens(code, incomplete_tokens)
13
- end
14
-
15
- def calc_nesting_depth(opens)
16
- indent_level = 0
17
- nesting_level = 0
18
- opens.each_with_index do |t, index|
19
- case t.event
20
- when :on_heredoc_beg
21
- if opens[index + 1]&.event != :on_heredoc_beg
22
- if t.tok.start_with?('<<~')
23
- indent_level += 1
24
- else
25
- indent_level = 0
26
- end
27
- end
28
- when :on_tstring_beg, :on_regexp_beg, :on_symbeg
29
- indent_level += 1 if t.tok[0] == '%'
30
- when :on_embdoc_beg
31
- indent_level = 0
32
- else
33
- nesting_level += 1
34
- indent_level += 1
35
- end
36
- end
37
- [indent_level, nesting_level]
38
- end
39
-
40
- def process_indent_level(tokens)
41
- opens = KatakataIrb::TRex.parse(tokens)
42
- indent, _nesting = calc_nesting_depth(opens)
43
- indent * 2
44
- end
45
-
46
- def check_corresponding_token_depth(tokens, line_index)
47
- line_results = KatakataIrb::TRex.parse_line(tokens)
48
- result = line_results[line_index]
49
- return unless result
50
- _tokens, prev, opens, min_depth = result
51
- depth, = calc_nesting_depth(opens.take(min_depth))
52
- prev_depth, = calc_nesting_depth(prev)
53
- depth * 2 if depth < prev_depth
54
- end
55
-
56
- def ltype_from_open_tokens(opens)
57
- return nil if opens.empty?
58
- case opens.last.tok
59
- when ?`, /^<<[-~]?`/, /^%x.$/
60
- ?`
61
- when ?', /^<<[-~]?'/, /^%q.$/
62
- ?'
63
- when ?", /^<</, /^%.$/, /^%Q.$/
64
- ?"
65
- when ":'", ':"', ':', /^%s.$/
66
- ':'
67
- when /^%[iwIW].$/
68
- ']'
69
- when '/', /^%r.$/
70
- '/'
71
- end
72
- end
73
-
74
- def check_termination_in_prev_line(code, context: nil)
75
- tokens = self.class.ripper_lex_without_warning(code, context: context)
76
- last_newline_index = tokens.rindex { |t| t.tok.include?("\n") }
77
- index = (0...last_newline_index).reverse_each.find { |i| tokens[i].tok.include?("\n") }
78
- return false unless index
79
-
80
- last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
81
- first_token = last_line_tokens.find do |t|
82
- ![:on_sp, :on_ignored_sp, :on_comment].include?(t.event)
83
- end
84
-
85
- if first_token && first_token.state != Ripper::EXPR_DOT
86
- tokens_without_last_line = tokens[0..index]
87
- if check_termination(tokens_without_last_line)
88
- return last_line_tokens.map(&:tok).join
89
- end
90
- end
91
- false
92
- end
93
-
94
- def check_termination(tokens)
95
- opens = KatakataIrb::TRex.parse(tokens)
96
- opens.empty? && !process_continue(tokens)
97
- end
98
-
99
- def set_input(io, p = nil, context: nil, &block)
100
- @io = io
101
- if @io.respond_to?(:check_termination)
102
- @io.check_termination do |code|
103
- if Reline::IOGate.in_pasting?
104
- lex = RubyLex.new
105
- rest = lex.check_termination_in_prev_line(code, context: context)
106
- if rest
107
- Reline.delete_text
108
- rest.bytes.reverse_each do |c|
109
- Reline.ungetc(c)
110
- end
111
- true
112
- else
113
- false
114
- end
115
- else
116
- tokens = KatakataIrb::RubyLexPatch.complete_tokens(code, context: context)
117
- check_termination(tokens)
118
- end
119
- end
120
- end
121
- if @io.respond_to?(:dynamic_prompt)
122
- @io.dynamic_prompt do |lines|
123
- lines << '' if lines.empty?
124
- code = lines.map{ |l| l + "\n" }.join
125
- tokens = KatakataIrb::RubyLexPatch.complete_tokens code, context: context
126
- line_results = KatakataIrb::TRex.parse_line(tokens)
127
- continue = false
128
- tokens_until_line = []
129
- line_results.map.with_index do |(line_tokens, _prev_opens, next_opens), line_num_offset|
130
- line_tokens.each do |token, _s|
131
- tokens_until_line << token if token != tokens_until_line.last
132
- end
133
- unless (c = process_continue(tokens_until_line)).nil?
134
- continue = c
135
- end
136
- prompt next_opens, continue, line_num_offset
137
- end
138
- end
139
- end
140
-
141
- if p.respond_to?(:call)
142
- @input = p
143
- elsif block_given?
144
- @input = block
145
- else
146
- @input = Proc.new{@io.gets}
147
- end
148
- end
149
-
150
- def set_auto_indent(context)
151
- if @io.respond_to?(:auto_indent) and context.auto_indent_mode
152
- @io.auto_indent do |lines, line_index, byte_pointer, is_newline|
153
- if is_newline
154
- tokens = KatakataIrb::RubyLexPatch.complete_tokens(lines[0..line_index].join("\n"), context: context)
155
- process_indent_level tokens
156
- else
157
- code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
158
- last_line = lines[line_index]&.byteslice(0, byte_pointer)
159
- code += last_line if last_line
160
- tokens = KatakataIrb::RubyLexPatch.complete_tokens(code, context: context)
161
- check_corresponding_token_depth(tokens, line_index)
162
- end
163
- end
164
- end
165
- end
166
-
167
- def prompt(opens, continue, line_num_offset)
168
- ltype = ltype_from_open_tokens(opens)
169
- _indent, nesting_level = calc_nesting_depth(opens)
170
- @prompt.call(ltype, nesting_level, opens.any? || continue, @line_no + line_num_offset)
171
- end
172
-
173
- def store_prompt_to_irb(...)
174
- prompt(...) # TODO: do not use this. change the api. example: @input.call(prompt)
175
- end
176
-
177
- def readmultiline(context)
178
- if @io.respond_to? :check_termination
179
- store_prompt_to_irb [], false, 0
180
- @input.call
181
- else
182
- # nomultiline
183
- line = ''
184
- line_offset = 0
185
- store_prompt_to_irb [], false, 0
186
- loop do
187
- l = @input.call
188
- unless l
189
- return if line.empty?
190
- next
191
- end
192
- line << l
193
- tokens = KatakataIrb::RubyLexPatch.complete_tokens(line, context: context)
194
- _line_tokens, _prev_opens, next_opens = KatakataIrb::TRex.parse_line(tokens).last
195
- return line if next_opens.empty?
196
- line_offset += 1
197
- store_prompt_to_irb next_opens, true, line_offset
198
- end
199
- end
200
- end
201
-
202
- def each_top_level_statement(context = nil)
203
- loop do
204
- begin
205
- line = readmultiline(context)
206
- break unless line
207
- if line != "\n"
208
- line.force_encoding(@io.encoding)
209
- yield line, @line_no
210
- end
211
- @line_no += line.count("\n")
212
- rescue RubyLex::TerminateLineInput
213
- end
214
- end
215
- end
216
- end