lsp_router 0.1.0 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d57746f846403f9ca2c5a45bba0ecd01fdb6e907e05095431063b8bc4a0a5f80
4
- data.tar.gz: a3aa45e975f6db6712acd14edd1f5fcfa3603578572890c87c29d0e8abb34da9
3
+ metadata.gz: 5b81686d10b1edcb9c6b6ab51eedd3f8bd4ca71c3bd3d44b820fd416f2a48f0e
4
+ data.tar.gz: 85e81047822d36218ac021ccccb240af5fdc896dcb0218a8c835f613343dea1a
5
5
  SHA512:
6
- metadata.gz: 101ee8a0b48df239a88ee5a4a684f3591ab544a7e76e35cbea4ab30e12ef4f0711fbde52dca246e0f5729d49589ada0d8327cf242ede5e6ef3f3ce7a5c2e0dea
7
- data.tar.gz: dd2ec59d88c78cd1dd5111a0a6437ce87136b3ebc6fbdd1723b6a92e6d4a2e9ae5a6eff1c2c01ac61337e3e42dee342b8a4566b81e13367b03eb6154bcba149e
6
+ metadata.gz: 289f4683fc2aead84ac11c7655b1faeb142f3692d26af1683d62181a3fb6ea7ac345f016e1e27946c5229dd755c9e49afed0ef4d00b5b28a481e42b6763dc933
7
+ data.tar.gz: c1e65b91db8a71ba1ebfacd134dc2b3a133d569a7ae67346fcc7a004502a4eff1fba2924d755f9f14420f3ff6369e89bb36f60a60a01f014f5249aba160f7e02
data/README.md CHANGED
@@ -17,7 +17,7 @@ logfile '/tmp/lsp_router'
17
17
  loglevel :info
18
18
 
19
19
  server :rubocop do
20
- command 'rubocop-lsp'
20
+ command 'rubocop --lsp'
21
21
  mode :stdio
22
22
  end
23
23
 
@@ -27,7 +27,7 @@ server :solargraph do
27
27
  end
28
28
  ```
29
29
 
30
- この例では、`rubocop-lsp` と `solargraph stdio` を起動して、クライアントからの処理を振り分ける。
30
+ この例では、`rubocop --lsp` と `solargraph stdio` を起動して、クライアントからの処理を振り分ける。
31
31
  最初に各サーバーの capabilities を確認して、各サーバーにどの機能があるかを確認し、クライアントからの REQUEST は対応しているサーバーに渡す。複数のサーバーが同じ機能を持っていれば上に書いたサーバーが優先される。NOTIFICATION は全サーバーに渡す。
32
32
 
33
33
  ## Example
@@ -37,3 +37,7 @@ Emacs の Eglot の場合はこんな感じに設定するといいっぽい。
37
37
  ```
38
38
  (add-to-list 'eglot-server-programs '((ruby-mode ruby-ts-mode) . ("lsp_router" "--error=lsp_router.err" "lsp_router.conf")))
39
39
  ```
40
+
41
+ ## License
42
+
43
+ GPLv3
data/config/example.conf CHANGED
@@ -2,7 +2,7 @@ logfile '/tmp/lsp_router'
2
2
  loglevel :info
3
3
 
4
4
  server :rubocop do
5
- command 'rubocop-lsp'
5
+ command 'rubocop --lsp'
6
6
  mode :stdio
7
7
  end
8
8
 
@@ -16,6 +16,7 @@ class LspRouter
16
16
  @command = server.attr[:command]
17
17
  @stdin, @stdout, @stderr = Open3.popen3(@command)
18
18
  @capabilities = {}
19
+ @terminated = false
19
20
  end
20
21
 
21
22
  # @param req [Hash]
@@ -31,6 +32,7 @@ class LspRouter
31
32
 
32
33
  # @param data [Hash]
33
34
  def write(data)
35
+ return if @terminated
34
36
  log("#{name}<", data)
35
37
  json = data.to_json
36
38
  @stdin.puts "Content-Length: #{json.bytesize}\r\n\r\n"
@@ -40,7 +42,12 @@ class LspRouter
40
42
 
41
43
  # @return [Hash]
42
44
  def read
45
+ return nil if @terminated
43
46
  header = @stdout.gets("\r\n\r\n")
47
+ unless header
48
+ @terminated = true
49
+ return nil
50
+ end
44
51
  fields = header.lines.map do |line|
45
52
  n, v = line.chomp.split(/: */, 2)
46
53
  [n.downcase, v] if n
@@ -1,3 +1,3 @@
1
1
  class LspRouter
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.3'
3
3
  end
data/lib/lsp_router.rb CHANGED
@@ -42,13 +42,21 @@ class LspRouter
42
42
  end
43
43
 
44
44
  def loop
45
- req = @client.read
46
- servers = @config.servers.map{LspRouter::ServerSide.new(_1, logger: @logger)}
47
- primary = servers.first
45
+ @servers = @config.servers.map{LspRouter::ServerSide.new(_1, logger: @logger)}
46
+ @primary = @servers.first
47
+ @server_map = @servers.map.to_h{[_1.name.to_s, _1]}
48
+ @capa_server = {}
49
+
50
+ initial_packet
51
+ threads = server_loop
52
+ threads.push client_loop
53
+ threads.each(&:join)
54
+ end
48
55
 
56
+ def initial_packet
57
+ req = @client.read
49
58
  res = nil
50
- capa_server = {}
51
- servers.each do |server|
59
+ @servers.each do |server|
52
60
  data = server.init(req)
53
61
  if res
54
62
  res['result']['capabilities'].update(data.dig('result', 'capabilities')){|_, v, _| v}
@@ -56,39 +64,58 @@ class LspRouter
56
64
  res = data
57
65
  end
58
66
  server.capabilities.each_key do |key|
59
- capa_server[key] ||= server
67
+ @capa_server[key] ||= server
60
68
  end
61
69
  end
62
70
  @client.write(res)
71
+ end
63
72
 
64
- thr = Thread.new do
73
+ def client_loop
74
+ Thread.new do
65
75
  Thread.abort_on_exception = true
66
76
  while true
67
77
  data = @client.read
68
78
  break unless data
69
- if data['id']
70
- # request
79
+ if data['method'] == 'shutdown' || data['method'] == 'exit'
80
+ @servers.each{_1.write(data)}
81
+ break if data['method'] == 'exit'
82
+ next
83
+ end
84
+ if data['id'] # request or response
71
85
  method = data['method']&.split('/')&.last
72
- server = capa_server[method] || primary
73
- server.write(data)
74
- else
75
- # notification
76
- servers.each do |server|
77
- server.write(data)
86
+ if data['method'] # request
87
+ server = @capa_server[method] || @primary
88
+ data['id'] = [server.name, data['id']].to_json
89
+ else # response
90
+ server_name, id = JSON.parse(data['id'])
91
+ data['id'] = id
92
+ server = @server_map[server_name]
78
93
  end
94
+ server.write(data)
95
+ else # notification
96
+ @servers.each{_1.write(data)}
79
97
  end
80
98
  end
99
+ @logger.info "client: end"
81
100
  end
101
+ end
82
102
 
83
- servers.each do |server|
103
+ def server_loop
104
+ @servers.map do |server|
84
105
  Thread.new do
85
106
  Thread.abort_on_exception = true
86
107
  while true
87
108
  data = server.read
109
+ break unless data
110
+ if data['id'] && data['method'] # request
111
+ data['id'] = [server.name, data['id']].to_json
112
+ elsif data['id'] # response
113
+ data['id'] = JSON.parse(data['id']).last rescue data['id']
114
+ end
88
115
  @client.write(data)
89
116
  end
117
+ @logger.info "server: [#{server.name}] end"
90
118
  end
91
119
  end
92
- thr.join
93
120
  end
94
121
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lsp_router
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - TOMITA Masahiro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-20 00:00:00.000000000 Z
11
+ date: 2023-12-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: routing multiple LSP server by capability
14
14
  email: