nrepl-lazuli 0.2.6 → 0.3.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 +4 -4
- data/lib/nrepl-lazuli/connection.rb +25 -15
- data/lib/nrepl-lazuli/server.rb +48 -14
- data/lib/nrepl-lazuli.rb +5 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2439208ce1a3db5af7c886aa95b577bb713667461c92d129e997f378ca704926
|
4
|
+
data.tar.gz: 6aabf3d36d3996ff158a2c50ebaa6239570e4799614a8d7110d50df7ca1ede4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 755e29ac97e588baca03a48914cc968d23d96961c66c4a3778554bc29b2d14f05ac236f9d15a1b565318cab9a11c28bc1a07cf096911da656f1450c4ae52ac7f
|
7
|
+
data.tar.gz: a6fabeadef479c719f9fa60b53587e85d0d25fd88e96a03311103b0a5a581cccb54425ebd68c9e75cb01e69335dc755631699153bb44501ec51d756d0dc693a8
|
@@ -4,18 +4,18 @@ module NREPL
|
|
4
4
|
|
5
5
|
def initialize(
|
6
6
|
input, debug: false, out: input,
|
7
|
-
watches: NREPL.class_variable_get(:@@bindings),
|
8
7
|
binding: nil,
|
9
|
-
bindings: {}
|
8
|
+
bindings: {},
|
9
|
+
bindings_by_id: {}
|
10
10
|
)
|
11
11
|
@debug = debug
|
12
12
|
@in = input
|
13
13
|
@out = out
|
14
14
|
@pending_evals = {}
|
15
|
-
@watches = watches
|
16
15
|
@counter = 0
|
17
16
|
@binding = binding
|
18
17
|
@bindings = bindings
|
18
|
+
@bindings_by_id = bindings_by_id
|
19
19
|
end
|
20
20
|
|
21
21
|
def treat_messages!
|
@@ -28,6 +28,8 @@ module NREPL
|
|
28
28
|
treat_msg(msg)
|
29
29
|
end
|
30
30
|
@pending_evals.each { |(i, _)| clear_eval!(i) }
|
31
|
+
rescue Errno::ECONNRESET
|
32
|
+
@pending_evals.each { |(i, _)| clear_eval!(i) }
|
31
33
|
end
|
32
34
|
|
33
35
|
def treat_msg(msg)
|
@@ -40,6 +42,9 @@ module NREPL
|
|
40
42
|
eval_op(msg, false)
|
41
43
|
when 'eval_pause'
|
42
44
|
eval_op(msg, true)
|
45
|
+
when 'last_exception'
|
46
|
+
ex = Server.class_variable_get(:@@last_exception)
|
47
|
+
send_msg(response_for(msg, { 'result' => ex.inspect, 'status' => ['done'] }))
|
43
48
|
when 'eval_resume'
|
44
49
|
msg['id'] ||= "eval_#{@counter += 1}"
|
45
50
|
stop_id = msg['stop_id']
|
@@ -52,7 +57,14 @@ module NREPL
|
|
52
57
|
when 'unwatch'
|
53
58
|
msg['id'] ||= "eval_#{@counter += 1}"
|
54
59
|
watch_id = msg['watch_id']
|
55
|
-
@
|
60
|
+
info = @bindings_by_id.delete(watch_id)
|
61
|
+
if(info)
|
62
|
+
file_info = @bindings.fetch(info[:file], {})
|
63
|
+
content = file_info.fetch(info[:row], {})
|
64
|
+
content.delete(watch_id)
|
65
|
+
file_info.delete(info[:row]) if(content.empty?)
|
66
|
+
@bindings.delete(info[:file]) if(file_info.empty?)
|
67
|
+
end
|
56
68
|
|
57
69
|
send_msg(response_for(msg, {
|
58
70
|
'status' => ['done'],
|
@@ -110,7 +122,6 @@ module NREPL
|
|
110
122
|
begin
|
111
123
|
eval_msg(msg, stop)
|
112
124
|
rescue Exception => e
|
113
|
-
puts e.backtrace
|
114
125
|
send_exception(msg, e)
|
115
126
|
ensure
|
116
127
|
@pending_evals.delete(id) unless stop
|
@@ -150,7 +161,7 @@ module NREPL
|
|
150
161
|
original_bind = if msg['stop_id']
|
151
162
|
@pending_evals.fetch(msg['stop_id'], {})[:binding]
|
152
163
|
elsif msg['watch_id']
|
153
|
-
@
|
164
|
+
@bindings_by_id.fetch(msg['watch_id'], {})[:binding]
|
154
165
|
else
|
155
166
|
find_row_based_binding(msg) || @binding
|
156
167
|
end
|
@@ -162,6 +173,12 @@ module NREPL
|
|
162
173
|
end
|
163
174
|
end
|
164
175
|
|
176
|
+
private def evaluate_code(code, file, line, bind)
|
177
|
+
bind ||= @@binding
|
178
|
+
line = line ? line + 1 : 1
|
179
|
+
eval(code, bind, file || "EVAL", line).inspect
|
180
|
+
end
|
181
|
+
|
165
182
|
private def find_row_based_binding(msg)
|
166
183
|
file = msg['file']
|
167
184
|
row = msg['line']
|
@@ -170,7 +187,7 @@ module NREPL
|
|
170
187
|
rows_bindings = @bindings[file]
|
171
188
|
return unless rows_bindings
|
172
189
|
found_row = row.downto(-1).find { |k| rows_bindings[k] }
|
173
|
-
rows_bindings[found_row][
|
190
|
+
rows_bindings[found_row].values[-1] if found_row
|
174
191
|
end
|
175
192
|
|
176
193
|
private def define_stop_function!(msg, method_name)
|
@@ -228,9 +245,6 @@ module NREPL
|
|
228
245
|
send_msg(response_for(msg, { 'versions' => versions }))
|
229
246
|
end
|
230
247
|
|
231
|
-
# @param [TCPSocket] client
|
232
|
-
# @param [Hash] msg
|
233
|
-
# @param [Exception] e
|
234
248
|
def send_exception(msg, e)
|
235
249
|
send_msg(response_for(msg, { 'ex' => e.message, 'status' => ['done', 'error'] }))
|
236
250
|
end
|
@@ -244,8 +258,4 @@ module NREPL
|
|
244
258
|
end
|
245
259
|
|
246
260
|
# To avoid locally binding with the NREPL::Connection module
|
247
|
-
|
248
|
-
define_method(:evaluate_code) do |code, file, line, bind|
|
249
|
-
bind ||= b
|
250
|
-
eval(code, bind, file || "EVAL", line || 0).inspect
|
251
|
-
end
|
261
|
+
NREPL::Connection.class_variable_set(:@@binding, binding)
|
data/lib/nrepl-lazuli/server.rb
CHANGED
@@ -13,6 +13,14 @@ module NREPL
|
|
13
13
|
attr_reader :debug, :port, :host
|
14
14
|
alias debug? debug
|
15
15
|
|
16
|
+
def self.spawn(args = {})
|
17
|
+
t = Thread.new {
|
18
|
+
new(**args).start
|
19
|
+
}
|
20
|
+
sleep 0.1
|
21
|
+
t[:nrepl_server]
|
22
|
+
end
|
23
|
+
|
16
24
|
def self.start(**kwargs)
|
17
25
|
new(**kwargs).start
|
18
26
|
end
|
@@ -21,7 +29,14 @@ module NREPL
|
|
21
29
|
new(**kwargs.merge(binding: binding)).start
|
22
30
|
end
|
23
31
|
|
24
|
-
def initialize(
|
32
|
+
def initialize(
|
33
|
+
port: DEFAULT_PORT,
|
34
|
+
host: DEFAULT_HOST,
|
35
|
+
debug: false,
|
36
|
+
binding: nil,
|
37
|
+
pwd: Dir.pwd,
|
38
|
+
tracing: true
|
39
|
+
)
|
25
40
|
@port = port
|
26
41
|
@pwd = pwd
|
27
42
|
@host = host
|
@@ -29,8 +44,12 @@ module NREPL
|
|
29
44
|
@connections = Set.new
|
30
45
|
@binding = binding
|
31
46
|
@bindings = {}
|
47
|
+
@bindings_by_id = {}
|
48
|
+
@tracing = tracing
|
49
|
+
Thread.current[:nrepl_server] = self
|
32
50
|
NREPL.class_variable_set(:@@connections, @connections)
|
33
51
|
NREPL.class_variable_set(:@@bindings, @bindings)
|
52
|
+
NREPL.class_variable_set(:@@bindings_by_id, @bindings_by_id)
|
34
53
|
end
|
35
54
|
|
36
55
|
private def record_port
|
@@ -44,31 +63,45 @@ module NREPL
|
|
44
63
|
puts "Running in debug mode" if debug?
|
45
64
|
record_port
|
46
65
|
|
66
|
+
@old_out, @old_err = $stdout, $stderr
|
47
67
|
$stdout = FakeStdout.new(@connections, STDOUT, "out")
|
48
68
|
$stderr = FakeStdout.new(@connections, STDERR, "err")
|
49
|
-
auto_create_bindings!
|
69
|
+
auto_create_bindings! if @tracing
|
50
70
|
|
51
71
|
Signal.trap("INT") { stop }
|
52
72
|
Signal.trap("TERM") { stop }
|
53
73
|
|
54
|
-
|
74
|
+
@socket = TCPServer.new(host, port)
|
55
75
|
loop do
|
56
|
-
|
57
|
-
|
76
|
+
break if @socket.closed?
|
77
|
+
Thread.start(@socket.accept) do |client|
|
78
|
+
connection = Connection.new(
|
79
|
+
client,
|
80
|
+
debug: debug?,
|
81
|
+
binding: @binding,
|
82
|
+
bindings_by_id: @bindings_by_id,
|
83
|
+
bindings: @bindings
|
84
|
+
)
|
58
85
|
@connections << connection
|
59
86
|
connection.treat_messages!
|
60
87
|
@connections.delete(connection)
|
61
88
|
end
|
62
89
|
end
|
90
|
+
rescue IOError
|
91
|
+
puts "Server closed" if debug?
|
63
92
|
ensure
|
64
93
|
File.unlink(PORT_FILENAME)
|
65
94
|
end
|
66
95
|
|
67
96
|
def auto_create_bindings!
|
68
97
|
dir_regex = Regexp.new("^#{Regexp.escape(@pwd)}")
|
69
|
-
@call_trace = TracePoint.new(:call) do |tp|
|
98
|
+
@call_trace = TracePoint.new(:class, :call) do |tp|
|
99
|
+
id = "#{tp.path}:#{tp.lineno}"
|
100
|
+
b = tp.binding
|
101
|
+
@bindings_by_id[id] = {binding: b, file: tp.path, row: tp.lineno-1}
|
70
102
|
@bindings[tp.path] ||= {}
|
71
|
-
@bindings[tp.path][tp.lineno-1]
|
103
|
+
@bindings[tp.path][tp.lineno-1] ||= {}
|
104
|
+
@bindings[tp.path][tp.lineno-1][id] = b
|
72
105
|
if tp.path =~ dir_regex
|
73
106
|
@connections.each do |connection|
|
74
107
|
connection.send_msg(
|
@@ -82,16 +115,17 @@ module NREPL
|
|
82
115
|
end
|
83
116
|
@call_trace.enable
|
84
117
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
118
|
+
@ex_trace = TracePoint.new(:raise) do |tp|
|
119
|
+
e = tp.raised_exception
|
120
|
+
@@last_exception = [:error, e.inspect.sub(/\>$/, ' stack=' + e.backtrace.inspect+'>')]
|
121
|
+
end
|
122
|
+
@ex_trace.enable
|
90
123
|
end
|
91
124
|
|
92
125
|
def stop
|
93
|
-
|
94
|
-
|
126
|
+
@connections = []
|
127
|
+
$stdout, $stderr = @old_out, @old_err
|
128
|
+
@socket.close
|
95
129
|
end
|
96
130
|
end
|
97
131
|
|
data/lib/nrepl-lazuli.rb
CHANGED
@@ -8,16 +8,19 @@ module NREPL
|
|
8
8
|
|
9
9
|
require_relative 'nrepl-lazuli/server'
|
10
10
|
@@bindings = {}
|
11
|
+
@@bindings_by_id = {}
|
11
12
|
@@connections = Set.new
|
12
13
|
|
13
14
|
def self.watch!(binding, id=nil)
|
14
15
|
loc = caller_locations[0]
|
15
|
-
file = loc.
|
16
|
+
file = loc.path
|
16
17
|
row = loc.lineno
|
17
18
|
id ||= "#{file}:#{row}"
|
18
19
|
|
20
|
+
@@bindings_by_id[id] = {binding: binding, file: file, row: loc.lineno-1}
|
19
21
|
@@bindings[file] ||= {}
|
20
|
-
@@bindings[file][loc.lineno-1]
|
22
|
+
@@bindings[file][loc.lineno-1] ||= {}
|
23
|
+
@@bindings[file][loc.lineno-1][id] = binding
|
21
24
|
|
22
25
|
@@connections.each do |connection|
|
23
26
|
connection.send_msg(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nrepl-lazuli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maurício Szabo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bencode
|
@@ -54,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
requirements: []
|
57
|
-
rubygems_version: 3.5.
|
57
|
+
rubygems_version: 3.5.9
|
58
58
|
signing_key:
|
59
59
|
specification_version: 4
|
60
60
|
summary: A Ruby nREPL server
|