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 的温和教程 的相关文章

  • 如何更改 emacs 上的光标颜色

    我对 Emacs 的颜色做了一些更改 现在唯一的问题是光标在黑色背景上为黑色 我必须更改它 我该怎么办 如果您运行的是最新版本的 emacs 您可以使用 Set cursor color to white set cursor color
  • 为什么这个 Clojure 减速器 r/fold 没有提供任何性能优势?

    我想知道为什么下面的代码在 r fold 的情况下没有提供加速 我对减速器有什么误解吗 我在一个相当慢的 尽管有 2 个核心 Ubuntu 12 04 开发盒上运行它 通过 emacs 和 lein 运行 每个都有相同的结果 require
  • 用于正则表达式匹配及其在字符串中的位置的紧凑 Clojure 代码

    斯图尔特 哈洛威举了个例子 re seq w The quick brown fox 作为在 Clojure 中查找正则表达式匹配项的自然方法 在他的书中 这种构造与匹配器上的迭代进行了对比 如果人们关心的只是一份比赛列表 那就太好了 但是
  • 在 Emacs ruby​​ 模式下使用制表符缩进而不是空格

    我一直在尝试配置 Emacs 以便在缩进 Ruby 代码时插入一个 制表符 而不是一系列 空格 到目前为止 我已经尝试设置 varruby indent tabs mode to t这样 根据文档 它将 如果非零 则在 ruby 模式下插入
  • Emacs:当光标位于右括号时匹配括号

    之前有人问过 Emacs 当光标位于其上时突出显示匹配的括号 而不是其后 https stackoverflow com questions 16399530 emacs highlight matching paren when curs
  • 将向量作为绑定传递给 for 宏时出现问题

    我有任意数量的列表 我想使用 for 宏来处理它们 我想创建一个传递向量作为绑定的函数 因为列表的数量各不相同 如果我对绑定进行硬编码 它会按我的预期工作 gt def list1 pink green gt def list2 dog c
  • 让 Emacs ansiterm 和 Zsh 更好地发挥作用

    我一直在尝试在 emacs 会话中使用 Zsh 而无需 emacs 重新映射所有 Zsh 键 我发现 ansi term 对此非常有效 但是我仍然遇到一些问题 我输出了很多垃圾字符 我可以用以下方法修复它 Setup proper term
  • 如何使用 Emacs 通过 HTTP 打开远程文件?

    大多数开源软件都通过某些 HTTP 服务公开其代码 我想从 Emacs 打开并浏览此类代码 但 AFAICS trapmp 只允许ssh and ftp 因此 我的第一个问题是如何打开 HTTP URL 以便在 Emacs 中进行读取 然后
  • 将剪贴板上的图像粘贴到 Emacs Org 模式文件而不保存它

    由于我使用 Emacs Org 模式作为研究日志 有时我想通过屏幕截图来跟踪某些内容 但我绝对不想保存它们 所以我想知道是否有任何方法可以将这些数字插入到我的组织模式文件中 就像使用 word 从剪贴板复制它们一样 您想要的确切功能目前尚未
  • Emacs 行编号性能

    我试过了linum and nlinum 两者对于超过 100k 行的文件的性能都很糟糕 for x in 1 100000 do echo x done gt 100k txt emacs q 100k txt M x load libr
  • 从一个文件重新归档到另一文件

    我正在尝试基于 emacs 实现 GTDhttp members optusnet com au charles57 GTD gtd workflow html http members optusnet com au charles57
  • 在 Clojure 和其他 Lisp 方言中,在函数名称末尾使用星号的约定是什么?

    请注意 我不是在谈论符号名称中的耳罩 这个问题在Clojure 常量的约定 样式和用法 https stackoverflow com questions 3579063 conventions style and usage for cl
  • 在 Emacs 中,如何根据缓冲区名称自动启用次要模式?

    我有一个 Emacs 扩展 它创建一个名为 erl output 该缓冲区仅由以下内容创建fundamental mode默认情况下 有什么办法可以自动启用compilation minor mode在那个缓冲区上 要自动更改主要模式 您可
  • 无法删除 IntelliJ/Cursive 中的括号

    我正在使用 IntelliJ Cursive 编写 Clojure 我发现 删除括号的唯一方法就是将其中的内容完全删除 然后才能将括号删除 例如 假设我有以下代码 list 我只想删除左括号 一旦我在左括号上按退格键 IDE 就会忽略此行为
  • Emacs 在多个文件中查找并替换正则表达式 (find-name-dired + Q),不保存我的缓冲区?

    我不明白这是怎么回事 我已经在整个目录中进行了搜索和替换 使用 M x 查找名称 dired RET 选择我的项目的根目录 输入 rb 作为要匹配的文件名 按 t 选择找到的所有文件 按 Q shift Q 开始搜索 替换 输入 交易 作为
  • Clojure:只能从尾部位置重复

    我正在尝试递归地反转列表 但是我得到了Can only recur from tail position运行时 这到底意味着什么 如何改进我的代码才能使其正常工作 defn recursive reverse coll loop coll
  • 将数据库与 Clojure 结合使用

    有哪些使用 Clojure 数据库的方法 我从 Clojure 知道你可以用 Java 做任何事情 但这意味着我最终可能会使用一些过于复杂的东西 比如 Hibernate 这与 Clojure 的简单性相冲突 有什么建议或意见吗 Cloju
  • 如何编写 Clojure 宏来从字符串创建正则表达式?

    我正在创建一个方便的宏 部分便利在于可以仅使用字符串来指定正则表达式 而不是使用 re 表示法 我无法弄清楚的一部分是如何让宏获取字符串并将其重写为 Clojure 正则表达式 例如 生成 re 符号 我认为这是一个语法 转义问题 我的第一
  • 如何在 emacs 中自动回答是或否

    I binded function semantic symref to key C c C r like this global set key kbd C c C r semantic symref everytime I presse
  • emacs 中 ansi term 中的奇怪字符

    我编写了一个 C 程序 当我在 ansi term 中使用 g 编译它时 显示了一些奇怪的字符 如果需要 错误是我没有声明变量 n 我该如何纠正这个问题 啊 测试了这个 setq locale coding system utf 8 set

随机推荐