Skip to content

Commit

Permalink
Allowing remote LSP for superbol
Browse files Browse the repository at this point in the history
  • Loading branch information
Stevendeo committed Aug 23, 2024
1 parent d9b0282 commit 60eb348
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 5 deletions.
1 change: 1 addition & 0 deletions sphinx/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Welcome to SuperBOL Studio OSS
commands
API doc <https://ocamlpro.github.io/superbol-studio-oss/doc>
license
remote-lsp

Sources and Issues on Github <https://github.com/ocamlpro/superbol-studio-oss>

Expand Down
25 changes: 25 additions & 0 deletions sphinx/remote-lsp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.. remote-lsp
You can simulate a remote LSP with the following scripts:

Start a server on any port (here I chose 8000):
`$ nc -k -l localhost 8000 > test.nc`

Then, use the following script to read on a file:
```
touch $1
inotifywait -m -e modify $1 | while read line
do
if [ ! -s $1 ]; then
echo 'Waiting for content'
else
cat $1 | superbol lsp > superbol.log
> $1
fi
done
```

and call it with `test.nc`.

TODO: this script only receives information, but does not send it back to
VSCODE; it only writes it in superbol.log. It should answer to the client.
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,38 @@ module StaticFeature = struct
[@@js.builder]]
end

module StreamInfo = struct
include Interface.Make ()

type njs_stream

let njs_stream_of_string str : njs_stream =
Format.ksprintf
Js_of_ocaml.Js.Unsafe.eval_string
"new joo_global_object.webSocket (`%s`);"
str

let njs_stream_of_js = Obj.magic

let njs_stream_to_js = Obj.magic

include
[%js:
val writer : t -> njs_stream [@@js.get]

val reader : t -> njs_stream [@@js.get]

val detached : t -> bool option [@@js.get]

val create :
writer:njs_stream
-> reader:njs_stream
-> ?detached:bool
-> unit
-> t
[@@js.builder]]
end

module DidChangeConfiguration = struct
include Interface.Make ()

Expand All @@ -211,6 +243,13 @@ module LanguageClient = struct
-> t
[@@js.new "vscode_languageclient.LanguageClient"]

val make_stream :
id:string
-> name:string
-> (unit -> StreamInfo.t Promise.t)
-> t
[@@js.new "vscode_languageclient.LanguageClient"]

val start : t -> unit Promise.t [@@js.call]

val isRunning : t -> bool [@@js.call]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,28 @@ module DidChangeConfiguration : sig
val create : settings:Ojs.t -> unit -> t
end

module StreamInfo : sig
include Js.T

type njs_stream

val njs_stream_of_string : string -> njs_stream

val writer : t -> njs_stream [@@js.get]

val reader : t -> njs_stream [@@js.get]

val detached : t -> bool option [@@js.get]

val create :
writer:njs_stream
-> reader:njs_stream
-> ?detached:bool
-> unit
-> t
[@@js.builder]
end

module LanguageClient : sig
include Js.T

Expand All @@ -179,6 +201,12 @@ module LanguageClient : sig
-> unit
-> t

val make_stream :
id:string
-> name:string
-> (unit -> StreamInfo.t Promise.t)
-> t

val start : t -> unit Promise.t

val isRunning : t -> bool
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
joo_global_object.vscode_languageclient = require("vscode-languageclient");
joo_global_object.webSocket = require("ws");
36 changes: 31 additions & 5 deletions src/vscode/superbol-vscode-platform/superbol_instance.ml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type t = {
}
type client = LanguageClient.t


let id = "superbol-free-lsp"

let name = "SuperBOL Language Server"

let make ~context = { context; language_client = None }

let client { language_client; _ } = language_client
Expand All @@ -38,12 +43,33 @@ let stop_language_server t =
let start_language_server ({ context; _ } as t) =
let open Promise.Syntax in
let* () = stop_language_server t in
let serverOptions =
Superbol_languageclient.server_options ~context
in
let client =
LanguageClient.make ()
~id: "superbol-free-lsp"
~name: "SuperBOL Language Server"
~serverOptions:(Superbol_languageclient.server_options ~context)
~clientOptions:(Superbol_languageclient.client_options ())
let cmd = Executable.command serverOptions in
if String.starts_with ~prefix:"ws://" cmd then
LanguageClient.make_stream
~id
~name
(fun () ->
let njs_stream =
Vscode_languageclient.StreamInfo.njs_stream_of_string cmd
in
Promise.return (
Vscode_languageclient.StreamInfo.create
~writer:njs_stream
~reader:njs_stream
()
)
)
else
let clientOptions = Superbol_languageclient.client_options () in
LanguageClient.make ()
~id
~name
~serverOptions
~clientOptions
in
let+ () = LanguageClient.start client in
t.language_client <- Some client
Expand Down

0 comments on commit 60eb348

Please sign in to comment.