nvim 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d8207d1ea220ae3a18b71de6377beaac8f117b7b8fb2c816f773a36dc2852043
4
+ data.tar.gz: eb0c7bf8c52bc66a26952c5985edc3a0ffca154b0ba51560f9802428e51594b2
5
+ SHA512:
6
+ metadata.gz: 17c4b731220d2da8b667da00bfba85b63f27664d0d6119f4d021b92e66c24ecabd279abc090b8cba6b5ff84baeb2561d6ce3410c7fabb1c91a94857c82d2f82e
7
+ data.tar.gz: 3197fe71bdd9506350206fff209e2b0c9fb93bfa926f204e4bebcbacfee849a566b42f9f576efdeb86ee751fbc7b8197a07329fe6e2e9191b735ad86ac3c9604
data/INFO.yaml ADDED
@@ -0,0 +1,18 @@
1
+ #
2
+ # INFO.yaml -- Version number etc.
3
+ #
4
+
5
+ nvim:
6
+ version: 1.0.0
7
+ license: BSD-2-Clause+
8
+ authors:
9
+ - Bertram Scharpf
10
+ email: software@bertram-scharpf.de
11
+
12
+ summary: Yet another Ruby client for Neovim
13
+ description: |-
14
+ A simple Ruby client for Neovim.
15
+ Clean code, minimal dependecies, no frills, no wokeness.
16
+
17
+ homepage: http://bertram-scharpf.de
18
+
data/LICENSE ADDED
@@ -0,0 +1,52 @@
1
+ # BSD-2-clause license, extended by language use conditions
2
+
3
+ Copyright (C) 2024, Bertram Scharpf <software@bertram-scharpf.de>.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are
8
+ met:
9
+
10
+ * Redistributions of source code must retain the above copyright
11
+ notice, this list of conditions and the following disclaimer.
12
+
13
+ * Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in
15
+ the documentation and/or other materials provided with the
16
+ distribution.
17
+
18
+ * Redistributions must not contain any clauses about anticipated
19
+ harassment or discrimination, nor must they be held in a so-called
20
+ "inclusive language". As far as German language is used, the
21
+ conditions mentioned below additionally apply.
22
+
23
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
27
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+
35
+
36
+ ## Use of the German Language
37
+
38
+ Beim Gebrauch deutscher Sprache sind Weiterentwicklungen und
39
+ -verbreitungen nur gestattet unter Einhaltung folgender
40
+ zusätzlicher Bedingungen:
41
+
42
+ * Keine Verwendung von sogenannter „geschlechtergerechter Sprache“,
43
+ also Anfügen von weiblichen Endungen mit Binnen-I, Sternchen,
44
+ Doppelpunkt, Unterstrich oder ähnlichem, oder Konstruktionen, die
45
+ den Sachverhalt falsch wiedergeben („Radfahrende“, „Studierende“).
46
+
47
+ * Keine Verwendung der „reformierten Rechtschreibung“ von 1996,
48
+ insbesondere Doppel-S am Silbenende, „plazieren“ mit T, sowie
49
+ Großschreibung von Wendungen wie „des weiteren“.
50
+
51
+
52
+ <!-- vim:set ft=markdown : -->
data/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # Ruby-Nvim
2
+
3
+ Ruby support for [Neovim](https://github.com/neovim/neovim).
4
+
5
+ Clean code, minimal dependecies, no frills, no wokeness.
6
+
7
+ *I would have written a shorter letter, but I did not have the time.* --
8
+ Blaise Pascal
9
+
10
+
11
+ ## Installation
12
+
13
+ ```shell
14
+ sudo gem uninstall neovim || true
15
+ sudo gem install nvim
16
+ ```
17
+
18
+ You may prefer to also install the dependencies. Yet, this is not
19
+ neccessary, as they are small and Ruby-Nvim includes a copy of them.
20
+
21
+ ```shell
22
+ sudo gem install supplement mplight
23
+ ```
24
+
25
+
26
+ ## Usage
27
+
28
+
29
+ ### Command, Function and Autoload Plugins
30
+
31
+ Put this into a new buffer:
32
+
33
+ ```ruby
34
+ Neovim.plugin do |dsl|
35
+ dsl.command :SetLine, nargs: 1 do |client,(str)|
36
+ client.set_current_line str
37
+ end
38
+ dsl.function :Sum, nargs: 2, sync: true do |client,(x,y)|
39
+ x + y
40
+ end
41
+ dsl.autocmd :BufEnter, pattern: "*.rb" do |client|
42
+ client.command "echom 'Hello, Ruby!'"
43
+ end
44
+ end
45
+ ```
46
+
47
+ Then run these Vim commands:
48
+
49
+ ```vim
50
+ w ++p ~/.config/nvim/rplugin/ruby/demo.rb
51
+ UpdateRemotePlugins
52
+
53
+ " Check the generated manifest file
54
+ split ~/.local/share/nvim/rplugin.vim
55
+ help remote-plugin-manifest
56
+ ```
57
+
58
+ Open a new Neovim and see what happens:
59
+
60
+ ```vim
61
+ e dummy.rb
62
+ SetLine some text
63
+ echo Sum(13,7)
64
+ ```
65
+
66
+
67
+ ### Calling the :ruby... Interface
68
+
69
+ The `:ruby...` commands and the `rubyeval()` function behave as descibed
70
+ in `:h ruby`.
71
+
72
+ Additionally you can directly execute the buffers contents:
73
+
74
+ ```vim
75
+ set number
76
+ ```
77
+
78
+ ```
79
+ 1 class C
80
+ 2 def f
81
+ 3 :F
82
+ 4 end
83
+ 5 end
84
+ 6 c = C.new
85
+ ~
86
+ ~
87
+ ~
88
+ :1,6ruby |
89
+ ```
90
+
91
+ The last value, if it is not `nil`, will be added through `#inspect` as
92
+ a comment.
93
+
94
+ ```
95
+ 1 class C
96
+ 2 def f
97
+ 3 :F
98
+ 4 end
99
+ 5 end
100
+ 6 c = C.new
101
+ 7 #=> #<C:0x000001b347456478>
102
+ ~
103
+ ~
104
+ :
105
+ ```
106
+
107
+ The classes and variables will be preserved and are available during the
108
+ next call.
109
+
110
+ ```
111
+ 5 end
112
+ 6 c = C.new
113
+ 7 #=> #<C:0x00001fd2fd1f89d0>
114
+ 8 [ c.f, C]
115
+ ~
116
+ ~
117
+ ~
118
+ :8ruby |
119
+ ```
120
+
121
+ This results in:
122
+
123
+ ```
124
+ 7 #=> #<C:0x00001fd2fd1f89d0>
125
+ 8 [ c.f, C]
126
+ 9 #=> [:F, C]
127
+ ~
128
+ ~
129
+ :
130
+ ```
131
+
132
+ Output will be added to the buffer, too.
133
+
134
+ ```
135
+ 1 puts "ba" + "na"*2
136
+ 2 print "hell"
137
+ 3 puts "o"
138
+ ~
139
+ ~
140
+ :%ruby |
141
+ ```
142
+
143
+ Further, a simple number/cash summing tool is included.
144
+
145
+ ```
146
+ Apples : 3.99
147
+ Bananas : 5 * 0.40 # multiplication
148
+ Oranges : 3.59 | -10% # percentage added (here subtracted)
149
+ Kiwi : 0,40 # comma is allowed
150
+ Coconut : 5,- # empty decimal places
151
+ ~
152
+ ~
153
+ :%ruby +
154
+ ```
155
+
156
+
157
+ ### Modern rpcrequest() Calls
158
+
159
+ Put this into a new buffer:
160
+
161
+ ```ruby
162
+ require "neovim"
163
+ counter = 0
164
+ Neovim.start_remote do |dsl|
165
+ dsl.register_handler "rb_add" do |client,n|
166
+ counter += n
167
+ client.command "echo 'Counter value now is: '..#{counter}..'.'"
168
+ end
169
+ dsl.register_handler "rb_raise" do |client|
170
+ raise "Ouch!"
171
+ end
172
+ end
173
+ ```
174
+
175
+ Then enter these Vim commands:
176
+
177
+ ```vim
178
+ w demo_remote.rb
179
+ let chan = jobstart(['ruby','demo_remote.rb'], { 'rpc': v:true })
180
+ call rpcrequest(chan, 'rb_add', 7)
181
+ call rpcrequest(chan, 'rb_raise')
182
+ call jobstop(chan)
183
+ ```
184
+
185
+ If you prefer, you can also use a shebang line.
186
+
187
+ ```ruby
188
+ #!/usr/bin/env ruby
189
+ require "neovim"
190
+ Neovim.start_remote do |dsl|
191
+ # ... (as above)
192
+ end
193
+ ```
194
+
195
+ Then enter these Vim commands:
196
+
197
+ ```vim
198
+ w demo_remote.rb
199
+ !chmod +x %
200
+ let chan = jobstart('./demo_remote.rb', { 'rpc': v:true })
201
+ " proceed as above
202
+ ```
203
+
204
+
205
+ ### Logging and Debugging
206
+
207
+ Logging is a easy as this:
208
+
209
+ ```shell
210
+ export NVIM_RUBY_LOG_LEVEL=all NVIM_RUBY_LOG_FILE=nvim.log
211
+ nvim +'ruby puts "hi"*10'
212
+ ```
213
+
214
+ To show the log levels, simply run in Neovim:
215
+
216
+ ```vim
217
+ ruby puts Neovim::Logging::LEVELS.keys
218
+ ```
219
+
220
+ If you are inside a [Tmux](https://tmux.github.io), you might prefer to trace the colored log in a split window.
221
+
222
+ ```shell
223
+ tmux split-window -fhd 'echo -e "\e[33m==== $$ ==== `tty` ====\e[m" ; ln -sf `tty` /tmp/tmux-`id -u`/debug ; exec cat >/dev/null 2>&1'
224
+ export NVIM_RUBY_LOG_LEVEL=all NVIM_RUBY_LOG_FILE=/tmp/tmux-`id -u`/debug
225
+
226
+ examples/demo_attach
227
+
228
+ nvim +'ruby puts "hi"*10'
229
+ ```
230
+
231
+ You may start an interactive session and control a running Neovim through it.
232
+ Open Neovim specifying the `--listen` option
233
+
234
+ ```shell
235
+ nvim --listen /path/to/some.sock
236
+ ```
237
+
238
+ or ask the running Neovim for its server name.
239
+
240
+ ```vim
241
+ echo v:servername
242
+ ```
243
+
244
+ Then connect to it. This requires the [Intar](https://github.com/BertramScharpf/ruby-intar) gem.
245
+
246
+ ```
247
+ $ intar -r neovim/remote
248
+ main:0:001> include Neovim
249
+ => Object
250
+ main:0:002> Remote.start_client ConnectionUnix, "/path/to/some.sock" do |c|&
251
+ main:1:001> c.command "e /etc/passwd"
252
+ main:1:002> b = c.get_current_buf
253
+ => #<Neovim::Buffer:400 1>
254
+ main:1:003> b[1]
255
+ => ["root:*:0:0:Charlie &:/root:/bin/sh"]
256
+ main:1:004> \q!!
257
+ ```
258
+
259
+
260
+ ## Copyright
261
+
262
+ * (C) 2024 Bertram Scharpf <software@bertram-scharpf.de>
263
+ * License: [BSD-2-Clause+](./LICENSE)
264
+
data/Rakefile ADDED
@@ -0,0 +1,68 @@
1
+ #
2
+ # Rakefile -- Generate files
3
+ #
4
+
5
+
6
+ INFOFILE = "lib/neovim/info.rb"
7
+
8
+
9
+ GENERATED = [ INFOFILE]
10
+
11
+ task :default => GENERATED
12
+ task :infofile => INFOFILE
13
+
14
+
15
+ file INFOFILE => "INFO.yaml" do |f|
16
+ create_info f.name, f.source
17
+ end
18
+
19
+
20
+ task :clean do
21
+ rm *GENERATED
22
+ end
23
+
24
+
25
+ def commit
26
+ c = `git rev-parse --short HEAD`
27
+ c.chomp!
28
+ c
29
+ end
30
+
31
+ def create_info dst, src
32
+ File.open dst, "w" do |vf|
33
+ require "yaml"
34
+ m = YAML.load File.read src
35
+ name = m.keys.first
36
+ args = m[ name]
37
+ args[ :commit] = commit
38
+ unless args[ :authors] then
39
+ u = args.delete :author
40
+ args[ :authors] = [ u] if u
41
+ end
42
+ vf.puts 'require "neovim/meta.rb"'
43
+ vf.print "Neovim::INFO = Neovim::Meta.new #{name.inspect}"
44
+ args.each { |k,v|
45
+ vf.puts ","
46
+ vf.print " #{k.to_sym}: #{v.inspect}"
47
+ }
48
+ vf.puts
49
+ end
50
+ end
51
+
52
+
53
+ task :diffdeps do
54
+ %w(mplight).each { |gem|
55
+ c = `gem contents #{gem}`
56
+ unless $?.success? then
57
+ puts "Gem #{gem} not installed. Cannot compare."
58
+ next
59
+ end
60
+ (c.split $/).each { |file|
61
+ if file =~ %r[/gems/#{gem}-.*/lib/(.*\.rb)$] then
62
+ ours = "lib/neovim/foreign/#$1"
63
+ sh *%W(nvim -d #{ours} #{file}) if File.exist? ours
64
+ end
65
+ }
66
+ }
67
+ end
68
+
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # bin/neovim-ruby-host -- Child started by Neovim
5
+ #
6
+
7
+ require "neovim/host"
8
+
9
+
10
+ module Neovim
11
+
12
+ class <<self
13
+
14
+ def plugin &block
15
+ require "neovim/vimscript_provider"
16
+ run_dsl DslVimscript, &block
17
+ end
18
+
19
+ private
20
+
21
+ def run_dsl dsl
22
+ @host or raise "Can't add plugins outside of a running session."
23
+ dsl.open @path, @host do |dsl|
24
+ yield dsl
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ if $*.delete "--version" then
31
+ puts [ Neovim::INFO.name, Neovim::INFO.version].join " "
32
+ exit
33
+ end
34
+
35
+ r = Host.run do |h|
36
+ begin
37
+ @host = h
38
+ $*.each do |p|
39
+ @path = p
40
+ Kernel.load @path, true
41
+ ensure
42
+ @path = nil
43
+ end
44
+ ensure
45
+ @host = nil
46
+ end
47
+ end
48
+ exit r.to_i
49
+
50
+ end
51
+
@@ -0,0 +1,108 @@
1
+ #
2
+ # neovim/client.rb -- Clients
3
+ #
4
+
5
+ require "neovim/foreign/supplement"
6
+
7
+ require "neovim/remote_object"
8
+
9
+
10
+ module Neovim
11
+
12
+ class Client
13
+
14
+ @strict = true
15
+ class <<self
16
+ attr_accessor :strict
17
+ end
18
+
19
+ class UnknownApiFunction < RuntimeError ; end
20
+ class UnknownApiObjectFunction < RuntimeError ; end
21
+
22
+
23
+ attr_reader :channel_id
24
+
25
+ def initialize comm, channel_id
26
+ @comm, @channel_id = comm, channel_id
27
+ @functions = {}
28
+ @objfuncs = Hash.new do |h,k| h[k] = {} end
29
+ end
30
+
31
+ def inspect
32
+ "#<#{self.class} #@channel_id>"
33
+ end
34
+
35
+ def add_functions list, prefixes
36
+ list.each { |fn|
37
+ next if fn[ "deprecated_since"] && self.class.strict
38
+ n = fn[ "name"]
39
+ next unless n =~ /\Anvim_/
40
+ @functions[ $'.to_sym] = n
41
+ t, = prefixes.find { |t,p| n =~ p }
42
+ @objfuncs[ t][ $'.to_sym] = n if t
43
+ }
44
+ end
45
+
46
+
47
+ def call_api name, *args
48
+ f = @functions[ name.to_sym]
49
+ f or raise UnknownApiFunction, "Function: #{name}"
50
+ @comm.request f, *args
51
+ end
52
+
53
+ def call_obj obj, name, *args
54
+ n = obj.type
55
+ f = @objfuncs[ n.to_sym][ name.to_sym]
56
+ f or raise UnknownApiObjectFunction, "Object: #{n}, Function: #{name}"
57
+ @comm.request f, obj.index, *args
58
+ end
59
+
60
+
61
+
62
+ def method_missing sym, *args
63
+ call_api sym, *args
64
+ rescue UnknownApiFunction
65
+ super
66
+ end
67
+
68
+ def respond_to_missing? sym, priv = nil
69
+ # Be aware that calling a proc (our handlers) with a single argument
70
+ # asks whether that argument is an array. In case it is a Client object,
71
+ # we end up here with +sym = to_ary+.
72
+ @functions[ sym.to_sym].to_bool
73
+ end
74
+
75
+ def methods regular = true
76
+ s = super
77
+ s |= @functions.keys if regular
78
+ s
79
+ end
80
+
81
+
82
+ def has_obj_function? obj, name
83
+ @objfuncs[ obj.type][ name.to_sym].to_bool
84
+ end
85
+
86
+ def obj_functions obj
87
+ @objfuncs[ obj.type].keys
88
+ end
89
+
90
+
91
+
92
+ def message str
93
+ call_api :out_write, str
94
+ str.end_with? $/ or call_api :out_write, $/
95
+ end
96
+
97
+
98
+ include OptionAccess
99
+ OPTION_PARAM = nil
100
+
101
+ def command arg ; call_api :command, arg ; end
102
+
103
+ def evaluate expr ; call_api :eval, expr ; end
104
+
105
+ end
106
+
107
+ end
108
+
@@ -0,0 +1,129 @@
1
+ #
2
+ # neovim/connection.rb -- Connections
3
+ #
4
+
5
+ require "neovim/logging"
6
+ require "neovim/client"
7
+ require "neovim/info"
8
+
9
+
10
+ module Neovim
11
+
12
+ class Connection < MPLight::Types
13
+
14
+ include Logging
15
+
16
+ include MPLight::Packer, MPLight::Unpacker
17
+
18
+ attr_reader :client
19
+
20
+ def initialize rd, wr
21
+ super
22
+ default_to_string!
23
+ init_input rd
24
+ init_output wr
25
+ @errors = {}
26
+ end
27
+
28
+ def additional_data ; [ *super, @client] ; end
29
+
30
+
31
+ def error id
32
+ @errors[ id] || "Error #{id}"
33
+ end
34
+
35
+
36
+ def start comm, client_name, client_type, client_methods = nil
37
+ comm.notify :nvim_set_client_info, client_name, Neovim::INFO.version_h, client_type, client_methods||{}, Neovim::INFO.attributes
38
+ channel_id, api_info = *(comm.request :nvim_get_api_info)
39
+ @client = Client.new comm, channel_id
40
+ prefixes = {}
41
+ api_info[ "types"].each do |type,info|
42
+ type = type.to_sym
43
+ prefixes[ type] = /\A#{info[ "prefix"]}/
44
+ register_type type, info[ "id"]
45
+ end
46
+ @client.add_functions api_info[ "functions"], prefixes
47
+ api_info[ "error_types"].each { |type,info|
48
+ register_error type, info[ "id"]
49
+ }
50
+ nil
51
+ end
52
+
53
+ private
54
+
55
+ def register_type type, id
56
+ klass = Neovim.const_get type
57
+ klass or raise "Class #{type} is not defined."
58
+ klass < RemoteObject or raise "Class #{klass} is not a descendant of RemoteObject."
59
+ log :debug2, "Registering type", type: type, id: id
60
+ register id, klass
61
+ end
62
+
63
+ def register_error id, type
64
+ @errors[ id] = type
65
+ end
66
+
67
+ end
68
+
69
+
70
+ class ConnectionTcp < Connection
71
+ class <<self
72
+ def open_files host, port
73
+ require "socket"
74
+ TCPSocket.open host, port do |socket|
75
+ yield (new socket, socket)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ class ConnectionUnix < Connection
82
+ class <<self
83
+ def open_files path
84
+ require "socket"
85
+ UNIXSocket.open path do |socket|
86
+ yield (new socket, socket)
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ class ConnectionChild < Connection
93
+
94
+ class <<self
95
+
96
+ def open_files *argv
97
+ eb = "--embed"
98
+ argv.unshift eb unless argv.include? eb
99
+ argv.unshift path
100
+ IO.popen argv, "r+" do |io|
101
+ Process.detach io.pid
102
+ yield (new io, io)
103
+ end
104
+ end
105
+
106
+ def path
107
+ ENV[ "NVIM_EXECUTABLE"].notempty? || "nvim"
108
+ end
109
+
110
+ def version
111
+ IO.popen [ path, "--version"] do |io|
112
+ io.gets[ /\ANVIM +v?(.+)/, 1]
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+
120
+ class ConnectionStdio < Connection
121
+ class <<self
122
+ def open_files *argv
123
+ yield (new $stdin, $stdout)
124
+ end
125
+ end
126
+ end
127
+
128
+ end
129
+