How to clear the REPL in cider-mode?

2019-03-16 14:19发布

问题:

I am not meaning cleaning up the text output of REPL; I mean cleaning up all evaluated results in REPL. During developing, repeatedly C-c C-q and C-c M-j is low efficiency.


UPDATE

There may be some bad debug behaviour of mine. I am not sure how other people develop progs with CIDER, but I really need the functionality mentioned above. I guess other developers also encounter same problems as mine.

For example, at the top of a clojure prog unit, I use declare to declare a function foo, which is used by another function bar, and foo is implemented after bar. Then, I C-c C-k, etc, and the prog goes well. Later, I removed the forward declaration of foo occasionally. What does happen? The prog still goes well. REALLY? Then, I commit my whole job and terminate the CIDER REPL session happily.

Disaster on morning: Symbol foo not found!

That's my story. So, nobody has ever encountered similar problems?

回答1:

Try the (refresh) function in the clojure.tools.namespace.repl namespace:

The refresh function will scan all the directories on the classpath for Clojure source files, read their ns declarations, build a graph of their dependencies, and load them in dependency order.

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

It doesn't seem to remove the vars declared in the user namespace, which I've typed into the REPL, but it does:

...unload (remove) the namespaces that changed to clear out any old definitions.

We generally add that plus a few other useful things to the user namespace, so it's loaded into the REPL on startup:

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

To keep that code separate from your main and test sources, put that in a file at <project root>/dev/user.clj, then add the following to your lein project.clj file:

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

(p.s. although it's not the question you want answered, for those seeing this answer and wanting to clear the text in the Cider REPL, it's C-c M-o (https://github.com/clojure-emacs/cider)



回答2:

Like others have already pointed out, the 'proper' solution is to use Stuart Sierra's component library.

But since you're running in CIDER, you can use C-c C-x to run cider-refresh, which will reload your project and thereby recreate your initial state.



回答3:

In EMACS when I works with Clojure in cider-mode, I use:

C-c M-o in the repl buffer

it is bound to cider-repl-clear-buffer



回答4:

If you're dealing with a large number of things which have state which you want to clear to have a clean developing environment you might consider doing one of the following:

1.) Reassess your design and see how much of that state is actually necessary. In many situations you might be using atoms, refs, or other stateful items unnecessarily and if you adopt a more functional approach, you won't find yourself needing to clear up your development environment as often.

Presuming legitimate reasons for using state:

2.) You can wipe out a namespace and all of it's contents by using the clojure function remove-ns: e.g. for a namespace called user.fancy-namespace you can clean the NS out by running (remove-ns 'user.fancy-namespace') and then simply re-evaluating the namespace. This works well for cleaning up a single namespace, but if the stateful items you need cleaned are in other namespaces, it can get tedious to do this for every namespace involved.

3.) Stuart Sierra's component library was designed to manage components which involve state. Very useful for managing DB connections, memcache clients, etc, but will require a re-architecting of your project in order to make full use of it.



回答5:

As mentioned by others, it is only necessary to clear the repl if you have variables which are holding state information. For non-state carrying components, just reloading the source buffer (re-evaluating it) is sufficient.

One very interesting way to manage a workflow which does have components that track state is Stuart Seirra's component framework. See http://youtu.be/13cmHf_kt-Q

Another approach is to write your code using defonce rather than def, which will allow you to reload your source code without redefining state variables.

If on the other hand, you want to do this to clean up defn or defmacro definitions you don't need i.e. clean out 'polution' from your repl, then to be honest, I wouldn't bother. If nothing is calling a defn or macro, it really doesn't matter.