static void HandleMessage(BDictionary message, TcpClient client) { var opValue = message["op"]; var opString = opValue as BString; if (opString != null) { var session = GetSession(message); switch (opString.ToString()) { case "clone": var newSession = CloneSession(session); SendMessage( new BDictionary { { "id", message["id"] }, { "status", new BList { "done" } }, { "new-session", newSession.ToString() } }, client); break; case "describe": // TODO include arcadia version var clojureVersion = (IPersistentMap)RT.var("clojure.core", "*clojure-version*").deref(); var clojureMajor = (int)clojureVersion.valAt(Keyword.intern("major")); var clojureMinor = (int)clojureVersion.valAt(Keyword.intern("minor")); var clojureIncremental = (int)clojureVersion.valAt(Keyword.intern("incremental")); var clojureQualifier = (string)clojureVersion.valAt(Keyword.intern("qualifier")); SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done" } }, { "ops", new BDictionary { { "eval", 1 }, { "describe", 1 }, { "clone", 1 }, } }, { "versions", new BDictionary { { "clojure", new BDictionary { { "major", clojureMajor }, { "minor", clojureMinor }, { "incremental", clojureIncremental }, { "qualifier", clojureQualifier } } }, { "nrepl", new BDictionary { { "major", 0 }, { "minor", 2 }, { "incremental", 3 } } } } } }, client); break; case "eval": var fn = new EvalFn(message, client); addCallbackVar.invoke(fn); break; default: SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done", "error", "unknown-op" } } }, client); break; } } }
static void HandleMessage(BDictionary message, TcpClient client) { var opValue = message["op"]; var opString = opValue as BString; var autoCompletionSupportEnabled = RT.booleanCast(((IPersistentMap)configVar.invoke()).valAt(Keyword.intern("nrepl-auto-completion"))); if (opString != null) { var session = GetSession(message); switch (opString.ToString()) { case "clone": var newSession = CloneSession(session); SendMessage( new BDictionary { { "id", message["id"] }, { "status", new BList { "done" } }, { "new-session", newSession.ToString() } }, client); break; case "describe": // TODO include arcadia version var clojureVersion = (IPersistentMap)RT.var("clojure.core", "*clojure-version*").deref(); var clojureMajor = (int)clojureVersion.valAt(Keyword.intern("major")); var clojureMinor = (int)clojureVersion.valAt(Keyword.intern("minor")); var clojureIncremental = (int)clojureVersion.valAt(Keyword.intern("incremental")); var clojureQualifier = (string)clojureVersion.valAt(Keyword.intern("qualifier")); var supportedOps = new BDictionary { { "eval", 1 }, { "load-file", 1 }, { "describe", 1 }, { "clone", 1 }, { "info", 1 }, { "eldoc", 1 }, { "classpath", 1 }, }; // Debug.Log("Autocomplete support is enabled?: " + autoCompletionSupportEnabled); if (autoCompletionSupportEnabled) { supportedOps.Add("complete", 1); } SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done" } }, { "ops", supportedOps }, { "versions", new BDictionary { { "clojure", new BDictionary { { "major", clojureMajor }, { "minor", clojureMinor }, { "incremental", clojureIncremental }, { "qualifier", clojureQualifier } } }, { "nrepl", new BDictionary { { "major", 0 }, { "minor", 2 }, { "incremental", 3 } } } } } }, client); break; case "eval": var fn = new EvalFn(message, client); addCallbackVar.invoke(fn); break; case "load-file": message["code"] = new BString("(do " + message["file"].ToString() + " )"); var loadFn = new EvalFn(message, client); addCallbackVar.invoke(loadFn); break; case "eldoc": case "info": String symbolStr = message["symbol"].ToString(); // Editors like Calva that support doc-on-hover sometimes will ask about empty strings or spaces if (symbolStr == "" || symbolStr == null || symbolStr == " ") { break; } IPersistentMap symbolMetadata = null; try { symbolMetadata = (IPersistentMap)metaVar.invoke(nsResolveVar.invoke( findNsVar.invoke(symbolVar.invoke(message["ns"].ToString())), symbolVar.invoke(symbolStr))); } catch (TypeNotFoundException) { // We'll just ignore this call if the type cannot be found. This happens sometimes. // TODO: One particular case when this happens is when querying info for a namespace. // That case should be handled separately (e.g., via `find-ns`?) } if (symbolMetadata != null) { var resultMessage = new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done" } } }; foreach (var entry in symbolMetadata) { if (entry.val() != null) { String keyStr = entry.key().ToString().Substring(1); String keyVal = entry.val().ToString(); if (keyStr == "arglists") { keyStr = "arglists-str"; } if (keyStr == "forms") { keyStr = "forms-str"; } resultMessage[keyStr] = new BString(keyVal); } } SendMessage(resultMessage, client); } else { SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done", "no-info" } } }, client); } break; case "complete": // When autoCompletionSupportEnabled is false, we don't advertise auto-completion support. // some editors seem to ignore this and request anyway, so we return an unknown op message. if (!autoCompletionSupportEnabled) { SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done", "error", "unknown-op" } } }, client); break; } Namespace ns = Namespace.find(Symbol.create(message["ns"].ToString())); var sessionBindings = _sessions[session]; var completeBindings = sessionBindings; if (ns != null) { completeBindings = completeBindings.assoc(RT.CurrentNSVar, ns); } // Make sure to eval this in the right namespace Var.pushThreadBindings(completeBindings); BList completions = (BList)completeVar.invoke(message["symbol"].ToString()); Var.popThreadBindings(); SendMessage(new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done" } }, { "completions", completions } }, client); break; case "classpath": BList classpath = new BList(); foreach (String p in Environment.GetEnvironmentVariable("CLOJURE_LOAD_PATH").Split(System.IO.Path.PathSeparator)) { if (p != "") { classpath.Add(Path.GetFullPath(p)); } } SendMessage(new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done" } }, { "classpath", classpath }, }, client); break; default: SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done", "error", "unknown-op" } } }, client); break; } } }
static void HandleMessage(BDictionary message, TcpClient client) { var opValue = message["op"]; var opString = opValue as BString; if (opString != null) { var session = GetSession(message); switch (opString.ToString()) { case "clone": var newSession = CloneSession(session); SendMessage( new BDictionary { { "id", message["id"] }, { "status", new BList { "done" } }, { "new-session", newSession.ToString() } }, client); break; case "describe": // TODO include arcadia version var clojureVersion = (IPersistentMap)RT.var("clojure.core", "*clojure-version*").deref(); var clojureMajor = (int)clojureVersion.valAt(Keyword.intern("major")); var clojureMinor = (int)clojureVersion.valAt(Keyword.intern("minor")); var clojureIncremental = (int)clojureVersion.valAt(Keyword.intern("incremental")); var clojureQualifier = (string)clojureVersion.valAt(Keyword.intern("qualifier")); SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done" } }, { "ops", new BDictionary { { "eval", 1 }, { "load-file", 1 }, { "describe", 1 }, { "clone", 1 }, { "info", 1 }, } }, { "versions", new BDictionary { { "clojure", new BDictionary { { "major", clojureMajor }, { "minor", clojureMinor }, { "incremental", clojureIncremental }, { "qualifier", clojureQualifier } } }, { "nrepl", new BDictionary { { "major", 0 }, { "minor", 2 }, { "incremental", 3 } } } } } }, client); break; case "eval": var fn = new EvalFn(message, client); addCallbackVar.invoke(fn); break; case "load-file": message["code"] = new BString("(do " + message["file"].ToString() + " )"); var loadFn = new EvalFn(message, client); addCallbackVar.invoke(loadFn); break; case "info": var symbolMetadata = (IPersistentMap)metaVar.invoke(nsResolveVar.invoke( findNsVar.invoke(symbolVar.invoke(message["ns"].ToString())), symbolVar.invoke(message["symbol"].ToString()))); if (symbolMetadata != null) { var resultMessage = new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done" } } }; foreach (var entry in symbolMetadata) { if (entry.val() != null) { resultMessage[entry.key().ToString().Substring(1)] = new BString(entry.val().ToString()); } } SendMessage(resultMessage, client); } else { SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done", "no-info" } } }, client); } break; default: SendMessage( new BDictionary { { "id", message["id"] }, { "session", session.ToString() }, { "status", new BList { "done", "error", "unknown-op" } } }, client); break; } } }