]> code.delx.au - dotemacs/blob - lisp/my-find-test-file.el
69ca72fae064f2d4f77f221d79383c33f82457a5
[dotemacs] / lisp / my-find-test-file.el
1 ;;; -*- lexical-binding: t -*-
2
3 (require 'cl-lib)
4 (require 'counsel)
5
6 (defun my/prod-file-p (file)
7 (not (or (string-match-p "test" file)
8 (string-match-p "spec" file))))
9
10 (defun my/matching-test-file-p (test-file base-name extension)
11 (cl-loop for pattern in (list
12 (concat "test/.*" base-name "[^/]*\\." extension "$")
13 (concat "spec/.*" base-name "[^/]*\\." extension "$")
14 (concat "test[^/]*" base-name "[^/]*\\." extension "$")
15 (concat base-name "[^/]*test\\." extension "$")
16 (concat base-name "[^/]*spec\\." extension "$"))
17 for matched = (string-match-p pattern test-file)
18 until matched
19 finally return (not (null matched))))
20
21 (defun my/matching-prod-file-p (prod-file base-name extension)
22 (dolist (pattern '("test" "it.spec" "spec" "^\\.*" "\\.*$"))
23 (setq base-name (replace-regexp-in-string pattern "" base-name)))
24 (and (my/prod-file-p prod-file)
25 (string-match-p (concat base-name "[^/]*\\." extension "$") prod-file)))
26
27 (defun my/find-prod-or-test-file ()
28 "Find test file in the current Git repository."
29 (interactive)
30
31 (setq counsel--git-dir (locate-dominating-file
32 default-directory ".git"))
33 (if (null counsel--git-dir)
34 (error "Not in a git repository")
35 (setq counsel--git-dir (expand-file-name
36 counsel--git-dir))
37
38 (let* ((default-directory counsel--git-dir)
39 (files (split-string
40 (shell-command-to-string counsel-git-cmd)
41 "\n"
42 t))
43 (base-name (file-name-sans-extension (file-name-nondirectory (buffer-file-name))))
44 (extension (file-name-extension (buffer-file-name)))
45 (predicate (if (my/prod-file-p (buffer-file-name)) #'my/matching-test-file-p #'my/matching-prod-file-p))
46 (results nil))
47
48 (dolist (file files)
49 (if (funcall predicate file base-name extension)
50 (cl-pushnew file results)))
51
52 (cl-case (length results)
53 (0 (message "No matching file found."))
54 (1 (find-file (car results)))
55 (t (ivy-read "Find test file" results
56 :action #'counsel-git-action
57 :caller 'counsel-git))))))