reline 0.0.4

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