-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpypath-1.0.el
93 lines (77 loc) · 3.25 KB
/
pypath-1.0.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
;;; pypath.el --- Get dotted path for Python defun -*- lexical-binding: t -*-
;; Copyright 2019 by Dave Pearson <[email protected]>
;; Author: Dave Pearson <[email protected]>
;; Version: 1.0
;; Keywords: languages
;; URL: https://github.com/davep/pypath.el
;; Package-Requires: ((emacs "25"))
;; 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 <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; pypath.el is a quick-and-dirty tool to help me find the dotted path/name
;; of the current defun in a Python file. It's mostly useful when I want to
;; test a very specific unit test when working on a Django application. It
;; also assumes that pipenv is the way to handle things.
;;
;; It's highly unlikely to be useful to anyone else.
;;; Code:
(require 'python)
(require 'subr-x)
(defun pypath--find-manage (path route)
"Look for manage.py.
PATH is where we've got left to look, and ROUTE is where we've
been. If manage.py is found the route to it will be returned."
(if (file-exists-p (string-join (append (reverse path) (list "manage.py")) "/"))
route
(when path
(pypath--find-manage (cdr path) (cons (car path) route)))))
(defun pypath--get-path ()
"Get the full dotted path for the current Python code.
As a side-effect, various environmental checks are done and if
there is a problem an `error' is thrown. Rules include:
- Current buffer must be in `python-mode'
- Current buffer must have a non-nil `buffer-file-name'
- `python-info-current-defun' must return a non-nil value"
(unless (derived-mode-p 'python-mode)
(error "This is only designed for use with `python-mode'"))
(unless (buffer-file-name)
(error "Buffer must be associated with an actual file"))
(let ((pyfun (python-info-current-defun)))
(unless pyfun
(error "No Python defun found around `point'"))
(let* ((path (reverse (split-string (buffer-file-name) "/")))
(module (file-name-sans-extension (pop path)))
(pyfun (string-join (append (pypath--find-manage path nil) (list module pyfun)) ".")))
pyfun)))
;;;###autoload
(defun pypath ()
"Get hold of the dotted path of the current Python function.
As well as displaying it with `message', the path is also placed
into the kill ring with `kill-new'."
(interactive)
(when-let ((pyfun (pypath--get-path)))
(kill-new pyfun)
(message "%s" pyfun)))
;;;###autoload
(defun pypath-django-test ()
"Get the full Django test command.
As well as displaying it with `message', the path is also placed
into the kill ring with `kill-new'."
(interactive)
(when-let ((pyfun (pypath--get-path))
(test (format "pipenv run ./manage.py test -v2 %s" pyfun)))
(kill-new test)
(message "%s" test)))
(provide 'pypath)
;;; pypath.el ends here