Skip to content

Custom source path #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,31 @@ SLIME is available via
[swank-clojure](http://github.com/technomancy/swank-clojure) in `clojure-mode` 1.x.
SLIME support was removed in version 2.x in favor of `nrepl.el`.

## Customizing the source path

In some cases you may want your clojure source to be under a nested
directory inside `src` (e.g. you have more then one language) so you
put your clojure code in `PROJECT_ROOT/src/clj` and your clojure tests
in `PROJECT_ROOT/test/clj`. This breaks 2 features:

* Jumping to test/implementation.
* Creating/updating the `ns` form.

In order to get these features back you have to specify the path
inside the `src` and `test` directories. This is done by setting the
`clojure-source-nested-directory` variable. While it could be set
globally (which will affect *all* your projects) it's meant to be set
on per-project basis via the [directory variables][dv] mechanism.
Here's a sample `.dir-locals.el` file that matches the example above.
It should be created at the project root:

```elisp
((clojure-mode
(clojure-source-nested-directory . "/clj")))
```

[dv]: http://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html

## License

Copyright © 2007-2013 Jeffrey Chu, Lennart Staflin, Phil Hagelberg,
Expand Down
42 changes: 38 additions & 4 deletions clojure-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,18 @@ use (put-clojure-indent 'some-symbol 'defun)."
:group 'clojure-mode
:set 'add-custom-clojure-indents)

(defcustom clojure-source-nested-directory ""
"Custom source path (nested inside the 'src' and 'test' directories).
If your source is in PROJECT_ROOT/src/clojure instead of
PROJECT_ROOT/src and your tests are in PROJECT_ROOT/test/clojure
then set this value to '/clojure' (note the leading '/'). This
affect setting/updating the namespace and switching from test to
implementation.

Note that it should be the same heirarchy for both src and test!"
:group 'clojure-mode
:type 'string)

(define-clojure-indent
;; built-ins
(ns 1)
Expand Down Expand Up @@ -938,14 +950,23 @@ returned."



(defun clojure-source-nested-directory ()
"clojure-source-nested-directory should start with a slash and end without."
(if (string= "" clojure-source-nested-directory)
clojure-source-nested-directory
(replace-regexp-in-string
"/$" ""
(file-truename (concat "/" clojure-source-nested-directory)))))

(defun clojure-expected-ns ()
"Returns the namespace name that the file should have."
(let* ((project-dir (file-truename
(locate-dominating-file default-directory
"project.clj")))
(depth (length (split-string (clojure-source-nested-directory) "/")))
(relative (substring (file-truename (buffer-file-name)) (length project-dir) -4)))
(replace-regexp-in-string
"_" "-" (mapconcat 'identity (cdr (split-string relative "/")) "."))))
"_" "-" (mapconcat 'identity (nthcdr depth (split-string relative "/")) "."))))

(defun clojure-insert-ns-form ()
(interactive)
Expand Down Expand Up @@ -986,9 +1007,13 @@ returned."
"Returns the path of the test file for the given namespace."
(let* ((namespace (clojure-underscores-for-hyphens namespace))
(segments (split-string namespace "\\.")))
(format "%stest/%s_test.clj"
(file-name-as-directory
(locate-dominating-file buffer-file-name "src/"))
(format "%s%s_test.clj"
(file-truename
(concat
(file-name-as-directory
(locate-dominating-file buffer-file-name "src/"))
(file-name-as-directory
(concat "test/" (clojure-source-nested-directory)))))
(mapconcat 'identity segments "/"))))

(defvar clojure-test-for-fn 'clojure-test-for
Expand All @@ -1006,10 +1031,19 @@ Clojure test file for the given namespace.")
(clojure-test-jump-to-implementation)
(clojure-jump-to-test)))

(defun safe-nested-directory-p (v)
"Tests whether the nested directory value is safe for .dir-locals.el.

It mainly guards against errors trying to make the nested
directory not a subdir of the original source directory"
(and (stringp v)
(not (string-match-p "\\.\\." v))))

;;;###autoload
(progn
(put 'clojure-test-ns-segment-position 'safe-local-variable 'integerp)
(put 'clojure-mode-load-command 'safe-local-variable 'stringp)
(put 'clojure-source-nested-directory 'safe-local-variable 'safe-nested-directory-p)

(add-to-list 'auto-mode-alist '("\\.clj\\'" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.dtm\\'" . clojure-mode))
Expand Down
10 changes: 8 additions & 2 deletions clojure-test-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
(declare-function nrepl-current-ns "nrepl.el")
(declare-function nrepl-current-tooling-session "nrepl.el")
(declare-function nrepl-current-connection-buffer "nrepl.el")
(declare-function clojure-source-nested-directory "clojure-mode.el")

;; Faces

Expand Down Expand Up @@ -336,8 +337,13 @@ Retuns the problem overlay if such a position is found, otherwise nil."
(namespace-end (split-string (car (last segments)) "_"))
(namespace-end (mapconcat 'identity (butlast namespace-end 1) "_"))
(impl-segments (append (butlast segments 1) (list namespace-end))))
(format "%s/src/%s.clj"
(locate-dominating-file buffer-file-name "src/")
(format "%s/%s.clj"
(file-truename
(concat
(file-name-as-directory
(locate-dominating-file buffer-file-name "src/"))
(file-name-as-directory
(concat "src/" (clojure-source-nested-directory)))))
(mapconcat 'identity impl-segments "/"))))

(defvar clojure-test-implementation-for-fn 'clojure-test-implementation-for
Expand Down