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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e7940230b6c771925c5ee557cecd7a98e043cbe94fed89efe8dee2ce77611c5
4
- data.tar.gz: e36fda8c9c90cdb098e8e5e8307ce487cb28776d3c0de28e075964fea7acb4ed
3
+ metadata.gz: e7d68153dc3d474b045d5856d097c51670cfeb3ae688396a45c5cd16d117232a
4
+ data.tar.gz: 5e65794b9839a3f7d9c0aa341f3675c58e1a25290afa0f57f532cb1cb23a8be2
5
5
  SHA512:
6
- metadata.gz: e7a121b406ed724c1c433cd9a854f6082d1628b0557ebc9fb9bbd6f9e6c8a26c2f9c0390708f954ef3154b107d5234d7a332e343911426585c7fb9ec82b35247
7
- data.tar.gz: e183f6dc2766a16297f27fbf08b7c164b9b43e8c88b753fff43bedb96b1a3ef2b7649187a53703a6d591e18c6c1d3fc7d578f7af9ac4b5b39b87c861b392f490
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.5.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-04-04 00:00:00.000000000 Z
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