reline 0.1.6 → 0.2.0

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.
@@ -1,5 +1,19 @@
1
1
  require 'reline/unicode'
2
2
 
3
+ =begin
4
+
5
+ \ |
6
+ \ | <--- whipped cream
7
+ \ |
8
+ \ |
9
+ \-~~|
10
+ \ | <--- shibori kutigane (piping nozzle in Japanese)
11
+ \Ml
12
+ (\ __ __
13
+ ( \--( ) )
14
+ (__(__)__) <--- compressed whipped cream
15
+ =end
16
+
3
17
  class Sibori
4
18
  attr_writer :output
5
19
 
@@ -35,11 +35,16 @@ class Reline::Unicode
35
35
  }
36
36
  EscapedChars = EscapedPairs.keys.map(&:chr)
37
37
 
38
- CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
39
- OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/
40
38
  NON_PRINTING_START = "\1"
41
39
  NON_PRINTING_END = "\2"
42
- WIDTH_SCANNER = /\G(?:#{NON_PRINTING_START}|#{NON_PRINTING_END}|#{CSI_REGEXP}|#{OSC_REGEXP}|\X)/
40
+ CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
41
+ OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/
42
+ WIDTH_SCANNER = /\G(?:(#{NON_PRINTING_START})|(#{NON_PRINTING_END})|(#{CSI_REGEXP})|(#{OSC_REGEXP})|(\X))/o
43
+ NON_PRINTING_START_INDEX = 0
44
+ NON_PRINTING_END_INDEX = 1
45
+ CSI_REGEXP_INDEX = 2
46
+ OSC_REGEXP_INDEX = 3
47
+ GRAPHEME_CLUSTER_INDEX = 4
43
48
 
44
49
  def self.get_mbchar_byte_size_by_first_char(c)
45
50
  # Checks UTF-8 character byte size
@@ -72,20 +77,42 @@ class Reline::Unicode
72
77
  }.join
73
78
  end
74
79
 
80
+ require 'reline/unicode/east_asian_width'
81
+
82
+ MBCharWidthRE = /
83
+ (?<width_2_1>
84
+ [#{ EscapedChars.map {|c| "\\x%02x" % c.ord }.join }] (?# ^ + char, such as ^M, ^H, ^[, ...)
85
+ )
86
+ | (?<width_3>^\u{2E3B}) (?# THREE-EM DASH)
87
+ | (?<width_0>^\p{M})
88
+ | (?<width_2_2>
89
+ #{ EastAsianWidth::TYPE_F }
90
+ | #{ EastAsianWidth::TYPE_W }
91
+ )
92
+ | (?<width_1>
93
+ #{ EastAsianWidth::TYPE_H }
94
+ | #{ EastAsianWidth::TYPE_NA }
95
+ | #{ EastAsianWidth::TYPE_N }
96
+ )
97
+ | (?<ambiguous_width>
98
+ #{EastAsianWidth::TYPE_A}
99
+ )
100
+ /x
101
+
75
102
  def self.get_mbchar_width(mbchar)
76
- case mbchar.encode(Encoding::UTF_8)
77
- when *EscapedChars # ^ + char, such as ^M, ^H, ^[, ...
78
- 2
79
- when /^\u{2E3B}/ # THREE-EM DASH
80
- 3
81
- when /^\p{M}/
82
- 0
83
- when EastAsianWidth::TYPE_A
84
- Reline.ambiguous_width
85
- when EastAsianWidth::TYPE_F, EastAsianWidth::TYPE_W
86
- 2
87
- when EastAsianWidth::TYPE_H, EastAsianWidth::TYPE_NA, EastAsianWidth::TYPE_N
88
- 1
103
+ ord = mbchar.ord
104
+ if (0x00 <= ord and ord <= 0x1F)
105
+ return 2
106
+ elsif (0x20 <= ord and ord <= 0x7E)
107
+ return 1
108
+ end
109
+ m = mbchar.encode(Encoding::UTF_8).match(MBCharWidthRE)
110
+ case
111
+ when m[:width_2_1], m[:width_2_2] then 2
112
+ when m[:width_3] then 3
113
+ when m[:width_0] then 0
114
+ when m[:width_1] then 1
115
+ when m[:ambiguous_width] then Reline.ambiguous_width
89
116
  else
90
117
  nil
91
118
  end
@@ -97,13 +124,14 @@ class Reline::Unicode
97
124
  rest = str.encode(Encoding::UTF_8)
98
125
  in_zero_width = false
99
126
  rest.scan(WIDTH_SCANNER) do |gc|
100
- case gc
101
- when NON_PRINTING_START
127
+ case
128
+ when gc[NON_PRINTING_START_INDEX]
102
129
  in_zero_width = true
103
- when NON_PRINTING_END
130
+ when gc[NON_PRINTING_END_INDEX]
104
131
  in_zero_width = false
105
- when CSI_REGEXP, OSC_REGEXP
106
- else
132
+ when gc[CSI_REGEXP_INDEX], gc[OSC_REGEXP_INDEX]
133
+ when gc[GRAPHEME_CLUSTER_INDEX]
134
+ gc = gc[GRAPHEME_CLUSTER_INDEX]
107
135
  unless in_zero_width
108
136
  width += get_mbchar_width(gc)
109
137
  end
@@ -124,14 +152,17 @@ class Reline::Unicode
124
152
  rest = str.encode(Encoding::UTF_8)
125
153
  in_zero_width = false
126
154
  rest.scan(WIDTH_SCANNER) do |gc|
127
- case gc
128
- when NON_PRINTING_START
155
+ case
156
+ when gc[NON_PRINTING_START_INDEX]
129
157
  in_zero_width = true
130
- when NON_PRINTING_END
158
+ when gc[NON_PRINTING_END_INDEX]
131
159
  in_zero_width = false
132
- when CSI_REGEXP, OSC_REGEXP
133
- lines.last << gc
134
- else
160
+ when gc[CSI_REGEXP_INDEX]
161
+ lines.last << gc[CSI_REGEXP_INDEX]
162
+ when gc[OSC_REGEXP_INDEX]
163
+ lines.last << gc[OSC_REGEXP_INDEX]
164
+ when gc[GRAPHEME_CLUSTER_INDEX]
165
+ gc = gc[GRAPHEME_CLUSTER_INDEX]
135
166
  unless in_zero_width
136
167
  mbchar_width = get_mbchar_width(gc)
137
168
  if (width += mbchar_width) > max_width
@@ -427,8 +458,8 @@ class Reline::Unicode
427
458
  [byte_size, width]
428
459
  end
429
460
 
430
- def self.vi_forward_word(line, byte_pointer)
431
- if (line.bytesize - 1) > byte_pointer
461
+ def self.vi_forward_word(line, byte_pointer, drop_terminate_spaces = false)
462
+ if line.bytesize > byte_pointer
432
463
  size = get_next_mbchar_size(line, byte_pointer)
433
464
  mbchar = line.byteslice(byte_pointer, size)
434
465
  if mbchar =~ /\w/
@@ -443,7 +474,7 @@ class Reline::Unicode
443
474
  else
444
475
  return [0, 0]
445
476
  end
446
- while (line.bytesize - 1) > (byte_pointer + byte_size)
477
+ while line.bytesize > (byte_pointer + byte_size)
447
478
  size = get_next_mbchar_size(line, byte_pointer + byte_size)
448
479
  mbchar = line.byteslice(byte_pointer + byte_size, size)
449
480
  case started_by
@@ -457,7 +488,8 @@ class Reline::Unicode
457
488
  width += get_mbchar_width(mbchar)
458
489
  byte_size += size
459
490
  end
460
- while (line.bytesize - 1) > (byte_pointer + byte_size)
491
+ return [byte_size, width] if drop_terminate_spaces
492
+ while line.bytesize > (byte_pointer + byte_size)
461
493
  size = get_next_mbchar_size(line, byte_pointer + byte_size)
462
494
  mbchar = line.byteslice(byte_pointer + byte_size, size)
463
495
  break if mbchar =~ /\S/
@@ -591,5 +623,3 @@ class Reline::Unicode
591
623
  [byte_size, width]
592
624
  end
593
625
  end
594
-
595
- require 'reline/unicode/east_asian_width'
@@ -1,16 +1,16 @@
1
1
  class Reline::Unicode::EastAsianWidth
2
2
  # This is based on EastAsianWidth.txt
3
- # http://www.unicode.org/Public/13.0.0/ucd/EastAsianWidth.txt
3
+ # EastAsianWidth.txt
4
4
 
5
5
  # Fullwidth
6
- TYPE_F = /^([#{ %W(
6
+ TYPE_F = /^[#{ %W(
7
7
  \u{3000}
8
8
  \u{FF01}-\u{FF60}
9
9
  \u{FFE0}-\u{FFE6}
10
- ).join }])/
10
+ ).join }]/
11
11
 
12
12
  # Halfwidth
13
- TYPE_H = /^([#{ %W(
13
+ TYPE_H = /^[#{ %W(
14
14
  \u{20A9}
15
15
  \u{FF61}-\u{FFBE}
16
16
  \u{FFC2}-\u{FFC7}
@@ -18,10 +18,10 @@ class Reline::Unicode::EastAsianWidth
18
18
  \u{FFD2}-\u{FFD7}
19
19
  \u{FFDA}-\u{FFDC}
20
20
  \u{FFE8}-\u{FFEE}
21
- ).join }])/
21
+ ).join }]/
22
22
 
23
23
  # Wide
24
- TYPE_W = /^([#{ %W(
24
+ TYPE_W = /^[#{ %W(
25
25
  \u{1100}-\u{115F}
26
26
  \u{231A}-\u{231B}
27
27
  \u{2329}-\u{232A}
@@ -136,10 +136,10 @@ class Reline::Unicode::EastAsianWidth
136
136
  \u{1FAD0}-\u{1FAD6}
137
137
  \u{20000}-\u{2FFFD}
138
138
  \u{30000}-\u{3FFFD}
139
- ).join }])/
139
+ ).join }]/
140
140
 
141
141
  # Narrow
142
- TYPE_NA = /^([#{ %W(
142
+ TYPE_NA = /^[#{ %W(
143
143
  \u{0020}-\u{007E}
144
144
  \u{00A2}-\u{00A3}
145
145
  \u{00A5}-\u{00A6}
@@ -147,10 +147,10 @@ class Reline::Unicode::EastAsianWidth
147
147
  \u{00AF}
148
148
  \u{27E6}-\u{27ED}
149
149
  \u{2985}-\u{2986}
150
- ).join }])/
150
+ ).join }]/
151
151
 
152
152
  # Ambiguous
153
- TYPE_A = /^([#{ %W(
153
+ TYPE_A = /^[#{ %W(
154
154
  \u{00A1}
155
155
  \u{00A4}
156
156
  \u{00A7}-\u{00A8}
@@ -330,10 +330,10 @@ class Reline::Unicode::EastAsianWidth
330
330
  \u{E0100}-\u{E01EF}
331
331
  \u{F0000}-\u{FFFFD}
332
332
  \u{100000}-\u{10FFFD}
333
- ).join }])/
333
+ ).join }]/
334
334
 
335
335
  # Neutral
336
- TYPE_N = /^([#{ %W(
336
+ TYPE_N = /^[#{ %W(
337
337
  \u{0000}-\u{001F}
338
338
  \u{007F}-\u{00A0}
339
339
  \u{00A9}
@@ -1160,5 +1160,5 @@ class Reline::Unicode::EastAsianWidth
1160
1160
  \u{1FBF0}-\u{1FBF9}
1161
1161
  \u{E0001}
1162
1162
  \u{E0020}-\u{E007F}
1163
- ).join }])/
1163
+ ).join }]/
1164
1164
  end
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.1.6'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -233,7 +233,9 @@ class Reline::Windows
233
233
 
234
234
  def self.move_cursor_up(val)
235
235
  if val > 0
236
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y - val) * 65536 + cursor_pos.x)
236
+ y = cursor_pos.y - val
237
+ y = 0 if y < 0
238
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, y * 65536 + cursor_pos.x)
237
239
  elsif val < 0
238
240
  move_cursor_down(-val)
239
241
  end
@@ -241,6 +243,9 @@ class Reline::Windows
241
243
 
242
244
  def self.move_cursor_down(val)
243
245
  if val > 0
246
+ screen_height = get_screen_size.first
247
+ y = cursor_pos.y + val
248
+ y = screen_height - 1 if y > (screen_height - 1)
244
249
  @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x)
245
250
  elsif val < 0
246
251
  move_cursor_up(-val)
@@ -257,6 +262,8 @@ class Reline::Windows
257
262
 
258
263
  def self.scroll_down(val)
259
264
  return if val.zero?
265
+ screen_height = get_screen_size.first
266
+ val = screen_height - 1 if val > (screen_height - 1)
260
267
  scroll_rectangle = [0, val, get_screen_size.last, get_screen_size.first].pack('s4')
261
268
  destination_origin = 0 # y * 65536 + x
262
269
  fill = [' '.ord, 0].pack('SS')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-20 00:00:00.000000000 Z
11
+ date: 2020-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console
@@ -103,6 +103,7 @@ files:
103
103
  - lib/reline/key_stroke.rb
104
104
  - lib/reline/kill_ring.rb
105
105
  - lib/reline/line_editor.rb
106
+ - lib/reline/line_editor.rb.orig
106
107
  - lib/reline/sibori.rb
107
108
  - lib/reline/unicode.rb
108
109
  - lib/reline/unicode/east_asian_width.rb