Un dolce tutorial su Emacs / Swank / Paredit per Clojure


87

Mi trasferisco in Emacs per lavorare su Clojure / Lisp. Quali sono tutte le informazioni di cui ho bisogno per configurare su Emacs per poter fare quanto segue?

  1. abbinamento / generazione automatica delle parentesi di chiusura corrispondenti
  2. autoindent Lisp / Clojure style, non C ++ / Java style
  3. Evidenziazione della sintassi
  4. Invocare REPL
  5. Per poter caricare una parte di codice dal file nel REPL e valutarlo.

Sarebbe fantastico se potessi anche ottenere l'elenco dei comandi per ottenere queste cose dopo aver impostato le cose su Emacs.

Risposte:


89

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

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

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

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

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

  3. 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 useorequire 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 .emacscui 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-projectfunzione 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
      '(
        ; "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
Grazie mille per il bellissimo commento!
user855

3
Prego. Spero che ti metta sulla buona strada con Clojure. Buon hacking! :-)
Michał Marczyk

2
ł: Scrivi molto bene. Grazie.
Ralph

Questo è davvero un bel tutorial. Ho appena scoperto che l'opzione migliore è Emacs anche se non mi è piaciuto molto. IDEA, Eclipse e netbeans semplicemente non rientrano nell'immagine.
Adam Arold


8

Lo Starter kit Emacs ha ottenuto ottime recensioni per iniziare con Clojure:

Per rispondere solo alla parte sciccosa della tua domanda:

Leiningen è un modo molto semplice per impostare swank con il percorso di classe corretto e collegarlo a Emacs.

Un ottimo video è qui: http://vimeo.com/channels/fulldisclojure#8934942 Ecco un esempio di un file project.clj che

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

quindi esegui:

lein swank

e da Emacs:

 alt-x slime-connect


1

CIDER (Clojure Interactive Development Environment) deve essere menzionato qui.

Coprirà la maggior parte di ciò che stai cercando. Include:

  • REPL interattivo
  • debug
  • prova in esecuzione
  • navigazione del codice
  • ricerca della documentazione
  • molto di più

Oltre a CIDER, ci sono altri componenti aggiuntivi essenziali e piacevoli per lo sviluppo di clojure, che cercherò di raggruppare rispettivamente (e soggettivamente):

Essentials

  • smartparens - accoppiamento tra parentesi, manipolazione, navigazione (o parinfer se preferisci)

  • clj-refactor - ha un paio di funzioni sorprendenti, come l'aggiunta / la compilazione automatica di spazi dei nomi (potrebbe essere incorporato presto in CIDER)

  • clojure-mode - blocco dei caratteri, rientro, navigazione

  • azienda - framework di completamento del testo (o scegli un altro completamento automatico)

  • delimitatori arcobaleno : evidenzia / colora i delimitatori come parentesi, parentesi o parentesi graffe in base alla loro profondità

  • flycheck - estensione per il controllo della sintassi al volo

  • flycheck-clj-kondo - integrazione per clj-kondo

Sottigliezze

  • clojure-snippets - scorciatoie espandibili con tab per blocchi di codice più lunghi

  • dumb-jump - salta alle definizioni

  • quale-tasto : visualizza le associazioni di tasti disponibili nel popup

  • evidenzia parentesi - evidenzia le parentesi circostanti

  • crux - una raccolta di estensioni ridicolmente utili per Emacs

  • comment-dwim-2 - sostituzione per il built-in di Emacscomment-dwim

Elementi essenziali generali (per qualsiasi lingua)

  • magit - porcellana git all'interno di Emacs

  • proiettile - progetto mgmt per trovare file, cercare, ecc

  • helm - completamento incrementale e framework di restringimento della selezione (o swiper )

Altre risorse

Se stai cercando una configurazione che abbia già svolto la maggior parte / tutto questo lavoro per te, un paio di opzioni sono:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.