4

我是 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 会话并杀死那里的进程更好的方法......

4

3 回答 3

3

假设您想要的是运行一个码头服务器,并在您从 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 中,您可以在编写代码时打开一个 cider 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 模板,我发现运行它们并查看它们的作用非常有用。然后我倾向于挑选我喜欢的功能/选项。

于 2015-02-08T01:11:18.393 回答
1

这是我刚刚对类似问题给出的大部分答案:


尝试命名空间(refresh)中的函数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,然后将以下内容添加到您的 leinproject.clj文件中:

:profiles {:dev {:source-paths ["dev"]}}
于 2015-02-07T09:05:18.540 回答
0

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

(defonce server (fn [request] (-main)))
于 2015-02-15T14:21:52.267 回答