import文からファイルに飛びたい。
探せばもっと良いものがあるのだろうけれど、とりあえず欲しくなったので書いた。
emacs-lispの正規表現に先読みは無かったかな?(正規表現に一部気になる嫌なところがある)
(まだ、手元の環境にとても依存しているかも。動かないかも)
;; (defmacro python-ex:and-let* ;; (bindings &rest body) ;; "imported from srfi-2" ;; (reduce (function ;; (lambda (binding r) ;; (let ((head (car binding))) ;; (cond ((and (atom head) (symbolp head)) ;; (\` (let ((\, binding)) (when (\, head) (\, r))))) ;; ((listp head) ;; (\` (when (\, head) (\, r)))) ;; (t (error "and-let*: invalid head %s" head)))))) ;; bindings ;; :from-end ;; t ;; :initial-value ;; (\` (progn (\,@ body))))) ;; (put 'python-ex:and-let* 'lisp-indent-function 1) (defvar python-ex:module-tokens-regexp "[^ .]+\\(\\.[^ .]+\\)*") (defun python-ex:module-tokens-in-current-line () "[maybe] return match object or nil" (save-excursion (let ((rx (format "^[ \t]*\\(from +\\(%s\\) +import +[^ ]+\\|import +\\(%s\\)\\)" python-ex:module-tokens-regexp python-ex:module-tokens-regexp ))) (goto-char (point-at-bol)) (and (re-search-forward rx (point-at-eol) t 1) (or (match-string-no-properties 4) (match-string-no-properties 2)))))) (defun python-ex:module->path (module &optional force-reload-p) (python-ex:let1 path (replace-regexp-in-string "\\." "/" module) (loop for dir in (python-ex:sys-path force-reload-p) for d = (concat dir "/" path) if (file-exists-p d) return d else for file = (concat d ".py") when (file-exists-p file) return file))) (defun python-ex:current-library-path () "[maybe] return current library path from import sentence" (and-let* ((module (python-ex:module-tokens-in-current-line))) (python-ex:module->path (python-ex:module-tokens-in-current-line)))) (defun python-ex:ffap/import-sentence (other-frame-p) (interactive "P") "ffap for import sentence" (and-let* ((path (python-ex:current-library-path))) (cond (other-frame-p (find-file-other-frame path)) (t (find-file path))))) (define-key python-mode-map "\C-c\C-f" 'python-ex:ffap/import-sentence)
利用
import文にカーソルを合わせてC-c C-fをすると、対応したファイルに飛ぶ。。。はず。
(virtualenvとか使っている場合は無理かも)
#!/usr/bin/env python from django.core.management import execute_manager ;;この行にカーソルを合わせてC-c C-f try: import settings # Assumed to be in the same directory. except ImportError: import sys sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) sys.exit(1) if __name__ == "__main__": execute_manager(settings)