reline 0.0.0 → 0.0.1

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