reline 0.1.3

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.
@@ -0,0 +1,3 @@
1
+ module Reline
2
+ VERSION = '0.1.3'
3
+ end
@@ -0,0 +1,273 @@
1
+ require 'fiddle/import'
2
+
3
+ class Reline::Windows
4
+ def self.encoding
5
+ Encoding::UTF_8
6
+ end
7
+
8
+ def self.win?
9
+ true
10
+ end
11
+
12
+ RAW_KEYSTROKE_CONFIG = {
13
+ [224, 72] => :ed_prev_history, # ↑
14
+ [224, 80] => :ed_next_history, # ↓
15
+ [224, 77] => :ed_next_char, # →
16
+ [224, 75] => :ed_prev_char, # ←
17
+ [224, 83] => :key_delete, # Del
18
+ [224, 71] => :ed_move_to_beg, # Home
19
+ [224, 79] => :ed_move_to_end, # End
20
+ [ 0, 41] => :ed_unassigned, # input method on/off
21
+ [ 0, 72] => :ed_prev_history, # ↑
22
+ [ 0, 80] => :ed_next_history, # ↓
23
+ [ 0, 77] => :ed_next_char, # →
24
+ [ 0, 75] => :ed_prev_char, # ←
25
+ [ 0, 83] => :key_delete, # Del
26
+ [ 0, 71] => :ed_move_to_beg, # Home
27
+ [ 0, 79] => :ed_move_to_end # End
28
+ }
29
+
30
+ if defined? JRUBY_VERSION
31
+ require 'win32api'
32
+ else
33
+ class Win32API
34
+ DLL = {}
35
+ TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG}
36
+ POINTER_TYPE = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
37
+
38
+ WIN32_TYPES = "VPpNnLlIi"
39
+ DL_TYPES = "0SSI"
40
+
41
+ def initialize(dllname, func, import, export = "0", calltype = :stdcall)
42
+ @proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1')
43
+ import = @proto.chars.map {|win_type| TYPEMAP[win_type.tr(WIN32_TYPES, DL_TYPES)]}
44
+ export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)]
45
+ calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype]
46
+
47
+ handle = DLL[dllname] ||=
48
+ begin
49
+ Fiddle.dlopen(dllname)
50
+ rescue Fiddle::DLError
51
+ raise unless File.extname(dllname).empty?
52
+ Fiddle.dlopen(dllname + ".dll")
53
+ end
54
+
55
+ @func = Fiddle::Function.new(handle[func], import, export, calltype)
56
+ rescue Fiddle::DLError => e
57
+ raise LoadError, e.message, e.backtrace
58
+ end
59
+
60
+ def call(*args)
61
+ import = @proto.split("")
62
+ args.each_with_index do |x, i|
63
+ args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S"
64
+ args[i], = [x].pack("I").unpack("i") if import[i] == "I"
65
+ end
66
+ ret, = @func.call(*args)
67
+ return ret || 0
68
+ end
69
+ end
70
+ end
71
+
72
+ VK_MENU = 0x12
73
+ VK_LMENU = 0xA4
74
+ VK_CONTROL = 0x11
75
+ VK_SHIFT = 0x10
76
+ STD_INPUT_HANDLE = -10
77
+ STD_OUTPUT_HANDLE = -11
78
+ WINDOW_BUFFER_SIZE_EVENT = 0x04
79
+ FILE_TYPE_PIPE = 0x0003
80
+ FILE_NAME_INFO = 2
81
+ @@getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
82
+ @@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
83
+ @@GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L')
84
+ @@GetConsoleScreenBufferInfo = Win32API.new('kernel32', 'GetConsoleScreenBufferInfo', ['L', 'P'], 'L')
85
+ @@SetConsoleCursorPosition = Win32API.new('kernel32', 'SetConsoleCursorPosition', ['L', 'L'], 'L')
86
+ @@GetStdHandle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
87
+ @@FillConsoleOutputCharacter = Win32API.new('kernel32', 'FillConsoleOutputCharacter', ['L', 'L', 'L', 'L', 'P'], 'L')
88
+ @@ScrollConsoleScreenBuffer = Win32API.new('kernel32', 'ScrollConsoleScreenBuffer', ['L', 'P', 'P', 'L', 'P'], 'L')
89
+ @@hConsoleHandle = @@GetStdHandle.call(STD_OUTPUT_HANDLE)
90
+ @@hConsoleInputHandle = @@GetStdHandle.call(STD_INPUT_HANDLE)
91
+ @@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L')
92
+ @@ReadConsoleInput = Win32API.new('kernel32', 'ReadConsoleInput', ['L', 'P', 'L', 'P'], 'L')
93
+ @@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L')
94
+ @@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
95
+
96
+ @@input_buf = []
97
+ @@output_buf = []
98
+
99
+ def self.msys_tty?(io=@@hConsoleInputHandle)
100
+ # check if fd is a pipe
101
+ if @@GetFileType.call(io) != FILE_TYPE_PIPE
102
+ return false
103
+ end
104
+
105
+ bufsize = 1024
106
+ p_buffer = "\0" * bufsize
107
+ res = @@GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
108
+ return false if res == 0
109
+
110
+ # get pipe name: p_buffer layout is:
111
+ # struct _FILE_NAME_INFO {
112
+ # DWORD FileNameLength;
113
+ # WCHAR FileName[1];
114
+ # } FILE_NAME_INFO
115
+ len = p_buffer[0, 4].unpack("L")[0]
116
+ name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace)
117
+
118
+ # Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX')
119
+ # or a cygwin pty pipe ('\cygwin-XXXX-ptyN-XX')
120
+ name =~ /(msys-|cygwin-).*-pty/ ? true : false
121
+ end
122
+
123
+ def self.getwch
124
+ unless @@input_buf.empty?
125
+ return @@input_buf.shift
126
+ end
127
+ while @@kbhit.call == 0
128
+ sleep(0.001)
129
+ end
130
+ until @@kbhit.call == 0
131
+ ret = @@getwch.call
132
+ if ret == 0 or ret == 0xE0
133
+ @@input_buf << ret
134
+ ret = @@getwch.call
135
+ @@input_buf << ret
136
+ return @@input_buf.shift
137
+ end
138
+ begin
139
+ bytes = ret.chr(Encoding::UTF_8).bytes
140
+ @@input_buf.push(*bytes)
141
+ rescue Encoding::UndefinedConversionError
142
+ @@input_buf << ret
143
+ @@input_buf << @@getwch.call if ret == 224
144
+ end
145
+ end
146
+ @@input_buf.shift
147
+ end
148
+
149
+ def self.getc
150
+ num_of_events = 0.chr * 8
151
+ while @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) != 0 and num_of_events.unpack('L').first > 0
152
+ input_record = 0.chr * 18
153
+ read_event = 0.chr * 4
154
+ if @@ReadConsoleInput.(@@hConsoleInputHandle, input_record, 1, read_event) != 0
155
+ event = input_record[0, 2].unpack('s*').first
156
+ if event == WINDOW_BUFFER_SIZE_EVENT
157
+ @@winch_handler.()
158
+ end
159
+ end
160
+ end
161
+ unless @@output_buf.empty?
162
+ return @@output_buf.shift
163
+ end
164
+ input = getwch
165
+ meta = (@@GetKeyState.call(VK_LMENU) & 0x80) != 0
166
+ control = (@@GetKeyState.call(VK_CONTROL) & 0x80) != 0
167
+ shift = (@@GetKeyState.call(VK_SHIFT) & 0x80) != 0
168
+ force_enter = !input.instance_of?(Array) && (control or shift) && input == 0x0D
169
+ if force_enter
170
+ # It's treated as Meta+Enter on Windows
171
+ @@output_buf.push("\e".ord)
172
+ @@output_buf.push(input)
173
+ else
174
+ case input
175
+ when 0x00
176
+ meta = false
177
+ @@output_buf.push(input)
178
+ input = getwch
179
+ @@output_buf.push(*input)
180
+ when 0xE0
181
+ @@output_buf.push(input)
182
+ input = getwch
183
+ @@output_buf.push(*input)
184
+ when 0x03
185
+ @@output_buf.push(input)
186
+ else
187
+ @@output_buf.push(input)
188
+ end
189
+ end
190
+ if meta
191
+ "\e".ord
192
+ else
193
+ @@output_buf.shift
194
+ end
195
+ end
196
+
197
+ def self.ungetc(c)
198
+ @@output_buf.unshift(c)
199
+ end
200
+
201
+ def self.get_screen_size
202
+ csbi = 0.chr * 22
203
+ @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
204
+ csbi[0, 4].unpack('SS').reverse
205
+ end
206
+
207
+ def self.cursor_pos
208
+ csbi = 0.chr * 22
209
+ @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
210
+ x = csbi[4, 2].unpack('s*').first
211
+ y = csbi[6, 2].unpack('s*').first
212
+ Reline::CursorPos.new(x, y)
213
+ end
214
+
215
+ def self.move_cursor_column(val)
216
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, cursor_pos.y * 65536 + val)
217
+ end
218
+
219
+ def self.move_cursor_up(val)
220
+ if val > 0
221
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y - val) * 65536 + cursor_pos.x)
222
+ elsif val < 0
223
+ move_cursor_down(-val)
224
+ end
225
+ end
226
+
227
+ def self.move_cursor_down(val)
228
+ if val > 0
229
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x)
230
+ elsif val < 0
231
+ move_cursor_up(-val)
232
+ end
233
+ end
234
+
235
+ def self.erase_after_cursor
236
+ csbi = 0.chr * 24
237
+ @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
238
+ cursor = csbi[4, 4].unpack('L').first
239
+ written = 0.chr * 4
240
+ @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
241
+ end
242
+
243
+ def self.scroll_down(val)
244
+ return if val.zero?
245
+ scroll_rectangle = [0, val, get_screen_size.last, get_screen_size.first].pack('s4')
246
+ destination_origin = 0 # y * 65536 + x
247
+ fill = [' '.ord, 0].pack('SS')
248
+ @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
249
+ end
250
+
251
+ def self.clear_screen
252
+ # TODO: Use FillConsoleOutputCharacter and FillConsoleOutputAttribute
253
+ write "\e[2J"
254
+ write "\e[1;1H"
255
+ end
256
+
257
+ def self.set_screen_size(rows, columns)
258
+ raise NotImplementedError
259
+ end
260
+
261
+ def self.set_winch_handler(&handler)
262
+ @@winch_handler = handler
263
+ end
264
+
265
+ def self.prep
266
+ # do nothing
267
+ nil
268
+ end
269
+
270
+ def self.deprep(otio)
271
+ # do nothing
272
+ end
273
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reline
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - aycabta
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: io-console
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Alternative GNU Readline or Editline implementation by pure Ruby.
70
+ email:
71
+ - aycabta@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - BSDL
77
+ - COPYING
78
+ - README.md
79
+ - lib/reline.rb
80
+ - lib/reline/ansi.rb
81
+ - lib/reline/config.rb
82
+ - lib/reline/general_io.rb
83
+ - lib/reline/history.rb
84
+ - lib/reline/key_actor.rb
85
+ - lib/reline/key_actor/base.rb
86
+ - lib/reline/key_actor/emacs.rb
87
+ - lib/reline/key_actor/vi_command.rb
88
+ - lib/reline/key_actor/vi_insert.rb
89
+ - lib/reline/key_stroke.rb
90
+ - lib/reline/kill_ring.rb
91
+ - lib/reline/line_editor.rb
92
+ - lib/reline/unicode.rb
93
+ - lib/reline/unicode/east_asian_width.rb
94
+ - lib/reline/version.rb
95
+ - lib/reline/windows.rb
96
+ homepage: https://github.com/ruby/reline
97
+ licenses:
98
+ - Ruby License
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '2.5'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubygems_version: 3.1.2
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Alternative GNU Readline or Editline implementation by pure Ruby.
119
+ test_files: []