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
data/lib/katakata_irb/types.rb
CHANGED
@@ -11,10 +11,18 @@ module KatakataIrb::Types
|
|
11
11
|
|
12
12
|
Splat = Struct.new :item
|
13
13
|
|
14
|
+
MODULE_NAME_METHOD = Module.instance_method(:name)
|
15
|
+
|
16
|
+
def self.class_name_of(klass)
|
17
|
+
klass = klass.superclass if klass.singleton_class?
|
18
|
+
MODULE_NAME_METHOD.bind_call klass
|
19
|
+
end
|
20
|
+
|
14
21
|
def self.rbs_search_method(klass, method_name, singleton)
|
15
22
|
klass.ancestors.each do |ancestor|
|
16
|
-
|
17
|
-
|
23
|
+
name = class_name_of ancestor
|
24
|
+
next unless name
|
25
|
+
type_name = RBS::TypeName(name).absolute!
|
18
26
|
definition = (singleton ? rbs_builder.build_singleton(type_name) : rbs_builder.build_instance(type_name)) rescue nil
|
19
27
|
method = definition&.methods&.[](method_name)
|
20
28
|
return method if method
|
@@ -22,9 +30,29 @@ module KatakataIrb::Types
|
|
22
30
|
nil
|
23
31
|
end
|
24
32
|
|
33
|
+
def self.method_return_type(type, method_name)
|
34
|
+
receivers = type.types.map do |t|
|
35
|
+
case t
|
36
|
+
in ProcType
|
37
|
+
[t, Proc, false]
|
38
|
+
in SingletonType
|
39
|
+
[t, t.module_or_class, true]
|
40
|
+
in InstanceType
|
41
|
+
[t, t.klass, false]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
types = receivers.flat_map do |receiver_type, klass, singleton|
|
45
|
+
method = rbs_search_method klass, method_name, singleton
|
46
|
+
next [] unless method
|
47
|
+
method.method_types.map do |method|
|
48
|
+
from_rbs_type(method.type.return_type, receiver_type, {})
|
49
|
+
end
|
50
|
+
end
|
51
|
+
UnionType[*types]
|
52
|
+
end
|
53
|
+
|
25
54
|
def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block)
|
26
|
-
|
27
|
-
receivers = types.map do |t|
|
55
|
+
receivers = type.types.map do |t|
|
28
56
|
case t
|
29
57
|
in ProcType
|
30
58
|
[t, Proc, false]
|
@@ -60,8 +88,15 @@ module KatakataIrb::Types
|
|
60
88
|
given << UnionType[*centers.drop(opts.size)]
|
61
89
|
expected << rest.type
|
62
90
|
end
|
63
|
-
score += given.zip(expected).
|
64
|
-
|
91
|
+
score += given.zip(expected).sum do |t, e|
|
92
|
+
e = from_rbs_type e, receiver_type
|
93
|
+
if intersect? t, e
|
94
|
+
1
|
95
|
+
elsif (intersect?(STRING, e) && t.methods.include?(:to_str)) || (intersect?(INTEGER, e) && t.methods.include?(:to_int)) || (intersect?(ARRAY, e) && t.methods.include?(:to_ary))
|
96
|
+
0.5
|
97
|
+
else
|
98
|
+
0
|
99
|
+
end
|
65
100
|
end
|
66
101
|
end
|
67
102
|
[[method_type, given || [], expected || []], score]
|
@@ -83,14 +118,24 @@ module KatakataIrb::Types
|
|
83
118
|
intersect.call(InstanceType, &:klass)
|
84
119
|
end
|
85
120
|
|
86
|
-
def self.type_from_object(object
|
121
|
+
def self.type_from_object(object)
|
122
|
+
case object
|
123
|
+
when Array, Hash, Module
|
124
|
+
type_from_object_recursive(object, max_level: 4)
|
125
|
+
else
|
126
|
+
klass = object.singleton_class rescue object.class
|
127
|
+
InstanceType.new klass
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.type_from_object_recursive(object, max_level:)
|
87
132
|
max_level -= 1
|
88
133
|
sample_size = 1000
|
89
134
|
case object
|
90
135
|
when Array
|
91
136
|
values = object.size > sample_size ? object.sample(sample_size) : object
|
92
137
|
if max_level > 0
|
93
|
-
InstanceType.new Array, { Elem: UnionType[*values.map {
|
138
|
+
InstanceType.new Array, { Elem: UnionType[*values.map { type_from_object_recursive(_1, max_level: max_level) }] }
|
94
139
|
else
|
95
140
|
InstanceType.new Array, { Elem: UnionType[*values.map(&:class).uniq.map { InstanceType.new _1 }] }
|
96
141
|
end
|
@@ -98,8 +143,8 @@ module KatakataIrb::Types
|
|
98
143
|
keys = object.size > sample_size ? object.keys.sample(sample_size) : object.keys
|
99
144
|
values = object.size > sample_size ? object.values.sample(sample_size) : object.values
|
100
145
|
if max_level > 0
|
101
|
-
key_types = keys.map {
|
102
|
-
value_types = values.map {
|
146
|
+
key_types = keys.map { type_from_object_recursive(_1, max_level: max_level) }
|
147
|
+
value_types = values.map { type_from_object_recursive(_1, max_level: max_level) }
|
103
148
|
InstanceType.new Hash, { K: UnionType[*key_types], V: UnionType[*value_types] }
|
104
149
|
else
|
105
150
|
key_types = keys.map(&:class).uniq.map { InstanceType.new _1 }
|
@@ -120,9 +165,11 @@ module KatakataIrb::Types
|
|
120
165
|
end
|
121
166
|
def transform() = yield(self)
|
122
167
|
def methods() = @module_or_class.methods
|
123
|
-
def all_methods() = methods
|
168
|
+
def all_methods() = methods | Kernel.methods
|
124
169
|
def constants() = @module_or_class.constants
|
125
170
|
def types() = [self]
|
171
|
+
def nillable?() = false
|
172
|
+
def nonnillable() = self
|
126
173
|
end
|
127
174
|
|
128
175
|
class InstanceType
|
@@ -136,6 +183,8 @@ module KatakataIrb::Types
|
|
136
183
|
def all_methods() = @klass.instance_methods | @klass.private_instance_methods
|
137
184
|
def constants() = []
|
138
185
|
def types() = [self]
|
186
|
+
def nillable?() = (@klass == NilClass)
|
187
|
+
def nonnillable() = self
|
139
188
|
end
|
140
189
|
|
141
190
|
class ProcType
|
@@ -150,11 +199,13 @@ module KatakataIrb::Types
|
|
150
199
|
def all_methods() = Proc.instance_methods | Proc.private_instance_methods
|
151
200
|
def constants() = []
|
152
201
|
def types() = [self]
|
202
|
+
def nillable?() = (@klass == NilClass)
|
203
|
+
def nonnillable() = self
|
153
204
|
end
|
154
205
|
|
155
206
|
NIL = InstanceType.new NilClass
|
156
207
|
OBJECT = InstanceType.new Object
|
157
|
-
TRUE = InstanceType.new
|
208
|
+
TRUE = InstanceType.new TrueClass
|
158
209
|
FALSE = InstanceType.new FalseClass
|
159
210
|
SYMBOL = InstanceType.new Symbol
|
160
211
|
STRING = InstanceType.new String
|
@@ -203,6 +254,14 @@ module KatakataIrb::Types
|
|
203
254
|
UnionType[*types.map(&block)]
|
204
255
|
end
|
205
256
|
|
257
|
+
def nillable?
|
258
|
+
types.any?(&:nillable?)
|
259
|
+
end
|
260
|
+
|
261
|
+
def nonnillable
|
262
|
+
UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
|
263
|
+
end
|
264
|
+
|
206
265
|
def self.[](*types)
|
207
266
|
type = new(*types)
|
208
267
|
if type.types.empty?
|
@@ -219,6 +278,8 @@ module KatakataIrb::Types
|
|
219
278
|
def constants() = @types.flat_map(&:constants).uniq
|
220
279
|
end
|
221
280
|
|
281
|
+
BOOLEAN = UnionType[TRUE, FALSE]
|
282
|
+
|
222
283
|
def self.from_rbs_type(return_type, self_type, extra_vars = {})
|
223
284
|
case return_type
|
224
285
|
when RBS::Types::Bases::Self
|
@@ -238,7 +299,7 @@ module KatakataIrb::Types
|
|
238
299
|
end
|
239
300
|
UnionType[*types]
|
240
301
|
when RBS::Types::Bases::Bool
|
241
|
-
|
302
|
+
BOOLEAN
|
242
303
|
when RBS::Types::Bases::Instance
|
243
304
|
self_type.transform do |type|
|
244
305
|
case type
|
@@ -286,7 +347,7 @@ module KatakataIrb::Types
|
|
286
347
|
when :int
|
287
348
|
INTEGER
|
288
349
|
when :boolish
|
289
|
-
|
350
|
+
BOOLEAN
|
290
351
|
when :string
|
291
352
|
STRING
|
292
353
|
else
|
@@ -297,19 +358,13 @@ module KatakataIrb::Types
|
|
297
358
|
# unimplemented
|
298
359
|
OBJECT
|
299
360
|
when RBS::Types::ClassInstance
|
300
|
-
|
301
|
-
type.module_or_class if (type in SingletonType) && type.module_or_class.is_a?(Class)
|
302
|
-
end
|
303
|
-
if classes.empty?
|
304
|
-
klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
|
305
|
-
classes << klass if klass in Class
|
306
|
-
end
|
361
|
+
klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
|
307
362
|
if return_type.args
|
308
363
|
args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
|
309
364
|
names = rbs_builder.build_singleton(return_type.name).type_params
|
310
365
|
params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
|
311
366
|
end
|
312
|
-
|
367
|
+
InstanceType.new klass, params || {}
|
313
368
|
end
|
314
369
|
end
|
315
370
|
|
@@ -338,6 +393,25 @@ module KatakataIrb::Types
|
|
338
393
|
end
|
339
394
|
in [RBS::Types::Record, InstanceType] if value.klass == Hash
|
340
395
|
# TODO
|
396
|
+
in [RBS::Types::Interface,]
|
397
|
+
definition = rbs_builder.build_interface rbs_type.name
|
398
|
+
convert = {}
|
399
|
+
definition.type_params.zip(rbs_type.args).each do |from, arg|
|
400
|
+
convert[from] = arg.name if arg.is_a? RBS::Types::Variable
|
401
|
+
end
|
402
|
+
return if convert.empty?
|
403
|
+
ac = {}
|
404
|
+
definition.methods.each do |method_name, method|
|
405
|
+
return_type = method_return_type value, method_name
|
406
|
+
method.defs.each do |method_def|
|
407
|
+
interface_return_type = method_def.type.type.return_type
|
408
|
+
_match_free_variable convert, interface_return_type, return_type, ac
|
409
|
+
end
|
410
|
+
end
|
411
|
+
convert.each do |from, to|
|
412
|
+
values = ac[from]
|
413
|
+
(accumulator[to] ||= []).concat values if values
|
414
|
+
end
|
341
415
|
else
|
342
416
|
end
|
343
417
|
end
|
data/lib/katakata_irb/version.rb
CHANGED
data/lib/katakata_irb.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
def self.repl
|
4
|
-
require 'katakata_irb/completor'
|
5
|
-
KatakataIrb::Completor.setup
|
6
|
-
IRB.start(__FILE__)
|
7
|
-
end
|
1
|
+
require 'katakata_irb/version'
|
2
|
+
require 'katakata_irb/completor'
|
8
3
|
|
4
|
+
module KatakataIrb
|
9
5
|
def self.log_output=(output)
|
10
6
|
@log_output = output
|
11
7
|
end
|
@@ -14,3 +10,5 @@ module KatakataIrb
|
|
14
10
|
STDOUT.cooked { @log_output&.puts(...) }
|
15
11
|
end
|
16
12
|
end
|
13
|
+
|
14
|
+
KatakataIrb::Completor.setup
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: katakata_irb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tompng
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: irb
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.4.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rbs
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -27,8 +41,7 @@ dependencies:
|
|
27
41
|
description: IRB with Typed Completion
|
28
42
|
email:
|
29
43
|
- tomoyapenguin@gmail.com
|
30
|
-
executables:
|
31
|
-
- kirb
|
44
|
+
executables: []
|
32
45
|
extensions: []
|
33
46
|
extra_rdoc_files: []
|
34
47
|
files:
|
@@ -39,18 +52,11 @@ files:
|
|
39
52
|
- Rakefile
|
40
53
|
- bin/console
|
41
54
|
- bin/setup
|
42
|
-
- exe/kirb
|
43
55
|
- katakata_irb.gemspec
|
44
56
|
- lib/katakata_irb.rb
|
45
57
|
- lib/katakata_irb/completor.rb
|
46
|
-
- lib/katakata_irb/
|
47
|
-
- lib/katakata_irb/
|
48
|
-
- lib/katakata_irb/reline_patches/indent.patch
|
49
|
-
- lib/katakata_irb/reline_patches/raw.patch
|
50
|
-
- lib/katakata_irb/reline_patches/scrollbar.patch
|
51
|
-
- lib/katakata_irb/reline_patches/wholelines.patch
|
52
|
-
- lib/katakata_irb/ruby_lex_patch.rb
|
53
|
-
- lib/katakata_irb/trex.rb
|
58
|
+
- lib/katakata_irb/nesting_parser.rb
|
59
|
+
- lib/katakata_irb/scope.rb
|
54
60
|
- lib/katakata_irb/type_simulator.rb
|
55
61
|
- lib/katakata_irb/types.rb
|
56
62
|
- lib/katakata_irb/version.rb
|
@@ -69,14 +75,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
75
|
requirements:
|
70
76
|
- - ">="
|
71
77
|
- !ruby/object:Gem::Version
|
72
|
-
version: 3.
|
78
|
+
version: 3.0.0
|
73
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
80
|
requirements:
|
75
81
|
- - ">="
|
76
82
|
- !ruby/object:Gem::Version
|
77
83
|
version: '0'
|
78
84
|
requirements: []
|
79
|
-
rubygems_version: 3.4.
|
85
|
+
rubygems_version: 3.4.6
|
80
86
|
signing_key:
|
81
87
|
specification_version: 4
|
82
88
|
summary: IRB with Typed Completion
|
data/exe/kirb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require_relative '../lib/katakata_irb'
|
3
|
-
KatakataIrb.log_output = STDERR if ARGV.delete '--debug-output'
|
4
|
-
unless ARGV.delete '--without-patch'
|
5
|
-
require_relative '../lib/katakata_irb/reline_patch'
|
6
|
-
KatakataIrb::RelinePatch.require_patched_reline
|
7
|
-
require 'katakata_irb/ruby_lex_patch'
|
8
|
-
KatakataIrb::RubyLexPatch.patch_to_ruby_lex
|
9
|
-
end
|
10
|
-
require 'katakata_irb'
|
11
|
-
KatakataIrb.repl
|
@@ -1,43 +0,0 @@
|
|
1
|
-
module KatakataIrb; end
|
2
|
-
module KatakataIrb::RelinePatch
|
3
|
-
module RelinePatchIseqLoader; end
|
4
|
-
def self.require_patched_reline
|
5
|
-
# Apply patches of unmerged pull-request to reline
|
6
|
-
patches = %w[wholelines escapeseq indent raw scrollbar]
|
7
|
-
patched = {}
|
8
|
-
require 'reline/version.rb' # result of $LOAD_PATH.resolve_feature_path will change after this require
|
9
|
-
patches.each do |patch_name|
|
10
|
-
patch = File.read File.expand_path("reline_patches/#{patch_name}.patch", File.dirname(__FILE__))
|
11
|
-
current_patched = {}
|
12
|
-
patch.gsub(/^diff.+\nindex.+$/, '').split(/^--- a(.+)\n\+\+\+ b(.+)\n/).drop(1).each_slice(3) do |file, newfile, diff|
|
13
|
-
raise if file != newfile
|
14
|
-
_, path = $LOAD_PATH.resolve_feature_path file.sub(%r{^/lib/}, '')
|
15
|
-
code = current_patched[path] || patched[path] || File.read(path)
|
16
|
-
diff.split(/^@@.+\n/).drop(1).map(&:lines).each do |lines|
|
17
|
-
target = lines.reject { _1[0] == '+' }.map { _1[1..] }.join
|
18
|
-
replace = lines.reject { _1[0] == '-' }.map { _1[1..] }.join
|
19
|
-
if code.include? target
|
20
|
-
code = code.sub target, replace
|
21
|
-
elsif !code.include?(replace)
|
22
|
-
raise
|
23
|
-
end
|
24
|
-
end
|
25
|
-
current_patched[path] = code
|
26
|
-
end
|
27
|
-
patched.update current_patched
|
28
|
-
rescue
|
29
|
-
KatakataIrb.log_puts "Failed to apply katakata_irb/reline_patches/#{patch_name}.patch to reline"
|
30
|
-
end
|
31
|
-
|
32
|
-
RelinePatchIseqLoader.define_method :load_iseq do |fname|
|
33
|
-
if patched.key? fname
|
34
|
-
RubyVM::InstructionSequence.compile patched[fname], fname
|
35
|
-
else
|
36
|
-
RubyVM::InstructionSequence.compile_file fname
|
37
|
-
end
|
38
|
-
end
|
39
|
-
RubyVM::InstructionSequence.singleton_class.prepend RelinePatchIseqLoader
|
40
|
-
require 'reline'
|
41
|
-
RelinePatchIseqLoader.undef_method :load_iseq
|
42
|
-
end
|
43
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
|
2
|
-
index 1c33a4b..bbf5e6c 100644
|
3
|
-
--- a/lib/reline/line_editor.rb
|
4
|
-
+++ b/lib/reline/line_editor.rb
|
5
|
-
@@ -663,8 +663,10 @@ class Reline::LineEditor
|
6
|
-
dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
|
7
|
-
dialog_render_info = dialog.call(@last_key)
|
8
|
-
if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
|
9
|
-
+ lines = whole_lines
|
10
|
-
dialog.lines_backup = {
|
11
|
-
- lines: modify_lines(whole_lines),
|
12
|
-
+ unmodified_lines: lines,
|
13
|
-
+ lines: modify_lines(lines),
|
14
|
-
line_index: @line_index,
|
15
|
-
first_line_started_from: @first_line_started_from,
|
16
|
-
started_from: @started_from,
|
17
|
-
@@ -766,8 +768,10 @@ class Reline::LineEditor
|
18
|
-
Reline::IOGate.move_cursor_column(cursor_column)
|
19
|
-
move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
|
20
|
-
Reline::IOGate.show_cursor
|
21
|
-
+ lines = whole_lines
|
22
|
-
dialog.lines_backup = {
|
23
|
-
- lines: modify_lines(whole_lines),
|
24
|
-
+ unmodified_lines: lines,
|
25
|
-
+ lines: modify_lines(lines),
|
26
|
-
line_index: @line_index,
|
27
|
-
first_line_started_from: @first_line_started_from,
|
28
|
-
started_from: @started_from,
|
29
|
-
@@ -777,7 +781,7 @@ class Reline::LineEditor
|
30
|
-
private def reset_dialog(dialog, old_dialog)
|
31
|
-
return if dialog.lines_backup.nil? or old_dialog.contents.nil?
|
32
|
-
- prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
|
33
|
-
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:unmodified_lines])
|
34
|
-
visual_lines = []
|
35
|
-
visual_start = nil
|
36
|
-
dialog.lines_backup[:lines].each_with_index { |l, i|
|
37
|
-
@@ -888,7 +892,7 @@ class Reline::LineEditor
|
38
|
-
private def clear_each_dialog(dialog)
|
39
|
-
dialog.trap_key = nil
|
40
|
-
return unless dialog.contents
|
41
|
-
- prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
|
42
|
-
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:unmodified_lines])
|
43
|
-
visual_lines = []
|
44
|
-
visual_lines_under_dialog = []
|
45
|
-
visual_start = nil
|
@@ -1,25 +0,0 @@
|
|
1
|
-
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
|
2
|
-
index bbf5e6c..c9e613e 100644
|
3
|
-
--- a/lib/reline/line_editor.rb
|
4
|
-
+++ b/lib/reline/line_editor.rb
|
5
|
-
@@ -1707,17 +1707,18 @@ class Reline::LineEditor
|
6
|
-
end
|
7
|
-
new_lines = whole_lines
|
8
|
-
new_indent = @auto_indent_proc.(new_lines, @line_index, @byte_pointer, @check_new_auto_indent)
|
9
|
-
- new_indent = @cursor_max if new_indent&.> @cursor_max
|
10
|
-
if new_indent&.>= 0
|
11
|
-
md = new_lines[@line_index].match(/\A */)
|
12
|
-
prev_indent = md[0].count(' ')
|
13
|
-
if @check_new_auto_indent
|
14
|
-
- @buffer_of_lines[@line_index] = ' ' * new_indent + @buffer_of_lines[@line_index].lstrip
|
15
|
-
+ line = @buffer_of_lines[@line_index] = ' ' * new_indent + @buffer_of_lines[@line_index].lstrip
|
16
|
-
@cursor = new_indent
|
17
|
-
+ @cursor_max = calculate_width(line)
|
18
|
-
@byte_pointer = new_indent
|
19
|
-
else
|
20
|
-
@line = ' ' * new_indent + @line.lstrip
|
21
|
-
@cursor += new_indent - prev_indent
|
22
|
-
+ @cursor_max = calculate_width(@line)
|
23
|
-
@byte_pointer += new_indent - prev_indent
|
24
|
-
end
|
25
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
diff --git a/lib/reline.rb b/lib/reline.rb
|
2
|
-
index f22b573..8716a0c 100644
|
3
|
-
--- a/lib/reline.rb
|
4
|
-
+++ b/lib/reline.rb
|
5
|
-
@@ -281,19 +281,21 @@ module Reline
|
6
|
-
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
7
|
-
|
8
|
-
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
9
|
-
- unless confirm_multiline_termination
|
10
|
-
- raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
11
|
-
- end
|
12
|
-
- inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
13
|
-
+ Reline::IOGate.with_raw_input do
|
14
|
-
+ unless confirm_multiline_termination
|
15
|
-
+ raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
16
|
-
+ end
|
17
|
-
+ inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
18
|
-
|
19
|
-
- whole_buffer = line_editor.whole_buffer.dup
|
20
|
-
- whole_buffer.taint if RUBY_VERSION < '2.7'
|
21
|
-
- if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
|
22
|
-
- Reline::HISTORY << whole_buffer
|
23
|
-
- end
|
24
|
-
+ whole_buffer = line_editor.whole_buffer.dup
|
25
|
-
+ whole_buffer.taint if RUBY_VERSION < '2.7'
|
26
|
-
+ if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
|
27
|
-
+ Reline::HISTORY << whole_buffer
|
28
|
-
+ end
|
29
|
-
|
30
|
-
- line_editor.reset_line if line_editor.whole_buffer.nil?
|
31
|
-
- whole_buffer
|
32
|
-
+ line_editor.reset_line if line_editor.whole_buffer.nil?
|
33
|
-
+ whole_buffer
|
34
|
-
+ end
|
35
|
-
end
|
36
|
-
|
37
|
-
def readline(prompt = '', add_hist = false)
|
38
|
-
diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb
|
39
|
-
index ab147a6..ccebe15 100644
|
40
|
-
--- a/lib/reline/ansi.rb
|
41
|
-
+++ b/lib/reline/ansi.rb
|
42
|
-
@@ -142,6 +142,10 @@ class Reline::ANSI
|
43
|
-
@@output = val
|
44
|
-
end
|
45
|
-
|
46
|
-
+ def self.with_raw_input
|
47
|
-
+ @@input.raw { yield }
|
48
|
-
+ end
|
49
|
-
+
|
50
|
-
@@buf = []
|
51
|
-
def self.inner_getc
|
52
|
-
unless @@buf.empty?
|
53
|
-
diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb
|
54
|
-
index 92c76cb..9929846 100644
|
55
|
-
--- a/lib/reline/general_io.rb
|
56
|
-
+++ b/lib/reline/general_io.rb
|
57
|
-
@@ -31,6 +31,10 @@ class Reline::GeneralIO
|
58
|
-
@@input = val
|
59
|
-
end
|
60
|
-
|
61
|
-
+ def self.with_raw_input
|
62
|
-
+ yield
|
63
|
-
+ end
|
64
|
-
+
|
65
|
-
def self.getc
|
66
|
-
unless @@buf.empty?
|
67
|
-
return @@buf.shift
|
68
|
-
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
|
69
|
-
index 6acf969..e3985a3 100644
|
70
|
-
--- a/lib/reline/line_editor.rb
|
71
|
-
+++ b/lib/reline/line_editor.rb
|
72
|
-
@@ -452,7 +452,7 @@ class Reline::LineEditor
|
73
|
-
new_lines = whole_lines
|
74
|
-
prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
|
75
|
-
modify_lines(new_lines).each_with_index do |line, index|
|
76
|
-
- @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\n"
|
77
|
-
+ @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\r\n"
|
78
|
-
Reline::IOGate.erase_after_cursor
|
79
|
-
end
|
80
|
-
@output.flush
|
81
|
-
diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb
|
82
|
-
index b952329..7ea2a00 100644
|
83
|
-
--- a/lib/reline/windows.rb
|
84
|
-
+++ b/lib/reline/windows.rb
|
85
|
-
@@ -291,6 +291,10 @@ class Reline::Windows
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
+ def self.with_raw_input
|
90
|
-
+ yield
|
91
|
-
+ end
|
92
|
-
+
|
93
|
-
def self.getc
|
94
|
-
check_input_event
|
95
|
-
@@output_buf.shift
|
@@ -1,34 +0,0 @@
|
|
1
|
-
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
|
2
|
-
index 8153aab..50a063a 100644
|
3
|
-
--- a/lib/reline/line_editor.rb
|
4
|
-
+++ b/lib/reline/line_editor.rb
|
5
|
-
@@ -703,17 +703,17 @@ class Reline::LineEditor
|
6
|
-
dialog.scroll_top = dialog.pointer
|
7
|
-
end
|
8
|
-
pointer = dialog.pointer - dialog.scroll_top
|
9
|
-
+ else
|
10
|
-
+ dialog.scroll_top = 0
|
11
|
-
end
|
12
|
-
dialog.contents = dialog.contents[dialog.scroll_top, height]
|
13
|
-
end
|
14
|
-
- if dialog.contents and dialog.scroll_top >= dialog.contents.size
|
15
|
-
- dialog.scroll_top = dialog.contents.size - height
|
16
|
-
- end
|
17
|
-
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
18
|
-
bar_max_height = height * 2
|
19
|
-
moving_distance = (dialog_render_info.contents.size - height) * 2
|
20
|
-
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
|
21
|
-
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
|
22
|
-
+ bar_height = 1 if bar_height.zero?
|
23
|
-
dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
|
24
|
-
else
|
25
|
-
dialog.scrollbar_pos = nil
|
26
|
-
@@ -755,7 +755,7 @@ class Reline::LineEditor
|
27
|
-
str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
|
28
|
-
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
|
29
|
-
@output.write "\e[#{bg_color}m\e[#{fg_color}m#{str}"
|
30
|
-
- if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
|
31
|
-
+ if dialog.scrollbar_pos
|
32
|
-
@output.write "\e[37m"
|
33
|
-
if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
|
34
|
-
@output.write @full_block
|