nvim 1.4.0 → 1.5.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee36b4c5053b9d05ab3a47d66b5b248aeacc3ffd340b282db719200c298a3fe1
4
- data.tar.gz: aa714f06cd14114dfc406afbec1e38ce452ff3cdb935c0f2dfeecba6762c1ec3
3
+ metadata.gz: b2f33b262cf70f6226c1af40d6b6173c56f5d808e7e4ba6629caa342f3131944
4
+ data.tar.gz: b78833e0442c2ba8e6a74786576bb4dcfecf5ecebf005bd45dd1c9b4a49732f5
5
5
  SHA512:
6
- metadata.gz: 7867c1fc7051d1776058d412e71c56f4127d06176fa3b9f0ce744ab2171e738626eb47916dc186551799be637d7eca565a48ed24b19014400818c805548be7d9
7
- data.tar.gz: 8913f88061341f6282c05f041e8ac734bb664a775a711e00e1080af97d674a3b38e8988265fdb7d1ab38393615b48b08abd690cf1c8fbd6fa3d703f6d97c876a
6
+ metadata.gz: 49a0ba665e6d93a4f629b1b0375c29237d90cbb2510bb99d4ff3e4533f7e5cab68c76ee841cc7b25a5117411f5fb5e2ab24d3763f9cf4fa9617b9bef4d693cab
7
+ data.tar.gz: 1dafb13f71a994566f383577de178766fa6e0dc05a36075dc2af53c77cf3c5a0c8b21ac8dc08835fcbe89824441b857a193cfa8a503537f8ad642775276b8f6b
data/INFO.yaml CHANGED
@@ -3,7 +3,7 @@
3
3
  #
4
4
 
5
5
  nvim:
6
- version: 1.4.0
6
+ version: 1.5.1
7
7
  license: BSD-2-Clause+
8
8
  authors:
9
9
  - Bertram Scharpf
data/LICENSE CHANGED
@@ -36,8 +36,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
36
  ## Use of the German Language
37
37
 
38
38
  Beim Gebrauch deutscher Sprache sind Weiterentwicklungen und
39
- -verbreitungen nur gestattet unter Einhaltung folgender
40
- zusätzlicher Bedingungen:
39
+ -verbreitungen nur gestattet unter Einhaltung sowie abermaligen
40
+ Einforderns folgender zusätzlicher Bedingungen:
41
41
 
42
42
  * Keine Verwendung von sogenannter „geschlechtergerechter Sprache“,
43
43
  also Anfügen von weiblichen Endungen mit Binnen-I, Sternchen,
data/README.md CHANGED
@@ -15,7 +15,7 @@ sudo gem uninstall neovim || true
15
15
  sudo gem install nvim
16
16
  ```
17
17
 
18
- You may prefer to also install the dependencies. Yet, this is not
18
+ You may prefer to also install the dependencies. Yet, this is not
19
19
  neccessary, as they are small and Ruby-Nvim includes a copy of them.
20
20
 
21
21
  ```shell
@@ -91,7 +91,7 @@ set number
91
91
  :1,6ruby |
92
92
  ```
93
93
 
94
- The last value, if it is not `nil`, will be added through `#inspect` as
94
+ The last value, if it is not `nil`, will be added through `#inspect` as
95
95
  a comment.
96
96
 
97
97
  ```
@@ -132,7 +132,44 @@ This results in:
132
132
  :
133
133
  ```
134
134
 
135
- The anonymous variable `_` hold this last result.
135
+ To inhibit the output of the last value, add a minus (`-`) to the
136
+ `:ruby|` call.
137
+
138
+ ```
139
+ pp Regexp.constants
140
+ ~
141
+ ~
142
+ :.ruby |-
143
+ ```
144
+
145
+ In this case, you may even omit the pipe (`|`) character.
146
+
147
+
148
+ #### Last return value
149
+
150
+ The anonymous variable `_` will hold the result
151
+ of the last evaluation.
152
+
153
+ ```
154
+ 1 7*11*13
155
+ ~
156
+ ~
157
+ :%ruby |
158
+ ```
159
+
160
+ Then this will work:
161
+
162
+ ```
163
+ 1 7*11*13
164
+ 2 #=> 1001
165
+ 3 _ - 1
166
+ ~
167
+ ~
168
+ :3ruby |
169
+ ```
170
+
171
+
172
+ #### Standard output
136
173
 
137
174
  Output will be added to the buffer, too.
138
175
 
@@ -142,9 +179,63 @@ Output will be added to the buffer, too.
142
179
  3 puts "o"
143
180
  ~
144
181
  ~
182
+ :1,3ruby |
183
+ ```
184
+
185
+ Error output will be displayed on the command line,
186
+ highlighted by `ErrorMsg`.
187
+
188
+ ```
189
+ 1 $stderr.puts "Oh, no!"
190
+ ~
191
+ ~
192
+ :%ruby |
193
+ ```
194
+
195
+ This even applies to subprocesses. They won't mess up
196
+ the RPC communication.
197
+
198
+ ```
199
+ 1 system *%w(ls -l)
200
+ 2 system *%w(ls nonexistent)
201
+ ~
202
+ ~
145
203
  :%ruby |
146
204
  ```
147
205
 
206
+ Yet, you should avoid to use `fork` and `exec`, except when
207
+ you're absolutely sure what you're doing.
208
+
209
+
210
+ ### List all API functions
211
+
212
+ To show a list of the API functions call something like this:
213
+
214
+ ```
215
+ pp $vim.functions.sort
216
+ pp $vim.obj_classes.map { |c| [ c.type, ($vim.obj_functions c).sort] }.to_h
217
+ ~
218
+ ~
219
+ :%ruby |-
220
+ ```
221
+
222
+ Deprecated functions and old functions not starting with `nvim_` will be
223
+ hidden. The full list of API functions can be obtained by a call to
224
+ `get_api_info`.
225
+
226
+ ```
227
+ pp $vim.get_api_info
228
+ ~
229
+ ~
230
+ :.ruby |-
231
+ ```
232
+
233
+ See the script `examples/dump_api` for a more elaborated and colorized
234
+ output.
235
+
236
+
237
+ ### Calculator
238
+
148
239
  Further, a simple number/cash summing tool is included.
149
240
 
150
241
  ```
@@ -253,7 +344,7 @@ or ask the running Neovim for its server name.
253
344
  echo v:servername
254
345
  ```
255
346
 
256
- Then connect to it. This requires the [Intar](https://github.com/BertramScharpf/ruby-intar) gem.
347
+ Then connect to it. This requires the [Intar](https://github.com/BertramScharpf/ruby-intar) gem.
257
348
 
258
349
  ```
259
350
  $ intar -r neovim/remote
@@ -276,7 +367,7 @@ Put text into an X selection or a TMux register.
276
367
  ```vim
277
368
  let g:ruby_require = "neovim/tools/copy"
278
369
  '<,'>ruby xsel $lines
279
- '<,'>ruby xsel! $ines
370
+ '<,'>ruby xsel! $lines
280
371
  '<,'>ruby tmuxbuf $lines
281
372
  ```
282
373
 
data/examples/demo.rb ADDED
@@ -0,0 +1,35 @@
1
+ #
2
+ # demo.rb -- Demo plugin
3
+ #
4
+
5
+
6
+ Neovim.plugin do |dsl|
7
+
8
+ dsl.command :SetLine, nargs: 1 do |client,(str)|
9
+ client.set_current_line str
10
+ end
11
+
12
+ dsl.command :Fail, nargs: 0 do |client|
13
+ raise "ouch!"
14
+ end
15
+
16
+ dsl.function :Sum, nargs: 2, sync: true do |client,x,y|
17
+ x + y
18
+ end
19
+
20
+ dsl.function :Fail do |client|
21
+ raise "ouch!"
22
+ end
23
+
24
+ dsl.function :Other, nargs: 2, range: true, eval: "strftime('%s')" do |client,(x,y),range,evaled|
25
+ r = "<<<#{x}---#{y}===#{range}---#{evaled}>>>"
26
+ client.buf_set_lines 0, 0, 0, false, [r.inspect]
27
+ r
28
+ end
29
+
30
+ dsl.autocmd :BufEnter, pattern: "*.rb" do |client|
31
+ client.command "echom 'Hello, Ruby!'"
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # demo_attach -- Start a Neovim session and attach to it
5
+ #
6
+
7
+ require "neovim/remote"
8
+
9
+
10
+ module Neovim
11
+
12
+ SOCKET = "/tmp/nvim-#$$.sock"
13
+
14
+ system *%W(tmux split-window -dv nvim --listen #{SOCKET})
15
+
16
+ Remote.start_client ConnectionUnix, SOCKET, timeout: 1 do |c|
17
+ c.command "e /etc/passwd"
18
+ c.command "/home"
19
+ b = c.get_current_buf
20
+ puts b.inspect
21
+ puts
22
+ sleep 1
23
+ puts b[1]
24
+ w = c.get_current_win
25
+ puts w.index
26
+ puts b[w.line]
27
+ c.command "bw"
28
+ sleep 1
29
+ e = c.evaluate "3*9"
30
+ puts e.inspect
31
+ sleep 1
32
+ c.command "q"
33
+ rescue Remote::Disconnected
34
+ puts "done."
35
+ end
36
+
37
+ end
38
+
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # demo_intar -- Start a Neovim session, attach to it and control it from an interactive Ruby
5
+ #
6
+
7
+ require "neovim/remote"
8
+ require "intar"
9
+
10
+
11
+ module Neovim
12
+
13
+ SOCKET = "/tmp/nvim-#$$.sock"
14
+
15
+ system *%W(tmux split-window -dv nvim --listen #{SOCKET})
16
+
17
+ Remote.start_client ConnectionUnix, SOCKET, timeout: 1 do |c|
18
+ c.command "set cuc cul"
19
+ c.set_option buftype: "nofile"
20
+ c.set_option :nu
21
+ b = c.get_current_buf
22
+ w = c.get_current_win
23
+ b[] = ["A".."Z", "a".."z", "0".."9"].map { |r| r.to_a }.flatten.map { |x| x*4 }
24
+ c.message "Hello from interactive Ruby!"
25
+ Intar.open do |i|
26
+ i.set_var :c, c
27
+ i.set_var :b, b
28
+ i.set_var :w, w
29
+ puts <<~'EOT'
30
+ # Example calls:
31
+ c.set_option_value "nu", false, {}
32
+ w.set_option :nu, :rnu
33
+ puts w.index
34
+ puts b[w.line]
35
+ b[w.line] += ["----"]
36
+ b.map! w.line do |x| x << "!" end
37
+ c.call_function "setreg", ["a", "hello\nbye", "l"]
38
+ EOT
39
+ i.run
40
+ end
41
+ c.command "qa!"
42
+ rescue Remote::Disconnected
43
+ puts "done."
44
+ end
45
+
46
+ end
47
+
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # demo_remote.rb -- Demo for plain handlers
5
+ #
6
+
7
+ require "neovim"
8
+
9
+
10
+ if $stdin.tty? then
11
+ puts <<~EOT
12
+ " How to run this from inside Neovim:
13
+ let chan = jobstart(['ruby','#$0'], { 'rpc': v:true })
14
+ call rpcrequest(chan, 'rb_add', 7)
15
+ call rpcrequest(chan, 'rb_raise')
16
+ call jobstop(chan)
17
+ EOT
18
+ exit 1
19
+ end
20
+
21
+
22
+ counter = 0
23
+
24
+ Neovim.start_remote do |dsl|
25
+
26
+ dsl.register_handler "rb_add" do |client,n|
27
+ counter += n
28
+ client.command "echo 'Counter value now is: '..#{counter}..'.'"
29
+ end
30
+
31
+ dsl.register_handler "rb_raise" do |client|
32
+ raise "Ouch!"
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # examples/demo_remote_inside_block.rb -- Demo for plain handlers
5
+ #
6
+
7
+ require "neovim"
8
+
9
+
10
+ if $stdin.tty? then
11
+ puts <<~EOT
12
+ " How to run this from inside Neovim:
13
+ let chan = jobstart(['ruby','#$0', 'counter.log', 100], { 'rpc': v:true })
14
+ echo rpcrequest(chan, 'rb_add', 7)
15
+ echo jobstop(chan)
16
+ EOT
17
+ exit 1
18
+ end
19
+
20
+
21
+ logname, counter = *$*
22
+ logname ||= "counter.log"
23
+ counter = counter.to_i
24
+
25
+ File.open logname, "w" do |log|
26
+
27
+ log.puts "I was called with: #{$*.inspect}"
28
+ log.flush
29
+
30
+ Neovim.start_remote do |dsl|
31
+
32
+ dsl.register_handler "rb_add" do |client,n|
33
+ counter += n
34
+ client.command "echo 'Counter value now is: '..#{counter}..'.'"
35
+ log.puts "Counter: #{counter}"
36
+ log.flush
37
+ nil
38
+ end
39
+
40
+ end
41
+
42
+ ensure
43
+ log.puts "Bye from counter at #{counter}."
44
+ log.flush
45
+
46
+ end
47
+
data/examples/demo_sub ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # demo_sub -- Descend to a Neovim session with some text
5
+ #
6
+
7
+ require "neovim/host"
8
+
9
+
10
+ data = <<~EOT
11
+ Name: John Doe
12
+ Mail: jdoe@example.com
13
+ Password: verysecret
14
+ EOT
15
+
16
+ Neovim::Remote.run_sub do |dsl|
17
+ dsl.setup do |client|
18
+ d = data.split "\n"
19
+ client.put d, "l", false, false
20
+ client.command "autocmd BufUnload <buffer=%d> call rpcrequest(%d,'rb_yield_data',getline(1,'$'))" %
21
+ [ client.get_current_buf.number, client.channel_id]
22
+ end
23
+ dsl.register_handler "rb_yield_data" do |client,l|
24
+ data = l.join "\n"
25
+ end
26
+ end
27
+
28
+ puts $?.inspect
29
+ puts "data =", data
30
+
data/examples/dump_api ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # dump_api -- Dump NeoVim's API
5
+ #
6
+
7
+ usage = <<~EOT
8
+ #$0 | nvim - +'set ft=yaml' '+$' # dump as YAML
9
+ #$0 -a | nvim - +'set ft=yaml' '+$' # dump by "--api-info" option
10
+ #$0 -j | nvim - +'set ft=json' '+$' # dump as JSON
11
+
12
+ Or just source it from Neovim:
13
+
14
+ :let g:ruby_api_info="yaml"
15
+ :rubyfile #$0
16
+
17
+ EOT
18
+
19
+
20
+ if $vim then # We're getting called from inside a Neovim.
21
+
22
+ a = $vim.get_api_info
23
+ t = ($vim.get_var "ruby_api_info") rescue "yaml"
24
+ a = case t
25
+ when "yaml" then require "yaml" ; a.to_yaml
26
+ when "json" then require "json" ; JSON.pretty_generate a
27
+ end
28
+ a = a.split $/
29
+ $vim.command "vnew"
30
+ $vim.set_options ft: t, buftype: "nofile"
31
+ $vim.put a, "l", false, false
32
+
33
+
34
+ else
35
+
36
+ $:.unshift "../lib"
37
+ require "neovim/remote"
38
+
39
+
40
+ include Neovim
41
+
42
+
43
+ class DumpApi
44
+
45
+ def get json: nil, alt: nil
46
+ if json then
47
+ as_json
48
+ else
49
+ if alt then
50
+ alternative_yaml
51
+ else
52
+ as_yaml
53
+ end
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def api_info
60
+ Remote.open ConnectionChild, "-u", "NONE", "-n" do |s|
61
+ ch, ai = s.request :nvim_get_api_info
62
+ ai
63
+ end
64
+ end
65
+
66
+ def as_json
67
+ require "json"
68
+ JSON.pretty_generate api_info
69
+ end
70
+
71
+ def as_yaml
72
+ require "yaml"
73
+ api_info.to_yaml
74
+ end
75
+
76
+ def alternative_yaml
77
+ require "neovim/foreign/mplight"
78
+ require "yaml"
79
+ t = MPLight::Types.new
80
+ t.extend MPLight::Unpacker
81
+ IO.popen %w(nvim --api-info) do |r|
82
+ t.init_input r
83
+ return t.get.to_yaml
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+
90
+ if $*.delete '-h' then
91
+ puts usage
92
+ exit
93
+ end
94
+
95
+ output = DumpApi.new.get json: ($*.delete '-j'), alt: ($*.delete '-a')
96
+ puts output
97
+
98
+ end
99
+
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # examples/passwords -- Manage a file containing your passwords
5
+ #
6
+
7
+ # (C) 2025 Bertram Scharpf <software@bertram-scharpf.de>
8
+
9
+ require "neovim/host"
10
+
11
+
12
+ class Passwords
13
+
14
+ PW_FILE = File.expand_path "~/.config/mypasswords.asc"
15
+ RECIPIENT = "jdoe@example.com"
16
+
17
+ def initialize debug: false
18
+ @debug = debug
19
+ end
20
+
21
+ def run
22
+ contents = get_contents.split $/
23
+ Neovim::Remote.run_sub do |pw_dsl|
24
+ pw_dsl.setup do |client|
25
+ client.set_option shadafile: "NONE"
26
+ client.set_option filetype: "dosini"
27
+ client.put contents, "l", true, false
28
+ client.command "1"
29
+ client.get_current_line.empty? and client.del_current_line
30
+ {
31
+ "Save" => "rb_save",
32
+ "Totp" => "rb_totp",
33
+ }.each { |cmd,fn|
34
+ client.command "command -buffer -nargs=0 %s call rpcrequest(%d,'%s')" % [ cmd, client.channel_id, fn]
35
+ }
36
+ end
37
+ pw_dsl.register_handler "rb_save" do |client|
38
+ File.rename PW_FILE, "#{PW_FILE}.bak" rescue nil
39
+ IO.popen %W(gpg -a -r #{RECIPIENT} --encrypt -o #{PW_FILE}), "w" do |gpg|
40
+ gpg.puts client.get_current_buf[1..]
41
+ end
42
+ File.chmod 0600, PW_FILE
43
+ end
44
+ pw_dsl.register_handler "rb_totp" do |client|
45
+ require "potp"
46
+ require "neovim/tools/copy"
47
+ p = client.call_function "expand", [ "<cword>"]
48
+ key = (POTP::TOTP.new p).now if p.notempty? and p.length % 4 == 0
49
+ client.echo [ [ key]], true, {}
50
+ xsel key
51
+ rescue
52
+ client.err_writeln "No OTP under cursor?"
53
+ rescue ScriptError
54
+ client.err_writeln $!.message
55
+ end
56
+ end
57
+ end
58
+
59
+ def get_contents
60
+ r = IO.popen %W(gpg -d #{PW_FILE}), "r" do |gpg| gpg.read end
61
+ r.notempty? or <<~EOT
62
+ # Move the cursor to the OTP keyword and give the command `:Totp`.
63
+ # The TOTP key will be displayed and further copied to the clipboard.
64
+
65
+ [account "dummy"]
66
+ name = John Doe
67
+ password = very$ecret
68
+ optauth = GYS5L3N3E4AAYNMN562LW76TMWHQBJ4A
69
+
70
+ # As soon as you have set the `RECIPIENT` constant in the executable,
71
+ # you may save this file calling the command `:Save`.
72
+ EOT
73
+ end
74
+
75
+ new.run
76
+
77
+ end
78
+
data/lib/neovim/client.rb CHANGED
@@ -25,7 +25,7 @@ module Neovim
25
25
  def initialize comm, channel_id
26
26
  @comm, @channel_id = comm, channel_id
27
27
  @functions = {}
28
- @objfuncs = Hash.new do |h,k| h[k] = {} end
28
+ @objfuncs = {}
29
29
  end
30
30
 
31
31
  def inspect
@@ -36,10 +36,16 @@ module Neovim
36
36
  list.each { |fn|
37
37
  next if fn[ "deprecated_since"] && self.class.strict
38
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
39
+ if (b = n.starts_with? "nvim_") then
40
+ @functions[ n[ b...].to_sym] = n
41
+ end
42
+ prefixes.each { |t,p|
43
+ if (b = n.starts_with? p) then
44
+ @objfuncs[ t] ||= {}
45
+ @objfuncs[ t][ n[ b...].to_sym] = n
46
+ break
47
+ end
48
+ }
43
49
  }
44
50
  end
45
51
 
@@ -58,7 +64,6 @@ module Neovim
58
64
  end
59
65
 
60
66
 
61
-
62
67
  def method_missing sym, *args
63
68
  call_api sym, *args
64
69
  rescue UnknownApiFunction
@@ -78,17 +83,24 @@ module Neovim
78
83
  s
79
84
  end
80
85
 
86
+ def functions
87
+ @functions.keys
88
+ end
89
+
81
90
 
82
91
  def has_obj_function? obj, name
83
92
  @objfuncs[ obj.type][ name.to_sym].to_bool
84
93
  end
85
94
 
95
+ def obj_classes
96
+ RemoteObject.subclasses.select { |c| @objfuncs[ c.type] rescue nil }
97
+ end
98
+
86
99
  def obj_functions obj
87
100
  @objfuncs[ obj.type].keys
88
101
  end
89
102
 
90
103
 
91
-
92
104
  def message str
93
105
  call_api :out_write, str
94
106
  str.end_with? $/ or call_api :out_write, $/
@@ -100,6 +112,7 @@ module Neovim
100
112
 
101
113
  def command arg ; call_api :command, arg ; end
102
114
 
115
+ # Be aware that #eval was a private instance method from module Kernel.
103
116
  def evaluate expr ; call_api :eval, expr ; end
104
117
 
105
118
  end
@@ -40,7 +40,7 @@ module Neovim
40
40
  prefixes = {}
41
41
  api_info[ "types"].each do |type,info|
42
42
  type = type.to_sym
43
- prefixes[ type] = /\A#{info[ "prefix"]}/
43
+ prefixes[ type] = info[ "prefix"]
44
44
  register_type type, info[ "id"]
45
45
  end
46
46
  @client.add_functions api_info[ "functions"], prefixes
@@ -69,10 +69,19 @@ module Neovim
69
69
 
70
70
  class ConnectionTcp < Connection
71
71
  class <<self
72
- def open_files host, port
72
+ def open_files host, port, timeout: nil
73
+ due = Time.now + timeout if timeout
73
74
  require "socket"
74
- TCPSocket.open host, port do |socket|
75
- yield (new socket, socket)
75
+ begin
76
+ TCPSocket.open host, port do |socket|
77
+ due = nil
78
+ yield (new socket, socket)
79
+ end
80
+ rescue Errno::ECONNREFUSED
81
+ if due then
82
+ sleep 0.1
83
+ retry
84
+ end
76
85
  end
77
86
  end
78
87
  end
@@ -80,10 +89,19 @@ module Neovim
80
89
 
81
90
  class ConnectionUnix < Connection
82
91
  class <<self
83
- def open_files path
92
+ def open_files path, timeout: nil
93
+ due = Time.now + timeout if timeout
84
94
  require "socket"
85
- UNIXSocket.open path do |socket|
86
- yield (new socket, socket)
95
+ begin
96
+ UNIXSocket.open path do |socket|
97
+ due = nil
98
+ yield (new socket, socket)
99
+ end
100
+ rescue Errno::ENOENT
101
+ if due then
102
+ sleep 0.1
103
+ retry
104
+ end
87
105
  end
88
106
  end
89
107
  end
@@ -38,6 +38,10 @@ rescue LoadError
38
38
  self
39
39
  end
40
40
  end
41
+ def starts_with? oth ; o = oth.to_str ; o.length if start_with? o ; end
42
+ def ends_with? oth ; o = oth.to_str ; length - o.length if end_with? o ; end
43
+ alias starts_with starts_with?
44
+ alias ends_with ends_with?
41
45
  end
42
46
  end
43
47
 
@@ -142,6 +142,10 @@ module Neovim
142
142
 
143
143
  TYPE = :remote
144
144
 
145
+ def setup &block
146
+ add_setup_block &block
147
+ end
148
+
145
149
  def register_handler name, &block
146
150
  add_handler nil, name, &block
147
151
  end
data/lib/neovim/host.rb CHANGED
@@ -8,6 +8,32 @@ require "neovim/handler"
8
8
 
9
9
  module Neovim
10
10
 
11
+ class Remote
12
+
13
+ class <<self
14
+
15
+ def run_remote *args, **kwargs, &block
16
+ plugins = { remote: (DslRemote.open &block), }
17
+ start plugins, *args, **kwargs do |i|
18
+ i.start
19
+ i.run
20
+ end
21
+ rescue Remote::Disconnected
22
+ end
23
+
24
+ def run_sub socket: nil, timeout: nil, &block
25
+ socket ||= "/tmp/nvim-sub-#$$.sock"
26
+ f = fork { exec *%w(nvim --listen), socket }
27
+ Remote.run_remote ConnectionUnix, socket, timeout: timeout||1, &block
28
+ ensure
29
+ Process.waitpid f
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+
11
37
  class Provider < Remote
12
38
 
13
39
  class <<self
@@ -21,6 +47,7 @@ module Neovim
21
47
  def run plugins
22
48
  $stdin.tty? and raise "This program expects to be called by Neovim. It can't run interactively."
23
49
  start plugins do |h|
50
+ log :info, "Starting event loop."
24
51
  h.run
25
52
  nil
26
53
  rescue Remote::Disconnected
@@ -28,8 +55,13 @@ module Neovim
28
55
  nil
29
56
  rescue SignalException
30
57
  n = $!.signm.notempty? || $!.class.to_s
31
- log :fatal, "Signal was caught: #{n}"
32
- (n =~ /\A(?:SIG)?TERM\z/) ? 0 : 1
58
+ if n =~ /\A(?:SIG)?TERM\z/ then
59
+ log :info, "Exiting after terminate signal."
60
+ nil
61
+ else
62
+ log :fatal, "Signal was caught: #{n}"
63
+ 1
64
+ end
33
65
  rescue Exception
34
66
  log_exception :fatal
35
67
  2
@@ -47,7 +79,6 @@ module Neovim
47
79
  @plugins[ :base] = DslPlain.open do |dsl|
48
80
  dsl.plain "poll" do
49
81
  start
50
- @plugins.each_value { |p| p.setup @conn.client }
51
82
  "ok"
52
83
  end
53
84
  dsl.plain "specs", nargs: 1 do |source|
data/lib/neovim/info.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require "neovim/meta.rb"
2
2
  Neovim::INFO = Neovim::Meta.new "nvim",
3
- version: "1.4.0",
3
+ version: "1.5.1",
4
4
  license: "BSD-2-Clause+",
5
5
  authors: ["Bertram Scharpf"],
6
6
  email: "software@bertram-scharpf.de",
7
7
  summary: "Yet another Ruby client for Neovim",
8
8
  description: "A simple Ruby client for Neovim.\nClean code, minimal dependecies, no frills, no wokeness.",
9
9
  homepage: "https://github.com/BertramScharpf/ruby-nvim",
10
- commit: "3318cce"
10
+ commit: "3508371"
@@ -234,8 +234,8 @@ module Neovim
234
234
  **kwargs
235
235
  end
236
236
 
237
- def log_exception level
238
- Logging.put level, "Exception: #$!",
237
+ def log_exception level = nil
238
+ Logging.put level||:error, "Exception: #$!",
239
239
  sender: self, caller: (caller 1, 1).first,
240
240
  exception: $!.class
241
241
  $@.each { |b|
data/lib/neovim/remote.rb CHANGED
@@ -120,20 +120,20 @@ module Neovim
120
120
  end
121
121
  end
122
122
 
123
- def start plugins, *args
123
+ def start plugins, *args, **kwargs
124
124
  open_logfile do
125
- log :info, "Starting", args: $*
126
- open_conn *args do |conn|
125
+ log :debug1, "Starting", args: $*
126
+ open_conn *args, **kwargs do |conn|
127
127
  i = new plugins, conn
128
128
  yield i
129
129
  end
130
130
  ensure
131
- log :info, "Leaving"
131
+ log :debug1, "Leaving"
132
132
  end
133
133
  end
134
134
 
135
- def start_client *args
136
- start nil, *args do |i|
135
+ def start_client *args, **kwargs
136
+ start nil, *args, **kwargs do |i|
137
137
  yield i.start
138
138
  end
139
139
  end
@@ -154,7 +154,7 @@ module Neovim
154
154
  l.map! { |p| p.type }
155
155
  l.uniq!
156
156
  name = l.join "-"
157
- log :info, "Client Name", name: name
157
+ log :debug1, "Client Name", name: name
158
158
  "ruby-#{name}-host"
159
159
  else
160
160
  "ruby-client"
@@ -175,6 +175,7 @@ module Neovim
175
175
 
176
176
  def start
177
177
  @conn.start self
178
+ @plugins.each_value { |p| p.setup @conn.client }
178
179
  @conn.client
179
180
  end
180
181
 
@@ -209,7 +210,7 @@ module Neovim
209
210
  if @conn.client or not h.needs_client? then
210
211
  p.call
211
212
  else
212
- log :info, "Deferred handler for", name: message.method_name
213
+ log :debug1, "Deferred handler for", name: message.method_name
213
214
  @deferred ||= []
214
215
  @deferred.push p
215
216
  end
@@ -265,7 +266,7 @@ module Neovim
265
266
  @plugins.each_value do |plugin|
266
267
  h = plugin.get_handler name
267
268
  if h then
268
- log :info, "Found handler", name: name
269
+ log :debug1, "Found handler", name: name
269
270
  return h
270
271
  end
271
272
  end
@@ -131,7 +131,7 @@ module Neovim
131
131
  # Functions as described in ":h ruby"
132
132
 
133
133
  def name ; call_obj :get_name ; end
134
- def number ; call_obj :get_number ; end
134
+ def number ; index ; end
135
135
 
136
136
  def count ; call_obj :line_count ; end
137
137
  alias length count
@@ -19,20 +19,19 @@ end
19
19
  # The VIM module as documented in ":h ruby".
20
20
  module Vim
21
21
 
22
- class Buffer < ::Neovim::Buffer
23
- class <<self
24
- def current ; $vim.get_current_buf ; end
25
- def count ; $vim.list_bufs.size ; end
26
- def [] i ; $vim.list_bufs[ i] ; end
27
- end
22
+ Buffer = ::Neovim::Buffer
23
+ class <<Buffer
24
+ def current ; $vim.get_current_buf ; end
25
+ def count ; $vim.list_bufs.size ; end
26
+ def [] i ; $vim.list_bufs[ i] ; end
28
27
  end
29
28
 
30
- class Window < ::Neovim::Window
31
- class <<self
32
- def current ; $vim.get_current_win ; end
33
- def count ; $vim.get_current_tabpage.list_wins.size ; end
34
- def [] i ; $vim.get_current_tabpage.list_wins[ i] ; end
35
- end
29
+ Window = ::Neovim::Window
30
+ class <<Window
31
+ def current ; $vim.get_current_win ; end
32
+ def count ; $vim.get_current_tabpage.list_wins.size ; end
33
+ def [] i ; $vim.get_current_tabpage.list_wins[ i] ; end
34
+ self
36
35
  end
37
36
 
38
37
  class <<self
@@ -163,13 +162,14 @@ module Neovim
163
162
  # This is called by the +:ruby+ command.
164
163
  dsl.rpc :ruby_execute do |client,code,fst,lst|
165
164
  code.rstrip!
166
- if !code.notempty? or code == "|" then # Workaround because Neovim doesn't allow empty code (the ultimate Quine)
165
+ if code =~ /\A\|?(-)?\z/ then # | is a workaround because Neovim doesn't allow empty code (the ultimate Quine).
166
+ no_out = $1
167
167
  set_global_client client do
168
168
  client.command "#{lst}"
169
169
  code = (get_lines client, fst..lst).join $/
170
170
  WriteBuf.redirect client do
171
171
  r = script_binding.eval code, "ruby_run"
172
- unless r.nil? then
172
+ unless no_out or r.nil? then
173
173
  script_binding.local_variable_set :_, r
174
174
  puts "#=> #{r.inspect}"
175
175
  end
@@ -16,11 +16,16 @@ module Neovim
16
16
  case r
17
17
  when BigDecimal then
18
18
  r = r.to_s "F"
19
- r.sub! /(?:(\.)([0-9]+))?\z/ do
20
- (@sep||$1) + ($2.to_s.ljust @decs, "0")
19
+ if @decs.nonzero? then
20
+ r.sub! /(\.)(\d+)\z/ do (@sep||$1) + ($2.to_s.ljust @decs, "0") end
21
+ else
22
+ r.slice! /\.0+\z/
21
23
  end
22
24
  when Integer then
23
25
  r = r.to_s
26
+ if @decs.nonzero? then
27
+ r << (@sep||".") << "0"*@decs
28
+ end
24
29
  end
25
30
  r
26
31
  end
@@ -31,11 +36,13 @@ module Neovim
31
36
 
32
37
  def decs= d ; @decs = Integer d ; end
33
38
 
34
- def dot! ; @sep = "." ; end
39
+ def dot! ; @sep = "." ; end
35
40
  def dot? ; @sep == "." ; end
36
- def comma! ; @sep = "," ; end
41
+ def comma! ; @sep = "," ; end
37
42
  def comma? ; @sep == "," ; end
38
- def auto! ; @sep = nil ; end
43
+ def colon! ; @sep = ":" ; end
44
+ def colon? ; @sep == ":" ; end
45
+ def auto! ; @sep = nil ; end
39
46
 
40
47
  def add line
41
48
  line = line.chomp
@@ -43,9 +50,11 @@ module Neovim
43
50
  if $& =~ /!(\w+)/ then
44
51
  case $1
45
52
  when "c", "comma", "k", "komma" then comma!
53
+ when "l", "colon" then colon!
46
54
  when "d", "dot", "p", "point" then dot!
47
55
  when "a", "auto" then auto!
48
- when /\A\d+\z/ then @decs = $1.to_i
56
+ when /\A\d+\z/ then @decs = $&.to_i
57
+ when "all", "full", "places" then @decs = nil
49
58
  end
50
59
  end
51
60
  line.slice! /^.*:/
data/lib/neovim.rb CHANGED
@@ -19,11 +19,7 @@ module Neovim
19
19
  class <<self
20
20
 
21
21
  def start_remote &block
22
- Job.run mk_plugins &block
23
- end
24
-
25
- def mk_plugins &block
26
- { remote: (DslRemote.open &block) }
22
+ Job.run remote: (DslRemote.open &block)
27
23
  end
28
24
 
29
25
  end
data/nvim.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ #
2
+ # nvim.gemspec -- Gem specification
3
+ #
4
+
5
+ system *%w(rake infofile)
6
+
7
+ $:.unshift "./lib"
8
+ require "neovim/info"
9
+
10
+
11
+ Gem::Specification.new do |spec|
12
+ Neovim::INFO.mk_gemspec spec
13
+ spec.required_ruby_version = Gem::Requirement.new ">= 3.1.0"
14
+
15
+ spec.files = Dir[ "lib/**/*.rb"] + Dir[ "bin/*"]
16
+
17
+ spec.require_paths = %w(lib)
18
+ spec.bindir = "bin"
19
+ spec.executables = %w(neovim-ruby-host)
20
+
21
+ spec.extra_rdoc_files = %w(INFO.yaml LICENSE README.md)
22
+ spec.extra_rdoc_files += %w(Rakefile nvim.gemspec)
23
+ spec.extra_rdoc_files += Dir[ "examples/*"]
24
+
25
+ if false then
26
+ spec.add_dependency "supplement", "~> 2.18"
27
+ spec.add_dependency "mplight", "~> 1.0"
28
+ end
29
+
30
+ end
31
+
metadata CHANGED
@@ -1,28 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nvim
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bertram Scharpf
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-11-23 00:00:00.000000000 Z
10
+ date: 2025-01-14 00:00:00.000000000 Z
12
11
  dependencies: []
13
- description:
14
12
  email: software@bertram-scharpf.de
15
13
  executables:
16
14
  - neovim-ruby-host
17
15
  extensions: []
18
- extra_rdoc_files: []
16
+ extra_rdoc_files:
17
+ - INFO.yaml
18
+ - LICENSE
19
+ - README.md
20
+ - Rakefile
21
+ - nvim.gemspec
22
+ - examples/demo.rb
23
+ - examples/demo_attach
24
+ - examples/demo_intar
25
+ - examples/demo_remote.rb
26
+ - examples/demo_remote_inside_block.rb
27
+ - examples/demo_sub
28
+ - examples/dump_api
29
+ - examples/passwords
19
30
  files:
20
31
  - INFO.yaml
21
32
  - LICENSE
22
33
  - README.md
23
34
  - Rakefile
24
- - TODO
25
35
  - bin/neovim-ruby-host
36
+ - examples/demo.rb
37
+ - examples/demo_attach
38
+ - examples/demo_intar
39
+ - examples/demo_remote.rb
40
+ - examples/demo_remote_inside_block.rb
41
+ - examples/demo_sub
42
+ - examples/dump_api
43
+ - examples/passwords
26
44
  - lib/neovim.rb
27
45
  - lib/neovim/client.rb
28
46
  - lib/neovim/connection.rb
@@ -43,11 +61,11 @@ files:
43
61
  - lib/neovim/tools/calculator.rb
44
62
  - lib/neovim/tools/copy.rb
45
63
  - lib/neovim/vimscript_provider.rb
64
+ - nvim.gemspec
46
65
  homepage: https://github.com/BertramScharpf/ruby-nvim
47
66
  licenses:
48
67
  - BSD-2-Clause+
49
68
  metadata: {}
50
- post_install_message:
51
69
  rdoc_options: []
52
70
  require_paths:
53
71
  - lib
@@ -55,15 +73,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
73
  requirements:
56
74
  - - ">="
57
75
  - !ruby/object:Gem::Version
58
- version: 3.0.0
76
+ version: 3.1.0
59
77
  required_rubygems_version: !ruby/object:Gem::Requirement
60
78
  requirements:
61
79
  - - ">="
62
80
  - !ruby/object:Gem::Version
63
81
  version: '0'
64
82
  requirements: []
65
- rubygems_version: 3.5.22
66
- signing_key:
83
+ rubygems_version: 3.6.2
67
84
  specification_version: 4
68
85
  summary: Yet another Ruby client for Neovim
69
86
  test_files: []
data/TODO DELETED
@@ -1,2 +0,0 @@
1
- - system "ls" stürzt ab
2
- - Logdatei ins Standardverzeichnis