reline 0.0.0 → 0.0.1
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.rb +313 -94
- data/lib/reline/ansi.rb +60 -20
- data/lib/reline/config.rb +137 -85
- data/lib/reline/general_io.rb +64 -0
- data/lib/reline/history.rb +56 -0
- data/lib/reline/key_actor/emacs.rb +37 -38
- data/lib/reline/key_actor/vi_command.rb +34 -35
- data/lib/reline/key_actor/vi_insert.rb +160 -161
- data/lib/reline/key_stroke.rb +3 -24
- data/lib/reline/line_editor.rb +736 -217
- data/lib/reline/unicode.rb +113 -1
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +72 -12
- metadata +5 -3
data/lib/reline/unicode.rb
CHANGED
@@ -55,6 +55,17 @@ class Reline::Unicode
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
def self.escape_for_print(str)
|
59
|
+
str.chars.map! { |gr|
|
60
|
+
escaped = EscapedPairs[gr.ord]
|
61
|
+
if escaped && gr != -"\n" && gr != -"\t"
|
62
|
+
escaped
|
63
|
+
else
|
64
|
+
gr
|
65
|
+
end
|
66
|
+
}.join
|
67
|
+
end
|
68
|
+
|
58
69
|
def self.get_mbchar_width(mbchar)
|
59
70
|
case mbchar.encode(Encoding::UTF_8)
|
60
71
|
when *EscapedChars # ^ + char, such as ^M, ^H, ^[, ...
|
@@ -177,6 +188,107 @@ class Reline::Unicode
|
|
177
188
|
[byte_size, width]
|
178
189
|
end
|
179
190
|
|
191
|
+
def self.ed_transpose_words(line, byte_pointer)
|
192
|
+
right_word_start = nil
|
193
|
+
size = get_next_mbchar_size(line, byte_pointer)
|
194
|
+
mbchar = line.byteslice(byte_pointer, size)
|
195
|
+
if size.zero?
|
196
|
+
# ' aaa bbb [cursor]'
|
197
|
+
byte_size = 0
|
198
|
+
while 0 < (byte_pointer + byte_size)
|
199
|
+
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
|
200
|
+
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
|
201
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
202
|
+
byte_size -= size
|
203
|
+
end
|
204
|
+
while 0 < (byte_pointer + byte_size)
|
205
|
+
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
|
206
|
+
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
|
207
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
208
|
+
byte_size -= size
|
209
|
+
end
|
210
|
+
right_word_start = byte_pointer + byte_size
|
211
|
+
byte_size = 0
|
212
|
+
while line.bytesize > (byte_pointer + byte_size)
|
213
|
+
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
214
|
+
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
215
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
216
|
+
byte_size += size
|
217
|
+
end
|
218
|
+
after_start = byte_pointer + byte_size
|
219
|
+
elsif mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
220
|
+
# ' aaa bb[cursor]b'
|
221
|
+
byte_size = 0
|
222
|
+
while 0 < (byte_pointer + byte_size)
|
223
|
+
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
|
224
|
+
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
|
225
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
226
|
+
byte_size -= size
|
227
|
+
end
|
228
|
+
right_word_start = byte_pointer + byte_size
|
229
|
+
byte_size = 0
|
230
|
+
while line.bytesize > (byte_pointer + byte_size)
|
231
|
+
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
232
|
+
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
233
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
234
|
+
byte_size += size
|
235
|
+
end
|
236
|
+
after_start = byte_pointer + byte_size
|
237
|
+
else
|
238
|
+
byte_size = 0
|
239
|
+
while (line.bytesize - 1) > (byte_pointer + byte_size)
|
240
|
+
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
241
|
+
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
242
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
243
|
+
byte_size += size
|
244
|
+
end
|
245
|
+
if (byte_pointer + byte_size) == (line.bytesize - 1)
|
246
|
+
# ' aaa bbb [cursor] '
|
247
|
+
after_start = line.bytesize
|
248
|
+
while 0 < (byte_pointer + byte_size)
|
249
|
+
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
|
250
|
+
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
|
251
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
252
|
+
byte_size -= size
|
253
|
+
end
|
254
|
+
while 0 < (byte_pointer + byte_size)
|
255
|
+
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
|
256
|
+
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
|
257
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
258
|
+
byte_size -= size
|
259
|
+
end
|
260
|
+
right_word_start = byte_pointer + byte_size
|
261
|
+
else
|
262
|
+
# ' aaa [cursor] bbb '
|
263
|
+
right_word_start = byte_pointer + byte_size
|
264
|
+
while line.bytesize > (byte_pointer + byte_size)
|
265
|
+
size = get_next_mbchar_size(line, byte_pointer + byte_size)
|
266
|
+
mbchar = line.byteslice(byte_pointer + byte_size, size)
|
267
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
268
|
+
byte_size += size
|
269
|
+
end
|
270
|
+
after_start = byte_pointer + byte_size
|
271
|
+
end
|
272
|
+
end
|
273
|
+
byte_size = right_word_start - byte_pointer
|
274
|
+
while 0 < (byte_pointer + byte_size)
|
275
|
+
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
|
276
|
+
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
|
277
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
|
278
|
+
byte_size -= size
|
279
|
+
end
|
280
|
+
middle_start = byte_pointer + byte_size
|
281
|
+
byte_size = middle_start - byte_pointer
|
282
|
+
while 0 < (byte_pointer + byte_size)
|
283
|
+
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
|
284
|
+
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
|
285
|
+
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
|
286
|
+
byte_size -= size
|
287
|
+
end
|
288
|
+
left_word_start = byte_pointer + byte_size
|
289
|
+
[left_word_start, middle_start, right_word_start, after_start]
|
290
|
+
end
|
291
|
+
|
180
292
|
def self.vi_big_forward_word(line, byte_pointer)
|
181
293
|
width = 0
|
182
294
|
byte_size = 0
|
@@ -396,7 +508,7 @@ class Reline::Unicode
|
|
396
508
|
[byte_size, width]
|
397
509
|
end
|
398
510
|
|
399
|
-
def self.
|
511
|
+
def self.vi_first_print(line)
|
400
512
|
width = 0
|
401
513
|
byte_size = 0
|
402
514
|
while (line.bytesize - 1) > byte_size
|
data/lib/reline/version.rb
CHANGED
data/lib/reline/windows.rb
CHANGED
@@ -1,5 +1,56 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'fiddle/import'
|
2
|
+
|
3
|
+
class Reline::Windows
|
4
|
+
RAW_KEYSTROKE_CONFIG = {
|
5
|
+
[224, 72] => :ed_prev_history, # ↑
|
6
|
+
[224, 80] => :ed_next_history, # ↓
|
7
|
+
[224, 77] => :ed_next_char, # →
|
8
|
+
[224, 75] => :ed_prev_char, # ←
|
9
|
+
[224, 83] => :key_delete, # Del
|
10
|
+
[224, 71] => :ed_move_to_beg, # Home
|
11
|
+
[224, 79] => :ed_move_to_end, # End
|
12
|
+
}.each_key(&:freeze).freeze
|
13
|
+
|
14
|
+
class Win32API
|
15
|
+
DLL = {}
|
16
|
+
TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG}
|
17
|
+
POINTER_TYPE = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
|
18
|
+
|
19
|
+
WIN32_TYPES = "VPpNnLlIi"
|
20
|
+
DL_TYPES = "0SSI"
|
21
|
+
|
22
|
+
def initialize(dllname, func, import, export = "0", calltype = :stdcall)
|
23
|
+
@proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1')
|
24
|
+
import = @proto.chars.map {|win_type| TYPEMAP[win_type.tr(WIN32_TYPES, DL_TYPES)]}
|
25
|
+
export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)]
|
26
|
+
calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype]
|
27
|
+
|
28
|
+
handle = DLL[dllname] ||=
|
29
|
+
begin
|
30
|
+
Fiddle.dlopen(dllname)
|
31
|
+
rescue Fiddle::DLError
|
32
|
+
raise unless File.extname(dllname).empty?
|
33
|
+
Fiddle.dlopen(dllname + ".dll")
|
34
|
+
end
|
35
|
+
|
36
|
+
@func = Fiddle::Function.new(handle[func], import, export, calltype)
|
37
|
+
rescue Fiddle::DLError => e
|
38
|
+
raise LoadError, e.message, e.backtrace
|
39
|
+
end
|
40
|
+
|
41
|
+
def call(*args)
|
42
|
+
import = @proto.split("")
|
43
|
+
args.each_with_index do |x, i|
|
44
|
+
args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S"
|
45
|
+
args[i], = [x].pack("I").unpack("i") if import[i] == "I"
|
46
|
+
end
|
47
|
+
ret, = @func.call(*args)
|
48
|
+
return ret || 0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
VK_MENU = 0x12
|
53
|
+
VK_SHIFT = 0x10
|
3
54
|
STD_OUTPUT_HANDLE = -11
|
4
55
|
@@getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
|
5
56
|
@@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
|
@@ -12,7 +63,7 @@ module Reline
|
|
12
63
|
@@hConsoleHandle = @@GetStdHandle.call(STD_OUTPUT_HANDLE)
|
13
64
|
@@buf = []
|
14
65
|
|
15
|
-
def getwch
|
66
|
+
def self.getwch
|
16
67
|
while @@kbhit.call == 0
|
17
68
|
sleep(0.001)
|
18
69
|
end
|
@@ -29,13 +80,18 @@ module Reline
|
|
29
80
|
result
|
30
81
|
end
|
31
82
|
|
32
|
-
def getc
|
83
|
+
def self.getc
|
33
84
|
unless @@buf.empty?
|
34
85
|
return @@buf.shift
|
35
86
|
end
|
36
87
|
input = getwch
|
37
|
-
alt = (@@GetKeyState.call(
|
38
|
-
|
88
|
+
alt = (@@GetKeyState.call(VK_MENU) & 0x80) != 0
|
89
|
+
shift_enter = (@@GetKeyState.call(VK_SHIFT) & 0x80) != 0 && input.first == 0x0D
|
90
|
+
if shift_enter
|
91
|
+
# It's treated as Meta+Enter on Windows
|
92
|
+
@@buf.concat(["\e".ord])
|
93
|
+
@@buf.concat(input)
|
94
|
+
elsif input.size > 1
|
39
95
|
@@buf.concat(input)
|
40
96
|
else # single byte
|
41
97
|
case input[0]
|
@@ -61,10 +117,14 @@ module Reline
|
|
61
117
|
end
|
62
118
|
end
|
63
119
|
|
120
|
+
def self.ungetc(c)
|
121
|
+
@@buf.unshift(c)
|
122
|
+
end
|
123
|
+
|
64
124
|
def self.get_screen_size
|
65
125
|
csbi = 0.chr * 24
|
66
126
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
67
|
-
csbi[0, 4].unpack('SS')
|
127
|
+
csbi[0, 4].unpack('SS').reverse
|
68
128
|
end
|
69
129
|
|
70
130
|
def self.cursor_pos
|
@@ -72,7 +132,7 @@ module Reline
|
|
72
132
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
73
133
|
x = csbi[4, 2].unpack('s*').first
|
74
134
|
y = csbi[6, 4].unpack('s*').first
|
75
|
-
CursorPos.new(x, y)
|
135
|
+
Reline::CursorPos.new(x, y)
|
76
136
|
end
|
77
137
|
|
78
138
|
def self.move_cursor_column(val)
|
@@ -100,12 +160,12 @@ module Reline
|
|
100
160
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
101
161
|
cursor = csbi[4, 4].unpack('L').first
|
102
162
|
written = 0.chr * 4
|
103
|
-
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.
|
163
|
+
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
|
104
164
|
end
|
105
165
|
|
106
166
|
def self.scroll_down(val)
|
107
167
|
return if val.zero?
|
108
|
-
scroll_rectangle = [0, val, get_screen_size.
|
168
|
+
scroll_rectangle = [0, val, get_screen_size.first, get_screen_size.last].pack('s4')
|
109
169
|
destination_origin = 0 # y * 65536 + x
|
110
170
|
fill = [' '.ord, 0].pack('SS')
|
111
171
|
@@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
|
@@ -121,12 +181,12 @@ module Reline
|
|
121
181
|
raise NotImplementedError
|
122
182
|
end
|
123
183
|
|
124
|
-
def prep
|
184
|
+
def self.prep
|
125
185
|
# do nothing
|
126
186
|
nil
|
127
187
|
end
|
128
188
|
|
129
|
-
def deprep(otio)
|
189
|
+
def self.deprep(otio)
|
130
190
|
# do nothing
|
131
191
|
end
|
132
192
|
end
|
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.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -65,6 +65,8 @@ files:
|
|
65
65
|
- lib/reline.rb
|
66
66
|
- lib/reline/ansi.rb
|
67
67
|
- lib/reline/config.rb
|
68
|
+
- lib/reline/general_io.rb
|
69
|
+
- lib/reline/history.rb
|
68
70
|
- lib/reline/key_actor.rb
|
69
71
|
- lib/reline/key_actor/base.rb
|
70
72
|
- lib/reline/key_actor/emacs.rb
|
@@ -96,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
98
|
- !ruby/object:Gem::Version
|
97
99
|
version: '0'
|
98
100
|
requirements: []
|
99
|
-
rubygems_version: 3.0.
|
101
|
+
rubygems_version: 3.0.4
|
100
102
|
signing_key:
|
101
103
|
specification_version: 4
|
102
104
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|