Un suave tutorial de Emacs / Swank / Paredit para Clojure


87

Me estoy mudando a Emacs para trabajar en Clojure / Lisp. ¿Cuál es toda la información que necesito configurar en Emacs para poder hacer lo siguiente?

  1. Emparejamiento automático / generación de corchetes de cierre correspondientes
  2. autoindent estilo Lisp / Clojure, no estilo C ++ / Java
  3. Resaltado de sintaxis
  4. Invocando REPL
  5. Para poder cargar una parte del código del archivo en el REPL y evaluarlo.

Sería genial si también pudiera obtener la lista de comandos para obtener estas cosas después de configurar las cosas en Emacs.

Respuestas:


89

[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:

  1. 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.

  2. 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:

  1. 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.

  2. 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. :-)

  3. 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 useo requiresu 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 .emacsque 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-projectfunció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
      '(
        ; "deps/"
        "src/"
        "classes/"
        "test/"
        ))

(setq clojure-project-jar-classpaths
      '(
        ; "deps/"
        "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"))))

;;; original due to Phil Hagelberg
;;; (see `Best practices for Slime with Clojure' thread on Clojure Google Group)
(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)
  ;; I'm not sure if I want to mkdir; doing that would be a problem
  ;; if I wanted to open e.g. clojure or clojure-contrib as a project
  ;; (both lack "deps/")
                                        ; (mapcar (lambda (d) (mkdir d t)) '("deps" "src" "classes" "test"))
  (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 (expand-file-name "~/.clojure/clojure.jar")
          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))

2
¡Muchas gracias por la hermosa reseña!
user855

3
De nada. Espero que te ayude con Clojure. ¡Feliz piratería! :-)
Michał Marczyk

2
ł: Muy bonito escrito. Gracias.
Ralph

De hecho, es un tutorial muy agradable. Me acabo de enterar de que la mejor opción es Emacs, incluso si realmente no me gustó. IDEA, Eclipse y netbeans simplemente no encajan en la imagen.
Adam Arold


8

El kit de inicio de Emacs ha recibido excelentes críticas por comenzar con Clojure:

Para responder solo a la parte elegante de su pregunta:

Leiningen es una forma realmente fácil de configurar swank con el classpath correcto y conectarlo a Emacs.

Un gran video está aquí: http://vimeo.com/channels/fulldisclojure#8934942 Aquí hay un ejemplo de un archivo project.clj que

(defproject project "0.1"
    :dependencies [[org.clojure/clojure
                      "1.1.0-master-SNAPSHOT"]
                   [org.clojure/clojure-contrib
                      "1.0-SNAPSHOT"]]
    :dev-dependencies [[leiningen/lein-swank "1.1.0"]]
    :main my.project.main)

entonces corre:

lein swank

y de Emacs:

 alt-x slime-connect


1

CIDER (Clojure Interactive Development Environment) debe mencionarse aquí.

Cubrirá la mayor parte de lo que está buscando. Incluye:

  • REPL interactivo
  • depuración
  • prueba de funcionamiento
  • navegación de código
  • búsqueda de documentación
  • mucho más

Además de CIDER, hay algunos otros complementos esenciales y agradables para el desarrollo de clojure, que intentaré agrupar respectivamente (y subjetivamente):

Esenciales

  • smartparens : emparejamiento de paréntesis, manipulación, navegación (o parinfer si lo prefiere)

  • clj-refactor - tiene un par de características asombrosas, como agregar / compilar espacios de nombres automáticamente (es posible que se incorpore a CIDER pronto)

  • modo clojure - bloqueo de fuente, sangría, navegación

  • empresa : marco de finalización de texto (o elija otro autocompletador)

  • delimitadores de arco iris : resalta / colorea los delimitadores como paréntesis, corchetes o llaves de acuerdo con su profundidad

  • flycheck : extensión de comprobación de sintaxis sobre la marcha

  • flycheck-clj-kondo - integración para clj-kondo

Sutilezas

  • clojure-snippets : accesos directos expandibles con pestañas a fragmentos de código más largos

  • salto tonto - saltar a definiciones

  • which-key : muestra las combinaciones de teclas disponibles en una ventana emergente

  • resaltar paréntesis - resaltar los paréntesis circundantes

  • crux - una colección de extensiones ridículamente útiles para Emacs

  • comment-dwim-2 - reemplazo del incorporado de Emacscomment-dwim

Conceptos básicos generales (para cualquier idioma)

  • magit - porcelana git dentro de Emacs

  • proyectil - proyecto mgmt para encontrar archivos, buscar, etc.

  • timón - marco de reducción incremental de finalización y selección (o swiper )

Otros recursos

Si está buscando una configuración que ya haya realizado la mayor parte / todo este trabajo por usted, algunas opciones son:

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.