Мягкое руководство по Emacs / Swank / Paredit для Clojure

87

Я перехожу на Emacs, чтобы работать над Clojure / Lisp. Какую всю информацию мне нужно установить в Emacs, чтобы иметь возможность делать следующее?

  1. автоматическое сопоставление / создание соответствующих закрывающих скобок
  2. autoindent стиль Lisp / Clojure, а не стиль C ++ / Java
  3. Подсветка синтаксиса
  4. Вызов REPL
  5. Чтобы иметь возможность загружать часть кода из файла в REPL и оценивать его.

Было бы здорово, если бы я мог также получить список команд для получения этих вещей после настройки в Emacs.

user855
источник

Ответы:

89

[Правка от неавтора: это с 2010 года, и с мая 2011 года процесс был значительно упрощен. Я добавлю к этому ответу сообщение с моими примечаниями по настройке по состоянию на февраль 2012 года.]

Вам нужно будет собрать несколько частей: Emacs, SLIME (который отлично работает с Clojure - см. Swank-clojure), swank-clojure (реализация Clojure аналога сервера SLIME), clojure-mode, Paredit и, of конечно, для начала, банку Clojure, а затем, возможно, некоторые дополнения, среди которых Leiningen, возможно, был бы самым заметным. После того, как вы все это настроите, у вас будут - в Emacs - все функции рабочего процесса / редактирования, которые вы упомянули в вопросе.

Базовая настройка:

Ниже приведены отличные руководства, в которых описывается, как все это настроить; в Интернете есть больше, но некоторые из других сильно устарели, тогда как эти два кажутся сейчас нормальными:

  1. в котором обнаруживаются уловки торговли в отношении сообщения об авторстве закрытия в блоге Фила Хагельберга; Фил поддерживает swank-clojure и clojure-mode, а также пакет под названием Emacs Starter Kit, на который любой новичок в мире Emacs будет неплохо посоветовать. Эти инструкции, похоже, были обновлены с учетом недавних изменений в инфраструктуре; в случае сомнений поищите дополнительную информацию в группе Google Clojure.

  2. Настройка Clojure, Incanter, Emacs, Slime, Swank и Paredit разместите сообщение в блоге проекта Incanter. Incanter - это увлекательный пакет, предоставляющий R-подобный DSL для статистических вычислений, встроенный прямо в Clojure. Этот пост будет полезен, даже если вы не планируете использовать или даже не устанавливать Incanter.

Запускаем все на работу:

После того, как вы настроите все это, вы можете попробовать начать использовать его прямо сейчас, но я настоятельно рекомендую вам сделать следующее:

  1. Взгляните на руководство SLIME - оно включено в исходники и на самом деле очень читабельно. Кроме того, нет абсолютно никаких причин, по которым вы должны читать все 50-страничное руководство по монстрам; просто посмотрите вокруг, чтобы увидеть, какие функции доступны.

    Примечание: функция autodoc SLIME, обнаруженная в последних исходных кодах, несовместима с swank-clojure - эта проблема не возникнет, если вы последуете рекомендациям Фила Хагельберга использовать версию ELPA (см. Его вышеупомянутое сообщение в блоге для объяснения) или просто оставьте autodoc выключенным (что является положением по умолчанию). Последний вариант имеет некоторую привлекательность, поскольку вы все еще можете использовать последнюю версию SLIME с Common Lisp, если вы тоже его используете.

  2. Посмотрите документацию по paredit. Есть два способа сделать это: (1) посмотреть на источник - в верхней части файла есть огромное количество комментариев, которые содержат всю информацию, которая может вам понадобиться; (2) введите C-h mEmacs, когда активен paredit-mode - появится буфер с информацией о текущем основном режиме, за которым следует информация обо всех активных второстепенных режимах (paredit - один из них).

    Обновление: я только что нашел этот классный набор заметок на Paredit от Фила Хагельберга ... Это ссылка на текстовый файл, я помню, как где-то видел хороший набор слайдов с этой информацией, но, похоже, не могу найти его сейчас . В любом случае, это хорошее резюме того, как это работает. Обязательно взгляните на него, я не могу сейчас жить без Paredit, и я считаю, что этот файл должен упростить его использование. :-)

  3. Фактически, эта C-h mкомбинация расскажет вам обо всех привязках клавиш, действующих в SLIME REPL, в режиме clojure (вы должны помнить C-c C-kоб отправке текущего буфера для компиляции) и, действительно, в любом буфере Emacs.

Что касается загрузки кода из файла и последующего экспериментирования с ним в REPL: используйте вышеупомянутую C-c C-kкомбинацию для компиляции текущего буфера, а затем useили requireего пространства имен в REPL. Затем экспериментируйте.

Заключительные примечания:

Будьте готовы к тому, что какое-то время придется что-то подправить, пока все не щелкнет. В нем задействовано много инструментов, и их взаимодействие в основном довольно плавное, но не до такой степени, когда можно было бы с уверенностью предположить, что вам не придется сначала вносить некоторые корректировки.

Наконец, вот небольшой код, который я храню, и .emacsвы не найдете его в другом месте (хотя он основан на классной функции Фила Хагельберга). Я чередую запускать свои шикарные экземпляры с lein swank(одна из самых крутых возможностей Leiningen) и использовать clojure-projectфункцию, как показано ниже, чтобы начать все это из Emacs. Я приложил все усилия, чтобы последний создавал среду, близкую к той, которая предоставляется lein swank. Да, и если вам просто нужен REPL в Emacs для быстрого и грязного эксперимента, то при правильной настройке вы сможете использовать его M-x slimeнапрямую.

(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
Большое спасибо за красивую запись!
user855
3
Пожалуйста. Надеюсь, это поможет вам с Clojure. Удачного взлома! :-)
Michał Marczyk
2
ł: Очень хорошее написание. Спасибо.
Ральф
Это действительно очень хороший урок. Я только что узнал, что лучший вариант - это Emacs, даже если он мне не очень понравился. IDEA, Eclipse и netbeans просто не вписываются в картину.
Адам Арольд
10

Есть еще одно отличное руководство:

За 30-45 минут можно все настроить с нуля.

Учебное пособие не предполагает каких-либо предварительных знаний об Emacs (и Clojure тоже - в более ранних сообщениях есть хорошее вступление к Clojure).

Петр Кочанский
источник
8

Emacs Starter Kit получил отличные отзывы для начала работы с Clojure:

Чтобы ответить только на шикарную часть вашего вопроса:

Leiningen - действительно простой способ настроить swank с правильным путем к классам и подключить его к Emacs.

Здесь есть отличное видео: http://vimeo.com/channels/fulldisclojure#8934942 Вот пример файла project.clj, который

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

затем запустите:

lein swank

и из Emacs:

 alt-x slime-connect
Артур Ульфельдт
источник
1

Здесь необходимо упомянуть CIDER (интерактивную среду разработки Clojure).

Он покроет большую часть того, что вы ищете. Это включает в себя:

  • интерактивный REPL
  • отладка
  • тестовый запуск
  • код навигации
  • поиск документации
  • еще больше

Помимо CIDER, есть еще несколько важных и полезных дополнений для разработки clojure, которые я попытаюсь сгруппировать соответственно (и субъективно):

Основы

  • smartparens - парные скобки, манипуляции, навигация (или parinfer, если хотите)

  • clj-refactor –- имеет несколько удивительных функций, таких как автоматическое добавление / компиляция пространств имен (вскоре может быть включен в CIDER)

  • clojure-mode - блокировка шрифтов, отступы, навигация

  • компания - фреймворк автозаполнения (или выберите другой автозаполнитель)

  • радужные разделители - выделяет / раскрашивает разделители, такие как круглые, квадратные или фигурные скобки, в зависимости от их глубины

  • flycheck - расширение для оперативной проверки синтаксиса

  • flycheck-clj-kondo - интеграция для clj-kondo

Тонкости

  • clojure-snippets - расширяемые табуляцией ярлыки для более длинных фрагментов кода

  • dumb-jump - перейти к определениям

  • which-key - отображает доступные сочетания клавиш во всплывающем окне

  • выделить круглые скобки - выделить окружающие скобки

  • crux - Сборник смехотворно полезных расширений для Emacs

  • comment-dwim-2 - замена встроенного Emacscomment-dwim

Общие основы (для любого языка)

  • magit - git фарфор внутри Emacs

  • projectile - управление проектом для поиска файлов, поиска и т. д.

  • helm - структура добавочного завершения и сужения выбора (или swiper )

Другие источники

Если вы ищете установку, которая уже выполнила большую часть / всю эту работу за вас, есть несколько вариантов:

Мика Эллиотт
источник