]> code.delx.au - dotemacs/commitdiff
find-prod-or-test-file
authorJames Bunton <jamesbunton@delx.net.au>
Thu, 28 Jul 2016 13:42:52 +0000 (23:42 +1000)
committerJames Bunton <jamesbunton@delx.net.au>
Thu, 28 Jul 2016 13:43:14 +0000 (23:43 +1000)
init.el
lisp/my-find-test-file.el [new file with mode: 0644]
lisp/my-keys.el
snippets/emacs-lisp-mode/lexical [new file with mode: 0644]

diff --git a/init.el b/init.el
index 2af6ef5fdc3ffdac3af8fa8588133c7fbe7d6cad..934aa81b26e77d8c91e8b4ccad4f8857a16ff268 100644 (file)
--- a/init.el
+++ b/init.el
@@ -14,6 +14,7 @@
 (load-library "my-completion")
 (load-library "my-recentf")
 (load-library "my-flycheck")
+(load-library "my-find-test-file")
 (load-library "my-other-modes")
 (load-library "my-minor-modes")
 (load-library "my-file-modes")
diff --git a/lisp/my-find-test-file.el b/lisp/my-find-test-file.el
new file mode 100644 (file)
index 0000000..a792203
--- /dev/null
@@ -0,0 +1,58 @@
+;;; -*- lexical-binding: t -*-
+
+(require 'cl-lib)
+(require 'counsel)
+
+(defun my/prod-file-p (file)
+  (not (or (string-match-p "test" file)
+           (string-match-p "spec" file))))
+
+(defun my/matching-test-file-p (test-file base-name extension)
+  (let ((found nil))
+    (dolist (pattern (list
+                      (concat "test/.*" base-name "[^/]*\\." extension "$")
+                      (concat "spec/.*" base-name "[^/]*\\." extension "$")
+                      (concat "test[^/]*" base-name "[^/]*\\." extension "$")
+                      (concat base-name "[^/]*test\\." extension "$")
+                      (concat base-name "[^/]*spec\\." extension "$")))
+      (if (string-match-p pattern test-file)
+          (setq found t)))
+    found))
+
+(defun my/matching-prod-file-p (prod-file base-name extension)
+  (dolist (pattern '("test" "spec" "^\\.*" "\\.*$"))
+    (setq base-name (replace-regexp-in-string pattern "" base-name)))
+  (and (my/prod-file-p prod-file)
+       (string-match-p (concat base-name "[^/]*\\." extension "$") prod-file)))
+
+(defun my/find-prod-or-test-file ()
+  "Find test file in the current Git repository."
+  (interactive)
+
+  (setq counsel--git-dir (locate-dominating-file
+                          default-directory ".git"))
+  (if (null counsel--git-dir)
+      (error "Not in a git repository")
+    (setq counsel--git-dir (expand-file-name
+                            counsel--git-dir))
+
+    (let* ((default-directory counsel--git-dir)
+           (files (split-string
+                   (shell-command-to-string counsel-git-cmd)
+                   "\n"
+                   t))
+           (base-name (file-name-sans-extension (file-name-nondirectory (buffer-file-name))))
+           (extension (file-name-extension (buffer-file-name)))
+           (predicate (if (my/prod-file-p (buffer-file-name)) #'my/matching-test-file-p #'my/matching-prod-file-p))
+           (results nil))
+
+      (dolist (file files)
+        (if (funcall predicate file base-name extension)
+            (cl-pushnew file results)))
+
+      (cl-case (length results)
+        (0 (message "No matching file found."))
+        (1 (find-file (car results)))
+        (t (ivy-read "Find test file" results
+                     :action #'counsel-git-action
+                     :caller 'counsel-git))))))
index 39b68dccd2d7503347d5fe012a968e7bfd0a9409..3cb9160b5bdce674e2f1eb0e5d243fdc013ba028 100644 (file)
@@ -18,6 +18,7 @@
 (global-set-key (kbd "C-x c") 'my/kill-buffers-not-in-frame)
 (global-set-key (kbd "C-x C-b") 'ibuffer)
 (global-set-key (kbd "C-x C-r") 'ivy-recentf)
+(global-set-key (kbd "C-x t") 'my/find-prod-or-test-file)
 (global-set-key (kbd "C-c g d") 'git-gutter:popup-hunk)
 (global-set-key (kbd "C-c g p") 'git-gutter:previous-hunk)
 (global-set-key (kbd "C-c g n") 'git-gutter:next-hunk)
diff --git a/snippets/emacs-lisp-mode/lexical b/snippets/emacs-lisp-mode/lexical
new file mode 100644 (file)
index 0000000..5bfd611
--- /dev/null
@@ -0,0 +1,4 @@
+# name: emacs-lisp-lexical
+# key: lexical
+# --
+;;; -*- lexical-binding: t -*-