nvim 1.0.0 → 1.1.0
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 +4 -4
- data/INFO.yaml +2 -2
- data/README.md +28 -0
- data/bin/neovim-ruby-host +24 -21
- data/lib/neovim/connection.rb +2 -2
- data/lib/neovim/foreign/supplement.rb +9 -0
- data/lib/neovim/foreign/xxd.rb +195 -0
- data/lib/neovim/handler.rb +33 -20
- data/lib/neovim/host.rb +27 -47
- data/lib/neovim/info.rb +3 -3
- data/lib/neovim/logging.rb +16 -7
- data/lib/neovim/output.rb +142 -0
- data/lib/neovim/remote.rb +241 -18
- data/lib/neovim/remote_object.rb +7 -7
- data/lib/neovim/ruby_provider.rb +25 -110
- data/lib/neovim/tools/copy.rb +78 -0
- data/lib/neovim/vimscript_provider.rb +1 -1
- data/lib/neovim.rb +14 -4
- metadata +7 -6
- data/lib/neovim/messager.rb +0 -185
- data/lib/neovim/session.rb +0 -60
@@ -0,0 +1,142 @@
|
|
1
|
+
#
|
2
|
+
# neovim/output.rb -- Output to Neovim
|
3
|
+
#
|
4
|
+
|
5
|
+
|
6
|
+
module Neovim
|
7
|
+
|
8
|
+
class Write
|
9
|
+
class <<self
|
10
|
+
def open *args, **kwargs
|
11
|
+
i = new *args, **kwargs
|
12
|
+
yield i
|
13
|
+
ensure
|
14
|
+
i.finish
|
15
|
+
end
|
16
|
+
end
|
17
|
+
def initialize client, *rest
|
18
|
+
@client = client
|
19
|
+
end
|
20
|
+
def << arg
|
21
|
+
write arg.to_s
|
22
|
+
self
|
23
|
+
end
|
24
|
+
def print *args
|
25
|
+
args.each { |a| write a.to_s }
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
def puts *args
|
29
|
+
if args.empty? then
|
30
|
+
write $/
|
31
|
+
else
|
32
|
+
args.each { |a|
|
33
|
+
case a
|
34
|
+
when Array then
|
35
|
+
a.each { |e|
|
36
|
+
puts e
|
37
|
+
}
|
38
|
+
else
|
39
|
+
a = a.to_s
|
40
|
+
write a
|
41
|
+
write $/ unless a.end_with? $/
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
def flush
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class WriteStd < Write
|
52
|
+
class <<self
|
53
|
+
def redirect *args, **kwargs
|
54
|
+
open *args, **kwargs do |i|
|
55
|
+
old, $stdout = $stdout, i
|
56
|
+
yield
|
57
|
+
ensure
|
58
|
+
$stdout = old
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class WriteOut < WriteStd
|
65
|
+
def write *args
|
66
|
+
args.each { |a|
|
67
|
+
a = a.to_s
|
68
|
+
a.notempty? or next
|
69
|
+
@client.out_write a
|
70
|
+
@line_open = !(a.end_with? $/)
|
71
|
+
}
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
def finish
|
75
|
+
if @line_open then
|
76
|
+
@client.out_write $/
|
77
|
+
@line_open = nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class WriteErr < Write
|
83
|
+
class <<self
|
84
|
+
def redirect *args, **kwargs
|
85
|
+
open *args, **kwargs do |i|
|
86
|
+
old, $stderr = $stderr, i
|
87
|
+
yield
|
88
|
+
ensure
|
89
|
+
$stderr = old
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
def write *args
|
94
|
+
args.each { |a|
|
95
|
+
@rest ||= ""
|
96
|
+
@rest << a.to_s
|
97
|
+
while @rest =~ /#$// do
|
98
|
+
@client.err_writeln $`
|
99
|
+
@rest = $'
|
100
|
+
end
|
101
|
+
}
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
def finish
|
105
|
+
if @rest.notempty? then
|
106
|
+
@client.err_writeln @rest
|
107
|
+
@rest = nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class WriteBuf < WriteStd
|
113
|
+
def initialize *args, whole: nil, top: nil
|
114
|
+
super
|
115
|
+
@lines, @last = [], ""
|
116
|
+
@whole, @top = whole, top
|
117
|
+
end
|
118
|
+
def write *args
|
119
|
+
args.each { |a| @last << a.to_s }
|
120
|
+
loop do
|
121
|
+
n, r = @last.split $/, 2
|
122
|
+
r or break
|
123
|
+
@lines.push n
|
124
|
+
@last = r
|
125
|
+
end
|
126
|
+
nil
|
127
|
+
end
|
128
|
+
def finish
|
129
|
+
if @last.notempty? then
|
130
|
+
@lines.push @last
|
131
|
+
@last = nil
|
132
|
+
end
|
133
|
+
if @whole then
|
134
|
+
@client.buf_set_lines 0, 0, -1, true, @lines
|
135
|
+
else
|
136
|
+
@client.put @lines, "l", true, !@top
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
data/lib/neovim/remote.rb
CHANGED
@@ -1,53 +1,276 @@
|
|
1
1
|
#
|
2
|
-
# neovim/remote.rb --
|
2
|
+
# neovim/remote.rb -- Remote access for Neovim
|
3
3
|
#
|
4
4
|
|
5
|
-
require "neovim/
|
6
|
-
|
5
|
+
require "neovim/foreign/supplement"
|
6
|
+
|
7
|
+
require "neovim/logging"
|
8
|
+
require "neovim/connection"
|
7
9
|
|
8
10
|
|
9
11
|
module Neovim
|
10
12
|
|
11
|
-
class Remote
|
13
|
+
class Remote
|
14
|
+
|
15
|
+
class Message
|
16
|
+
|
17
|
+
@subs, @subh = [], {}
|
18
|
+
|
19
|
+
class <<self
|
20
|
+
|
21
|
+
def from_array ary
|
22
|
+
kind, *payload = *ary
|
23
|
+
klass = find kind
|
24
|
+
klass or raise "No message type for id #{kind.inspect}"
|
25
|
+
klass[ *payload]
|
26
|
+
end
|
27
|
+
|
28
|
+
def inherited cls ; @subs.push cls ; end
|
29
|
+
def find id
|
30
|
+
@subh[ id] ||= @subs.find { |c| c::ID == id }
|
31
|
+
end
|
32
|
+
|
33
|
+
alias [] new
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize *args
|
38
|
+
z = self.class::KEYS.zip args
|
39
|
+
@cont = z.inject Hash.new do |c,(h,k)| c[h] = k ; c end
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
43
|
+
"#<#{self.class.plain_name} #@cont>"
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
j = @cont.map { |k,v| "#{k}:#{v}" if v }.compact.join ","
|
48
|
+
"#{self.class.plain_name}(#{j})"
|
49
|
+
end
|
50
|
+
|
51
|
+
def method_missing sym, *args
|
52
|
+
if @cont.key? sym then @cont[ sym] else super end
|
53
|
+
end
|
54
|
+
|
55
|
+
def respond_to_missing? sym, priv = nil
|
56
|
+
@cont.key? sym.to_sym
|
57
|
+
end
|
58
|
+
|
59
|
+
def methods *args
|
60
|
+
super.concat @cont.keys
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_h ; @cont ; end
|
64
|
+
|
65
|
+
def fields ; @cont.fetch_values *self.class::KEYS ; end
|
66
|
+
|
67
|
+
def to_a
|
68
|
+
[self.class::ID, *fields]
|
69
|
+
end
|
70
|
+
|
71
|
+
class Request < Message
|
72
|
+
ID = 0
|
73
|
+
KEYS = %i(request_id method_name arguments)
|
74
|
+
end
|
75
|
+
|
76
|
+
class Response < Message
|
77
|
+
ID = 1
|
78
|
+
KEYS = %i(request_id error value)
|
79
|
+
def initialize *args
|
80
|
+
super
|
81
|
+
e = @cont[ :error]
|
82
|
+
if e and not Array === e then
|
83
|
+
@cont[ :error] = [0, e]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Notification < Message
|
89
|
+
ID = 2
|
90
|
+
KEYS = %i(method_name arguments)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
class ResponseError < StandardError ; end
|
96
|
+
|
97
|
+
class Disconnected < RuntimeError ; end
|
98
|
+
|
99
|
+
|
100
|
+
include Logging
|
12
101
|
|
13
102
|
class <<self
|
14
103
|
|
104
|
+
include Logging
|
105
|
+
|
106
|
+
private :new
|
107
|
+
|
108
|
+
def open_conn conntype, *args, **kwargs
|
109
|
+
conntype.open_files *args, **kwargs do |conn|
|
110
|
+
yield conn
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
public
|
115
|
+
|
116
|
+
def open conntype, *args, **kwargs
|
117
|
+
open_conn conntype, *args, **kwargs do |conn|
|
118
|
+
i = new nil, conn
|
119
|
+
yield i
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def start plugins, *args
|
124
|
+
open_logfile do
|
125
|
+
log :info, "Starting", args: $*
|
126
|
+
open_conn *args do |conn|
|
127
|
+
i = new plugins, conn
|
128
|
+
yield i
|
129
|
+
end
|
130
|
+
ensure
|
131
|
+
log :info, "Leaving"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
15
135
|
def start_client *args
|
16
|
-
start *args do |i|
|
136
|
+
start nil, *args do |i|
|
17
137
|
yield i.start
|
18
138
|
end
|
19
139
|
end
|
20
140
|
|
21
141
|
end
|
22
142
|
|
23
|
-
def initialize conn
|
24
|
-
|
143
|
+
def initialize plugins, conn
|
144
|
+
@conn = conn
|
145
|
+
@request_id = 0
|
146
|
+
@responses = {}
|
25
147
|
@plugins = {}
|
148
|
+
@plugins.update plugins if plugins
|
26
149
|
end
|
27
150
|
|
151
|
+
def client_name
|
152
|
+
l = @plugins.values.select { |p| p.type }
|
153
|
+
if l.notempty? then
|
154
|
+
l.map! { |p| p.type }
|
155
|
+
l.uniq!
|
156
|
+
name = l.join "-"
|
157
|
+
log :info, "Client Name", name: name
|
158
|
+
"ruby-#{name}-host"
|
159
|
+
else
|
160
|
+
"ruby-client"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def client_type ; self.class.plain_name.downcase ; end
|
165
|
+
|
166
|
+
def client_methods
|
167
|
+
l = @plugins.values.reject { |p| p.type }
|
168
|
+
if l.notempty? then
|
169
|
+
r = {}
|
170
|
+
l.each { |p| p.options { |name,opts| r[ name] = opts } }
|
171
|
+
r
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
28
176
|
def start
|
29
|
-
@conn.start
|
177
|
+
@conn.start self
|
30
178
|
@conn.client
|
31
179
|
end
|
32
180
|
|
33
|
-
def
|
34
|
-
|
181
|
+
def run until_id = nil
|
182
|
+
loop do
|
183
|
+
if @deferred and @conn.client then
|
184
|
+
d, @deferred = @deferred, nil
|
185
|
+
d.each { |p| p.call }
|
186
|
+
end
|
187
|
+
message = get
|
188
|
+
case message
|
189
|
+
when Message::Response then
|
190
|
+
if @responses.key? message.request_id then
|
191
|
+
@responses[ message.request_id] = message
|
192
|
+
else
|
193
|
+
log :warning, "Dropped response", message.request_id
|
194
|
+
end
|
195
|
+
when Message::Request, Message::Notification then
|
196
|
+
h = find_handler message.method_name
|
197
|
+
if h then
|
198
|
+
p = proc do
|
199
|
+
begin
|
200
|
+
log :debug1, "Calling handler", name: message.method_name, args: message.arguments
|
201
|
+
r = h.execute @conn.client, *message.arguments
|
202
|
+
log :debug1, "Handler result", result: r
|
203
|
+
rescue
|
204
|
+
e = [ 0, $!.to_s]
|
205
|
+
log_exception :error
|
206
|
+
end
|
207
|
+
put Message::Response[ message.request_id, e, r] if message.respond_to? :request_id
|
208
|
+
end
|
209
|
+
if @conn.client or not h.needs_client? then
|
210
|
+
p.call
|
211
|
+
else
|
212
|
+
log :info, "Deferred handler for", name: message.method_name
|
213
|
+
@deferred ||= []
|
214
|
+
@deferred.push p
|
215
|
+
end
|
216
|
+
else
|
217
|
+
if message.respond_to? :request_id then
|
218
|
+
put Message::Response[ message.request_id, [0, "No handler #{message.method_name}."], nil]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
break if until_id and @responses[ until_id]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def request method, *args
|
227
|
+
rid = @request_id = @request_id.succ
|
228
|
+
put Message::Request[ rid, method, args]
|
229
|
+
@responses[ rid] = nil
|
230
|
+
run rid
|
231
|
+
r = @responses.delete rid
|
232
|
+
if r.error then
|
233
|
+
t, e = *r.error
|
234
|
+
t = @conn.error t
|
235
|
+
raise ResponseError, "#{t}: #{e}"
|
236
|
+
end
|
237
|
+
r.value
|
238
|
+
end
|
35
239
|
|
240
|
+
def notify method, *args
|
241
|
+
put Message::Notification[ method, args]
|
242
|
+
end
|
243
|
+
|
244
|
+
private
|
245
|
+
|
246
|
+
def put msg
|
247
|
+
log :debug2, "Sending Message", data: msg
|
248
|
+
@conn.put msg.to_a
|
249
|
+
self
|
250
|
+
rescue Errno::EPIPE
|
251
|
+
raise Disconnected, "Broken pipe on write"
|
252
|
+
end
|
36
253
|
|
37
|
-
def
|
38
|
-
@
|
254
|
+
def get
|
255
|
+
IO.select [@conn.input], nil, nil
|
256
|
+
raise Disconnected, "EOF on wait" if @conn.eof?
|
257
|
+
msg = Message.from_array @conn.get
|
258
|
+
log :debug2, "Received Message", data: msg
|
259
|
+
msg
|
260
|
+
rescue EOFError
|
261
|
+
raise Disconnected, "EOF on read"
|
39
262
|
end
|
40
263
|
|
41
|
-
def
|
264
|
+
def find_handler name
|
42
265
|
@plugins.each_value do |plugin|
|
43
|
-
|
44
|
-
if
|
266
|
+
h = plugin.get_handler name
|
267
|
+
if h then
|
45
268
|
log :info, "Found handler", name: name
|
46
|
-
|
47
|
-
return handler.execute @conn.client, *args
|
269
|
+
return h
|
48
270
|
end
|
49
271
|
end
|
50
|
-
|
272
|
+
log :error, "No handler found for #{name}."
|
273
|
+
nil
|
51
274
|
end
|
52
275
|
|
53
276
|
end
|
data/lib/neovim/remote_object.rb
CHANGED
@@ -55,7 +55,7 @@ module Neovim
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def type
|
58
|
-
@type ||=
|
58
|
+
@type ||= plain_name.to_sym
|
59
59
|
end
|
60
60
|
|
61
61
|
end
|
@@ -231,7 +231,7 @@ module Neovim
|
|
231
231
|
def line_indices pos, len
|
232
232
|
if Range === pos then
|
233
233
|
r = pos
|
234
|
-
pos, lst = r.begin, r.end
|
234
|
+
pos, lst = r.begin||1, r.end||-1
|
235
235
|
lst += 1 unless r.exclude_end?
|
236
236
|
elsif pos.nil? then
|
237
237
|
pos, lst = 1, 0
|
@@ -241,7 +241,7 @@ module Neovim
|
|
241
241
|
if len then
|
242
242
|
lst = pos + (len >= 0 ? len : 0)
|
243
243
|
end
|
244
|
-
lst = 0 if pos < 0 and lst
|
244
|
+
lst = 0 if pos < 0 and lst > 0
|
245
245
|
yield pos-1, lst-1
|
246
246
|
end
|
247
247
|
|
@@ -249,11 +249,11 @@ module Neovim
|
|
249
249
|
line_indices pos, len do |*fl|
|
250
250
|
c = nil
|
251
251
|
fl.map! { |y|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
y + 1 + (c ||= count)
|
252
|
+
unless y >= 0 then
|
253
|
+
c ||= count
|
254
|
+
y += 1 + c
|
256
255
|
end
|
256
|
+
y
|
257
257
|
}
|
258
258
|
yield *fl
|
259
259
|
end
|
data/lib/neovim/ruby_provider.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
require "neovim/handler"
|
6
6
|
require "neovim/remote_object"
|
7
|
+
require "neovim/output"
|
7
8
|
|
8
9
|
|
9
10
|
class Object
|
@@ -51,118 +52,14 @@ end
|
|
51
52
|
|
52
53
|
module Neovim
|
53
54
|
|
54
|
-
class Write
|
55
|
-
class <<self
|
56
|
-
def open client
|
57
|
-
i = new client
|
58
|
-
yield i
|
59
|
-
ensure
|
60
|
-
i.finish
|
61
|
-
end
|
62
|
-
end
|
63
|
-
def initialize client
|
64
|
-
@client = client
|
65
|
-
end
|
66
|
-
def print *args
|
67
|
-
args.each { |a| write a.to_s }
|
68
|
-
nil
|
69
|
-
end
|
70
|
-
def puts *args
|
71
|
-
args.each { |a|
|
72
|
-
a = a.to_s
|
73
|
-
write a
|
74
|
-
write "\n" unless a.end_with? $/
|
75
|
-
}
|
76
|
-
nil
|
77
|
-
end
|
78
|
-
def flush
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
class WriteStd < Write
|
83
|
-
class <<self
|
84
|
-
def redirect client
|
85
|
-
open client do |i|
|
86
|
-
old, $stdout = $stdout, i
|
87
|
-
yield
|
88
|
-
ensure
|
89
|
-
$stdout = old
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
class WriteOut < WriteStd
|
96
|
-
def write *args
|
97
|
-
args.each { |a|
|
98
|
-
a.notempty? or next
|
99
|
-
@client.out_write a
|
100
|
-
@line_open = !(a.end_with? $/)
|
101
|
-
}
|
102
|
-
nil
|
103
|
-
end
|
104
|
-
def finish
|
105
|
-
if @line_open then
|
106
|
-
@client.out_write $/
|
107
|
-
@line_open = nil
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
class WriteErr < Write
|
113
|
-
class <<self
|
114
|
-
def redirect client
|
115
|
-
open client do |i|
|
116
|
-
old, $stderr = $stderr, i
|
117
|
-
yield
|
118
|
-
ensure
|
119
|
-
$stderr = old
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
def write *args
|
124
|
-
args.each { |a|
|
125
|
-
@rest ||= ""
|
126
|
-
@rest << a
|
127
|
-
while @rest =~ /#$// do
|
128
|
-
@client.err_writeln $`
|
129
|
-
@rest = $'
|
130
|
-
end
|
131
|
-
}
|
132
|
-
nil
|
133
|
-
end
|
134
|
-
def finish
|
135
|
-
if @rest.notempty? then
|
136
|
-
@client.err_writeln @rest
|
137
|
-
@rest = nil
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
class WriteBuf < WriteStd
|
143
|
-
def write *args
|
144
|
-
s = @rest||""
|
145
|
-
args.each { |a|
|
146
|
-
s << a
|
147
|
-
}
|
148
|
-
s = s.split $/, -1
|
149
|
-
@rest = s.pop
|
150
|
-
@client.put s, "l", true, false
|
151
|
-
nil
|
152
|
-
end
|
153
|
-
def finish
|
154
|
-
if @rest.notempty? then
|
155
|
-
@client.put [@rest], "l", true, false
|
156
|
-
@rest = nil
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
55
|
class DslProvider < DslBase
|
163
56
|
|
164
57
|
TYPE = :script
|
165
58
|
|
59
|
+
def initialize source
|
60
|
+
super *[]
|
61
|
+
end
|
62
|
+
|
166
63
|
def setup &block
|
167
64
|
add_setup_block &block
|
168
65
|
end
|
@@ -272,6 +169,21 @@ module Neovim
|
|
272
169
|
plugin_provider do |dsl|
|
273
170
|
|
274
171
|
dsl.setup do |client|
|
172
|
+
r = client.get_var "ruby_require" rescue nil
|
173
|
+
case r
|
174
|
+
when Array then r = r.notempty?
|
175
|
+
when nil then nil
|
176
|
+
else r = [r]
|
177
|
+
end
|
178
|
+
if r then
|
179
|
+
WriteOut.redirect client do # Protect the RPC interface against erroneous output.
|
180
|
+
r.each do |l|
|
181
|
+
require l
|
182
|
+
rescue LoadError
|
183
|
+
client.err_writeln + $!.to_s
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
275
187
|
$curbuf = client.get_current_buf
|
276
188
|
$curwin = client.get_current_win
|
277
189
|
end
|
@@ -301,10 +213,13 @@ module Neovim
|
|
301
213
|
if !code.notempty? or code == "|" then # Workaround because Neovim doesn't allow empty code (the ultimate Quine)
|
302
214
|
set_global_client client do
|
303
215
|
client.command "#{lst}"
|
304
|
-
code = (get_lines client, fst..lst).join
|
216
|
+
code = (get_lines client, fst..lst).join $/
|
305
217
|
WriteBuf.redirect client do
|
306
218
|
r = script_binding.eval code, "ruby_run"
|
307
|
-
r.nil?
|
219
|
+
unless r.nil? then
|
220
|
+
script_binding.local_variable_set :_, r
|
221
|
+
puts "#=> #{r.inspect}"
|
222
|
+
end
|
308
223
|
end
|
309
224
|
end
|
310
225
|
elsif code == "+" then
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#
|
2
|
+
# neovim/tools/copy.rb -- Set X11 selection and Tmux buffer
|
3
|
+
#
|
4
|
+
|
5
|
+
|
6
|
+
module Kernel
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def xsel data = nil, sel: :primary
|
11
|
+
if ($xsel ||= command? "xsel" ) then
|
12
|
+
cmd = [ $xsel]
|
13
|
+
case sel
|
14
|
+
when :primary then cmd.push "-p"
|
15
|
+
when :secondary then cmd.push "-s"
|
16
|
+
when :clipboard then cmd.push "-b"
|
17
|
+
end
|
18
|
+
ci, co = "-i", "-o"
|
19
|
+
elsif ($xclip ||= command? "xclip") then
|
20
|
+
cmd = [ $xclip, "-selection", sel.to_s]
|
21
|
+
ci, co = "-i", "-o"
|
22
|
+
end
|
23
|
+
cmd or raise ScriptError, "Sorry, Neither xsel nor xclip seem to be installed."
|
24
|
+
if data then
|
25
|
+
cmd.push ci
|
26
|
+
cmd_write cmd, data
|
27
|
+
else
|
28
|
+
cmd.push co
|
29
|
+
cmd_read cmd
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def xsel! data, sel: :clipboard
|
33
|
+
xsel data, sel: sel
|
34
|
+
end
|
35
|
+
|
36
|
+
def tmuxbuf data = nil, name: nil
|
37
|
+
$tmux ||= command? "tmux"
|
38
|
+
$tmux or raise ScriptError, "Sorry, TMux doesn't seem to be installed."
|
39
|
+
args = []
|
40
|
+
if name then
|
41
|
+
args.push "-b", name
|
42
|
+
end
|
43
|
+
args.push "-"
|
44
|
+
if data then
|
45
|
+
cmd_write [ $tmux, "load-buffer", *args], data
|
46
|
+
else
|
47
|
+
cmd_read [ $tmux, "save-buffer", *args]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def command? cmd
|
53
|
+
if cmd[ File::SEPARATOR] then
|
54
|
+
cmd if File.executable? cmd
|
55
|
+
else
|
56
|
+
(ENV[ "PATH"].split File::PATH_SEPARATOR).each { |p|
|
57
|
+
c = File.join p, cmd
|
58
|
+
return c if File.executable? c
|
59
|
+
}
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def cmd_write cmd, data
|
65
|
+
case data
|
66
|
+
when Array then data = data.join $/
|
67
|
+
when String then nil
|
68
|
+
else data = data.to_s
|
69
|
+
end
|
70
|
+
IO.popen cmd, "w" do |t| t.write data end
|
71
|
+
end
|
72
|
+
|
73
|
+
def cmd_read cmd
|
74
|
+
IO.popen cmd, "r" do |t| t.read end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|