[Edición de no autor: esto es de 2010, y el proceso se ha simplificado significativamente desde mayo de 2011. Agregaré una publicación a esta respuesta con mis notas de configuración a partir de febrero de 2012.]
Tendrá que juntar algunas piezas: Emacs, SLIME (que funciona perfectamente bien con Clojure - vea swank-clojure), swank-clojure (la implementación de Clojure de la contraparte del servidor de SLIME), clojure-mode, Paredit y, de Por supuesto, el jar de Clojure para empezar, luego quizás algunos extras entre los cuales Leiningen quizás sea el más notable. Una vez que haya configurado todo, tendrá, dentro de Emacs, todas las funciones de flujo de trabajo / edición que menciona en la pregunta.
Configuración básica:
Los siguientes son excelentes tutoriales que describen cómo configurar todo esto; hay más en la Web, pero algunos de los otros están bastante desactualizados, mientras que estos dos parecen estar bien por ahora:
en el que se encuentran trucos del oficio relacionados con la publicación de autoría de clojure en el blog de Phil Hagelberg; Phil mantiene swank-clojure y clojure-mode, así como un paquete llamado Emacs Starter Kit que es algo que cualquier recién llegado al mundo de Emacs haría bien en echar un vistazo. Estas instrucciones parecen haber sido actualizadas con cambios recientes en la infraestructura; en caso de duda, busque información adicional en el grupo de Google de Clojure.
Configuración de Clojure, Incanter, Emacs, Slime, Swank y Paredit post en el blog del proyecto Incanter. Incanter es un paquete fascinante que proporciona un DSL similar a R para cálculos estadísticos integrados directamente en Clojure. Esta publicación será útil incluso si no planea usar, o incluso instalar, Incanter.
Poniéndolo todo a trabajar:
Una vez que haya configurado todo esto, puede intentar comenzar a usarlo de inmediato, pero le recomiendo encarecidamente que haga lo siguiente:
Eche un vistazo al manual de SLIME: está incluido en las fuentes y en realidad es muy legible. Además, no hay absolutamente ninguna razón por la que deba leer todo el manual del monstruo de 50 páginas; solo eche un vistazo para ver qué funciones están disponibles.
Nota: la función autodoc de SLIME que se encuentra en las últimas fuentes upstream es incompatible con swank-clojure ; este problema no surgirá si sigue la recomendación de Phil Hagelberg de usar la versión ELPA (consulte la publicación de su blog antes mencionada para obtener una explicación) o simplemente deje autodoc desactivado (que es el estado predeterminado de las cosas). La última opción tiene un atractivo adicional en el sentido de que aún puede usar el último SLIME con Common Lisp, en caso de que también lo use.
Eche un vistazo a los documentos de paredit. Hay dos formas de hacerlo: (1) mire la fuente: hay una gran cantidad de comentarios en la parte superior del archivo que contienen toda la información que probablemente necesite; (2) escriba C-h mEmacs mientras paredit-mode está activo: aparecerá un búfer con información sobre el modo principal actual seguido de información sobre todos los modos menores activos (paredit es uno de esos).
Actualización: Acabo de encontrar este interesante conjunto de notas sobre Paredit de Phil Hagelberg ... Ese es un enlace a un archivo de texto, recuerdo haber visto un buen conjunto de diapositivas con esta información en alguna parte, pero parece que no puedo encontrarlo ahora . De todos modos, es un buen resumen de cómo funciona. Definitivamente échale un vistazo, no puedo vivir sin Paredit ahora y este archivo debería hacer que sea muy fácil comenzar a usarlo, creo. :-)
De hecho, la C-h mcombinación le informará sobre todas las combinaciones de teclas activas en SLIME REPL, en modo clojure (querrá recordar C-c C-kpara enviar el búfer actual para compilación) y de hecho en cualquier búfer de Emacs.
En cuanto a cargar el código desde un archivo y luego experimentar con él en el REPL: use la C-c C-kcombinación antes mencionada para compilar el búfer actual, luego use
o require
su espacio de nombres en el REPL. A continuación, experimente.
Notas finales:
Esté preparado para tener que modificar las cosas por un tiempo antes de que todo haga clic. Hay muchas herramientas involucradas y sus interacciones son en su mayoría bastante fluidas, pero no hasta el punto en que sería seguro asumir que no tendrá que hacer algunos ajustes inicialmente.
Finalmente, aquí hay un fragmento de código que guardo y .emacs
que no encontrará en ningún otro lugar (aunque está basado en una función interesante de Phil Hagelberg). Alterno entre iniciar mis instancias swank con lein swank
(una de las características más interesantes de Leiningen) y usar la clojure-project
función que se encuentra a continuación para iniciar todo desde dentro de Emacs. He hecho todo lo posible para que este último produzca un entorno que coincida con el proporcionado por lein swank
. Ah, y si solo desea un REPL en Emacs para un experimento rápido y sucio, entonces con la configuración correcta debería poder usarlo M-x slimedirectamente.
(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))