Um tutorial suave para Emacs / Swank / Paredit para Clojure

87

Estou mudando para o Emacs para trabalhar no Clojure / Lisp. Quais são todas as informações que preciso para configurar no Emacs para poder fazer o seguinte?

  1. correspondência / geração automática de colchetes de fechamento correspondentes
  2. estilo Lisp / Clojure autoindent, não estilo C ++ / Java
  3. Realce de sintaxe
  4. Invocando REPL
  5. Ser capaz de carregar uma parte do código do arquivo no REPL e avaliá-lo.

Seria ótimo se eu também pudesse obter a lista de comandos para obter essas coisas depois de configurar as coisas no Emacs.

user855
fonte

Respostas:

89

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

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

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

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

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

  3. 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, useou requireseu 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 .emacsque 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-projectfunçã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))
Michał Marczyk
fonte
2
Muito obrigado pelo belo artigo!
user855
3
De nada. Espero que você comece a trabalhar com Clojure. Feliz hackeamento! :-)
Michał Marczyk
2
ł: Muito bom escrever. Obrigado.
Ralph
Esse é um tutorial muito bom, de fato. Acabei de descobrir que a melhor opção é o Emacs, mesmo que não tenha gostado muito. IDEA, Eclipse e netbeans simplesmente não se encaixam na imagem.
Adam Arold
8

O kit Emacs Starter recebeu ótimas críticas para começar a usar o Clojure:

Para responder apenas à parte elegante de sua pergunta:

Leiningen é uma maneira realmente fácil de configurar o swank com o classpath correto e conectá-lo ao Emacs.

Um ótimo vídeo está aqui: http://vimeo.com/channels/fulldisclojure#8934942 Aqui está um exemplo de um arquivo project.clj que

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

então corra:

lein swank

e do Emacs:

 alt-x slime-connect
Arthur Ulfeldt
fonte
1

CIDER (Clojure Interactive Development Environment) deve ser mencionado aqui.

Ele cobrirá a maior parte do que você está procurando. Inclui:

  • REPL interativo
  • depuração
  • execução de teste
  • navegação de código
  • pesquisa de documentação
  • muito mais

Além do CIDER, existem alguns outros complementos essenciais e interessantes para o desenvolvimento de clojure, que tentarei agrupar respectivamente (e subjetivamente):

Essenciais

  • smartparens - parênteses emparelhamento, manipulação, navegação (ou parinfer se você preferir)

  • clj-refactor –- tem alguns recursos incríveis, como namespaces de adição / compilação automática (pode ser incorporado ao CIDER em breve)

  • clojure-mode - font-lock, recuo, navegação

  • empresa - estrutura de preenchimento de texto (ou escolha outro completador automático)

  • Delimitadores de arco-íris - destaca / coloriza delimitadores como parênteses, colchetes ou colchetes de acordo com sua profundidade

  • flycheck - extensão de verificação de sintaxe em tempo real

  • flycheck-clj-kondo - integração para clj-kondo

Gentilezas

  • clojure-snippets - atalhos expansíveis por guia para blocos de código mais longos

  • salto burro - pula para as definições

  • qual tecla - exibe as combinações de teclas disponíveis em pop-up

  • destacar parênteses - destacar os parênteses circundantes

  • crux - uma coleção de extensões ridiculamente úteis para o Emacs

  • comment-dwim-2 - substituição do Emacs embutidocomment-dwim

General Essentials (para qualquer idioma)

  • magit - porcelana git dentro do Emacs

  • projétil - gerenciamento de projeto para encontrar arquivos, pesquisar, etc

  • leme - completação incremental e estrutura de estreitamento de seleção (ou swiper )

Outros recursos

Se você estiver procurando por uma configuração que já fez a maior parte / todo esse trabalho para você, algumas opções são:

Micah Elliott
fonte