REPLSmuggler
Documentation for REPLSmuggler.
REPLSmuggler is meant to evaluate code coming from various clients in your REPL. The main goal is for an editor to send a bunch of lines of code with some metadata giving the name of the file and the line. REPLSmuggler
will evaluate the code and send back the return value. If an error is raised, it will send the traceback to the client.
See also the the companion plugin for NeoVim.
Usage
Using REPLSmuggler is as simple as:
julia> using REPLSmugglers
julia> smuggle()
[ Info: Ahoy, now smuggling from socket /run/user/1000/julia/replsmuggler/contraband_clandestine_operation.
Task (runnable) @0x0000753a784c6bd0
Internals
REPLSmuggler
REPLSmuggler.CURRENT_SMUGGLER
— ConstantStore the current server.
REPLSmuggler.basepath
— Methodbasepath()
Return a path where REPLSmuggler can store its socket, depending on the OS.
- For Linux:
/run/user/<uid>/julia/replsmuggler/
- For Windows:
\\.\pipe\
- For MacOS:
~/Library/Application Support/julia/replsmuggler/
REPLSmuggler.smuggle
— Methodsmuggle([name]; basepath=basepath(), serializer=MsgPack)
Start a server using a UNIX sockets with a random name and MsgPack.jl
as a serializer. The socket will be stored in joinpath(basepath, name)
. If name
is not provided, REPLSmuggler will try randomly generated names until a non-already-existing socket name is found.
For example, on linux, you could find the socket in /run/user/1000/julia/replsmuggler/clandestine_underworld
if the name was chosen to be clandestine_underworld
.
The socket name is displayed in the REPL, and the server is accessible through CURRENT_SMUGGLER
.
See also basepath.
Protocol
REPLSmuggler.Protocols
— ModuleDefinition of the protocol used by REPLSmuggler.jl. It is based on MsgPack-RPC, see here:
- https://github.com/msgpack/msgpack/blob/master/spec.md
- https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
The actual (de)serialization from and to MsgPack objects is handled by MsgPack.jl through a lightweight wrapper defined in MsgPackSerializer
.
The protocol consists of requests messages and their corresponding response messages. There can also be notification messages.
As per the specification, a request is serialized to an array of four elements, that could be written in Julia as follow:
[type::UInt8, msgid::UInt32, method::String, params::Vector{Any}]
Where type = 0x00
. For convenience, we define a structure and teach MsgPack.jl
to serialize it.
A response message should be serialized as:
[type::UInt8, msgid::UInt32, error::Any, result::Any]
Where type = 0x01
. msgid
is the identifier of the corresponding request.
Finally, a notification has the form:
[type::UInt8, method::String, params::Vector{Any}]
Where type = 0x02
.
Defined methods for requests.
We allow the client to run the following methods. If a method is unknown by the server, it will raise an error.
eval
: Evaluate a chunk of code. Parameters:file::String
line::UInt32
code::String
interrupt
: Interrupt the current evaluation. No parameter.exit
: Stop the current session. No parameter.
Responses of the server.
The result field is a string of what would be printed in the REPL. It is empty if an error occured.
If an error occured, then the error field is a three-elements array structured as follow:
exception::String
: Name of the exception, e.g."ValueError"
,exception_text::String
: Text, e.g."This value cannot be < 0."
,stacktrace::Vector{Tuple{String, UInt32, String}}
: The stacktrace, with each row being(file, line, function)
.
Notifications by the server.
Currently, the following notifications can be sent by the server. If a notification received by the client is unknown, it should simply be ignored without erroring.
handshake
: Sent at the begining of a session, mainly to ensure the correct version of the protocol is being used. Parameters:myname::String
: Name of the server. Will typically beREPLSmuggler
, but could be replaced if other implementations of the protocol were to exist.version::String
: A sementic versioning version number telling the client which version of the protocol is being used by the server.
Typical session:
- The client connects to the server.
- The server sends a
handshake
notification. - The client checks it is running the correct version of the protocol.
- The client runs requests (
eval
,interrupts
...) - The server responds to the requests.
- The client runs
exit
. - The server stops all the running code and close the session.
Note that any interrupt of the connection (i.e. closing the socket) is equivalent to sending an exit
request.
REPLSmuggler.Protocols.PROTOCOL_MAGIC
— ConstantName of the protocol implementation.
REPLSmuggler.Protocols.PROTOCOL_VERSION
— ConstantProtocol version.
REPLSmuggler.Protocols.AbstractMsgPackRPC
— TypeRepresents a MsgPackRPC message. type
needs not to be stored explicitely.
REPLSmuggler.Protocols.AbstractResponse
— TypeRepresents a response.
REPLSmuggler.Protocols.MsgType
— TypeMsgPackRPC message types.
REPLSmuggler.Protocols.Notification
— TypeRepresents a notification.
REPLSmuggler.Protocols.ProtocolException
— TypeUsed internally to report protocol exceptions.
REPLSmuggler.Protocols.Request
— TypeRepresents a request.
REPLSmuggler.Protocols.Error
— MethodError(msgid, error, stackframe)
REPLSmuggler.Protocols.Handshake
— MethodHandshake()
Create a hand-shake notification.
REPLSmuggler.Protocols.Result
— MethodResult(msgid, result)
REPLSmuggler.Protocols.astuple
— Functionastuple(message)
Returns a vector from the message that can be serialized.
REPLSmuggler.Protocols.deserialize
— Functionserialize(protocol)
De-serialize an AbstractMsgPackRPC
. Must be implemented by the serializer, e.g. MsgPackSerializer.jl
.
REPLSmuggler.Protocols.dispatchonmessage
— Methoddispatchonmessage(protocol, f, args...; kwargs)
Deserialize a request, and send it to the correct method of f
. f
should define methods with a first parameter being of type Val{:method}
where method
can be: "eval"
, "interrupt"
, or "exit"
. f
is called as:
f(Val(method), args..., request.msgid, request.params...; kwargs...)
A ProtocolException
might be raised if the request is malformed.
REPLSmuggler.Protocols.serialize
— Functionserialize(protocol, message)
Serialize an AbstractMsgPackRPC
. Must be implemented by the serializer, e.g. MsgPackSerializer.jl
.
Server
REPLSmuggler.Server
— ModuleImplementation of the server for REPLSmuggler.jl -the brain of REPSmuggler.jl.
The handling of the communication protocol is done by Protocols
.
The implementation is heavily inspired by the server from RemoteREPL.jl.
REPLSmuggler.Server.Session
— TypeThe session of a client.
REPLSmuggler.Server.Smuggler
— TypeStore the sessions of a server.
REPLSmuggler.Server.deserialize_requests
— MethodDispatch repeatedly the incoming requests of a session.
REPLSmuggler.Server.evaluate_entries
— Methodevaluate_entries(session)
Repeatedly evaluate the code put to the input channel of the session
.
REPLSmuggler.Server.evaluate_entry
— Methodevaluate_entry(session, msgid, file, line, value)
Evaluate the code in value
in the context of the given session
, replacing the context of the code with file
and line
. If an error occurs, it will put a using Base: JuliaSyntax Protocols.Error
to the outgoing channel of the session.
REPLSmuggler.Server.getsession
— Methodgetsession(smuggler)
Return a Session
through a call to waitsession
.
REPLSmuggler.Server.serialize_responses
— MethodSend repeatedly the responses of a given session.
REPLSmuggler.Server.serve_repl
— MethodServe sessions to clients connecting to a server.
REPLSmuggler.Server.serve_repl_session
— MethodServe one session, starting three loops to evaluate the entries, serialize the responses and deserialize the requests.
REPLSmuggler.Server.sessions
— MethodGet the sessions.
REPLSmuggler.Server.treatrequest
— FunctionFed to Protocols.dispatchonmessage
to respond accordingly to incoming requests.
REPLSmuggler.Server.vessel
— MethodGet the vessel.
REPLSmuggler.Server.waitsession
— MethodHas to be implemented for each specific server. See for example SocketSmugglers
.
Should return the specific of a session used to build a Session
.
Default implementation
REPLSmuggler.MsgPackSerializer
— ModuleThe default serializer for REPLSmuggler.jl
REPLSmuggler.SocketSmugglers
— ModuleA specific kind of server for UNIX sockets / Windows pipes.
Index
REPLSmuggler.MsgPackSerializer
REPLSmuggler.Protocols
REPLSmuggler.Server
REPLSmuggler.SocketSmugglers
REPLSmuggler.CURRENT_SMUGGLER
REPLSmuggler.Protocols.PROTOCOL_MAGIC
REPLSmuggler.Protocols.PROTOCOL_VERSION
REPLSmuggler.Protocols.AbstractMsgPackRPC
REPLSmuggler.Protocols.AbstractResponse
REPLSmuggler.Protocols.MsgType
REPLSmuggler.Protocols.Notification
REPLSmuggler.Protocols.ProtocolException
REPLSmuggler.Protocols.Request
REPLSmuggler.Server.Session
REPLSmuggler.Server.Smuggler
REPLSmuggler.Protocols.Error
REPLSmuggler.Protocols.Handshake
REPLSmuggler.Protocols.Result
REPLSmuggler.Protocols.astuple
REPLSmuggler.Protocols.deserialize
REPLSmuggler.Protocols.dispatchonmessage
REPLSmuggler.Protocols.serialize
REPLSmuggler.Server.deserialize_requests
REPLSmuggler.Server.evaluate_entries
REPLSmuggler.Server.evaluate_entry
REPLSmuggler.Server.getsession
REPLSmuggler.Server.serialize_responses
REPLSmuggler.Server.serve_repl
REPLSmuggler.Server.serve_repl_session
REPLSmuggler.Server.sessions
REPLSmuggler.Server.treatrequest
REPLSmuggler.Server.vessel
REPLSmuggler.Server.waitsession
REPLSmuggler.basepath
REPLSmuggler.smuggle