Delikatny samouczek dotyczący Emacs / Swank / Paredit dla Clojure

87

Przeprowadzam się do Emacs, aby pracować nad Clojure / Lisp. Jakie są wszystkie informacje potrzebne do skonfigurowania w Emacsie, aby móc wykonać następujące czynności?

  1. automatyczne dopasowywanie / generowanie odpowiednich nawiasów zamykających
  2. autoindent w stylu Lisp / Clojure, a nie w stylu C ++ / Java
  3. Podświetlanie składni
  4. Wywołanie REPL
  5. Aby móc załadować część kodu z pliku do REPL i ocenić go.

Byłoby wspaniale, gdybym mógł również uzyskać listę poleceń, aby uzyskać te rzeczy po skonfigurowaniu rzeczy w Emacsie.

user855
źródło

Odpowiedzi:

89

[Edytuj od osób niebędących autorami: pochodzi z 2010 r., A proces został znacznie uproszczony od maja 2011 r. Dodam do tej odpowiedzi post z notatkami dotyczącymi konfiguracji z lutego 2012 r.]

Będziesz musiał złożyć kilka elementów: Emacs, SLIME (który działa doskonale z Clojure - patrz swank-clojure), swank-clojure (implementacja Clojure odpowiednika serwera SLIME), tryb clojure, Paredit i, z Oczywiście, na początek słoik Clojure, a potem może jakieś dodatki, wśród których Leiningen byłby chyba najbardziej zauważalny. Gdy już to wszystko ustawisz, będziesz miał - w Emacsie - wszystkie funkcje przepływu pracy / edycji, o których wspomniałeś w pytaniu.

Podstawowe ustawienia:

Poniżej znajdują się świetne samouczki, które opisują, jak to wszystko ustawić; w sieci jest więcej, ale niektóre inne są dość przestarzałe, podczas gdy te dwa wydają się na razie w porządku:

  1. w którym znajdują się sztuczki branżowe dotyczące autorstwa clojure wpis na blogu Phila Hagelberga; Phil utrzymuje swank-clojure i clojure-mode, a także pakiet zwany Emacs Starter Kit, który jest czymś, na co każdy nowicjusz w świecie Emacsa powinien się przyjrzeć. Wydaje się, że te instrukcje zostały zaktualizowane wraz z ostatnimi zmianami w infrastrukturze; w razie wątpliwości poszukaj dodatkowych informacji w grupie Google Clojure.

  2. Konfigurowanie postów Clojure, Incanter, Emacs, Slime, Swank i Paredit na blogu projektu Incanter. Incanter to fascynujący pakiet zapewniający DSL podobny do R do obliczeń statystycznych osadzonych bezpośrednio w Clojure. Ten post będzie przydatny, nawet jeśli nie planujesz używać - ani nawet instalować - Incantera.

Wszystko działa:

Po skonfigurowaniu wszystkich tych rzeczy możesz spróbować od razu zacząć z nich korzystać, ale zdecydowanie radzę wykonać następujące czynności:

  1. Spójrz na instrukcję SLIME - jest zawarta w źródłach i właściwie jest bardzo czytelna. Nie ma też absolutnie żadnego powodu, dla którego powinieneś czytać cały 50-stronicowy podręcznik potwora; po prostu rozejrzyj się, aby zobaczyć, jakie funkcje są dostępne.

    Uwaga: funkcja autodoc SLIME, którą można znaleźć w najnowszych źródłach zewnętrznych, jest niekompatybilna ze swank-clojure - ten problem nie pojawi się, jeśli zastosujesz się do zalecenia Phila Hagelberga, aby używać wersji ELPA (wyjaśnienie znajduje się we wspomnianym wcześniej wpisie na blogu) lub po prostu wyłącz autodokres (co jest stanem domyślnym). Ta ostatnia opcja ma dodatkowy urok, ponieważ nadal możesz używać najnowszego SLIME z Common Lisp, na wypadek gdybyś również tego używał.

  2. Zapoznaj się z dokumentacją dotyczącą paredit. Można to zrobić na dwa sposoby: (1) spójrz na źródło - na początku pliku znajduje się ogromna liczba komentarzy, które zawierają wszystkie potrzebne informacje; (2) wpisz C-h mEmacs, gdy tryb paredit jest aktywny - pojawi się bufor z informacjami o aktualnym trybie głównym, a następnie informacje o wszystkich aktywnych trybach podrzędnych (jednym z nich jest paredit).

    Aktualizacja: Właśnie znalazłem ten fajny zestaw notatek na Paredit autorstwa Phila Hagelberga ... To jest link do pliku tekstowego, pamiętam, że widziałem gdzieś fajny zestaw slajdów z tymi informacjami, ale nie mogę ich teraz znaleźć . Zresztą to miłe podsumowanie tego, jak to działa. Zdecydowanie spójrz na to, nie mogę teraz żyć bez Paredit, a ten plik powinien bardzo ułatwić rozpoczęcie korzystania z niego, jak sądzę. :-)

  3. W rzeczywistości ta C-h mkombinacja powie ci o wszystkich przypisaniach klawiszowych aktywnych w SLIME REPL, w trybie clojure (będziesz chciał pamiętać C-c C-ko wysłaniu bieżącego bufora do kompilacji), a nawet w dowolnym buforze Emacsa.

Jeśli chodzi o ładowanie kodu z pliku, a następnie eksperymenty z nim w REPL: wykorzystanie wspomnianej C-c C-kkombinacji do sporządzenia bieżącego bufora, to uselub requirejego nazw w REPL. Następnie eksperymentuj.

Uwagi końcowe:

Przygotuj się na chwilę poprawiania rzeczy, zanim wszystko kliknie. W grę wchodzi wiele narzędzi, a ich interakcje są w większości dość płynne, ale nie na tyle, aby można było bezpiecznie założyć, że na początku nie będziesz musiał wprowadzać pewnych korekt.

Na koniec trzymam fragment kodu, .emacsktórego nie znajdziesz nigdzie indziej (chociaż jest oparty na fajnej funkcji Phila Hagelberga). Na przemian uruchamiam swoje instancje z lein swank(jedną z fajniejszych funkcji Leiningena) i korzystam z clojure-projectfunkcji przedstawionej poniżej, aby rozpocząć całość z poziomu Emacsa. Zrobiłem co w mojej mocy, aby te ostatnie tworzyły środowisko ściśle odpowiadające temu, które zapewnia lein swank. Aha, i jeśli chcesz tylko REPL w Emacsie do szybkiego i brudnego eksperymentu, to przy prawidłowej konfiguracji powinieneś być w stanie użyć M-x slimebezpośrednio.

(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))
Michał Marczyk
źródło
2
Bardzo dziękuję za piękny opis!
user855
3
Nie ma za co. Mam nadzieję, że dzięki Clojure będziesz na dobrej drodze. Miłego hakowania! :-)
Michał Marczyk
2
ł: Bardzo ładnie napisać. Dzięki.
Ralph
To naprawdę bardzo fajny tutorial. Właśnie się dowiedziałem, że najlepszą opcją jest Emacs, nawet jeśli mi się to nie podobało. IDEA, Eclipse i netbeans po prostu nie pasują do obrazu.
Adam Arold
8

Emacs Starter kit ma zdobyć świetne recenzje na rozpoczęcie pracy z Clojure:

Aby odpowiedzieć tylko na elegancką część twojego pytania:

Leiningen to naprawdę łatwy sposób na skonfigurowanie swanka z poprawną ścieżką klas i połączenie go z Emacsem.

Świetny film jest tutaj: http://vimeo.com/channels/fulldisclojure#8934942 Oto przykład pliku project.clj, który

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

następnie uruchomić:

lein swank

i od Emacsa:

 alt-x slime-connect
Arthur Ulfeldt
źródło
1

Należy tu wspomnieć o CIDER (Clojure Interactive Development Environment).

Obejmuje większość tego, czego szukasz. Obejmuje:

  • interaktywna REPL
  • debugowanie
  • test działa
  • nawigacja po kodzie
  • wyszukiwanie dokumentacji
  • dużo więcej

Oprócz CIDER istnieje kilka innych niezbędnych i przyjemnych w użyciu dodatków do tworzenia clojure, które spróbuję odpowiednio pogrupować (i subiektywnie):

Niezbędniki

  • smartparens - parowanie w nawiasach, manipulacja, nawigacja (lub parinfer, jeśli wolisz)

  • clj-refactor –- ma kilka niesamowitych funkcji, takich jak automatyczne dodawanie / kompilowanie przestrzeni nazw (może wkrótce zostać włączone do CIDER)

  • clojure-mode - blokada czcionki, wcięcia, nawigacja

  • firma - framework uzupełniania tekstu (lub wybierz inny autouzupełnianie)

  • ograniczniki tęczy - podświetla / koloruje ograniczniki, takie jak nawiasy, nawiasy lub nawiasy klamrowe w zależności od ich głębokości

  • flycheck - rozszerzenie sprawdzające składnię w locie

  • flycheck-clj-kondo - integracja dla clj-kondo

Grzeczności

Ogólne podstawy (dla dowolnego języka)

  • magit - git porcelain wewnątrz Emacsa

  • pocisk - zarządzanie projektem służące do znajdowania plików, wyszukiwania itp

  • hełm - ramy stopniowego uzupełniania i zawężania selekcji (lub swiper )

Inne zasoby

Jeśli szukasz konfiguracji, która wykonała już większość / całą tę pracę za Ciebie, kilka opcji to:

Micah Elliott
źródło