Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple ide server instances #2586

Merged
merged 3 commits into from
Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions docs/source/implementation/ide-protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ The first version of Idris (written in Haskell and is at v1.3.3) implements vers

The protocol and its serialisation/deserialisation routines are part of the `Protocol` submodule hierarchy and are packaged in the `idris2protocols.ipkg` package.

Starting IDE Mode
-----------------

To initiate the IDE-Protocol on stdin/stdout, use the ``--ide-mode`` command line option.
To run the protocol over a TCP socket, use the ``--ide-mode-socket`` option: ::

idris2 --ide-mode-socket
53864

By default this will chose an open port, print the number of the port to stdout followed by a newline, and listen to that socket on localhost.
You may optionally specify the hostname and port to listen to: ::

idris2 --ide-mode-socket localhost:12345
12345

The IDE-Protocol will run on that socket, and Idris will exit when the client disconnects from the socket.


Protocol Overview
-----------------
Expand All @@ -23,7 +40,7 @@ A reply can consist of multiple messages: any number of messages to inform the u
The wire format is the length of the message in characters, encoded in 6 characters hexadecimal, followed by the message encoded as S-expression (sexp).
Additionally, each request includes a unique integer (counting upwards), which is repeated in all messages corresponding to that request.

An example interaction from loading the file ``/home/hannes/empty.idr`` looks as follows on the wire:::
An example interaction from loading the file ``/home/hannes/empty.idr`` looks as follows on the wire: ::

00002a((:load-file "/home/hannes/empty.idr") 1)
000039(:write-string "Type checking /home/hannes/empty.idr" 1)
Expand Down Expand Up @@ -180,17 +197,17 @@ New in Version 2 of the protocol are:
Possible Replies
----------------

Possible replies include a normal final reply:::
Possible replies include a normal final reply: ::

(:return (:ok SEXP [HIGHLIGHTING]) ID)
(:return (:error String [HIGHLIGHTING]) ID)

A normal intermediate reply:::
A normal intermediate reply: ::

(:output (:ok SEXP [HIGHLIGHTING]) ID)
(:output (:error String [HIGHLIGHTING]) ID)

Informational and/or abnormal replies:::
Informational and/or abnormal replies: ::

(:write-string String ID)
(:set-prompt String ID)
Expand Down Expand Up @@ -266,7 +283,7 @@ Idris supports instructing editors how to colour their code.
When elaborating source code or REPL input, Idris will locate regions of the source code corresponding to names, and emit information about these names using the same metadata as output highlighting.

These messages will arrive as replies to the command that caused elaboration to occur, such as ``:load-file`` or ``:interpret``.
They have the format:::
They have the format: ::

(:output (:ok (:highlight-source POSNS)) ID)

Expand Down
7 changes: 3 additions & 4 deletions src/Idris/CommandLine.idr
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ data CLOpt
||| Extract the host and port to bind the IDE socket to
export
ideSocketModeAddress : List CLOpt -> (String, Int)
ideSocketModeAddress [] = ("localhost", 38398)
ideSocketModeAddress [] = ("localhost", 0)
ideSocketModeAddress (IdeModeSocket hp :: _) =
let (h, p) = String.break (== ':') hp
port = fromMaybe 38398 (portPart p >>= parsePositive)
port = fromMaybe 0 (portPart p >>= parsePositive)
host = if h == "" then "localhost" else h
in (host, port)
where
Expand Down Expand Up @@ -300,8 +300,7 @@ options = [MkOpt ["--check", "-c"] [] [CheckOnly]
(Just "Run the REPL with machine-readable syntax"),
MkOpt ["--ide-mode-socket"] [Optional "host:port"]
(\hp => [IdeModeSocket $ fromMaybe (formatSocketAddress (ideSocketModeAddress [])) hp])
(Just $ "Run the ide socket mode on given host and port " ++
showDefault (formatSocketAddress (ideSocketModeAddress []))),
(Just $ "Run the ide socket mode on given host and port (random open socket by default)"),

optSeparator,
MkOpt ["--client"] [Required "REPL command"] (\f => [RunREPL f])
Expand Down
4 changes: 3 additions & 1 deletion src/Idris/IDEMode/REPL.idr
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import System.File

import Network.Socket
import Network.Socket.Data
import Network.Socket.Raw

import TTImp.Interactive.Completion

Expand Down Expand Up @@ -69,7 +70,8 @@ initIDESocketFile h p = do
then
pure (Left ("Failed to listen on socket with error: " ++ show res))
else
do putStrLn (show p)
do p <- getSockPort sock
putStrLn (show p)
fflush stdout
res <- accept sock
case res of
Expand Down