clojure-vim / acid.nvim

Asynchronous Clojure Interactive Development
161 stars 12 forks source link

Require/eval fails when the folder hierarchy isn't typical for a Clojure project #44

Open daveyarwood opened 5 years ago

daveyarwood commented 5 years ago

Since updating recently, I am no longer seeing evaluation results in the buffer. Running :AcidRequire and then using cpp to evaluate a form has no visible effect.

I noticed that when I press cqp to get the prompt, the namespace is incorrect. In this particular project, I have a frontend folder and a backend folder, and acid appears to be incorrectly prefixing the namespace with backend.:

;; should be `geir-backend.main-class`
backend.geir-backend.main-class=>

From /tmp/acid-log-handler.log:

2019-03-25 10:58:58,436 - [acid.nvim :DEBUG] - fpath is None
2019-03-25 10:58:58,439 - [acid.nvim :DEBUG] - Hitting cache for ns 'backend.geir-backend.main-class'
2019-03-25 10:58:58,443 - [acid.session :INFO] - sending data -> {'id': '46e7cf434bb8400da8c54f61634ade04', 'op': 'eval', 'code': "(require '[backend.geir-backend.main-class :reload :all])"}
2019-03-25 10:58:58,516 - [acid :INFO] - {'session': '502fc4e3-4dd6-48c8-aa92-fc22efde7c2f', 'root-ex': 'class java.io.FileNotFoundException', 'id': '46e7cf434bb8400da8c54f61634ade04', 'ex': 'class java.io.FileNotFoundException', 'status': ['eval-error']}
2019-03-25 10:58:58,520 - [acid.session :INFO] - stopped watching key 46e7cf434bb8400da8c54f61634ade04-d557c178c25946b6aa8c6ae79f3de6a9-watcher
2019-03-25 10:58:58,522 - [acid :INFO] - {'id': '46e7cf434bb8400da8c54f61634ade04', 'session': '502fc4e3-4dd6-48c8-aa92-fc22efde7c2f', 'out': '\x1b[1;31mjava.io.FileNotFoundException\x1b[m: \x1b[3mCould not locate backend/geir_backend/main_class__init.class, backend/geir_backend/main_class.clj or backend/geir_backend/main_class.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.\x1b[m\n'}
2019-03-25 10:58:58,524 - [acid :INFO] - {'status': ['done'], 'id': '46e7cf434bb8400da8c54f61634ade04', 'session': '502fc4e3-4dd6-48c8-aa92-fc22efde7c2f'}
2019-03-25 10:58:59,939 - [acid.nvim :DEBUG] - fpath is None
2019-03-25 10:58:59,943 - [acid.nvim :DEBUG] - Hitting cache for ns 'backend.geir-backend.main-class'
2019-03-25 10:58:59,947 - [acid.session :INFO] - sending data -> {'ns': 'backend.geir-backend.main-class', 'id': '9439db61023a4c2aa6db6c36b93c2cbc', 'op': 'eval', 'code': '(def stop-server! (constantly false))'}
2019-03-25 10:59:00,008 - [acid :INFO] - {'status': ['namespace-not-found', 'done', 'error'], 'ns': 'backend.geir-backend.main-class', 'id': '9439db61023a4c2aa6db6c36b93c2cbc', 'session': '435fa752-561c-4403-ae00-6a7d9657cc54'}
2019-03-25 10:59:00,010 - [acid.session :INFO] - stopped watching key 9439db61023a4c2aa6db6c36b93c2cbc-b9cc3943c497474db87c2f381dd63996-watcher
2019-03-25 10:59:00,019 - [acid :INFO] - {'status': ['done'], 'id': '9439db61023a4c2aa6db6c36b93c2cbc', 'session': '435fa752-561c-4403-ae00-6a7d9657cc54'}

I tried doing the same thing in another project with a "standard" Clojure folder hierarchy, and there is no problem, so this appears to be a bug where acid uses the file path to determine the namespace name. I think it should probably parse the ns declaration at the top of the file instead?

rinx commented 5 years ago

@daveyarwood Did you try to specify g:acid_alt_paths like following?

let g:acid_alt_paths = ['src/backend', 'src/frontend']

After telling your paths to Acid, :AcidRequire will work fine, I think.

However, I agree with your opinion that it is better to parse the ns declarations. :laughing:

hkupty commented 5 years ago

Parsing the file for the ns, when I wrote acid, was probably more complicated than figuring out with the paths. Take for example this top part of a clojure file:

;; TODO This file should be merged with sample.utils
(ns sample.tools)

Or this sample from eftest:

(ns ^:eftest/synchronized foo.core-test (:require [clojure.test :refer :all] [foo.core :refer :all]))

Or even a hypothetical poorly formatted file:

(
  ns something)

None of those would reliably give me a ns unless I parse/interpret clojure, which is something that feels very hacky to do in Python.

I can give another shot. I won't remove the path-based ns finding since this is the most reliable way (obviously, when everything is configured), but I'm open to suggestions for the cases above.

Cheers

SevereOverfl0w commented 5 years ago

You can use nrepl to query for the classpath, and use that as your roots (after filtering out jars).

daveyarwood commented 5 years ago

@rinx Specifying let g:acid_alt_paths = ['src/backend'] did the trick! Thanks, it wasn't obvious that there was a config option for that.

@hkupty I see your point about parsing the ns form being complicated. Seems like there ought to be a better way. @SevereOverfl0w 's idea sounds promising!

hkupty commented 5 years ago

@SevereOverfl0w Could you elaborate? I like the idea of outsourcing to the nrepl.

SevereOverfl0w commented 5 years ago

I think cider provides a classpath op, it will return a list which is the classpath. If you filter it to just directories, it should give you back a list like /home/dominic/project/src/backend etc. it will also include test, resources and anything else.

You may have a few false-positives (e.g. /home/dominic/.gitlibs/edge/foo.bar) but they don't really matter for calculating the ns that should be used.

hkupty commented 5 years ago

Amazing! I'll try that.