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