nvim 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ #
2
+ # neovim/foreign/mplight/bufferio.rb -- Buffer behaving like an IO
3
+ #
4
+
5
+ # The purpose of this is simply to reduce dependencies.
6
+
7
+ begin
8
+ require "mplight/bufferio"
9
+ rescue LoadError
10
+
11
+ # ----------------------------------------------------------------
12
+ #
13
+ # mplight/bufferio.rb -- Buffer behaving like an IO
14
+ #
15
+
16
+
17
+ module MPLight
18
+
19
+ class BufferIO
20
+
21
+ attr_reader :data
22
+
23
+ def initialize str = nil
24
+ @data = str||""
25
+ end
26
+
27
+ def binmode
28
+ @data.force_encoding Encoding::ASCII_8BIT
29
+ end
30
+ def sync= _ ; end
31
+ def sync ; true ; end
32
+
33
+ def write d
34
+ @data << d
35
+ end
36
+
37
+ def read n
38
+ @data.slice! 0, n
39
+ end
40
+
41
+ def flush
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ # ----------------------------------------------------------------
49
+
50
+ end
51
+
@@ -0,0 +1,327 @@
1
+ #
2
+ # neovim/foreign/mplight.rb -- Lightweight MessagePack implementation
3
+ #
4
+
5
+ # The purpose of this is simply to reduce dependencies.
6
+
7
+ begin
8
+ require "mplight"
9
+ rescue LoadError
10
+
11
+ # ----------------------------------------------------------------
12
+ #
13
+ # mplight.rb -- Lightweight MessagePack implementation
14
+ #
15
+
16
+
17
+ module MPLight
18
+
19
+ VERSION = "1.0".freeze
20
+
21
+ class Error ; end
22
+
23
+
24
+ class Types
25
+
26
+ def initialize *args, **kwargs
27
+ @cls = {}
28
+ @ids = {}
29
+ register -1, Time
30
+ end
31
+
32
+ def register id, klass
33
+ @cls[ id], @ids[ klass] = klass, id
34
+ end
35
+
36
+ def dump obj
37
+ t = @ids[ obj.class]
38
+ unless t then
39
+ return if @default_to_string
40
+ raise Error, "Unregistered class: #{obj.class}"
41
+ end
42
+ [ t, obj.to_mpdata]
43
+ end
44
+
45
+ def default_to_string! ; @default_to_string = true ; end
46
+
47
+ def create id, data
48
+ c = @cls[ id]
49
+ c or raise Error, "Unregistered type id: #{obj.class}"
50
+ c.from_mpdata data, *additional_data
51
+ end
52
+
53
+ def additional_data
54
+ []
55
+ end
56
+
57
+ end
58
+
59
+
60
+ module Packer
61
+
62
+ attr_reader :output
63
+
64
+ def init_output output
65
+ @output = output
66
+ @output.binmode
67
+ @output.sync = true
68
+ self
69
+ end
70
+
71
+ def do_output output
72
+ oi = @output
73
+ init_output output
74
+ yield
75
+ ensure
76
+ @output = oi
77
+ end
78
+
79
+ def put obj
80
+ case obj
81
+ when nil then write_fmt 0xc0
82
+ when false then write_fmt 0xc2
83
+ when true then write_fmt 0xc3
84
+ when Integer then
85
+ if obj >= 0 then
86
+ case obj
87
+ when ...0x80 then write_fmt obj
88
+ when ...0x100 then write_fmt 0xcc ; write_pack obj, "C"
89
+ when ...0x10000 then write_fmt 0xcd ; write_pack obj, "S>"
90
+ when ...0x100000000 then write_fmt 0xce ; write_pack obj, "L>"
91
+ when ...0x10000000000000000 then write_fmt 0xcf ; write_pack obj, "Q>"
92
+ else raise ArgumentError, "Integer too large: #{obj}"
93
+ end
94
+ else
95
+ case obj
96
+ when -0x20... then write_fmt obj+256
97
+ when -0x80... then write_fmt 0xd0 ; write_pack obj, "c"
98
+ when -0x8000... then write_fmt 0xd1 ; write_pack obj, "s>"
99
+ when -0x80000000... then write_fmt 0xd2 ; write_pack obj, "l>"
100
+ when -0x8000000000000000... then write_fmt 0xd3 ; write_pack obj, "q>"
101
+ else raise ArgumentError, "Integer too large: #{obj}"
102
+ end
103
+ end
104
+ when Float then
105
+ case
106
+ when false then write_fmt 0xca ; write_pack obj, "g"
107
+ else write_fmt 0xcb ; write_pack obj, "G"
108
+ end
109
+ when String then
110
+ if obj.encoding == Encoding::ASCII_8BIT then
111
+ l = obj.size
112
+ case l
113
+ when ...0x100 then write_fmt 0xc4 ; write_pack l, "C"
114
+ when ...0x10000 then write_fmt 0xc5 ; write_pack l, "S>"
115
+ when ...0x100000000 then write_fmt 0xc6 ; write_pack l, "L>"
116
+ else raise ArgumentError, "Byte array too long: #{l} bytes"
117
+ end
118
+ else
119
+ obj = obj.encode Encoding::UTF_8 unless obj.encoding == Encoding::UTF_8
120
+ l = obj.bytesize
121
+ case l
122
+ when ...0x20 then write_fmt 0xa0+l
123
+ when ...0x100 then write_fmt 0xd9 ; write_pack l, "C"
124
+ when ...0x10000 then write_fmt 0xda ; write_pack l, "S>"
125
+ when ...0x100000000 then write_fmt 0xdb ; write_pack l, "L>"
126
+ else raise ArgumentError, "String too long: #{l} bytes"
127
+ end
128
+ end
129
+ write_pack obj, "A*"
130
+ when Array then
131
+ l = obj.length
132
+ case l
133
+ when ...0x10 then write_fmt 0x90+l
134
+ when ...0x10000 then write_fmt 0xdc ; write_pack l, "S>"
135
+ when ...0x100000000 then write_fmt 0xdd ; write_pack l, "L>"
136
+ else raise ArgumentError, "Array too long: #{l} elements"
137
+ end
138
+ obj.each { |o| put o }
139
+ when Hash then
140
+ l = obj.length
141
+ case l
142
+ when ...0x10 then write_fmt 0x80+l
143
+ when ...0x10000 then write_fmt 0xde ; write_pack l, "S>"
144
+ when ...0x100000000 then write_fmt 0xdf ; write_pack l, "L>"
145
+ else raise ArgumentError, "Hash too long: #{l} keys"
146
+ end
147
+ obj.each { |k,v| put k ; put v }
148
+ when Symbol then
149
+ put obj.to_s
150
+ else
151
+ type, data = dump obj
152
+ type or return put obj.to_s
153
+ l = data.bytesize
154
+ case l
155
+ when 0x01 then write_fmt 0xd4 ; write_pack type, "c"
156
+ when 0x02 then write_fmt 0xd5 ; write_pack type, "c"
157
+ when 0x04 then write_fmt 0xd6 ; write_pack type, "c"
158
+ when 0x08 then write_fmt 0xd7 ; write_pack type, "c"
159
+ when 0x10 then write_fmt 0xd8 ; write_pack type, "c"
160
+ when ...0x100 then write_fmt 0xc7 ; write_pack l, "C" ; write_pack type, "c"
161
+ when ...0x10000 then write_fmt 0xc8 ; write_pack l, "S>" ; write_pack type, "c"
162
+ when ...0x100000000 then write_fmt 0xc9 ; write_pack l, "L>" ; write_pack type, "c"
163
+ else raise ArgumentError, "Object too large: #{l} bytes"
164
+ end
165
+ write_pack data, "A*"
166
+ end
167
+ self
168
+ end
169
+
170
+ private
171
+
172
+ def write_pack i, t
173
+ d = [i].pack t
174
+ @output.write d
175
+ end
176
+
177
+ def write_fmt i
178
+ write_pack i, "C"
179
+ end
180
+
181
+ end
182
+
183
+
184
+ module Unpacker
185
+
186
+ attr_reader :input
187
+
188
+ def init_input input
189
+ @input = input
190
+ @input.binmode
191
+ self
192
+ end
193
+
194
+ def do_input input
195
+ oi = @input
196
+ init_input input
197
+ yield
198
+ ensure
199
+ @input = oi
200
+ end
201
+
202
+ def eof?
203
+ @input.eof?
204
+ end
205
+
206
+ def get
207
+ fmt = (read 1).unpack1 "C"
208
+ case fmt >> 7
209
+ when 0b0 then fmt
210
+ else
211
+ case fmt >> 5
212
+ when 0b111 then fmt - 256
213
+ when 0b101 then get_str fmt&0b11111
214
+ else
215
+ case fmt >> 4
216
+ when 0b1000 then get_hsh fmt&0b1111
217
+ when 0b1001 then get_ary fmt&0b1111
218
+ else
219
+ case fmt
220
+ when 0xc0 then nil
221
+ when 0xc1 then raise ArgumentError, "Illegal format: #{fmt}"
222
+ when 0xc2 then false
223
+ when 0xc3 then true
224
+ when 0xc4 then read get_len1
225
+ when 0xc5 then read get_len2
226
+ when 0xc6 then read get_len4
227
+ when 0xc7 then get_ext get_len1
228
+ when 0xc8 then get_ext get_len2
229
+ when 0xc9 then get_ext get_len4
230
+ when 0xca then (read 4).unpack1 "g"
231
+ when 0xcb then (read 8).unpack1 "G"
232
+ when 0xcc then (read 1).unpack1 "C"
233
+ when 0xcd then (read 2).unpack1 "S>"
234
+ when 0xce then (read 4).unpack1 "L>"
235
+ when 0xcf then (read 8).unpack1 "Q>"
236
+ when 0xd0 then (read 1).unpack1 "c"
237
+ when 0xd1 then (read 2).unpack1 "s>"
238
+ when 0xd2 then (read 4).unpack1 "l>"
239
+ when 0xd3 then (read 8).unpack1 "q>"
240
+ when 0xd4 then get_ext 1
241
+ when 0xd5 then get_ext 2
242
+ when 0xd6 then get_ext 4
243
+ when 0xd7 then get_ext 8
244
+ when 0xd8 then get_ext 16
245
+ when 0xd9 then get_str get_len1
246
+ when 0xda then get_str get_len2
247
+ when 0xdb then get_str get_len4
248
+ when 0xdc then get_ary get_len2
249
+ when 0xdd then get_ary get_len4
250
+ when 0xde then get_hsh get_len2
251
+ when 0xdf then get_hsh get_len4
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
257
+
258
+ private
259
+
260
+ def read n
261
+ @input.read n
262
+ end
263
+
264
+ def get_len1 ; (read 1).unpack1 "C" ; end
265
+ def get_len2 ; (read 2).unpack1 "S>" ; end
266
+ def get_len4 ; (read 4).unpack1 "L>" ; end
267
+
268
+ def get_str len
269
+ (read len).force_encoding Encoding::UTF_8
270
+ end
271
+
272
+ def get_ary len
273
+ (0...len).map { get }
274
+ end
275
+
276
+ def get_hsh len
277
+ (0...len).inject Hash.new do |h,| k = get ; h[k] = get ; h end
278
+ end
279
+
280
+ def get_ext len
281
+ type = (read 1).unpack1 "c"
282
+ create type, (read len)
283
+ end
284
+
285
+ end
286
+
287
+ end
288
+
289
+
290
+ class Time
291
+
292
+ class <<self
293
+
294
+ def from_mpdata data, *args
295
+ case data.length
296
+ when 4 then
297
+ s, = data.unpack "L>"
298
+ Time.at s
299
+ when 8 then
300
+ t, = data.unpack "Q>"
301
+ n = t >> 34
302
+ t &= 0x3ffffffff
303
+ Time.at t, n, :nanosecond
304
+ when 12 then
305
+ n, s = data.unpack "L>Q>"
306
+ Time.at s, n, :nanosecond
307
+ else
308
+ raise ArgumentError, "Illegal time data: #{data.inspect}"
309
+ end
310
+ end
311
+
312
+ end
313
+
314
+ def to_mpdata
315
+ case
316
+ when tv_nsec.zero? && tv_sec < 0x100000000 then [ tv_sec].pack "L>"
317
+ when tv_sec < 0x400000000 then [ (tv_nsec << 34)|tv_sec].pack "Q>"
318
+ else [ tv_nsec, tv_sec].pack "L>Q>"
319
+ end
320
+ end
321
+
322
+ end
323
+
324
+ # ----------------------------------------------------------------
325
+
326
+ end
327
+
@@ -0,0 +1,20 @@
1
+ #
2
+ # neovim/foreign/supplement/socket.rb -- Addition usefull Ruby socket functions
3
+ #
4
+
5
+ # The purpose of this is simply to reduce dependencies.
6
+
7
+ begin
8
+ require "supplement/socket"
9
+ rescue LoadError
10
+ require "socket"
11
+ class TCPServer
12
+ alias accept_orig accept
13
+ private :accept_orig
14
+ def accept
15
+ a = accept_orig
16
+ if block_given? then yield a else a end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,34 @@
1
+ #
2
+ # neovim/foreign/supplement.rb -- Addition usefull Ruby functions
3
+ #
4
+
5
+ # The purpose of this is simply to reduce dependencies.
6
+
7
+ begin
8
+ require "supplement"
9
+ rescue LoadError
10
+ class NilClass ; def notempty? ; end ; end
11
+ class String ; def notempty? ; self unless empty? ; end ; end
12
+ class Array ; def notempty? ; self unless empty? ; end ; end
13
+ class NilClass ; def to_bool ; false ; end ; end
14
+ class FalseClass ; def to_bool ; false ; end ; end
15
+ class Object ; def to_bool ; true ; end ; end
16
+ class <<Struct ; alias [] new ; end
17
+ class String
18
+ def axe n
19
+ if n < length then
20
+ e = "..."
21
+ l = e.length
22
+ if n > l then
23
+ n -= l
24
+ else
25
+ l = 0
26
+ end
27
+ (slice 0, n) << "..."[0,l]
28
+ else
29
+ self
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,139 @@
1
+ #
2
+ # lib/neovim/handler.rb -- Handlers
3
+ #
4
+
5
+ require "neovim/foreign/supplement"
6
+
7
+
8
+ module Neovim
9
+
10
+ class Handler
11
+
12
+ attr_reader :spec
13
+
14
+ def initialize name, type = nil, sync = nil, **options, &block
15
+ @block = block
16
+ standardize options
17
+ @spec = {
18
+ name: name,
19
+ opts: options,
20
+ type: type,
21
+ sync: sync,
22
+ }
23
+ @spec.compact!
24
+ end
25
+
26
+ def name ; @spec[ :name] ; end
27
+ def opts ; @spec[ :opts] ; end
28
+ alias options opts
29
+ def sync ; @spec[ :sync] ; end
30
+ alias sync? sync
31
+
32
+ def execute *args
33
+ @block.call *args
34
+ end
35
+
36
+ private
37
+
38
+ def standardize opts
39
+ opts.each { |k,v|
40
+ case v
41
+ when false then opts[ k] = nil
42
+ when true then opts[ k] = ""
43
+ when String, Integer then
44
+ else opts[ k] = v.to_s
45
+ end
46
+ }
47
+ opts.compact!
48
+ end
49
+
50
+ end
51
+
52
+ class DslBase
53
+
54
+ class Plugins
55
+
56
+ attr_reader :type
57
+
58
+ def initialize type, setup_blocks, handlers
59
+ @type, @setup_blocks, @handlers = type, setup_blocks, handlers
60
+ end
61
+
62
+ def setup client
63
+ @setup_blocks.each { |b| b.call client }
64
+ end
65
+
66
+ def get_handler name
67
+ @handlers[ name]
68
+ end
69
+
70
+ def specs
71
+ @handlers.map { |_,handler| handler.spec }
72
+ end
73
+
74
+ def options
75
+ @handlers.each { |name,handler| yield name, handler.options }
76
+ end
77
+
78
+ end
79
+
80
+ include Logging
81
+
82
+ class <<self
83
+ private :new
84
+ def open source, host
85
+ i = new source
86
+ yield i
87
+ i.add_plugins source, host
88
+ end
89
+ end
90
+
91
+ def initialize source
92
+ @setup_blocks = []
93
+ @handlers = {}
94
+ end
95
+
96
+ def add_plugins source, host
97
+ host.add_plugins source, (Plugins.new self.class::TYPE, @setup_blocks, @handlers)
98
+ end
99
+
100
+ private
101
+
102
+ def add_handler qualified_name, name, type = nil, sync = nil, **opts, &block
103
+ name = name.to_s
104
+ qualified_name ||= name
105
+ h = Handler.new name, type, sync, **opts, &block
106
+ log :info, "Adding Handler", qualified_name: qualified_name, handler: h.spec
107
+ @handlers[ qualified_name] = h
108
+ end
109
+
110
+ def add_setup_block &block
111
+ @setup_blocks.push block
112
+ end
113
+
114
+ end
115
+
116
+ class DslPlain < DslBase
117
+
118
+ TYPE = :base
119
+
120
+ def plain name, **opts
121
+ add_handler nil, name, **opts do |client,*args|
122
+ yield *args
123
+ end
124
+ end
125
+
126
+ end
127
+
128
+ class DslRemote < DslBase
129
+
130
+ TYPE = :remote
131
+
132
+ def register_handler name, &block
133
+ add_handler nil, name, &block
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+
@@ -0,0 +1,87 @@
1
+ #
2
+ # neovim/host.rb -- Host for Neovim
3
+ #
4
+
5
+ require "neovim/remote"
6
+
7
+
8
+ module Neovim
9
+
10
+ class Host < Remote
11
+
12
+ class <<self
13
+
14
+ def start
15
+ super ConnectionStdio do |h|
16
+ yield h
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ attr_reader :plugins
23
+
24
+ BASE = :base
25
+
26
+ def initialize conn
27
+ super
28
+ DslPlain.open BASE, self do |dsl|
29
+ dsl.plain "poll" do
30
+ start
31
+ @plugins.each_value { |p| p.setup @conn.client }
32
+ "ok"
33
+ end
34
+ dsl.plain "specs", nargs: 1 do |source|
35
+ p = @plugins[ source]
36
+ p or raise "Unknown plugin #{source}"
37
+ p.specs
38
+ end
39
+ dsl.plain "nvim_error_event", nargs: 2 do |errid,msg|
40
+ raise "#{@conn.error errid} from Neovim: #{msg}"
41
+ end
42
+ end
43
+ end
44
+
45
+ def client_name
46
+ types = @plugins.map { |_,p| p.type if p.type != BASE }
47
+ types.uniq!
48
+ types.compact!
49
+ name = types.join "-"
50
+ log :info, "Client Name", name: name
51
+ "ruby-#{name}-host"
52
+ end
53
+
54
+ def client_methods
55
+ r = {}
56
+ @plugins[ BASE].options { |name,opts| r[ name] = opts }
57
+ r
58
+ end
59
+
60
+
61
+ class <<self
62
+
63
+ def run
64
+ $stdin.tty? and raise "This program expects to be called by Neovim. It can't run interactively."
65
+ Host.start do |h|
66
+ yield h
67
+ h.run
68
+ nil
69
+ rescue Messager::Disconnected
70
+ log :fatal, "Disconnected"
71
+ nil
72
+ rescue SignalException
73
+ n = $!.signm
74
+ log :fatal, "Signal was caught: #{n}"
75
+ (n =~ /\A(?:SIG)?TERM\z/) ? 0 : 1
76
+ rescue Exception
77
+ log_exception :fatal
78
+ 2
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
@@ -0,0 +1,10 @@
1
+ require "neovim/meta.rb"
2
+ Neovim::INFO = Neovim::Meta.new "nvim",
3
+ version: "1.0.0",
4
+ license: "BSD-2-Clause+",
5
+ authors: ["Bertram Scharpf"],
6
+ email: "software@bertram-scharpf.de",
7
+ summary: "Yet another Ruby client for Neovim",
8
+ description: "A simple Ruby client for Neovim.\nClean code, minimal dependecies, no frills, no wokeness.",
9
+ homepage: "http://bertram-scharpf.de",
10
+ commit: "e927f7e"