[Editar de não-autor: é de 2010 e o processo foi significativamente simplificado desde maio de 2011. Adicionarei uma postagem a esta resposta com minhas notas de configuração em fevereiro de 2012.]
Você precisará juntar algumas peças: Emacs, SLIME (que funciona perfeitamente bem com Clojure - veja swank-clojure), swank-clojure (a implementação Clojure da contraparte do servidor SLIME), modo clojure, Paredit e, de claro, o jarro de Clojure para começar, então talvez alguns extras entre os quais Leiningen seria talvez o mais notável. Depois de configurar tudo, você terá - dentro do Emacs - todos os recursos de fluxo de trabalho / edição que você mencionou na pergunta.
Configuração básica:
Os seguintes são ótimos tutoriais que descrevem como configurar tudo isso; há mais na Web, mas alguns dos outros estão bastante desatualizados, enquanto esses dois parecem estar ok por enquanto:
em que são encontrados truques do comércio em relação à postagem de autoria de clojure no blog de Phil Hagelberg; Phil mantém o swank-clojure e o clojure-mode, bem como um pacote chamado Emacs Starter Kit que é algo que qualquer novato no mundo do Emacs faria bem em dar uma olhada. Essas instruções parecem ter sido atualizadas com as mudanças recentes na infraestrutura; em caso de dúvida, procure informações adicionais no grupo do Google de Clojure.
Configurando Clojure, Incanter, Emacs, Slime, Swank e Paredit post no blog do projeto Incanter. Incanter é um pacote fascinante que fornece uma DSL semelhante a R para cálculos estatísticos incorporados diretamente no Clojure. Este post será útil mesmo se você não planeja usar - ou mesmo instalar - o Incanter.
Colocando tudo para funcionar:
Depois de configurar tudo isso, você pode tentar e começar a usá-lo imediatamente, mas eu recomendo fortemente que você faça o seguinte:
Dê uma olhada no manual do SLIME - está incluído nas fontes e é realmente muito legível. Além disso, não há absolutamente nenhuma razão para você ler todo o manual do monstro de 50 páginas; basta dar uma olhada para ver quais recursos estão disponíveis.
Observação: o recurso autodoc do SLIME, conforme encontrado nas fontes upstream mais recentes, é incompatível com swank-clojure - esse problema não surgirá se você seguir a recomendação de Phil Hagelberg de usar a versão ELPA (consulte a postagem do blog mencionada anteriormente para obter uma explicação) ou simplesmente deixe o autodoc desligado (que é o estado padrão das coisas). A última opção tem algum apelo adicional, pois você ainda pode usar o SLIME mais recente com Common Lisp, caso você também use.
Dê uma olhada na documentação do paredit. Existem duas maneiras de fazer isso: (1) olhar para a fonte - há uma grande quantidade de comentários na parte superior do arquivo que contém todas as informações de que você provavelmente precisará; (2) digite C-h mno Emacs enquanto o modo paredit está ativo - um buffer aparecerá com informações sobre o modo principal atual seguido por informações sobre todos os modos secundários ativos (paredit é um deles).
Atualizar: Acabei de encontrar este conjunto legal de notas no Paredit por Phil Hagelberg ... Esse é um link para um arquivo de texto, lembro-me de ter visto um bom conjunto de slides com essas informações em algum lugar, mas não consigo encontrar agora . De qualquer forma, é um bom resumo de como funciona. Definitivamente dê uma olhada nisso, eu não posso viver sem Paredit agora e este arquivo deve facilitar muito para começar a usá-lo, eu acredito. :-)
Na verdade, a C-h mcombinação irá informá-lo sobre todos os atalhos de teclado ativos no SLIME REPL, no modo clojure (você vai querer lembrarC-c C-k de enviar o buffer atual para compilação) e de fato em qualquer buffer Emacs.
Quanto a carregar o código de um arquivo e, em seguida, experimentá-lo no REPL: use o mencionado C-c C-k combinação para compilar o buffer atual, use
ou require
seu namespace no REPL. Em seguida, experimente.
Notas finais:
Esteja preparado para ajustar as coisas por um tempo antes de tudo clicar. Há muitas ferramentas envolvidas e suas interações são, em sua maioria, bastante suaves, mas não a ponto de ser seguro assumir que você não terá que fazer alguns ajustes inicialmente.
Finalmente, aqui está um trecho de código que mantenho e .emacs
que você não encontrará em nenhum outro lugar (embora seja baseado em uma função legal de Phil Hagelberg). Eu alterno entre iniciar minhas instâncias swank com lein swank
(um dos recursos mais legais do Leiningen) e usar a clojure-project
função conforme encontrada abaixo para iniciar tudo de dentro do Emacs. Fiz o meu melhor para fazer com que o último produzisse um ambiente que correspondesse perfeitamente ao fornecido por lein swank
. Ah, e se você quer apenas um REPL no Emacs para uma experiência rápida e suja, então com a configuração correta você poderá usar M-x slimediretamente.
(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))