2010-08-12 17 views
5

Ich bin gerade dabei, einer vorhandenen J2EE-Webanwendung Funktionalität in einem Tomcat-Container hinzuzufügen, und ich schreibe meine Ergänzungen mit Clojure. Meine Einrichtung ist einfach: Ich füge nur Aufrufe zu statischen Methoden hinzu, die von clojure generiert wurden, und schreibe die ganze harte Arbeit von der Clojure-Seite aus. Der Build-Prozess besteht darin, clojure code (lein uberjar) zu kompilieren und dann den Java-Code mit diesem jar auf dem Klassenpfad zu kompilieren.Wie verbinde ich eine Clojure-Quelldatei mit einer laufenden Clojure-Replik auf Emacs?

In der Webapp-Init habe ich einen Aufruf an eine generierte Klasse, die einen Swank-Server mit einem (swank/start-repl) startet. Ich möchte in der Lage sein, den Schleim meiner Aquamacs mit diesem Server zu verbinden und interaktiv von dort zu arbeiten (bis zu einem gewissen Punkt werde ich nichts versuchen, was eine Neukompilierung auf der Java-Seite erfordert). Aber ich habe eine Situation, die ich nicht ganz verstehe. Wenn ich eine \M-x slime-connect mache, bekomme ich eine REPL-Eingabeaufforderung (nachdem ich benachrichtigt wurde, dass es keinen minderwertigen Lisp-Prozess gibt, was meiner Meinung nach in Ordnung ist, da der untergeordnete Lisp-Prozess außerhalb von Emacs-Kontrolle läuft). Ich kann Formulare perfekt auswerten, und ich kann sogar Dinge wie my.own.namespace/my-var untersuchen. Wenn ich jedoch eine Datei mit einem bereits kompilierten Clojure-Code besuche, kann ich den Schleim nicht als Quelle erkennen lassen. Betrachten wir ein einfaches clojure Datei:

(ns my.namespace 
    (:gen-class 
    :name my.namespace 
    :methods [#^{:static true} [testFunc [] void]])) 

(def *secret* "shhhh") 

(defn -testFunc [] 
    (println (str "our secret is: " secret))) 

Unter der Annahme, dass dies in der uberjar durch die Webapp geladen zusammengestellt und enthalten ist, kann ich eval/inspizieren my.namespace/*secret*. Aber wenn ich versuche, innerhalb des Codepuffers auszuprobieren, denkt Slime, dass ich auf dem Namespace user bin (was sogar Sinn machen kann!). Aber jetzt habe ich noch eine einzige Arbeitsmöglichkeit - ich muss alle Formulare in der Datei nacheinander auswerten! \C-c \C-l (Laden der Quelldatei) wird nichts tun - scheinbar nur NULL zurückgibt und sonst nichts ausgibt. Alles kompilieren scheint genau das zu tun - es kompiliert, zeigt Fehler an, wenn es sie findet, ändert aber meinen Namensraum nicht. Und das Seltsamste ist das \C-~ (Sync Paket und Verzeichnis), das mit Common Lisp genau das macht, was ich will, aber hier friert es die Clojure REPL für immer ein.

Es gibt immer die Möglichkeit, zu der REPL zu wechseln, indem Sie (in-ns 'my.namespace) eingeben, und dann funktioniert alles ordnungsgemäß. Aber das ist einfach nicht praktisch genug, wenn die Clojure-Dateien an Zahl zunehmen (da der Namespace des Code-Puffers sich nicht automatisch ändert!)

Meine Frage ist also, ob mir ein Grundbefehl fehlt/Konfiguration - oder wenn es einen offensichtlichen Grund dafür gibt, dass dieses Verhalten als solches auftritt.

+0

Zitieren der Frage: "Kompilieren alles scheint genau das zu tun" - was meinst du? Das heißt, auf welche Methode des Ladens von Clojure-Code beziehen Sie sich, wenn Sie "alles kompilieren" sagen (Clojure-Code wird immer kompiliert, aber Sie haben wahrscheinlich einige SLIME-Funktion im Hinterkopf). Und welches Ergebnis erwarten Sie genau? –

+0

"Alles kompilieren" - "Cc Ck" wird alle Formulare im Puffer der Datei auf Emacs kompilieren, Fehler auf diesen Formularen darstellen und effektiv neu definierte (und neu definierte) Formulare dynamisch verfügbar machen (zB wird ein Webapp-Aufruf verwendet) dieser neu kompilierte Code). Entschuldige, dass ich nicht so klar bin wie ich. – Edgar

+0

Ich erwartete ein ähnliches Verhalten wie beim Starten von SLIME mit 'Mx swank-clojure-project': Beim Wechsel in den Puffer einer Datei wird der Namespace automatisch geändert, also wird der Namespace' user' nicht ausgewertet . Alternativ sollte beim Kompilieren/Laden des Puffers unter Verwendung von "C-c C-k"/"C-c C-l" alle Formen ausgewertet werden, einschließlich des anfänglichen "(ns ...)", wodurch zu einem bestimmten Namensraum gewechselt wird und alle nachfolgenden Variablen dazu gehören. Ist das nicht das erwartete Verhalten in einer Standardkonfiguration? (Ich könnte es in die falsche Richtung sehen ...) – Edgar

Antwort

1

Ich habe gerade herausgefunden, dass das Entfernen des Schuldigen für dieses Problem: slime-redirect-inferior-output, von Slime-repl.el, wurde von einem Hook aufgerufen, den ich eingerichtet hatte. Es stellt sich heraus, dass es ohne einen inferior-lisp-Prozess nicht gut läuft (lesen Sie, ein Swank-Server, der innerhalb von emacs gestartet wurde).

So ein schneller Workaround-Hack ist nur das error Formular aus dieser Funktion entfernen, wie this. Jetzt wird der Hook fortgesetzt und die Namespaces werden automatisch berechnet. Wie beabsichtigt. Danke für die Vorschläge, trotzdem - sie haben mich zu dieser Lösung geführt!

5

Ich mag Ihr Problem missverstehen, aber können Sie nicht (während Sie diesen hypothetischen Puffer in Emacs besuchen) C-c C-k drücken, um den Puffer in Ihrer aktuellen Clojure-Instanz zu kompilieren (welcher Slime ist damit verbunden)?

Wechseln Sie dann im Slime-Puffer mit einem (in-ns 'my.namespace) in diesen Namensraum. Dann sollten Sie Zugriff auf das haben, was Sie in diesem Namespace kompiliert haben.

+0

Hmm, wie ich im Kommentar einer Frage geschrieben habe, wird diese Kompilation funktionieren, aber mein Punkt ist, dass ich daran gewöhnt bin "(in-ns 'my .namespace) 'nach einer Kompilier-/Ladedatei implizit sein. Es funktionierte so in jeder Common Lisp-Implementierung, die ich mit SLIME, IIRC verwendet habe; Auch wenn man Namespaces manuell in einem 10 oder mehr Dateiprojekt umschalten muss (speziell bei mehr als wünschenswertem Clojure-Neustart), führt das zu Müdigkeit - und kurz danach, Wahnsinn :) - wenn ich also etwas falsch mache und die Interaktion nicht Ich habe das so gemacht, ich werde einen Workaround programmieren! – Edgar

+0

Oh, auch die '(in-ns 'my.namespace)' funktioniert überhaupt nicht, wenn an Ort und Stelle, auf dem .clj-Dateipuffer ausgewertet - ich muss es auf der REPL tun, dann wechselt der Puffer dieser Datei Namensraum. Das ist für mich auch weniger als offensichtlich. – Edgar

+0

Sie haben völlig Recht - es ist ein Schmerz in den Arsch. Ich glaube, ich habe mich einfach daran gewöhnt und vor Clojure nicht mit Slime/Swank codiert. Lass es mich wissen, wenn du eine Arbeit bekommst! Ich nehme an, die Dinge arbeiten jetzt für dich? Gibt es noch etwas, das unbeantwortet bleibt? (Nicht, dass ich irgendwas geantwortet hätte, aber ich würde gerne wissen, ob ich noch helfen kann!) – Isaac

2

Das automatische Wechseln von Namespaces beim Kompilieren war nie der Standard für Swank-Clojure, obwohl es möglicherweise eine optionale Schleimfunktion ist, die zufällig mit Clojure zusammenarbeitet. Aber C-c M-p, um den repl in den Namespace des aktuellen Puffers zu schalten, hat immer für mich funktioniert, und ich habe noch nie von jemandem gehört, der Probleme damit hat.

Laufen Sie auf den neuesten stabilen Versionen von Clojure-Modus und Slime-Repl? Hast du swank-clojure.el installiert? (Sie sollten es nicht brauchen.) Es hört sich an, als könnte dies an nicht übereinstimmenden Versionen der elisp-Bibliotheken liegen. Wenn das nicht das Problem ist, könnte es ein Aquamacs Bug sein; swank-clojure wurde entwickelt, um mit GNU Emacs zu arbeiten. Es könnte auch ein Fehler im Schleim sein, wenn du aus dem Kofferraum kommst und nicht aus der neuesten Elpa-Version.

+1

Ich habe vor ein paar Stunden festgestellt, dass 'C-c M-p' perfekt auf meinem Setup funktioniert (Aquamacs, neuste stabile Version von clojure-mode und slime-repl, clojure-1.2-rc1).Was bleibt, ist das 'C-c ~', aber ich vermute, dass der SLIME-Befehl nur für Common-Lisp-Implementierungen funktioniert. Was ich erwartet habe zu arbeiten, ist ein 'C-c C-l' (Laden) für eine Datei - Ich habe erwartet, dass der Namespace sich ändert, aber es wird nicht! Nur zum Vorteil der zukünftigen Leser funktioniert auch die Funktion, die ich in http://gist.github.com/522706 skizziert habe, aber sie fragt nicht nach einem Namespace - sie erraten es von Anfang an (ns ...) 'Form im Puffer. – Edgar