tpope / vim-fireplace

fireplace.vim: Clojure REPL support
https://www.vim.org/scripts/script.php?script_id=4978
1.75k stars 139 forks source link

Autoconnect using ~/.lein/repl_port when editing a clojure file outside of a project #121

Closed smackesey closed 5 years ago

smackesey commented 10 years ago

When lein repl is run outside of a project, it uses the user namespace and creates ~/.lein/repl_port. I like to write one-off scripts that are outside of any project. It would be nice to have fireplace autoconnect to this "global REPL" when editing a clojure file that is outside of any project.

tpope commented 10 years ago

Good idea; I didn't realize lein started creating that file. One complication is that it's tough to tell whether a file is part of a project or not (bearing in mind that not all projects are lein projects).

smackesey commented 10 years ago

Hmm, I'm very new to Clojure (and really the Java ecosystem)and still learning about such things. Looking at the source in plugin/fireplace.vim though, it looks like fireplace only autoconnects to a REPL in a lein project. It looks up the directory tree from the current file for the containing directory of project.clj (the leiningen project root). If it doesn't find project.clj, no attempt to auto-connect is made. It would seem easy enough (and I'd be happy to put in a PR implementing this) to have it look for ~/.lein/repl_port if it doesn't find a leiningen root project.clj.

To understand your concern, are you thinking that a user using another other project type that doesn't have project.clj (who currently must manually connect) will inadvertently autoconnect to a global lein REPL that they happen to be running when they open a clojure file in their project? If that's the problem, I can think of a few ways to deal with it.

tpope commented 10 years ago

Yep, that's the problem. Some thoughts:

smackesey commented 10 years ago

If the 'path' of the buffer has been changed to anything other than $CLASSPATH (e.g. by classpath.vim), it's part of a proper project.

It seems likely that if 'path' has been changed, then we're in a project, but I'm not sure the converse is true. If the converse doesn't work then this isn't a good indicator of being in a project.

If there's a proper namespace header, it's probably part of a proper project.

This could be good. I'm not yet experienced enough with Clojure to know whether my non-project scripts are likely to contain namespace headers, so I can't really comment.

Connecting is cheap, so we could do that on loading the first Clojure buffer, then decide when to use it dynamically.

To clarify, are you saying that fireplace always attempt to autoconnect with ~/.lein/repl_port only on the first clojure buffer opened in Vim, then only later based on some other criteria (eg the namespace header)? I imagine that many of the scripts I write will actually be written while already working on some Clojure project, so my workflow at least would need to rely on these other criteria.

Another possibility is to have a variable that holds a set of patterns that act as project identifiers. The default would just be ['project.clj] (and maybe the names of common files for other kinds of projects). Then when hunt is called it looks for any of these files to identify a project. Or, the user could actually write a function returning true/false that's executed by hunt at each step up the directory tree. This would provide maximum flexibility. The default function would just check for project.clj.

tpope commented 10 years ago

No progress on the big problem yet, but I did expose an API for connecting to a port file to play with:

autocmd User FireplacePreConnect call fireplace#register_port_file(expand('~/.lein/repl-port'), '/tmp')

Now files in /tmp will use the standalone repl.

cpixl commented 9 years ago

Just to note... I had the same problem on my setup, but fireplace#register_port_file(expand('~/.lein/repl-port'), '/') made my day :)

tpope commented 5 years ago

I think that's a bit too aggressive to bake in, but totally adequate as a configurable solution.