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) @0x0000753a784c6bd0You are then able to send code and get notified when an error happens.
At any point you can show the current smuggler by calling showsmuggler() in the REPL.
smuggle can also be used the other way around, to directly send diagnostics to your editor. For example, if your editor has smuggled the following function:
function bad_bad_bad()
error("hey!")
endYou can send back diagnostics to the editor directly from the REPL by catching an exception.
julia> try
bad_bad_bad()
catch exc
smuggle(exc)
endYou can even send directly diagnostics, without looking for code that has actually been sent by the editor:
julia> smuggle("hey", "foo", "$(pwd())/test.jl", 11, "none")There's also an extension to work with JET's reports. Say you smuggled the following functions:
function foo(s0)
a = []
for s in split(s0)
push!(a, bar(s))
end
return sum(a)
end
bar(s::String) = parse(Int, s)You can smuggle back to the editor JET's report as follow:
julia> smuggle(@report_call foo("1 2 3"))Internals
REPLSmuggler
REPLSmuggler.CURRENT_SMUGGLER — Constant
Store the current server.
REPLSmuggler.basepath — Method
basepath()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.showsmuggler — Method
Print the current smuggler pathREPLSmuggler.smuggle — Method
smuggle(title, diagnostic, filename, line, function)Smuggle a diagnostic in file filename, function function, at line line.
REPLSmuggler.smuggle — Method
smuggle([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.
REPLSmuggler.smuggle — Method
smuggle(stacks::Base.ExceptionStack)Smuggle an exception stack. In the Julia REPL the err variable is implicitly defined and contains the stack from the last thrown error.
Examples
julia> error("foo")
ERROR: foo
Stacktrace:
[...]
julia> smuggle(err)REPLSmuggler.smuggle — Method
smuggle(exception, stackframes=stacktrace(Base.catch_stacktrace()))Smuggle an exception. Can be used to report on exceptions thrown by code evaluated by the user in the REPL.
Examples
try
error("foo")
catch exc
smuggle(exc)
endProtocol
REPLSmuggler.Protocols — Module
Definition 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::Stringline::UInt32code::String
configure: Configure the current session. Parameters:settings::Dict{String, Any}
evalbyblocks::Boolshould the session evaluate entries by block rather than
showdir::String: directory to store images.enableimages::String: Should we display objects displayable as images be showed as images?iocontext::Dict{String,Any}: IOContext options forshow.
interrupt: Interrupt the current evaluation. No parameter.exit: Stop the current session. No parameter.
Responses of the server.
The result field is empty if an error occured. Otherwise it contains three elements:
linenumber::UInt32: Line that produced the output,mime::String: MIME of the answer. If it istext/plainthe output should be displayed as is. The other supported MIME types are listed inIMAGE_MIMEand are meant to display image results.output: The output. Ifmimeistext/plainthis is aStringto be displayed, otherwise it is a path to an image (String) corresponding to the MIME type.
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, module). Module can benil.
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.
diagnostic: Sent following the evaluation of some code by the user from the REPL. For example, this could be used via a direct call to display a diagnostic on a specific line, or to report an exception from some code evaluated by the user, or report diagnostic from other packages such asJET.jl. This is very similar to how an exception would be handled when executing code. Parameters:title::String: Short title for the diagnostic.diagnostic::String: The diagnostic that is to be displayed.stacktrace::Vector{Tuple{String, UInt32, String}}: The stacktrace, with
(file, line, function).
Typical session:
- The client connects to the server.
- The server sends a
handshakenotification. - 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.IMAGE_MIME — Constant
Supported image MIME types.
REPLSmuggler.Protocols.PROTOCOL_MAGIC — Constant
Name of the protocol implementation.
REPLSmuggler.Protocols.PROTOCOL_VERSION — Constant
Protocol version.
REPLSmuggler.Protocols.AbstractMsgPackRPC — Type
Represents a MsgPackRPC message. type needs not to be stored explicitely.
REPLSmuggler.Protocols.AbstractResponse — Type
Represents a response.
REPLSmuggler.Protocols.MsgType — Type
MsgPackRPC message types.
REPLSmuggler.Protocols.Notification — Type
Represents a notification.
REPLSmuggler.Protocols.ProtocolException — Type
Used internally to report protocol exceptions.
REPLSmuggler.Protocols.Request — Type
Represents a request.
REPLSmuggler.Protocols.Diagnostic — Method
Diagnostic(title, diagnostic, stackframe)See protocol's definition and build stackframe accordingly.
REPLSmuggler.Protocols.Error — Method
Error(msgid, error, stackframe)REPLSmuggler.Protocols.Handshake — Method
Handshake()Create a hand-shake notification.
REPLSmuggler.Protocols.Result — Method
Result(msgid, line, [mime=MIME("text/plain"),] result)REPLSmuggler.Protocols.astuple — Function
astuple(message)Returns a vector from the message that can be serialized.
REPLSmuggler.Protocols.deserialize — Function
serialize(protocol)De-serialize an AbstractMsgPackRPC. Must be implemented by the serializer, e.g. MsgPackSerializer.jl.
REPLSmuggler.Protocols.dispatchonmessage — Method
dispatchonmessage(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 — Function
serialize(protocol, message)Serialize an AbstractMsgPackRPC. Must be implemented by the serializer, e.g. MsgPackSerializer.jl.
Server
REPLSmuggler.Server — Module
Implementation 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 — Type
The session of a client.
REPLSmuggler.Server.Smuggler — Type
Store the sessions of a server.
REPLSmuggler.Server.deserialize_requests — Method
Dispatch repeatedly the incoming requests of a session.
REPLSmuggler.Server.evaluate_entries — Method
evaluate_entries(session)Repeatedly evaluate the code put to the input channel of the session.
REPLSmuggler.Server.evaluate_entry — Function
evaluate_entry(session, msgid, file, line, value, repl=Base.active_repl))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 — Method
getsession(smuggler)Return a Session through a call to waitsession.
REPLSmuggler.Server.serialize_responses — Method
Send repeatedly the responses of a given session.
REPLSmuggler.Server.serve_repl — Method
Serve sessions to clients connecting to a server.
REPLSmuggler.Server.serve_repl_session — Method
Serve one session, starting three loops to evaluate the entries, serialize the responses and deserialize the requests.
REPLSmuggler.Server.sessions — Method
Get the sessions.
REPLSmuggler.Server.treatrequest — Function
Fed to Protocols.dispatchonmessage to respond accordingly to incoming requests.
REPLSmuggler.Server.vessel — Method
Get the vessel.
REPLSmuggler.Server.waitsession — Method
Has 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 — Module
The default serializer for REPLSmuggler.jl
REPLSmuggler.SocketSmugglers — Module
A specific kind of server for UNIX sockets / Windows pipes.
Index
REPLSmuggler.MsgPackSerializerREPLSmuggler.ProtocolsREPLSmuggler.ServerREPLSmuggler.SocketSmugglersREPLSmuggler.CURRENT_SMUGGLERREPLSmuggler.Protocols.IMAGE_MIMEREPLSmuggler.Protocols.PROTOCOL_MAGICREPLSmuggler.Protocols.PROTOCOL_VERSIONREPLSmuggler.Protocols.AbstractMsgPackRPCREPLSmuggler.Protocols.AbstractResponseREPLSmuggler.Protocols.MsgTypeREPLSmuggler.Protocols.NotificationREPLSmuggler.Protocols.ProtocolExceptionREPLSmuggler.Protocols.RequestREPLSmuggler.Server.SessionREPLSmuggler.Server.SmugglerREPLSmuggler.Protocols.DiagnosticREPLSmuggler.Protocols.ErrorREPLSmuggler.Protocols.HandshakeREPLSmuggler.Protocols.ResultREPLSmuggler.Protocols.astupleREPLSmuggler.Protocols.deserializeREPLSmuggler.Protocols.dispatchonmessageREPLSmuggler.Protocols.serializeREPLSmuggler.Server.deserialize_requestsREPLSmuggler.Server.evaluate_entriesREPLSmuggler.Server.evaluate_entryREPLSmuggler.Server.getsessionREPLSmuggler.Server.serialize_responsesREPLSmuggler.Server.serve_replREPLSmuggler.Server.serve_repl_sessionREPLSmuggler.Server.sessionsREPLSmuggler.Server.treatrequestREPLSmuggler.Server.vesselREPLSmuggler.Server.waitsessionREPLSmuggler.basepathREPLSmuggler.showsmugglerREPLSmuggler.smuggleREPLSmuggler.smuggleREPLSmuggler.smuggleREPLSmuggler.smuggle