[Правка от неавтора: это с 2010 года, и с мая 2011 года процесс был значительно упрощен. Я добавлю к этому ответу сообщение с моими примечаниями по настройке по состоянию на февраль 2012 года.]
Вам нужно будет собрать несколько частей: Emacs, SLIME (который отлично работает с Clojure - см. Swank-clojure), swank-clojure (реализация Clojure аналога сервера SLIME), clojure-mode, Paredit и, of конечно, для начала, банку Clojure, а затем, возможно, некоторые дополнения, среди которых Leiningen, возможно, был бы самым заметным. После того, как вы все это настроите, у вас будут - в Emacs - все функции рабочего процесса / редактирования, которые вы упомянули в вопросе.
Базовая настройка:
Ниже приведены отличные руководства, в которых описывается, как все это настроить; в Интернете есть больше, но некоторые из других сильно устарели, тогда как эти два кажутся сейчас нормальными:
в котором обнаруживаются уловки торговли в отношении сообщения об авторстве закрытия в блоге Фила Хагельберга; Фил поддерживает swank-clojure и clojure-mode, а также пакет под названием Emacs Starter Kit, на который любой новичок в мире Emacs будет неплохо посоветовать. Эти инструкции, похоже, были обновлены с учетом недавних изменений в инфраструктуре; в случае сомнений поищите дополнительную информацию в группе Google Clojure.
Настройка Clojure, Incanter, Emacs, Slime, Swank и Paredit разместите сообщение в блоге проекта Incanter. Incanter - это увлекательный пакет, предоставляющий R-подобный DSL для статистических вычислений, встроенный прямо в Clojure. Этот пост будет полезен, даже если вы не планируете использовать или даже не устанавливать Incanter.
Запускаем все на работу:
После того, как вы настроите все это, вы можете попробовать начать использовать его прямо сейчас, но я настоятельно рекомендую вам сделать следующее:
Взгляните на руководство SLIME - оно включено в исходники и на самом деле очень читабельно. Кроме того, нет абсолютно никаких причин, по которым вы должны читать все 50-страничное руководство по монстрам; просто посмотрите вокруг, чтобы увидеть, какие функции доступны.
Примечание: функция autodoc SLIME, обнаруженная в последних исходных кодах, несовместима с swank-clojure - эта проблема не возникнет, если вы последуете рекомендациям Фила Хагельберга использовать версию ELPA (см. Его вышеупомянутое сообщение в блоге для объяснения) или просто оставьте autodoc выключенным (что является положением по умолчанию). Последний вариант имеет некоторую привлекательность, поскольку вы все еще можете использовать последнюю версию SLIME с Common Lisp, если вы тоже его используете.
Посмотрите документацию по paredit. Есть два способа сделать это: (1) посмотреть на источник - в верхней части файла есть огромное количество комментариев, которые содержат всю информацию, которая может вам понадобиться; (2) введите C-h mEmacs, когда активен paredit-mode - появится буфер с информацией о текущем основном режиме, за которым следует информация обо всех активных второстепенных режимах (paredit - один из них).
Обновление: я только что нашел этот классный набор заметок на Paredit от Фила Хагельберга ... Это ссылка на текстовый файл, я помню, как где-то видел хороший набор слайдов с этой информацией, но, похоже, не могу найти его сейчас . В любом случае, это хорошее резюме того, как это работает. Обязательно взгляните на него, я не могу сейчас жить без Paredit, и я считаю, что этот файл должен упростить его использование. :-)
Фактически, эта 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
'(
"src/"
"classes/"
"test/"
))
(setq clojure-project-jar-classpaths
'(
"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"))))
(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)
(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 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))