reline 0.5.10 → 0.5.12
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/lib/reline/config.rb +22 -26
- data/lib/reline/history.rb +3 -3
- data/lib/reline/io/ansi.rb +31 -93
- data/lib/reline/io/dumb.rb +5 -2
- data/lib/reline/io/windows.rb +66 -59
- data/lib/reline/key_stroke.rb +19 -8
- data/lib/reline/line_editor.rb +163 -260
- data/lib/reline/unicode.rb +58 -68
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +6 -6
- metadata +3 -3
- data/lib/reline/terminfo.rb +0 -158
data/lib/reline/unicode.rb
CHANGED
@@ -54,6 +54,22 @@ class Reline::Unicode
|
|
54
54
|
}.join
|
55
55
|
end
|
56
56
|
|
57
|
+
def self.safe_encode(str, encoding)
|
58
|
+
# Reline only supports utf-8 convertible string.
|
59
|
+
converted = str.encode(encoding, invalid: :replace, undef: :replace)
|
60
|
+
return converted if str.encoding == Encoding::UTF_8 || converted.encoding == Encoding::UTF_8 || converted.ascii_only?
|
61
|
+
|
62
|
+
# This code is essentially doing the same thing as
|
63
|
+
# `str.encode(utf8, **replace_options).encode(encoding, **replace_options)`
|
64
|
+
# but also avoids unneccesary irreversible encoding conversion.
|
65
|
+
converted.gsub(/\X/) do |c|
|
66
|
+
c.encode(Encoding::UTF_8)
|
67
|
+
c
|
68
|
+
rescue Encoding::UndefinedConversionError
|
69
|
+
'?'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
57
73
|
require 'reline/unicode/east_asian_width'
|
58
74
|
|
59
75
|
def self.get_mbchar_width(mbchar)
|
@@ -105,9 +121,14 @@ class Reline::Unicode
|
|
105
121
|
end
|
106
122
|
end
|
107
123
|
|
108
|
-
|
124
|
+
# This method is used by IRB
|
125
|
+
def self.split_by_width(str, max_width)
|
126
|
+
lines = split_line_by_width(str, max_width)
|
127
|
+
[lines, lines.size]
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.split_line_by_width(str, max_width, encoding = str.encoding, offset: 0)
|
109
131
|
lines = [String.new(encoding: encoding)]
|
110
|
-
height = 1
|
111
132
|
width = offset
|
112
133
|
rest = str.encode(Encoding::UTF_8)
|
113
134
|
in_zero_width = false
|
@@ -116,10 +137,8 @@ class Reline::Unicode
|
|
116
137
|
case
|
117
138
|
when non_printing_start
|
118
139
|
in_zero_width = true
|
119
|
-
lines.last << NON_PRINTING_START
|
120
140
|
when non_printing_end
|
121
141
|
in_zero_width = false
|
122
|
-
lines.last << NON_PRINTING_END
|
123
142
|
when csi
|
124
143
|
lines.last << csi
|
125
144
|
unless in_zero_width
|
@@ -131,15 +150,13 @@ class Reline::Unicode
|
|
131
150
|
end
|
132
151
|
when osc
|
133
152
|
lines.last << osc
|
134
|
-
seq << osc
|
153
|
+
seq << osc unless in_zero_width
|
135
154
|
when gc
|
136
155
|
unless in_zero_width
|
137
156
|
mbchar_width = get_mbchar_width(gc)
|
138
157
|
if (width += mbchar_width) > max_width
|
139
158
|
width = mbchar_width
|
140
|
-
lines << nil
|
141
159
|
lines << seq.dup
|
142
|
-
height += 1
|
143
160
|
end
|
144
161
|
end
|
145
162
|
lines.last << gc
|
@@ -147,11 +164,13 @@ class Reline::Unicode
|
|
147
164
|
end
|
148
165
|
# The cursor moves to next line in first
|
149
166
|
if width == max_width
|
150
|
-
lines << nil
|
151
167
|
lines << String.new(encoding: encoding)
|
152
|
-
height += 1
|
153
168
|
end
|
154
|
-
|
169
|
+
lines
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.strip_non_printing_start_end(prompt)
|
173
|
+
prompt.gsub(/\x01([^\x02]*)(?:\x02|\z)/) { $1 }
|
155
174
|
end
|
156
175
|
|
157
176
|
# Take a chunk of a String cut by width with escape sequences.
|
@@ -173,10 +192,8 @@ class Reline::Unicode
|
|
173
192
|
case
|
174
193
|
when non_printing_start
|
175
194
|
in_zero_width = true
|
176
|
-
chunk << NON_PRINTING_START
|
177
195
|
when non_printing_end
|
178
196
|
in_zero_width = false
|
179
|
-
chunk << NON_PRINTING_END
|
180
197
|
when csi
|
181
198
|
has_csi = true
|
182
199
|
chunk << csi
|
@@ -245,27 +262,23 @@ class Reline::Unicode
|
|
245
262
|
end
|
246
263
|
|
247
264
|
def self.em_forward_word(line, byte_pointer)
|
248
|
-
width = 0
|
249
265
|
byte_size = 0
|
250
266
|
while line.bytesize > (byte_pointer + byte_size)
|
251
267
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
252
268
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
253
269
|
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
254
|
-
width += get_mbchar_width(mbchar)
|
255
270
|
byte_size += size
|
256
271
|
end
|
257
272
|
while line.bytesize > (byte_pointer + byte_size)
|
258
273
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
259
274
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
260
275
|
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
261
|
-
width += get_mbchar_width(mbchar)
|
262
276
|
byte_size += size
|
263
277
|
end
|
264
|
-
|
278
|
+
byte_size
|
265
279
|
end
|
266
280
|
|
267
281
|
def self.em_forward_word_with_capitalization(line, byte_pointer)
|
268
|
-
width = 0
|
269
282
|
byte_size = 0
|
270
283
|
new_str = String.new
|
271
284
|
while line.bytesize > (byte_pointer + byte_size)
|
@@ -273,7 +286,6 @@ class Reline::Unicode
|
|
273
286
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
274
287
|
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
275
288
|
new_str += mbchar
|
276
|
-
width += get_mbchar_width(mbchar)
|
277
289
|
byte_size += size
|
278
290
|
end
|
279
291
|
first = true
|
@@ -287,50 +299,43 @@ class Reline::Unicode
|
|
287
299
|
else
|
288
300
|
new_str += mbchar.downcase
|
289
301
|
end
|
290
|
-
width += get_mbchar_width(mbchar)
|
291
302
|
byte_size += size
|
292
303
|
end
|
293
|
-
[byte_size,
|
304
|
+
[byte_size, new_str]
|
294
305
|
end
|
295
306
|
|
296
307
|
def self.em_backward_word(line, byte_pointer)
|
297
|
-
width = 0
|
298
308
|
byte_size = 0
|
299
309
|
while 0 < (byte_pointer - byte_size)
|
300
310
|
size = get_prev_mbchar_size(line, byte_pointer - byte_size)
|
301
311
|
mbchar = line.byteslice(byte_pointer - byte_size - size, size)
|
302
312
|
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
303
|
-
width += get_mbchar_width(mbchar)
|
304
313
|
byte_size += size
|
305
314
|
end
|
306
315
|
while 0 < (byte_pointer - byte_size)
|
307
316
|
size = get_prev_mbchar_size(line, byte_pointer - byte_size)
|
308
317
|
mbchar = line.byteslice(byte_pointer - byte_size - size, size)
|
309
318
|
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
310
|
-
width += get_mbchar_width(mbchar)
|
311
319
|
byte_size += size
|
312
320
|
end
|
313
|
-
|
321
|
+
byte_size
|
314
322
|
end
|
315
323
|
|
316
324
|
def self.em_big_backward_word(line, byte_pointer)
|
317
|
-
width = 0
|
318
325
|
byte_size = 0
|
319
326
|
while 0 < (byte_pointer - byte_size)
|
320
327
|
size = get_prev_mbchar_size(line, byte_pointer - byte_size)
|
321
328
|
mbchar = line.byteslice(byte_pointer - byte_size - size, size)
|
322
329
|
break if mbchar =~ /\S/
|
323
|
-
width += get_mbchar_width(mbchar)
|
324
330
|
byte_size += size
|
325
331
|
end
|
326
332
|
while 0 < (byte_pointer - byte_size)
|
327
333
|
size = get_prev_mbchar_size(line, byte_pointer - byte_size)
|
328
334
|
mbchar = line.byteslice(byte_pointer - byte_size - size, size)
|
329
335
|
break if mbchar =~ /\s/
|
330
|
-
width += get_mbchar_width(mbchar)
|
331
336
|
byte_size += size
|
332
337
|
end
|
333
|
-
|
338
|
+
byte_size
|
334
339
|
end
|
335
340
|
|
336
341
|
def self.ed_transpose_words(line, byte_pointer)
|
@@ -435,73 +440,61 @@ class Reline::Unicode
|
|
435
440
|
end
|
436
441
|
|
437
442
|
def self.vi_big_forward_word(line, byte_pointer)
|
438
|
-
width = 0
|
439
443
|
byte_size = 0
|
440
444
|
while (line.bytesize - 1) > (byte_pointer + byte_size)
|
441
445
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
442
446
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
443
447
|
break if mbchar =~ /\s/
|
444
|
-
width += get_mbchar_width(mbchar)
|
445
448
|
byte_size += size
|
446
449
|
end
|
447
450
|
while (line.bytesize - 1) > (byte_pointer + byte_size)
|
448
451
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
449
452
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
450
453
|
break if mbchar =~ /\S/
|
451
|
-
width += get_mbchar_width(mbchar)
|
452
454
|
byte_size += size
|
453
455
|
end
|
454
|
-
|
456
|
+
byte_size
|
455
457
|
end
|
456
458
|
|
457
459
|
def self.vi_big_forward_end_word(line, byte_pointer)
|
458
460
|
if (line.bytesize - 1) > byte_pointer
|
459
461
|
size = get_next_mbchar_size(line, byte_pointer)
|
460
|
-
mbchar = line.byteslice(byte_pointer, size)
|
461
|
-
width = get_mbchar_width(mbchar)
|
462
462
|
byte_size = size
|
463
463
|
else
|
464
|
-
return
|
464
|
+
return 0
|
465
465
|
end
|
466
466
|
while (line.bytesize - 1) > (byte_pointer + byte_size)
|
467
467
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
468
468
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
469
469
|
break if mbchar =~ /\S/
|
470
|
-
width += get_mbchar_width(mbchar)
|
471
470
|
byte_size += size
|
472
471
|
end
|
473
|
-
prev_width = width
|
474
472
|
prev_byte_size = byte_size
|
475
473
|
while line.bytesize > (byte_pointer + byte_size)
|
476
474
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
477
475
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
478
476
|
break if mbchar =~ /\s/
|
479
|
-
prev_width = width
|
480
477
|
prev_byte_size = byte_size
|
481
|
-
width += get_mbchar_width(mbchar)
|
482
478
|
byte_size += size
|
483
479
|
end
|
484
|
-
|
480
|
+
prev_byte_size
|
485
481
|
end
|
486
482
|
|
487
483
|
def self.vi_big_backward_word(line, byte_pointer)
|
488
|
-
width = 0
|
489
484
|
byte_size = 0
|
490
485
|
while 0 < (byte_pointer - byte_size)
|
491
486
|
size = get_prev_mbchar_size(line, byte_pointer - byte_size)
|
492
487
|
mbchar = line.byteslice(byte_pointer - byte_size - size, size)
|
493
488
|
break if mbchar =~ /\S/
|
494
|
-
width += get_mbchar_width(mbchar)
|
495
489
|
byte_size += size
|
496
490
|
end
|
497
491
|
while 0 < (byte_pointer - byte_size)
|
498
492
|
size = get_prev_mbchar_size(line, byte_pointer - byte_size)
|
499
493
|
mbchar = line.byteslice(byte_pointer - byte_size - size, size)
|
500
494
|
break if mbchar =~ /\s/
|
501
|
-
width += get_mbchar_width(mbchar)
|
502
495
|
byte_size += size
|
503
496
|
end
|
504
|
-
|
497
|
+
byte_size
|
505
498
|
end
|
506
499
|
|
507
500
|
def self.vi_forward_word(line, byte_pointer, drop_terminate_spaces = false)
|
@@ -515,10 +508,9 @@ class Reline::Unicode
|
|
515
508
|
else
|
516
509
|
started_by = :non_word_printable
|
517
510
|
end
|
518
|
-
width = get_mbchar_width(mbchar)
|
519
511
|
byte_size = size
|
520
512
|
else
|
521
|
-
return
|
513
|
+
return 0
|
522
514
|
end
|
523
515
|
while line.bytesize > (byte_pointer + byte_size)
|
524
516
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
@@ -531,18 +523,16 @@ class Reline::Unicode
|
|
531
523
|
when :non_word_printable
|
532
524
|
break if mbchar =~ /\w|\s/
|
533
525
|
end
|
534
|
-
width += get_mbchar_width(mbchar)
|
535
526
|
byte_size += size
|
536
527
|
end
|
537
|
-
return
|
528
|
+
return byte_size if drop_terminate_spaces
|
538
529
|
while line.bytesize > (byte_pointer + byte_size)
|
539
530
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
540
531
|
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
541
532
|
break if mbchar =~ /\S/
|
542
|
-
width += get_mbchar_width(mbchar)
|
543
533
|
byte_size += size
|
544
534
|
end
|
545
|
-
|
535
|
+
byte_size
|
546
536
|
end
|
547
537
|
|
548
538
|
def self.vi_forward_end_word(line, byte_pointer)
|
@@ -556,10 +546,9 @@ class Reline::Unicode
|
|
556
546
|
else
|
557
547
|
started_by = :non_word_printable
|
558
548
|
end
|
559
|
-
width = get_mbchar_width(mbchar)
|
560
549
|
byte_size = size
|
561
550
|
else
|
562
|
-
return
|
551
|
+
return 0
|
563
552
|
end
|
564
553
|
if (line.bytesize - 1) > (byte_pointer + byte_size)
|
565
554
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
@@ -571,13 +560,11 @@ class Reline::Unicode
|
|
571
560
|
else
|
572
561
|
second = :non_word_printable
|
573
562
|
end
|
574
|
-
second_width = get_mbchar_width(mbchar)
|
575
563
|
second_byte_size = size
|
576
564
|
else
|
577
|
-
return
|
565
|
+
return byte_size
|
578
566
|
end
|
579
567
|
if second == :space
|
580
|
-
width += second_width
|
581
568
|
byte_size += second_byte_size
|
582
569
|
while (line.bytesize - 1) > (byte_pointer + byte_size)
|
583
570
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
@@ -590,7 +577,6 @@ class Reline::Unicode
|
|
590
577
|
end
|
591
578
|
break
|
592
579
|
end
|
593
|
-
width += get_mbchar_width(mbchar)
|
594
580
|
byte_size += size
|
595
581
|
end
|
596
582
|
else
|
@@ -598,12 +584,10 @@ class Reline::Unicode
|
|
598
584
|
when [:word, :non_word_printable], [:non_word_printable, :word]
|
599
585
|
started_by = second
|
600
586
|
else
|
601
|
-
width += second_width
|
602
587
|
byte_size += second_byte_size
|
603
588
|
started_by = second
|
604
589
|
end
|
605
590
|
end
|
606
|
-
prev_width = width
|
607
591
|
prev_byte_size = byte_size
|
608
592
|
while line.bytesize > (byte_pointer + byte_size)
|
609
593
|
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
@@ -614,16 +598,13 @@ class Reline::Unicode
|
|
614
598
|
when :non_word_printable
|
615
599
|
break if mbchar =~ /[\w\s]/
|
616
600
|
end
|
617
|
-
prev_width = width
|
618
601
|
prev_byte_size = byte_size
|
619
|
-
width += get_mbchar_width(mbchar)
|
620
602
|
byte_size += size
|
621
603
|
end
|
622
|
-
|
604
|
+
prev_byte_size
|
623
605
|
end
|
624
606
|
|
625
607
|
def self.vi_backward_word(line, byte_pointer)
|
626
|
-
width = 0
|
627
608
|
byte_size = 0
|
628
609
|
while 0 < (byte_pointer - byte_size)
|
629
610
|
size = get_prev_mbchar_size(line, byte_pointer - byte_size)
|
@@ -636,7 +617,6 @@ class Reline::Unicode
|
|
636
617
|
end
|
637
618
|
break
|
638
619
|
end
|
639
|
-
width += get_mbchar_width(mbchar)
|
640
620
|
byte_size += size
|
641
621
|
end
|
642
622
|
while 0 < (byte_pointer - byte_size)
|
@@ -648,14 +628,25 @@ class Reline::Unicode
|
|
648
628
|
when :non_word_printable
|
649
629
|
break if mbchar =~ /[\w\s]/
|
650
630
|
end
|
651
|
-
width += get_mbchar_width(mbchar)
|
652
631
|
byte_size += size
|
653
632
|
end
|
654
|
-
|
633
|
+
byte_size
|
634
|
+
end
|
635
|
+
|
636
|
+
def self.common_prefix(list, ignore_case: false)
|
637
|
+
return '' if list.empty?
|
638
|
+
|
639
|
+
common_prefix_gcs = list.first.grapheme_clusters
|
640
|
+
list.each do |item|
|
641
|
+
gcs = item.grapheme_clusters
|
642
|
+
common_prefix_gcs = common_prefix_gcs.take_while.with_index do |gc, i|
|
643
|
+
ignore_case ? gc.casecmp?(gcs[i]) : gc == gcs[i]
|
644
|
+
end
|
645
|
+
end
|
646
|
+
common_prefix_gcs.join
|
655
647
|
end
|
656
648
|
|
657
649
|
def self.vi_first_print(line)
|
658
|
-
width = 0
|
659
650
|
byte_size = 0
|
660
651
|
while (line.bytesize - 1) > byte_size
|
661
652
|
size = get_next_mbchar_size(line, byte_size)
|
@@ -663,9 +654,8 @@ class Reline::Unicode
|
|
663
654
|
if mbchar =~ /\S/
|
664
655
|
break
|
665
656
|
end
|
666
|
-
width += get_mbchar_width(mbchar)
|
667
657
|
byte_size += size
|
668
658
|
end
|
669
|
-
|
659
|
+
byte_size
|
670
660
|
end
|
671
661
|
end
|
data/lib/reline/version.rb
CHANGED
data/lib/reline.rb
CHANGED
@@ -6,7 +6,6 @@ require 'reline/key_actor'
|
|
6
6
|
require 'reline/key_stroke'
|
7
7
|
require 'reline/line_editor'
|
8
8
|
require 'reline/history'
|
9
|
-
require 'reline/terminfo'
|
10
9
|
require 'reline/io'
|
11
10
|
require 'reline/face'
|
12
11
|
require 'rbconfig'
|
@@ -308,7 +307,8 @@ module Reline
|
|
308
307
|
otio = io_gate.prep
|
309
308
|
|
310
309
|
may_req_ambiguous_char_width
|
311
|
-
|
310
|
+
key_stroke.encoding = encoding
|
311
|
+
line_editor.reset(prompt)
|
312
312
|
if multiline
|
313
313
|
line_editor.multiline_on
|
314
314
|
if block_given?
|
@@ -412,7 +412,7 @@ module Reline
|
|
412
412
|
end
|
413
413
|
|
414
414
|
private def may_req_ambiguous_char_width
|
415
|
-
@ambiguous_width =
|
415
|
+
@ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
|
416
416
|
return if defined? @ambiguous_width
|
417
417
|
io_gate.move_cursor_column(0)
|
418
418
|
begin
|
@@ -421,7 +421,7 @@ module Reline
|
|
421
421
|
# LANG=C
|
422
422
|
@ambiguous_width = 1
|
423
423
|
else
|
424
|
-
@ambiguous_width = io_gate.cursor_pos.x
|
424
|
+
@ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
|
425
425
|
end
|
426
426
|
io_gate.move_cursor_column(0)
|
427
427
|
io_gate.erase_after_cursor
|
@@ -486,8 +486,8 @@ module Reline
|
|
486
486
|
def self.core
|
487
487
|
@core ||= Core.new { |core|
|
488
488
|
core.config = Reline::Config.new
|
489
|
-
core.key_stroke = Reline::KeyStroke.new(core.config)
|
490
|
-
core.line_editor = Reline::LineEditor.new(core.config
|
489
|
+
core.key_stroke = Reline::KeyStroke.new(core.config, core.encoding)
|
490
|
+
core.line_editor = Reline::LineEditor.new(core.config)
|
491
491
|
|
492
492
|
core.basic_word_break_characters = " \t\n`><=;|&{("
|
493
493
|
core.completer_word_break_characters = " \t\n`><=;|&{("
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.12
|
5
5
|
platform: ruby
|
6
|
+
original_platform: ''
|
6
7
|
authors:
|
7
8
|
- aycabta
|
8
9
|
bindir: bin
|
9
10
|
cert_chain: []
|
10
|
-
date: 2024-
|
11
|
+
date: 2024-11-28 00:00:00.000000000 Z
|
11
12
|
dependencies:
|
12
13
|
- !ruby/object:Gem::Dependency
|
13
14
|
name: io-console
|
@@ -50,7 +51,6 @@ files:
|
|
50
51
|
- lib/reline/key_stroke.rb
|
51
52
|
- lib/reline/kill_ring.rb
|
52
53
|
- lib/reline/line_editor.rb
|
53
|
-
- lib/reline/terminfo.rb
|
54
54
|
- lib/reline/unicode.rb
|
55
55
|
- lib/reline/unicode/east_asian_width.rb
|
56
56
|
- lib/reline/version.rb
|
data/lib/reline/terminfo.rb
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
# Ignore warning `Add fiddle to your Gemfile or gemspec` in Ruby 3.4.
|
3
|
-
# terminfo.rb and ansi.rb supports fiddle unavailable environment.
|
4
|
-
verbose, $VERBOSE = $VERBOSE, nil
|
5
|
-
require 'fiddle'
|
6
|
-
require 'fiddle/import'
|
7
|
-
rescue LoadError
|
8
|
-
module Reline::Terminfo
|
9
|
-
def self.curses_dl
|
10
|
-
false
|
11
|
-
end
|
12
|
-
end
|
13
|
-
ensure
|
14
|
-
$VERBOSE = verbose
|
15
|
-
end
|
16
|
-
|
17
|
-
module Reline::Terminfo
|
18
|
-
extend Fiddle::Importer
|
19
|
-
|
20
|
-
class TerminfoError < StandardError; end
|
21
|
-
|
22
|
-
def self.curses_dl_files
|
23
|
-
case RUBY_PLATFORM
|
24
|
-
when /mingw/, /mswin/
|
25
|
-
# aren't supported
|
26
|
-
[]
|
27
|
-
when /cygwin/
|
28
|
-
%w[cygncursesw-10.dll cygncurses-10.dll]
|
29
|
-
when /darwin/
|
30
|
-
%w[libncursesw.dylib libcursesw.dylib libncurses.dylib libcurses.dylib]
|
31
|
-
else
|
32
|
-
%w[libncursesw.so libcursesw.so libncurses.so libcurses.so]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
@curses_dl = false
|
37
|
-
def self.curses_dl
|
38
|
-
return @curses_dl unless @curses_dl == false
|
39
|
-
if Fiddle.const_defined?(:TYPE_VARIADIC)
|
40
|
-
curses_dl_files.each do |curses_name|
|
41
|
-
result = Fiddle::Handle.new(curses_name)
|
42
|
-
rescue Fiddle::DLError
|
43
|
-
next
|
44
|
-
else
|
45
|
-
@curses_dl = result
|
46
|
-
break
|
47
|
-
end
|
48
|
-
end
|
49
|
-
@curses_dl = nil if @curses_dl == false
|
50
|
-
@curses_dl
|
51
|
-
end
|
52
|
-
end if not Reline.const_defined?(:Terminfo) or not Reline::Terminfo.respond_to?(:curses_dl)
|
53
|
-
|
54
|
-
module Reline::Terminfo
|
55
|
-
dlload curses_dl
|
56
|
-
#extern 'int setupterm(char *term, int fildes, int *errret)'
|
57
|
-
@setupterm = Fiddle::Function.new(curses_dl['setupterm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
58
|
-
#extern 'char *tigetstr(char *capname)'
|
59
|
-
@tigetstr = Fiddle::Function.new(curses_dl['tigetstr'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
|
60
|
-
begin
|
61
|
-
#extern 'char *tiparm(const char *str, ...)'
|
62
|
-
@tiparm = Fiddle::Function.new(curses_dl['tiparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)
|
63
|
-
rescue Fiddle::DLError
|
64
|
-
# OpenBSD lacks tiparm
|
65
|
-
#extern 'char *tparm(const char *str, ...)'
|
66
|
-
@tiparm = Fiddle::Function.new(curses_dl['tparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)
|
67
|
-
end
|
68
|
-
begin
|
69
|
-
#extern 'int tigetflag(char *str)'
|
70
|
-
@tigetflag = Fiddle::Function.new(curses_dl['tigetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
71
|
-
rescue Fiddle::DLError
|
72
|
-
# OpenBSD lacks tigetflag
|
73
|
-
#extern 'int tgetflag(char *str)'
|
74
|
-
@tigetflag = Fiddle::Function.new(curses_dl['tgetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
75
|
-
end
|
76
|
-
begin
|
77
|
-
#extern 'int tigetnum(char *str)'
|
78
|
-
@tigetnum = Fiddle::Function.new(curses_dl['tigetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
79
|
-
rescue Fiddle::DLError
|
80
|
-
# OpenBSD lacks tigetnum
|
81
|
-
#extern 'int tgetnum(char *str)'
|
82
|
-
@tigetnum = Fiddle::Function.new(curses_dl['tgetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
83
|
-
end
|
84
|
-
|
85
|
-
def self.setupterm(term, fildes)
|
86
|
-
errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
87
|
-
ret = @setupterm.(term, fildes, errret_int)
|
88
|
-
case ret
|
89
|
-
when 0 # OK
|
90
|
-
@term_supported = true
|
91
|
-
when -1 # ERR
|
92
|
-
@term_supported = false
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
class StringWithTiparm < String
|
97
|
-
def tiparm(*args) # for method chain
|
98
|
-
Reline::Terminfo.tiparm(self, *args)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.tigetstr(capname)
|
103
|
-
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
104
|
-
capability = @tigetstr.(capname)
|
105
|
-
case capability.to_i
|
106
|
-
when 0, -1
|
107
|
-
raise TerminfoError, "can't find capability: #{capname}"
|
108
|
-
end
|
109
|
-
StringWithTiparm.new(capability.to_s)
|
110
|
-
end
|
111
|
-
|
112
|
-
def self.tiparm(str, *args)
|
113
|
-
new_args = []
|
114
|
-
args.each do |a|
|
115
|
-
new_args << Fiddle::TYPE_INT << a
|
116
|
-
end
|
117
|
-
@tiparm.(str, *new_args).to_s
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.tigetflag(capname)
|
121
|
-
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
122
|
-
flag = @tigetflag.(capname).to_i
|
123
|
-
case flag
|
124
|
-
when -1
|
125
|
-
raise TerminfoError, "not boolean capability: #{capname}"
|
126
|
-
when 0
|
127
|
-
raise TerminfoError, "can't find capability: #{capname}"
|
128
|
-
end
|
129
|
-
flag
|
130
|
-
end
|
131
|
-
|
132
|
-
def self.tigetnum(capname)
|
133
|
-
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
134
|
-
num = @tigetnum.(capname).to_i
|
135
|
-
case num
|
136
|
-
when -2
|
137
|
-
raise TerminfoError, "not numeric capability: #{capname}"
|
138
|
-
when -1
|
139
|
-
raise TerminfoError, "can't find capability: #{capname}"
|
140
|
-
end
|
141
|
-
num
|
142
|
-
end
|
143
|
-
|
144
|
-
# NOTE: This means Fiddle and curses are enabled.
|
145
|
-
def self.enabled?
|
146
|
-
true
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.term_supported?
|
150
|
-
@term_supported
|
151
|
-
end
|
152
|
-
end if Reline::Terminfo.curses_dl
|
153
|
-
|
154
|
-
module Reline::Terminfo
|
155
|
-
def self.enabled?
|
156
|
-
false
|
157
|
-
end
|
158
|
-
end unless Reline::Terminfo.curses_dl
|