[Modifica da non autore: è del 2010 e il processo è stato notevolmente semplificato da maggio 2011. Aggiungerò un post a questa risposta con le mie note di configurazione a partire da febbraio 2012.]
Avrai bisogno di mettere insieme alcuni pezzi: Emacs, SLIME (che funziona perfettamente con Clojure - vedi swank-clojure), swank-clojure (l'implementazione Clojure della controparte server di SLIME), clojure-mode, Paredit e, di Ovviamente il barattolo Clojure per cominciare, poi forse qualche extra tra cui Leiningen sarebbe forse il più notevole. Una volta che hai impostato tutto, avrai - all'interno di Emacs - tutte le funzionalità di flusso di lavoro / modifica che menzioni nella domanda.
Configurazione di base:
I seguenti sono ottimi tutorial che descrivono come impostare tutto questo; c'è di più sul Web, ma alcuni degli altri sono abbastanza obsoleti, mentre questi due sembrano essere ok per ora:
in cui si trovano trucchi del mestiere riguardanti il post sulla paternità di clojure sul blog di Phil Hagelberg; Phil mantiene swank-clojure e clojure-mode, così come un pacchetto chiamato Emacs Starter Kit che è qualcosa che qualsiasi nuovo arrivato nel mondo di Emacs farebbe bene a dare un'occhiata. Queste istruzioni sembrano essere state aggiornate con le recenti modifiche all'infrastruttura; in caso di dubbio, cerca ulteriori informazioni sul gruppo Google di Clojure.
Impostare Clojure, Incanter, Emacs, Slime, Swank e Paredit post sul blog del progetto Incanter. Incanter è un pacchetto affascinante che fornisce un DSL simile a R per calcoli statistici incorporati direttamente in Clojure. Questo post sarà utile anche se non prevedi di utilizzare - o addirittura installare - Incanter.
Mettere tutto al lavoro:
Una volta impostato tutto questo, potresti provare a iniziare a usarlo subito, ma ti consiglio vivamente di fare quanto segue:
Dai un'occhiata al manuale di SLIME: è incluso nei sorgenti ed è in realtà molto leggibile. Inoltre, non c'è assolutamente alcun motivo per cui dovresti leggere l'intero manuale di 50 pagine del mostro; dai un'occhiata in giro per vedere quali funzioni sono disponibili.
Nota: la funzione autodoc di SLIME come si trova nelle ultime fonti upstream è incompatibile con swank-clojure : questo problema non si presenterà se segui la raccomandazione di Phil Hagelberg di utilizzare la versione ELPA (vedi il suo post sul blog di cui sopra per una spiegazione) o semplicemente lasciare disattivato l'autodoc (che è lo stato delle cose predefinito). Quest'ultima opzione ha un certo fascino in più in quanto puoi ancora utilizzare l'ultimo SLIME con Common Lisp, nel caso in cui lo usi anche tu.
Dai un'occhiata ai documenti per paredit. Ci sono due modi per farlo: (1) guarda la fonte - c'è un'enorme quantità di commenti all'inizio del file che contengono tutte le informazioni di cui potresti aver bisogno; (2) tipoC-h m in Emacs mentre la modalità paredit è attiva: apparirà un buffer con le informazioni sulla modalità principale corrente seguita da informazioni su tutte le modalità minori attive (paredit è una di quelle).
Aggiornamento: ho appena trovato questo bel set di note su Paredit di Phil Hagelberg ... Questo è un collegamento a un file di testo, ricordo di aver visto un bel set di diapositive con queste informazioni da qualche parte, ma non riesco a trovarlo ora . Comunque, è un bel riassunto di come funziona. Sicuramente dai un'occhiata, non posso vivere senza Paredit ora e questo file dovrebbe rendere molto facile iniziare a usarlo, credo. :-)
Infatti, la C-h mcombinazione ti dirà di tutte le combinazioni di tasti attive in SLIME REPL, in modalità clojure (ti consigliamo di ricordarti C-c C-kdi inviare il buffer corrente per la compilazione) e in effetti in qualsiasi buffer di Emacs.
Per quanto riguarda il caricamento del codice da un file e poi sperimentarlo al REPL: utilizzare la suddetta C-c C-kcombinazione per compilare il buffer corrente, quindi use
orequire
suo namespace nel REPL. Quindi, sperimenta.
Note finali:
Preparati a dover modificare le cose per un po 'prima che tutto scatti. Ci sono molti strumenti coinvolti e le loro interazioni sono per lo più abbastanza fluide, ma non al punto in cui sarebbe lecito ritenere che inizialmente non sarà necessario apportare alcune modifiche.
Infine, ecco un po 'di codice che tengo in .emacs
cui non troverai altrove (sebbene sia basato su una funzione interessante di Phil Hagelberg). Alterna tra l'avvio delle mie istanze swank con lein swank
(una delle caratteristiche più interessanti di Leiningen) e l'utilizzo della clojure-project
funzione come trovata di seguito per avviare il tutto da Emacs. Ho fatto del mio meglio per fare in modo che quest'ultimo producesse un ambiente strettamente corrispondente a quello fornito da lein swank
. Oh, e se vuoi solo un REPL in Emacs per un esperimento veloce e sporco, allora con la configurazione corretta dovresti essere in grado di usarlo M-x slimedirettamente.
(setq clojure-project-extra-classpaths
'(
"src/"
"classes/"
"test/"
))
(setq clojure-project-jar-classpaths
'(
"lib/"
))
(defun find-clojure-project-jars (path)
(apply #'append
(mapcar (lambda (d)
(loop for jar in (remove-if (lambda (f) (member f '("." "..")))
(directory-files d t))
collect jar into jars
finally return jars))
(remove-if-not #'file-exists-p
clojure-project-jar-classpaths))))
(defun find-clojure-jar (jars)
(let ((candidates
(remove-if-not
(lambda (jar)
(string-match-p "clojure\\([0-9.-]+\\(SNAPSHOT|MASTER\\)?\\)?\\.jar$" jar))
jars)))
(if candidates
(car candidates)
(expand-file-name "~/.clojure/clojure.jar"))))
(defun find-clojure-contrib-jar (jars)
(let ((candidates
(remove-if-not
(lambda (jar)
(string-match-p "clojure-contrib\\([0-9.-]+\\(SNAPSHOT|MASTER\\)?\\)?\\.jar$" jar))
jars)))
(if candidates
(car candidates)
(expand-file-name "~/.clojure/clojure-contrib.jar"))))
(defun clojure-project (path)
"Sets up classpaths for a clojure project and starts a new SLIME session.
Kills existing SLIME session, if any."
(interactive (list (ido-read-directory-name
"Project root:"
(locate-dominating-file default-directory "pom.xml"))))
(when (get-buffer "*inferior-lisp*")
(kill-buffer "*inferior-lisp*"))
(cd path)
(let* ((jars (find-clojure-project-jars path))
(clojure-jar (find-clojure-jar jars))
(clojure-contrib-jar (find-clojure-contrib-jar jars)))
(setq swank-clojure-binary nil
swank-clojure-jar-path clojure-jar
swank-clojure-extra-classpaths
(cons clojure-contrib-jar
(append (mapcar (lambda (d) (expand-file-name d path))
clojure-project-extra-classpaths)
(find-clojure-project-jars path)))
swank-clojure-extra-vm-args
(list (format "-Dclojure.compile.path=%s"
(expand-file-name "classes/" path)))
slime-lisp-implementations
(cons `(clojure ,(swank-clojure-cmd) :init swank-clojure-init)
(remove-if #'(lambda (x) (eq (car x) 'clojure))
slime-lisp-implementations))))
(slime))