reline 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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