【问题标题】:Clojure coding with Emacs and Cider使用 Emacs 和 Cider 进行 Clojure 编码
【发布时间】:2015-04-05 14:29:35
【问题描述】:

我是 Clojure 编码的新手,并且阅读了许多文章来设置 Emacs 以进行开发。
设置本身按设计工作,但我一直在从 Cider 会话运行服务器,并在进行任何代码更改时完全杀死 Emacs。或者,我需要从 shell 会话中找到服务器进程,然后从那里杀死它。这远非理想。

clojure-getting-started/web.clj

(defn -main [& [port]]
  (let [port (Integer. (or port (env :port) 5000))]
    (jetty/run-jetty (site #'app) {:port port :join? false})))

苹果酒会议

clojure-getting-started.web> (defonce server (-main))

启动服务器后,(server) 函数会出现以下错误:

1. Unhandled java.lang.ClassCastException
   org.eclipse.jetty.server.Server cannot be cast to clojure.lang.IFn


错误消息是有道理的,但是如何仅使用 Emacs 刷新我的代码库?
我想(并希望)有比在 Emacs 上启动 shell 会话并杀死那里的进程更好的方法......

【问题讨论】:

  • 我建议您阅读此 github.com/stuartsierra/component 并观看此视频 youtube.com/watch?v=13cmHf_kt-Q 以大致了解如何启动、停止、重新加载代码和启动 Web 服务器
  • 您查看github.com/clojure-emacs/cider#basic-usage 和那里列出的键盘快捷键了吗?您可能只想在更改后重新评估缓冲区 (C-c C-k)(或对单个表单使用 C-x C-e)。如果您确实需要重新启动 Clojure,您可以停止它 (C-c C-q) 并从 Emacs (M-x cider-jack-in) 内重新启动。 server 也是一个简单的 var,而不是函数,所以只需 server 将返回服务器对象(当您评估 (defonce server ...) 时,它是通过 -main 启动的。最后,您想查看 lein-ring 插件这将简化您的工作流程。
  • 如果您是 Clojure 的新手,请查看电子书 Clojure for the Brave and True 的这一章:braveclojure.com/basic-emacs 了解安装 Emacs 和苹果酒。

标签: emacs clojure cider


【解决方案1】:

假设您想要的是运行一个码头服务器,并在您从 emacs 中更改代码时让它加载或重新加载您的代码。虽然已经给出的建议很好,但在开始时它可能比您需要的更复杂。我的建议是利用 lein 的一些模板,这些模板将为您设置默认环境和工作流程。然后,您可以在了解更多信息时优化此默认设置,直到获得适合您的工作流程。我的建议是从默认的 compojure 模板开始,即

lein new compojure my-project

这将创建一个包含基本 ring 和 compojure 库和 lein 插件以及简单的开发配置文件的基本项目。

编辑 src/my_project/handler.clj 文件并添加 ring.middleware.reload 中间件,例如

(ns my-project.handler
  (:require [compojure.core :refer :all]
            [compojure.route :as route]
            [ring.middleware.reload :refer [wrap-reload]]
            [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))

(defroutes app-routes
  (GET "/" [] "Hello World")
  (route/not-found "Not Found"))

(def app
  (-> app-routes
      wrap-reload
      (wrap-defaults site-defaults)))

wrap-reload 中间件将导致您的代码在修改时重新加载。您无需重新启动码头服务器即可使代码更改生效 - 只需重新加载页面。

在终端运行

lein ring server

lein ring server-headless

这将启动一个侦听端口 3000 的码头服务器。然后在 emacs 中,您可以在编写代码时打开一个苹果酒 repl 使用。除非您对 project.clj 文件进行更改,否则您不需要重新启动服务器进程。与苹果酒工艺相同。

然后,一旦您对此感到满意,请查看 lein-ring 文档。在那里,您将找到有关如何在项目中设置 repl.clj 文件的信息。一旦你这样做了,你就可以做类似的事情

lein repl

然后从该 repl 中,执行类似的操作

(start-server)

这将启动服务器。然后,您可以切换到 emacs,而不是运行 cider-jack-in,您可以执行 cider-connect,这将连接到已经运行 repl 而不是启动第二个 repl 会话。稍后,如果您决定开始查看 clojurescript,您可以查看一些用于 clojure+clojurescript 应用程序的默认模板。我很喜欢figwheel,也很喜欢用试剂,所以我也觉得试剂模板不错。

那里有很多 lein 模板,我发现运行它们并查看它们的作用非常有用。然后我倾向于挑选我喜欢的功能/选项。

【讨论】:

  • leiningen 的复合模板将ring/ring-defaults 添加为命名空间要求。 ring-defaults 包含一个重新加载功能(我假设它的包装重新加载)。所以不需要特别包含 require 指令。
  • 应用的定义中不需要包含wrap-reload函数,即。在(def app ,,,)wrap-defaults 中间件包含在保存 .clj 文件时重新加载更改的功能。从app-routes 调用的代码或它调用的函数(等等)对代码所做的任何更改都会注入到正在运行的 REPL 中。此函数链之外的任何更改,尤其是添加库,都需要重新启动服务器。
【解决方案2】:

这是我刚刚给similar question 的大部分答案:


clojure.tools.namespace.repl 命名空间中尝试(refresh) 函数:

刷新函数将扫描类路径中的所有目录以查找 Clojure 源文件,读取它们的 ns 声明,构建它们的依赖关系图,并按依赖顺序加载它们。

https://github.com/clojure/tools.namespace#reloading-code-usage

我们通常会在 user 命名空间中添加一些其他有用的东西,所以它会在启动时加载到 REPL 中:

(ns user
  (:require [clojure.tools.namespace.repl :refer [refresh]]
            [clojure.repl :refer [doc source]]
            [clojure.pprint :refer [pprint pp]]
            [midje.repl :as midje]
            [clojure.stacktrace :as st]))

要将该代码与您的主源和测试源分开,请将其放在 <project root>/dev/user.clj 的文件中,然后将以下内容添加到您的 lein project.clj 文件中:

:profiles {:dev {:source-paths ["dev"]}}

【讨论】:

    【解决方案3】:

    关于 ClassCastException - 服务器需要是 1 个参数的函数:

    (defonce server (fn [request] (-main)))
    

    【讨论】:

      猜你喜欢
      • 2015-11-16
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      • 2015-01-18
      • 2014-09-03
      • 1970-01-01
      • 2015-10-10
      • 2014-10-06
      相关资源
      最近更新 更多