;;; jao-clojure.el --- Clojure utilities -*- lexical-binding: t; -*- ;; Copyright (C) 2025 Jose Antonio Ortega Ruiz ;; Author: Jose Antonio Ortega Ruiz ;; Keywords: languages ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; Helpers for clojure coding ;;; Code: (require 'clojure-mode) (require 'project) ;;;; Jumping between implementation and test files (defun jao-clojure--ext-dir (prefix) (let* ((ext (file-name-extension buffer-file-name)) (ext-rx (format "/%s/" ext))) (if (string-match-p ext-rx buffer-file-name) (format "%s/%s" prefix ext) prefix))) (defun jao-clojure-find-current-test () (save-excursion (and (re-search-backward "(deftest\\(?:\\W+^:\\w+\\)*\\W+\\b\\(.+\\)\\b" nil t) (match-string-no-properties 1)))) (defvar jao-clojure--src-candidates '("lib" "src" "srv" "app")) (defun jao-clojure--test-namespace-p (ns) (or (string-suffix-p "-test" ns) (string-match "\\(.+\\)\\.\\(test\\)\\(\\..+\\)" ns))) (defun jao-clojure-test-buffer-p () (jao-clojure--test-namespace-p (clojure-find-ns))) (defun jao-clojure--test-for (namespace sep) (funcall cider-test-infer-test-ns namespace)) (defun jao-clojure--infer-test-ns (ns) (if (jao-clojure--test-namespace-p ns) ns (jao-clojure--test-for ns "."))) (defun jao-clojure--root () (project-root (project-current))) (defun jao-clojure-jump-to-test () "Jump from implementation to test file." (interactive) (let* ((f (format "%s/%s/%s.%s" (jao-clojure--root) (jao-clojure--ext-dir "test") (jao-clojure--test-for (clojure-find-ns) "/") (file-name-extension buffer-file-name))) (f (replace-regexp-in-string "-" "_" f))) (find-file f))) (defun jao-clojure--implementation-for (namespace) (let ((n (replace-regexp-in-string "-test$" "" namespace))) (replace-regexp-in-string "\\.test\\." "." n))) (defun jao-clojure--find-implementation (src) (let ((f (format "%s/%s/%s.%s" (jao-clojure--root) (jao-clojure--ext-dir src) (jao-clojure--implementation-for (clojure-find-ns)) (file-name-extension buffer-file-name)))) (and (file-exists-p f) f))) (defun jao-clojure-jump-to-implementation () "Jump from test file to implementation." (interactive) (let ((impl (car (seq-keep #'jao-clojure--find-implementation jao-clojure--src-candidates)))) (if impl (find-file impl) (message "No implementation file found")))) (defun jao-clojure-other-file () "Toggle between implementation and test file" (interactive) (if (jao-clojure-test-buffer-p) (jao-clojure-jump-to-implementation) (jao-clojure-jump-to-test))) (provide 'jao-clojure) ;;; jao-clojure.el ends here