textbringer 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b83487edc5f542afe9444b4393375aedd1ea82b4893997b17c6c4a33a3a4d76
4
- data.tar.gz: 60b6f47109aad0c55ed9832b97a8a54a65ad7cf7cac95341a20b2f01ba23234d
3
+ metadata.gz: 9641c360dd5bb038429536d85e666ff3518e37413eeece13898fa1a730665193
4
+ data.tar.gz: e2e9f71f90e060e30aac0bfa273fe65349eacc633f83c7c6dda034aa160436c6
5
5
  SHA512:
6
- metadata.gz: 17399f8a6297f0b77cd03cdac6c24c64b6e6da82dc596b6e5bdfa7ba807cdcb8c9e32d12e376b219941ee14a2ef4a60e63bab9e2a07723a107b5e01b259eb034
7
- data.tar.gz: 27b5e0e6011257b5beafc563b439944a72c7018cd058060bde55618369a55ec2c6596840f0de661a075f361485f5f27e76d908c6b04360f1342986a48b78797d
6
+ metadata.gz: 285df14ab50ac3b27e5c61a3c24503c7ce724b84a918072ada9e920c323f94c46564b329a3217950bddeee5e1c4b5e83f426ad577bb8cb6596004c2b374fd12d
7
+ data.tar.gz: 6ed66854359cdd89310f77cb79c2b14cdafe4b5c7636aee662c7d1a4103563388e183bf11b5b7aab45fd691b70fa16c5d33f66231f109c6a733d05c98f1087e2
@@ -5,6 +5,7 @@ on: [push]
5
5
  jobs:
6
6
  build:
7
7
  runs-on: macos-latest
8
+ timeout-minutes: 10
8
9
  steps:
9
10
  - uses: actions/checkout@master
10
11
  - name: Install dependencies
@@ -8,6 +8,7 @@ jobs:
8
8
  matrix:
9
9
  ruby: [ head, 3.1, 3.0, 2.7, 2.6 ]
10
10
  runs-on: ubuntu-latest
11
+ timeout-minutes: 10
11
12
  steps:
12
13
  - uses: actions/checkout@v2
13
14
  - uses: ruby/setup-ruby@v1
@@ -8,6 +8,7 @@ jobs:
8
8
  strategy:
9
9
  matrix:
10
10
  ruby: [ 'mingw', 'mswin', '3.0', '2.7', '2.6' ]
11
+ timeout-minutes: 10
11
12
  steps:
12
13
  - uses: actions/checkout@v2
13
14
  - name: Set up Ruby
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 1.1.2
2
+
3
+ * Buf fixes.
4
+
1
5
  ## 1.1.1
2
6
 
3
7
  * Bug fixes.
data/exe/textbringer CHANGED
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $VERBOSE = nil
3
+ require "warning"
4
+
5
+ Warning.ignore(/already initialized constant /)
6
+ Warning.ignore(/previous definition of /)
4
7
 
5
8
  require "textbringer"
6
9
 
@@ -58,6 +58,8 @@ module Textbringer
58
58
  end
59
59
  }
60
60
 
61
+ STRING_HAS_BYTE_BASED_METHODS = String.instance_methods.include?(:bytesplice)
62
+
61
63
  if !defined?(@@detect_encoding_proc)
62
64
  @@detect_encoding_proc = DEFAULT_DETECT_ENCODING
63
65
 
@@ -268,7 +270,14 @@ module Textbringer
268
270
 
269
271
  def file_encoding=(enc)
270
272
  @file_encoding = Encoding.find(enc)
271
- @binary = enc == Encoding::ASCII_8BIT
273
+ @binary = @file_encoding == Encoding::ASCII_8BIT
274
+ if STRING_HAS_BYTE_BASED_METHODS
275
+ if @binary
276
+ @contents.force_encoding(Encoding::ASCII_8BIT)
277
+ else
278
+ @contents.force_encoding(Encoding::UTF_8)
279
+ end
280
+ end
272
281
  end
273
282
 
274
283
  def binary?
@@ -437,20 +446,26 @@ module Textbringer
437
446
  end
438
447
 
439
448
  def to_s
440
- result = (@contents[0...@gap_start] + @contents[@gap_end..-1])
441
- result.force_encoding(Encoding::UTF_8) unless @binary
449
+ result = @contents.byteslice(0...@gap_start) +
450
+ @contents.byteslice(@gap_end..-1)
451
+ if !@binary && !STRING_HAS_BYTE_BASED_METHODS
452
+ result.force_encoding(Encoding::UTF_8)
453
+ end
442
454
  result
443
455
  end
444
456
 
445
457
  def substring(s, e)
446
458
  result =
447
459
  if s > @gap_start || e <= @gap_start
448
- @contents[user_to_gap(s)...user_to_gap(e)]
460
+ @contents.byteslice(user_to_gap(s)...user_to_gap(e))
449
461
  else
450
462
  len = @gap_start - s
451
- @contents[user_to_gap(s), len] + @contents[@gap_end, e - s - len]
463
+ @contents.byteslice(user_to_gap(s), len) +
464
+ @contents.byteslice(@gap_end, e - s - len)
452
465
  end
453
- result.force_encoding(Encoding::UTF_8) unless @binary
466
+ if !@binary && !STRING_HAS_BYTE_BASED_METHODS
467
+ result.force_encoding(Encoding::UTF_8)
468
+ end
454
469
  result
455
470
  end
456
471
 
@@ -459,7 +474,7 @@ module Textbringer
459
474
  @contents.byteslice(location)
460
475
  else
461
476
  @contents.byteslice(location + gap_size)
462
- end
477
+ end&.force_encoding(Encoding::ASCII_8BIT)
463
478
  end
464
479
 
465
480
  def byte_before(location = @point)
@@ -506,11 +521,19 @@ module Textbringer
506
521
  end
507
522
 
508
523
  def get_line_and_column(pos)
509
- line = 1 + @contents[0...user_to_gap(pos)].count("\n")
524
+ line = 1 + @contents.byteslice(0...user_to_gap(pos)).count("\n")
510
525
  if pos == point_min
511
526
  column = 1
512
527
  else
513
- i = @contents.rindex("\n", user_to_gap(pos - 1))
528
+ if STRING_HAS_BYTE_BASED_METHODS
529
+ begin
530
+ i = @contents.byterindex("\n", user_to_gap(get_pos(pos, -1)))
531
+ rescue RangeError
532
+ i = nil
533
+ end
534
+ else
535
+ i = @contents.rindex("\n", user_to_gap(pos - 1))
536
+ end
514
537
  if i
515
538
  i += 1
516
539
  else
@@ -539,7 +562,11 @@ module Textbringer
539
562
  pos = point_min
540
563
  i = 1
541
564
  while i < n && pos < @contents.bytesize
542
- pos = @contents.index("\n", pos)
565
+ if STRING_HAS_BYTE_BASED_METHODS
566
+ pos = @contents.byteindex("\n", pos)
567
+ else
568
+ pos = @contents.index("\n", pos)
569
+ end
543
570
  break if pos.nil?
544
571
  i += 1
545
572
  pos += 1
@@ -552,11 +579,14 @@ module Textbringer
552
579
 
553
580
  def insert(x, merge_undo = false)
554
581
  s = x.to_s
582
+ if !binary? && !s.valid_encoding?
583
+ raise EditorError, "Invalid encoding: #{s.dump}"
584
+ end
555
585
  check_read_only_flag
556
586
  pos = @point
557
587
  size = s.bytesize
558
588
  adjust_gap(size)
559
- @contents[@point, size] = s.b
589
+ splice_contents(@point, size, STRING_HAS_BYTE_BASED_METHODS ? s : s.b)
560
590
  @marks.each do |m|
561
591
  if m.location > @point
562
592
  m.location += size
@@ -604,7 +634,7 @@ module Textbringer
604
634
  if n > 0
605
635
  str = substring(s, pos)
606
636
  # fill the gap with NUL to avoid invalid byte sequence in UTF-8
607
- @contents[@gap_end...user_to_gap(pos)] = "\0" * (pos - @point)
637
+ splice_contents(@gap_end...user_to_gap(pos), "\0" * (pos - @point))
608
638
  @gap_end += pos - @point
609
639
  @marks.each do |m|
610
640
  if m.location > pos
@@ -619,7 +649,7 @@ module Textbringer
619
649
  str = substring(pos, s)
620
650
  update_line_and_column(@point, pos)
621
651
  # fill the gap with NUL to avoid invalid byte sequence in UTF-8
622
- @contents[user_to_gap(pos)...@gap_start] = "\0" * (@point - pos)
652
+ splice_contents(user_to_gap(pos)...@gap_start, "\0" * (@point - pos))
623
653
  @marks.each do |m|
624
654
  if m.location >= @point
625
655
  m.location -= @point - pos
@@ -941,7 +971,7 @@ module Textbringer
941
971
  adjust_gap
942
972
  len = e - s
943
973
  # fill the gap with NUL to avoid invalid byte sequence in UTF-8
944
- @contents[@gap_end, len] = "\0" * len
974
+ splice_contents(@gap_end, len, "\0" * len)
945
975
  @gap_end += len
946
976
  @marks.each do |m|
947
977
  if m.location > e
@@ -966,6 +996,9 @@ module Textbringer
966
996
  def clear
967
997
  check_read_only_flag
968
998
  @contents = +""
999
+ if binary? || !STRING_HAS_BYTE_BASED_METHODS
1000
+ @contents.force_encoding(Encoding::ASCII_8BIT)
1001
+ end
969
1002
  @point = @gap_start = @gap_end = 0
970
1003
  @marks.each do |m|
971
1004
  m.location = 0
@@ -1125,49 +1158,71 @@ module Textbringer
1125
1158
  byteindex(true, r, @point) == @point
1126
1159
  end
1127
1160
 
1128
- def byteindex(forward, re, pos)
1129
- @match_offsets = []
1130
- method = forward ? :index : :rindex
1131
- adjust_gap(0, point_max)
1132
- s = @contents[0...@gap_start]
1133
- if @binary
1134
- offset = pos
1135
- else
1136
- offset = s.byteslice(0, pos).force_encoding(Encoding::UTF_8).size
1137
- s.force_encoding(Encoding::UTF_8)
1138
- end
1139
- begin
1140
- i = s.send(method, re, offset)
1161
+ if STRING_HAS_BYTE_BASED_METHODS
1162
+ def byteindex(forward, re, pos)
1163
+ @match_offsets = []
1164
+ method = forward ? :byteindex : :byterindex
1165
+ adjust_gap(0, 0)
1166
+ s = @contents.byteslice(@gap_end..-1)
1167
+ unless binary?
1168
+ s.force_encoding(Encoding::UTF_8)
1169
+ end
1170
+ i = s.send(method, re, pos)
1141
1171
  if i
1142
1172
  m = Regexp.last_match
1143
- if m.nil?
1144
- # A bug of rindex
1145
- @match_offsets.push([pos, pos])
1146
- pos
1147
- else
1148
- b = m.pre_match.bytesize
1149
- e = b + m.to_s.bytesize
1150
- if e <= bytesize
1151
- @match_offsets.push([b, e])
1152
- match_beg = m.begin(0)
1153
- match_str = m.to_s
1154
- (1 .. m.size - 1).each do |j|
1155
- cb, ce = m.offset(j)
1156
- if cb.nil?
1157
- @match_offsets.push([nil, nil])
1158
- else
1159
- bb = b + match_str[0, cb - match_beg].bytesize
1160
- be = b + match_str[0, ce - match_beg].bytesize
1161
- @match_offsets.push([bb, be])
1173
+ (0 .. m.size - 1).each do |j|
1174
+ @match_offsets.push(m.byteoffset(j))
1175
+ end
1176
+ i
1177
+ else
1178
+ nil
1179
+ end
1180
+ end
1181
+ else
1182
+ def byteindex(forward, re, pos)
1183
+ @match_offsets = []
1184
+ method = forward ? :index : :rindex
1185
+ adjust_gap(0, 0)
1186
+ s = @contents[@gap_end..-1]
1187
+ if @binary
1188
+ offset = pos
1189
+ else
1190
+ offset = s.byteslice(0, pos).force_encoding(Encoding::UTF_8).size
1191
+ s.force_encoding(Encoding::UTF_8)
1192
+ end
1193
+ begin
1194
+ i = s.send(method, re, offset)
1195
+ if i
1196
+ m = Regexp.last_match
1197
+ if m.nil?
1198
+ # A bug of rindex
1199
+ @match_offsets.push([pos, pos])
1200
+ pos
1201
+ else
1202
+ b = m.pre_match.bytesize
1203
+ e = b + m.to_s.bytesize
1204
+ if e <= bytesize
1205
+ @match_offsets.push([b, e])
1206
+ match_beg = m.begin(0)
1207
+ match_str = m.to_s
1208
+ (1 .. m.size - 1).each do |j|
1209
+ cb, ce = m.offset(j)
1210
+ if cb.nil?
1211
+ @match_offsets.push([nil, nil])
1212
+ else
1213
+ bb = b + match_str[0, cb - match_beg].bytesize
1214
+ be = b + match_str[0, ce - match_beg].bytesize
1215
+ @match_offsets.push([bb, be])
1216
+ end
1162
1217
  end
1218
+ b
1219
+ else
1220
+ nil
1163
1221
  end
1164
- b
1165
- else
1166
- nil
1167
1222
  end
1223
+ else
1224
+ nil
1168
1225
  end
1169
- else
1170
- nil
1171
1226
  end
1172
1227
  end
1173
1228
  end
@@ -1248,7 +1303,7 @@ module Textbringer
1248
1303
  end
1249
1304
 
1250
1305
  def gap_filled_with_nul?
1251
- @contents[@gap_start...@gap_end]&.match?(/\A\0*\z/)
1306
+ @contents.byteslice(@gap_start...@gap_end)&.match?(/\A\0*\z/)
1252
1307
  end
1253
1308
 
1254
1309
  def composite_edit
@@ -1425,40 +1480,79 @@ module Textbringer
1425
1480
  else
1426
1481
  @contents = s.encode(Encoding::UTF_8)
1427
1482
  end
1428
- @contents.force_encoding(Encoding::ASCII_8BIT)
1483
+ if !STRING_HAS_BYTE_BASED_METHODS
1484
+ @contents.force_encoding(Encoding::ASCII_8BIT)
1485
+ end
1429
1486
  self.file_encoding = enc
1430
- case @contents
1431
- when /(?<!\r)\n/
1487
+ begin
1488
+ case @contents
1489
+ when /(?<!\r)\n/
1490
+ @file_format = :unix
1491
+ when /\r(?!\n)/
1492
+ @file_format = :mac
1493
+ @contents.gsub!(/\r/, "\n")
1494
+ when /\r\n/
1495
+ @file_format = :dos
1496
+ @contents.gsub!(/\r/, "")
1497
+ else
1498
+ @file_format = CONFIG[:default_file_format]
1499
+ end
1500
+ rescue ArgumentError
1432
1501
  @file_format = :unix
1433
- when /\r(?!\n)/
1434
- @file_format = :mac
1435
- @contents.gsub!(/\r/, "\n")
1436
- when /\r\n/
1437
- @file_format = :dos
1438
- @contents.gsub!(/\r/, "")
1439
- else
1440
- @file_format = CONFIG[:default_file_format]
1502
+ end
1503
+ end
1504
+
1505
+ if STRING_HAS_BYTE_BASED_METHODS
1506
+ def splice_contents(*args)
1507
+ @contents.bytesplice(*args)
1508
+ end
1509
+ else
1510
+ def splice_contents(*args)
1511
+ @contents.[]=(*args)
1441
1512
  end
1442
1513
  end
1443
1514
 
1444
1515
  def adjust_gap(min_size = 0, pos = @point)
1445
1516
  if @gap_start < pos
1446
1517
  len = user_to_gap(pos) - @gap_end
1447
- @contents[@gap_start, len] = @contents[@gap_end, len]
1448
- @gap_start += len
1449
- @gap_end += len
1518
+ s = @contents.byteslice(@gap_end, len)
1519
+ new_gap_start = @gap_start + len
1520
+ new_gap_end = @gap_end + len
1521
+ nul_filling_start = new_gap_start > @gap_end ? new_gap_start : @gap_end
1522
+ unless @binary
1523
+ # find the character boundary
1524
+ while nul_filling_start > @gap_end &&
1525
+ @contents.byteslice(nul_filling_start)&.b&.match?(/[\x80-\xbf]/n)
1526
+ nul_filling_start -= 1
1527
+ end
1528
+ end
1529
+ splice_contents(nul_filling_start...new_gap_end,
1530
+ "\0" * (new_gap_end - nul_filling_start))
1531
+ splice_contents(@gap_start...new_gap_start, s)
1532
+ @gap_start = new_gap_start
1533
+ @gap_end = new_gap_end
1450
1534
  elsif @gap_start > pos
1451
1535
  len = @gap_start - pos
1452
- @contents[@gap_end - len, len] = @contents[pos, len]
1453
- @gap_start -= len
1454
- @gap_end -= len
1536
+ s = @contents.byteslice(pos, len)
1537
+ new_gap_start = @gap_start - len
1538
+ new_gap_end = @gap_end - len
1539
+ nul_filling_end = new_gap_end < @gap_start ? new_gap_end : @gap_start
1540
+ unless @binary
1541
+ # find the character boundary
1542
+ while nul_filling_end < @gap_start &&
1543
+ @contents.byteslice(nul_filling_end)&.b&.match?(/[\x80-\xbf]/n)
1544
+ nul_filling_end += 1
1545
+ end
1546
+ end
1547
+ splice_contents(pos...nul_filling_end, "\0" * (nul_filling_end - pos))
1548
+ splice_contents(new_gap_end...@gap_end, s)
1549
+ @gap_start = new_gap_start
1550
+ @gap_end = new_gap_end
1455
1551
  end
1456
- # fill the gap with NUL to avoid invalid byte sequence in UTF-8
1457
- @contents[@gap_start...@gap_end] = "\0" * (@gap_end - @gap_start)
1458
1552
  if gap_size < min_size
1459
1553
  new_gap_size = GAP_SIZE + min_size
1460
1554
  extended_size = new_gap_size - gap_size
1461
- @contents[@gap_end, 0] = "\0" * extended_size
1555
+ splice_contents(@gap_end, 0, "\0" * extended_size)
1462
1556
  @gap_end += extended_size
1463
1557
  end
1464
1558
  end
@@ -1520,12 +1614,20 @@ module Textbringer
1520
1614
  def update_line_and_column(pos, new_pos)
1521
1615
  return if @save_point_level > 0
1522
1616
  if pos < new_pos
1523
- n = @contents[user_to_gap(pos)...user_to_gap(new_pos)].count("\n")
1617
+ n = @contents.byteslice(user_to_gap(pos)...user_to_gap(new_pos)).count("\n")
1524
1618
  if n == 0
1525
1619
  @current_column += substring(pos, new_pos).size
1526
1620
  else
1527
1621
  @current_line += n
1528
- i = @contents.rindex("\n", user_to_gap(new_pos - 1))
1622
+ if STRING_HAS_BYTE_BASED_METHODS
1623
+ begin
1624
+ i = @contents.byterindex("\n", user_to_gap(get_pos(new_pos, -1)))
1625
+ rescue RangeError
1626
+ i = nil
1627
+ end
1628
+ else
1629
+ i = @contents.rindex("\n", user_to_gap(new_pos - 1))
1630
+ end
1529
1631
  if i
1530
1632
  i += 1
1531
1633
  else
@@ -1534,12 +1636,20 @@ module Textbringer
1534
1636
  @current_column = 1 + substring(gap_to_user(i), new_pos).size
1535
1637
  end
1536
1638
  elsif pos > new_pos
1537
- n = @contents[user_to_gap(new_pos)...user_to_gap(pos)].count("\n")
1639
+ n = @contents.byteslice(user_to_gap(new_pos)...user_to_gap(pos)).count("\n")
1538
1640
  if n == 0
1539
1641
  @current_column -= substring(new_pos, pos).size
1540
1642
  else
1541
1643
  @current_line -= n
1542
- i = @contents.rindex("\n", user_to_gap(new_pos - 1))
1644
+ if STRING_HAS_BYTE_BASED_METHODS
1645
+ begin
1646
+ i = @contents.byterindex("\n", user_to_gap(get_pos(new_pos, - 1)))
1647
+ rescue RangeError
1648
+ i = nil
1649
+ end
1650
+ else
1651
+ i = @contents.rindex("\n", user_to_gap(new_pos - 1))
1652
+ end
1543
1653
  if i
1544
1654
  i += 1
1545
1655
  else
@@ -1573,8 +1683,13 @@ module Textbringer
1573
1683
  end
1574
1684
 
1575
1685
  def write_to_file(f)
1576
- [@contents[0...@gap_start], @contents[@gap_end..-1]].each do |s|
1577
- s.force_encoding(Encoding::UTF_8) unless @binary
1686
+ [
1687
+ @contents.byteslice(0...@gap_start),
1688
+ @contents.byteslice(@gap_end..-1)
1689
+ ].each do |s|
1690
+ if !STRING_HAS_BYTE_BASED_METHODS
1691
+ s.force_encoding(Encoding::UTF_8) unless @binary
1692
+ end
1578
1693
  case @file_format
1579
1694
  when :dos
1580
1695
  s.gsub!(/\n/, "\r\n")
@@ -72,7 +72,11 @@ module Textbringer
72
72
 
73
73
  define_command(:save_buffer, doc: "Save the current buffer to a file.") do
74
74
  if Buffer.current.file_name.nil?
75
- Buffer.current.file_name = read_file_name("File to save in: ")
75
+ file_name = read_file_name("File to save in: ")
76
+ if File.directory?(file_name)
77
+ file_name = File.expand_path(Buffer.current.name, file_name)
78
+ end
79
+ Buffer.current.file_name = file_name
76
80
  next if Buffer.current.file_name.nil?
77
81
  end
78
82
  if Buffer.current.file_modified?
@@ -138,7 +138,18 @@ module Textbringer
138
138
  end
139
139
  re = Regexp.new(Regexp.quote(ISEARCH_STATUS[:string]), options)
140
140
  last_pos = ISEARCH_STATUS[:last_pos]
141
- offset = forward ? last_pos : last_pos - ISEARCH_STATUS[:string].bytesize
141
+ if forward
142
+ offset = last_pos
143
+ else
144
+ Buffer.current.save_excursion do
145
+ pos = last_pos - ISEARCH_STATUS[:string].bytesize
146
+ goto_char(last_pos)
147
+ while Buffer.current.point > pos
148
+ backward_char
149
+ end
150
+ offset = Buffer.current.point
151
+ end
152
+ end
142
153
  if offset >= 0 && Buffer.current.byteindex(forward, re, offset)
143
154
  if Buffer.current != Buffer.minibuffer
144
155
  message(isearch_prompt + ISEARCH_STATUS[:string], log: false)
@@ -125,6 +125,7 @@ module Textbringer
125
125
  define_command(:complete_minibuffer) do
126
126
  minibuffer = Buffer.minibuffer
127
127
  completion_proc = minibuffer[:completion_proc]
128
+ ignore_case = minibuffer[:completion_ignore_case]
128
129
  if completion_proc
129
130
  xs = completion_proc.call(minibuffer.to_s)
130
131
  update_completions(xs)
@@ -136,7 +137,11 @@ module Textbringer
136
137
  s = y.size.downto(1).lazy.map { |i|
137
138
  y[0, i]
138
139
  }.find { |i|
139
- ys.all? { |j| j.start_with?(i) }
140
+ i = i.downcase if ignore_case
141
+ ys.all? { |j|
142
+ j = j.downcase if ignore_case
143
+ j.start_with?(i)
144
+ }
140
145
  }
141
146
  if s
142
147
  complete_minibuffer_with_string(s)
@@ -16,6 +16,7 @@ module Textbringer
16
16
  shell_command_switch: "-c",
17
17
  grep_command: "grep -nH -e",
18
18
  fill_column: 70,
19
+ read_file_name_completion_ignore_case: RUBY_PLATFORM.match?(/darwin/),
19
20
  default_input_method: "t_code"
20
21
  }
21
22
  end
@@ -55,7 +55,15 @@ module Textbringer
55
55
  @last_key = c
56
56
  @key_sequence << @last_key
57
57
  cmd = key_binding(@key_sequence)
58
- if cmd.is_a?(Symbol) || cmd.respond_to?(:call)
58
+ if cmd.nil?
59
+ keys = Keymap.key_sequence_string(@key_sequence)
60
+ @key_sequence.clear
61
+ @prefix_arg = nil
62
+ message("#{keys} is undefined")
63
+ Window.beep
64
+ elsif cmd.is_a?(Keymap)
65
+ # multi-stroke key binding?
66
+ else
59
67
  @this_command_keys = @key_sequence
60
68
  @key_sequence = []
61
69
  @this_command = cmd
@@ -73,13 +81,6 @@ module Textbringer
73
81
  @last_command = @this_command
74
82
  @this_command = nil
75
83
  end
76
- else
77
- if cmd.nil?
78
- keys = Keymap.key_sequence_string(@key_sequence)
79
- @key_sequence.clear
80
- @prefix_arg = nil
81
- message("#{keys} is undefined")
82
- end
83
84
  end
84
85
  Window.redisplay
85
86
  rescue Exception => e
@@ -137,7 +137,7 @@ module Textbringer
137
137
  }
138
138
 
139
139
  def read_from_minibuffer(prompt, completion_proc: nil, default: nil,
140
- initial_value: nil,
140
+ initial_value: nil, completion_ignore_case: false,
141
141
  keymap: MINIBUFFER_LOCAL_MAP)
142
142
  if Window.echo_area.active?
143
143
  raise EditorError,
@@ -146,10 +146,12 @@ module Textbringer
146
146
  old_buffer = Buffer.current
147
147
  old_window = Window.current
148
148
  old_completion_proc = Buffer.minibuffer[:completion_proc]
149
+ old_completion_ignore_case = Buffer.minibuffer[:completion_ignore_case]
149
150
  old_current_prefix_arg = Controller.current.current_prefix_arg
150
151
  old_minibuffer_map = Buffer.minibuffer.keymap
151
152
  Buffer.minibuffer.keymap = keymap
152
153
  Buffer.minibuffer[:completion_proc] = completion_proc
154
+ Buffer.minibuffer[:completion_ignore_case] = completion_ignore_case
153
155
  Window.echo_area.active = true
154
156
  begin
155
157
  Window.current = Window.echo_area
@@ -177,6 +179,7 @@ module Textbringer
177
179
  # Just in case old_window has been deleted by resize,
178
180
  # in which case Window.current is set to the first window.
179
181
  Window.current.buffer = Buffer.current = old_buffer
182
+ Buffer.minibuffer[:completion_ignore_case] = old_completion_ignore_case
180
183
  Buffer.minibuffer[:completion_proc] = old_completion_proc
181
184
  Buffer.minibuffer.keymap = old_minibuffer_map
182
185
  Buffer.minibuffer.disable_input_method
@@ -201,8 +204,10 @@ module Textbringer
201
204
  }
202
205
  }
203
206
  initial_value = default&.sub(%r"\A#{Regexp.quote(Dir.pwd)}/", "")
207
+ ignore_case = CONFIG[:read_file_name_completion_ignore_case]
204
208
  file = read_from_minibuffer(prompt, completion_proc: f,
205
- initial_value: initial_value)
209
+ initial_value: initial_value,
210
+ completion_ignore_case: ignore_case)
206
211
  File.expand_path(file)
207
212
  end
208
213
 
@@ -223,8 +228,10 @@ module Textbringer
223
228
  end
224
229
 
225
230
  def read_encoding(prompt, **opts)
231
+ encoding_names = (Encoding.list.map(&:name) + Encoding.aliases.keys).
232
+ map(&:downcase).uniq
226
233
  f = ->(s) {
227
- complete_for_minibuffer(s.upcase, Encoding.list.map(&:name))
234
+ complete_for_minibuffer(s.downcase, encoding_names)
228
235
  }
229
236
  read_from_minibuffer(prompt, completion_proc: f, **opts)
230
237
  end
@@ -1,3 +1,3 @@
1
1
  module Textbringer
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.2"
3
3
  end
@@ -687,6 +687,8 @@ module Textbringer
687
687
  else
688
688
  "U+%04X" % c.ord
689
689
  end
690
+ rescue ArgumentError
691
+ "0x" + c.unpack("H*")[0]
690
692
  end
691
693
 
692
694
  def escape(s)
data/textbringer.gemspec CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_runtime_dependency "clipboard", ">= 1.1"
27
27
  spec.add_runtime_dependency "fiddley", ">= 0.0.5"
28
28
  spec.add_runtime_dependency "editorconfig"
29
+ spec.add_runtime_dependency "warning"
29
30
 
30
31
  spec.add_development_dependency "bundler"
31
32
  spec.add_development_dependency "rake", ">= 12.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: textbringer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-06 00:00:00.000000000 Z
11
+ date: 2022-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: warning
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement