nrepl-lazuli 0.1.2 → 0.2.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/connection.rb +29 -2
- data/lib/nrepl/fake_stdout.rb +5 -22
- data/lib/nrepl/server.rb +77 -12
- data/lib/nrepl.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2deef62506da60f639206583fc37504630c3fdefcab9013a1ef25b354f51221c
|
4
|
+
data.tar.gz: 8374c37e1eae4d69479137163f10242ea0f287c9ffd099830b1d3d361b6c344c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c81e136417a9d6dac29f007a2539011baebc83d6975f1715eaa3f6f0799b4e63d4484bf834e729c0b53f65b0dcff09c917443f41c1f50edb1104cf3efb740390
|
7
|
+
data.tar.gz: a6293282dc353c2cfa998fd557a1c84a7482224009ea905f08f82c3615e38e64b4507f5927630be9f6e4e7a2d6a00a05d02e735f59b357249ccab0d7840e4a6c
|
data/lib/nrepl/connection.rb
CHANGED
@@ -2,13 +2,19 @@ module NREPL
|
|
2
2
|
class Connection
|
3
3
|
@@debug_counter = 0
|
4
4
|
|
5
|
-
def initialize(
|
5
|
+
def initialize(
|
6
|
+
input, debug: false, out: input,
|
7
|
+
watches: NREPL.class_variable_get(:@@watches), binding: nil,
|
8
|
+
auto_bindings: {}
|
9
|
+
)
|
6
10
|
@debug = debug
|
7
11
|
@in = input
|
8
12
|
@out = out
|
9
13
|
@pending_evals = {}
|
10
14
|
@watches = watches
|
11
15
|
@counter = 0
|
16
|
+
@binding = binding
|
17
|
+
@auto_bindings = auto_bindings
|
12
18
|
end
|
13
19
|
|
14
20
|
def treat_messages!
|
@@ -75,7 +81,15 @@ module NREPL
|
|
75
81
|
'op' => msg['op']
|
76
82
|
}))
|
77
83
|
end
|
78
|
-
|
84
|
+
when 'watches_for_file'
|
85
|
+
msg['id'] ||= "eval_#{@counter += 1}"
|
86
|
+
file = msg['file']
|
87
|
+
rows_bindings = @auto_bindings[file] || {}
|
88
|
+
send_msg(response_for(msg, {
|
89
|
+
'status' => ['done'],
|
90
|
+
'rows' => rows_bindings.keys.sort,
|
91
|
+
'op' => msg['op']
|
92
|
+
}))
|
79
93
|
else
|
80
94
|
send_msg(response_for(msg, {
|
81
95
|
'op' => msg['op'],
|
@@ -135,6 +149,8 @@ module NREPL
|
|
135
149
|
@pending_evals.fetch(msg['stop_id'], {})[:binding]
|
136
150
|
elsif msg['watch_id']
|
137
151
|
@watches.fetch(msg['watch_id'], {})[:binding]
|
152
|
+
else
|
153
|
+
find_row_based_binding(msg) || @binding
|
138
154
|
end
|
139
155
|
evaluate_code(code, msg['file'], msg['line'], original_bind)
|
140
156
|
end
|
@@ -144,6 +160,17 @@ module NREPL
|
|
144
160
|
end
|
145
161
|
end
|
146
162
|
|
163
|
+
private def find_row_based_binding(msg)
|
164
|
+
file = msg['file']
|
165
|
+
row = msg['line']
|
166
|
+
return if !file || !row
|
167
|
+
|
168
|
+
rows_bindings = @auto_bindings[file]
|
169
|
+
return unless rows_bindings
|
170
|
+
found_row = row.downto(-1).find { |k| rows_bindings[k] }
|
171
|
+
rows_bindings[found_row]
|
172
|
+
end
|
173
|
+
|
147
174
|
private def define_stop_function!(msg, method_name)
|
148
175
|
out, inp = IO.pipe
|
149
176
|
send_stopped = proc do |ctx_binding, original_msg, caller|
|
data/lib/nrepl/fake_stdout.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
1
3
|
module NREPL
|
2
|
-
class FakeStdout
|
4
|
+
class FakeStdout < SimpleDelegator
|
3
5
|
def initialize(connections, io, kind)
|
4
6
|
@connections = connections
|
5
7
|
@io = io
|
6
8
|
@kind = kind
|
9
|
+
super(io)
|
7
10
|
end
|
8
11
|
|
9
12
|
def <<(text)
|
@@ -21,33 +24,13 @@ module NREPL
|
|
21
24
|
nil
|
22
25
|
end
|
23
26
|
|
24
|
-
def method_missing(method, *)
|
25
|
-
@io.send(method, *)
|
26
|
-
end
|
27
|
-
|
28
27
|
def write(text)
|
29
|
-
@io.write(text)
|
30
28
|
@connections.each do |conn|
|
31
29
|
conn.send_msg(
|
32
30
|
@kind => text
|
33
31
|
)
|
34
32
|
end
|
35
|
-
|
36
|
-
|
37
|
-
def flush
|
38
|
-
@io.flush
|
39
|
-
end
|
40
|
-
|
41
|
-
def close
|
42
|
-
@io.close
|
43
|
-
end
|
44
|
-
|
45
|
-
def sync
|
46
|
-
@io.sync
|
47
|
-
end
|
48
|
-
|
49
|
-
def sync=(val)
|
50
|
-
@io.sync = val
|
33
|
+
@io.write(text)
|
51
34
|
end
|
52
35
|
end
|
53
36
|
end
|
data/lib/nrepl/server.rb
CHANGED
@@ -17,11 +17,18 @@ module NREPL
|
|
17
17
|
new(**kwargs).start
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def self.bind!(binding, **kwargs)
|
21
|
+
new(**kwargs.merge(binding: binding)).start
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(port: DEFAULT_PORT, host: DEFAULT_HOST, debug: false, binding: nil, pwd: Dir.pwd)
|
21
25
|
@port = port
|
26
|
+
@pwd = pwd
|
22
27
|
@host = host
|
23
28
|
@debug = debug
|
24
29
|
@connections = Set.new
|
30
|
+
@binding = binding
|
31
|
+
@auto_bindings = {}
|
25
32
|
NREPL.class_variable_set(:@@connections, @connections)
|
26
33
|
end
|
27
34
|
|
@@ -38,6 +45,7 @@ module NREPL
|
|
38
45
|
|
39
46
|
$stdout = FakeStdout.new(@connections, STDOUT, "out")
|
40
47
|
$stderr = FakeStdout.new(@connections, STDERR, "err")
|
48
|
+
auto_create_bindings!
|
41
49
|
|
42
50
|
Signal.trap("INT") { stop }
|
43
51
|
Signal.trap("TERM") { stop }
|
@@ -45,7 +53,7 @@ module NREPL
|
|
45
53
|
s = TCPServer.new(host, port)
|
46
54
|
loop do
|
47
55
|
Thread.start(s.accept) do |client|
|
48
|
-
connection = Connection.new(client, debug: debug
|
56
|
+
connection = Connection.new(client, debug: debug?, binding: @binding, auto_bindings: @auto_bindings)
|
49
57
|
@connections << connection
|
50
58
|
connection.treat_messages!
|
51
59
|
@connections.delete(connection)
|
@@ -55,23 +63,80 @@ module NREPL
|
|
55
63
|
File.unlink(PORT_FILENAME)
|
56
64
|
end
|
57
65
|
|
66
|
+
def auto_create_bindings!
|
67
|
+
dir_regex = Regexp.new("^#{Regexp.escape(@pwd)}")
|
68
|
+
@call_trace = TracePoint.new(:call) do |tp|
|
69
|
+
@auto_bindings[tp.path] ||= {}
|
70
|
+
@auto_bindings[tp.path][tp.lineno-1] = tp.binding
|
71
|
+
if tp.path =~ dir_regex
|
72
|
+
# puts "Tracing #{tp.path}:#{tp.lineno}"
|
73
|
+
@connections.each do |connection|
|
74
|
+
connection.send_msg(
|
75
|
+
'op' => 'hit_auto_watch',
|
76
|
+
'file' => tp.path,
|
77
|
+
'line' => tp.lineno-1,
|
78
|
+
'status' => ['done']
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
@call_trace.enable
|
84
|
+
end
|
85
|
+
|
58
86
|
def stop
|
59
87
|
Thread.exit
|
60
88
|
exit(0)
|
61
89
|
end
|
62
90
|
end
|
63
|
-
end
|
64
91
|
|
65
|
-
# Sorry, no other way...
|
66
|
-
module ThreadPatch
|
67
|
-
|
68
|
-
|
69
|
-
|
92
|
+
# Sorry, no other way...
|
93
|
+
module ThreadPatch
|
94
|
+
def initialize(*args, &b)
|
95
|
+
@parent = Thread.current
|
96
|
+
super
|
97
|
+
end
|
98
|
+
|
99
|
+
def parent
|
100
|
+
@parent
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
Thread.prepend(ThreadPatch)
|
105
|
+
|
106
|
+
# Also...
|
107
|
+
module MethodLocationFixer
|
108
|
+
def __lazuli_source_location
|
109
|
+
@__lazuli_source_location || source_location
|
110
|
+
end
|
70
111
|
end
|
71
112
|
|
72
|
-
|
73
|
-
|
113
|
+
module DefinitionFixer
|
114
|
+
@@definitions = {}
|
115
|
+
|
116
|
+
def __lazuli_source_location(method)
|
117
|
+
ancestors.each do |klass|
|
118
|
+
loc = (klass.instance_variable_get(:@__lazuli_methods) || {})[method]
|
119
|
+
return loc if loc
|
120
|
+
end
|
121
|
+
return instance_method(method).source_location
|
122
|
+
end
|
123
|
+
|
124
|
+
def method_added(method_name)
|
125
|
+
return if method_name == :__lazuli_source_location
|
126
|
+
# puts "Thing added #{method_name}"
|
127
|
+
path = caller.reject { |x| x =~ /gems.*gems/ }[0]
|
128
|
+
if path
|
129
|
+
(file, row) = path.split(/:/)
|
130
|
+
|
131
|
+
known = instance_variable_get(:@__lazuli_methods)
|
132
|
+
if !known
|
133
|
+
known = {}
|
134
|
+
instance_variable_set(:@__lazuli_methods, known)
|
135
|
+
end
|
136
|
+
known[method_name] = [file, row.to_i]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
Module.prepend(DefinitionFixer)
|
74
141
|
end
|
75
142
|
end
|
76
|
-
|
77
|
-
Thread.prepend(ThreadPatch)
|
data/lib/nrepl.rb
CHANGED
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.2.0
|
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-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bencode
|