Emacs/Swank/Paredit for Clojure 的温和教程

2024-05-09

我要转向 Emacs 来工作Clojure http://en.wikipedia.org/wiki/Clojure/Lisp。 为了能够执行以下操作,我需要在 Emacs 上设置哪些信息?

  1. 自动匹配/生成相应的右括号
  2. 自动缩进 Lisp/Clojure 风格,而不是 C++/Java 风格
  3. 语法高亮
  4. 调用REPL http://en.wikipedia.org/wiki/Read-eval-print_loop
  5. 能够将文件中的部分代码加载到 REPL 中并对其进行评估。

如果我在 Emacs 上完成设置后还可以获得获取这些内容的命令列表,那就太好了。


[非作者编辑:这是从 2010 年开始的,自 2011 年 5 月以来,该过程已经大大简化。我将在这个答案中添加一个帖子,其中包含截至 2012 年 2 月的设置说明。]

您需要将几部分放在一起:Emacs、SLIME(与 Clojure 完美配合——请参阅 swank-clojure)、swank-clojure(SLIME 的服务器对应项的 Clojure 实现)、clojure-mode、Paredit 以及当然,首先是 Clojure jar,然后可能还有一些额外的东西,其中 Leiningen 可能是最值得注意的。一旦你完成了所有设置,你将在 Emacs 中拥有你在问题中提到的所有工作流程/编辑功能。

基本设置:

以下是一些很棒的教程,描述了如何设置所有这些;网上还有更多,但其他一些已经过时了,而这两个目前看来还不错:

  1. 其中发现了有关 clojure 作者身份的交易技巧 http://technomancy.us/126在 Phil Hagelberg 的博客上发帖; Phil 维护着 swank-clojure 和 clojure-mode,以及一个名为 Emacs Starter Kit 的软件包,建议 Emacs 世界的任何新手都看看。这些说明似乎已随着最近基础设施的变化而更新;如有疑问,请在 Clojure 的 Google 小组中查找更多信息。

  2. 设置 Clojure、Incanter、Emacs、Slime、Swank 和 Paredit http://data-sorcery.org/2009/12/20/getting-started/在 Incanter 项目的博客上发表文章。 Incanter 是一个令人着迷的软件包,提供类似 R 的 DSL,用于嵌入到 Clojure 中的统计计算。即使您不打算使用(甚至不安装)Incanter,这篇文章也会很有用。

让一切发挥作用:

设置完所有这些内容后,您可以尝试立即开始使用它,但我强烈建议您执行以下操作:

  1. 看一下 SLIME 的手册——它包含在源代码中,实际上非常可读。另外,你绝对没有理由应该这样做read整本50页的怪物手册;只需环顾四周,看看有哪些功能可用。

    Note: 最新上游源中发现的 SLIME autodoc 功能与 swank-clojure 不兼容-- 如果您遵循 Phil Hagelberg 的建议使用 ELPA 版本(请参阅他前面提到的博客文章以获取解释)或简单地关闭 autodoc(这是默认状态),则不会出现此问题。后一个选项有一些额外的吸引力,因为您仍然可以将最新的 SLIME 与 Common Lisp 一起使用,如果您也使用它的话。

  2. Have a look at the docs for paredit. There are two ways to go about this: (1) look at the source -- there's a huge amount of comments at the top of the file which contain all the information you're likely to need; (2) type C-h m in Emacs while paredit-mode is active -- a buffer will pop up with information on the current major mode followed by information on all active minor modes (paredit is one of those).

    Update:我刚刚发现这组很酷的笔记 http://p.hagelb.org/paredit-outline关于 Phil Hagelberg 的 Paredit...这是一个文本文件的链接,我记得在某处看到过一组包含此信息的漂亮幻灯片,但现在似乎找不到了。不管怎样,这是对其工作原理的一个很好的总结。一定要看看它,我现在不能没有 Paredit,我相信这个文件应该会让我很容易开始使用它。 :-)

  3. In fact, the C-h m combination will tell you about all keybindings active at the SLIME REPL, in clojure-mode (you'll want to remember C-c C-k for sending the current buffer off for compilation) and indeed in any Emacs buffer.

As for loading the code from a file and then experimenting with it at the REPL: use the aforementioned C-c C-k combination to compile the current buffer, then use or require its namespace at the REPL. Next, experiment away.

最后注意事项:

准备好在一切顺利之前必须进行一段时间的调整。涉及到很多工具,它们的交互大多相当顺利,但还没有达到可以安全地假设您最初不需要进行一些调整的程度。

Finally, here's a bit of code I keep in .emacs which you won't find elsewhere (although it's based on a cool function by Phil Hagelberg). I alternate between starting my swank instances with lein swank (one of the cooler features of Leiningen) and using the clojure-project function as found below to start the whole thing from within Emacs. I've done my best to make the latter produce an environment closely matching that provided by lein swank. Oh, and if you just want a REPL in Emacs for a quick and dirty experiment, then with the correct setup you should be able to use M-x slime directly.

(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))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Emacs/Swank/Paredit for Clojure 的温和教程 的相关文章

随机推荐