web-dev-qa-db-fra.com

Un tutoriel doux pour Emacs / Swank / Paredit pour Clojure

Je déménage à Emacs pour travailler sur Clojure /LISP. Quelles sont toutes les informations dont j'ai besoin pour configurer sur Emacs pour pouvoir effectuer les opérations suivantes?

  1. correspondance/génération automatique des supports de fermeture correspondants
  2. style autoindent LISP/Clojure, pas le style C++/Java
  3. Mise en évidence de la syntaxe
  4. Invocation REPL
  5. Pour pouvoir charger une partie du code du fichier dans le REPL et l'évaluer.

Ce serait génial si je pouvais également obtenir la liste des commandes pour obtenir ces choses après avoir configuré les choses sur Emacs.

87
user855

[Edit from non-author: c'est à partir de 2010, et le processus a été considérablement simplifié depuis mai 2011. J'ajouterai un post à cette réponse avec mes notes de configuration à partir de février 2012.]

Vous devrez assembler quelques morceaux: Emacs, SLIME (qui fonctionne parfaitement avec Clojure - voir swank-clojure), swank-clojure (l'implémentation Clojure de l'homologue serveur de SLIME), clojure-mode, Paredit et, of bien sûr, le pot Clojure pour commencer, puis peut-être quelques extras parmi lesquels Leiningen serait peut-être le plus notable. Une fois que vous aurez tout configuré, vous aurez - dans Emacs - toutes les fonctionnalités de workflow/d'édition que vous mentionnez dans la question.

Configuration de base:

Les tutoriels suivants décrivent comment configurer tout cela; il y a plus sur le Web, mais certains des autres sont assez obsolètes, alors que ces deux semblent être corrects pour l'instant:

  1. dans lequel se trouvent des astuces du métier concernant la paternité de clojure poste sur le blog de Phil Hagelberg; Phil maintient swank-clojure et clojure-mode, ainsi qu'un package appelé Emacs Starter Kit, quelque chose que tout nouveau venu dans le monde Emacs serait bien avisé de regarder. Ces instructions semblent avoir été mises à jour avec les récentes modifications apportées à l'infrastructure; en cas de doute, recherchez des informations complémentaires sur le groupe Google de Clojure.

  2. Configuration de Clojure, Incanter, Emacs, Slime, Swank et Paredit poste sur le blog du projet Incanter. Incanter est un package fascinant fournissant une DSL de type R pour les calculs statistiques intégrés directement dans Clojure. Ce message sera utile même si vous ne prévoyez pas d'utiliser - ni même d'installer - Incanter.

Mettre tout cela au travail:

Une fois que vous avez configuré tout cela, vous pouvez essayer de commencer à l'utiliser immédiatement, mais je vous conseille fortement de faire ce qui suit:

  1. Jetez un œil au manuel de SLIME - il est inclus dans les sources et est en fait très lisible. De plus, il n'y a absolument aucune raison pour que vous devriez - lire tout le manuel du monstre de 50 pages; jetez un coup d'œil pour voir quelles fonctionnalités sont disponibles.

    Remarque: la fonctionnalité d'autodoc de SLIME trouvée dans les dernières sources en amont est incompatible avec swank-clojure - ce problème ne se posera pas si vous suivez La recommandation de Phil Hagelberg d'utiliser la version ELPA (voir son article de blog susmentionné pour une explication) ou tout simplement de laisser l'autodoc désactivé (ce qui est l'état par défaut des choses). Cette dernière option présente un attrait supplémentaire en ce sens que vous pouvez toujours utiliser la dernière SLIME avec Common LISP, au cas où vous l'utiliseriez également.

  2. Jetez un oeil à la documentation de paredit. Il y a deux façons de procéder: (1) regardez la source - il y a une énorme quantité de commentaires en haut du fichier qui contiennent toutes les informations dont vous aurez probablement besoin; (2) type C-h m dans Emacs pendant que le mode paredit est actif - un tampon apparaîtra avec des informations sur le mode majeur actuel suivi par des informations sur tous les modes mineurs actifs (le paredit en fait partie).

    Mise à jour: Je viens de trouver cet ensemble de notes sympa sur Paredit par Phil Hagelberg ... C'est un lien vers un fichier texte, je me souviens avoir vu un joli ensemble de diapositives avec ces informations quelque part, mais ne semble pas le trouver maintenant. Quoi qu'il en soit, c'est un bon résumé de son fonctionnement. Jetez-y un coup d'œil, je ne peux pas vivre sans Paredit maintenant et ce fichier devrait le rendre très facile à utiliser, je crois. :-)

  3. En fait, le C-h m La combinaison vous indiquera toutes les liaisons de touches actives sur SLIME REPL, en mode clojure (vous voudrez vous souvenir C-c C-k pour l'envoi du tampon en cours de compilation) et en effet dans n'importe quel tampon Emacs.

Quant au chargement du code à partir d'un fichier puis à l'expérimentation avec le REPL: utilisez ce qui précède C-c C-k pour compiler le tampon courant, puis use ou require son espace de noms au REPL. Ensuite, expérimentez.

Notes finales:

Soyez prêt à modifier les choses pendant un certain temps avant que tout ne clique. Il y a beaucoup d'outils impliqués et leurs interactions sont généralement assez fluides, mais pas au point où il serait prudent de supposer que vous n'aurez pas à effectuer certains ajustements au départ.

Enfin, voici un peu de code que je garde dans .emacs que vous ne trouverez pas ailleurs (bien qu'il soit basé sur une fonction sympa de Phil Hagelberg). J'alterne entre le démarrage de mes instances swank avec lein swank (l'une des fonctionnalités les plus intéressantes de Leiningen) et en utilisant clojure-project fonctionne comme indiqué ci-dessous pour démarrer le tout depuis Emacs. J'ai fait de mon mieux pour que ces derniers produisent un environnement proche de celui fourni par lein swank. Oh, et si vous voulez juste un REPL dans Emacs pour une expérience rapide et sale, alors avec la configuration correcte, vous devriez pouvoir utiliser M-x slime directement.

(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))
89
Michał Marczyk

Il existe un autre didacticiel excellent:

En 30 à 45 minutes, tout peut être configuré à partir de zéro.

Le tutoriel ne suppose aucune connaissance préalable d'Emacs (et Clojure aussi - dans les articles précédents, il y a une belle introduction à Clojure).

10
Piotr Kochański

Le kit Emacs Starter a reçu d'excellentes critiques pour commencer avec Clojure:

Pour répondre uniquement à la partie épurée de votre question:

Leiningen est un moyen très simple de configurer swank avec le chemin de classe correct et de le connecter à Emacs.

Une excellente vidéo est ici: http://vimeo.com/channels/fulldisclojure#8934942 Voici un exemple de fichier project.clj qui

(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)

puis lancez:

lein swank

et d'Emacs:

 alt-x slime-connect
8
Arthur Ulfeldt

Clojure avec Emacs on Clojure Documentation peut aussi être utile.

2
aholub7x