nrepl-lazuli 0.5.0 → 0.6.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/lib/nrepl-lazuli/bencode.rb +96 -0
- data/lib/nrepl-lazuli/client.rb +66 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7d68153dc3d474b045d5856d097c51670cfeb3ae688396a45c5cd16d117232a
|
4
|
+
data.tar.gz: 5e65794b9839a3f7d9c0aa341f3675c58e1a25290afa0f57f532cb1cb23a8be2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14c80200837368c174425e48735927e8c4e0be8214bbd5c1171e1338f19ac3b225b02a0631c9a269f19bc5846d7eb540944a96edf75ffd922cf8938923803f4a
|
7
|
+
data.tar.gz: e66a6400f737902c281c0c2c09c0d584ebbc5bd47a8d1262fd3b46db6afdbd32a57d1a5acfc220baa37bdf2fa9c02425d6f4f76acff4f16ecc7fca85bc5e910a
|
@@ -0,0 +1,96 @@
|
|
1
|
+
class BEncode
|
2
|
+
def self.encode(data)
|
3
|
+
case data
|
4
|
+
when Integer
|
5
|
+
"i#{data}e"
|
6
|
+
when String
|
7
|
+
"#{data.bytesize}:#{data}"
|
8
|
+
when Array
|
9
|
+
"l#{data.map { |e| encode(e) }.join}e"
|
10
|
+
when Hash
|
11
|
+
"d#{data.map { |k, v| encode(k) + encode(v) }.join}e"
|
12
|
+
else
|
13
|
+
raise ArgumentError, "Cannot BEncode type: #{data.class}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(stream)
|
18
|
+
@stream =
|
19
|
+
if stream.kind_of?(IO) || stream.kind_of?(StringIO)
|
20
|
+
stream
|
21
|
+
elsif stream.respond_to? :string
|
22
|
+
StringIO.new stream.string
|
23
|
+
elsif stream.respond_to? :to_s
|
24
|
+
StringIO.new stream.to_s
|
25
|
+
end
|
26
|
+
@encoding = @stream.external_encoding || Encoding::default_external
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse!
|
30
|
+
case peek
|
31
|
+
when ?i then parse_integer!
|
32
|
+
when ?l then parse_list!
|
33
|
+
when ?d then parse_dict!
|
34
|
+
when ?0 .. ?9 then parse_string!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def eos?
|
39
|
+
@stream.eof?
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def parse_integer!
|
45
|
+
@stream.getc
|
46
|
+
num = @stream.gets("e") or raise ArgumentError
|
47
|
+
num.chop.to_i
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_list!
|
51
|
+
@stream.getc
|
52
|
+
ary = []
|
53
|
+
ary.push(parse!) until peek == ?e
|
54
|
+
@stream.getc
|
55
|
+
ary
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_dict!
|
59
|
+
@stream.getc
|
60
|
+
hsh = {}
|
61
|
+
until peek == ?e
|
62
|
+
key = parse!
|
63
|
+
|
64
|
+
unless key.is_a? String or key.is_a? Integer
|
65
|
+
raise ArgumentError, "key must be a string or number"
|
66
|
+
end
|
67
|
+
|
68
|
+
val = parse!
|
69
|
+
|
70
|
+
hsh.store(key.to_s, val)
|
71
|
+
end
|
72
|
+
@stream.getc
|
73
|
+
hsh
|
74
|
+
end
|
75
|
+
|
76
|
+
def parse_string!
|
77
|
+
num = @stream.gets(":") or
|
78
|
+
raise ArgumentError, "invalid string length (no colon)"
|
79
|
+
|
80
|
+
begin
|
81
|
+
length = num.chop.to_i
|
82
|
+
return "" if length == 0 # Workaround for Rubinius bug
|
83
|
+
str = @stream.read(length).force_encoding(@encoding)
|
84
|
+
rescue => e
|
85
|
+
raise ArgumentError, "invalid string length #{e}"
|
86
|
+
end
|
87
|
+
|
88
|
+
str
|
89
|
+
end
|
90
|
+
|
91
|
+
def peek
|
92
|
+
c = @stream.getc
|
93
|
+
@stream.ungetc(c)
|
94
|
+
c
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'bencode'
|
4
|
+
require 'timeout'
|
5
|
+
|
6
|
+
module NREPL
|
7
|
+
class Client
|
8
|
+
attr_reader :host, :port
|
9
|
+
|
10
|
+
def initialize(port: DEFAULT_PORT, host: DEFAULT_HOST)
|
11
|
+
@port = port
|
12
|
+
@host = host
|
13
|
+
@socket = TCPSocket.new(@host, @port)
|
14
|
+
@bencode = BEncode.new(@socket)
|
15
|
+
@last_id = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def stop
|
19
|
+
unless closed?
|
20
|
+
@socket.close
|
21
|
+
@socket = nil
|
22
|
+
@bencode = nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def rpc(msg)
|
27
|
+
id = msg["id"] || msg[:id]
|
28
|
+
if(!id)
|
29
|
+
@last_id += 1
|
30
|
+
id = "autogen_#@last_id"
|
31
|
+
msg = msg.merge('id' => id)
|
32
|
+
end
|
33
|
+
|
34
|
+
write(msg)
|
35
|
+
Timeout.timeout(10) do
|
36
|
+
loop do
|
37
|
+
ret = read
|
38
|
+
if(ret["id"] == id)
|
39
|
+
break ret
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def write(msg)
|
46
|
+
@socket.write(BEncode.encode(msg))
|
47
|
+
@socket.flush
|
48
|
+
end
|
49
|
+
|
50
|
+
def read
|
51
|
+
@bencode.parse!
|
52
|
+
end
|
53
|
+
|
54
|
+
def register_session
|
55
|
+
write('op' => 'clone')
|
56
|
+
msg = read!
|
57
|
+
|
58
|
+
raise ArgumentError, "failed to create session" unless msg['new_session']
|
59
|
+
msg['new_session']
|
60
|
+
end
|
61
|
+
|
62
|
+
def closed?
|
63
|
+
@socket.nil?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nrepl-lazuli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maurício Szabo
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-05-06 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: A Ruby nREPL server, made to be used with Lazuli plug-in (but can be
|
13
13
|
used with any nREPL client too)
|
@@ -17,6 +17,8 @@ extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
19
|
- lib/nrepl-lazuli.rb
|
20
|
+
- lib/nrepl-lazuli/bencode.rb
|
21
|
+
- lib/nrepl-lazuli/client.rb
|
20
22
|
- lib/nrepl-lazuli/connection.rb
|
21
23
|
- lib/nrepl-lazuli/fake_stdout.rb
|
22
24
|
- lib/nrepl-lazuli/server.rb
|