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.
@@ -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.ed_move_to_begin(line)
511
+ def self.vi_first_print(line)
400
512
  width = 0
401
513
  byte_size = 0
402
514
  while (line.bytesize - 1) > byte_size
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.0.0'
2
+ VERSION = '0.0.1'
3
3
  end
@@ -1,5 +1,56 @@
1
- module Reline
2
- VK_LMENU = 0xA4
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(VK_LMENU) & 0x80) != 0
38
- if input.size > 1
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.first - cursor_pos.x, cursor, written)
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.last, get_screen_size.first].pack('s4')
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.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-04-23 00:00:00.000000000 Z
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.3
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.