X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=python%2Finit_python.el;h=4c71a2dbaee10a8ef5a80a7de428aa9f2bad734e;hb=a13a166794e1e6f22407e13110fe83b9cb095ab8;hp=38131c7e725db8b717c9ee60771b76111281e897;hpb=61cf5b5991669543f8710999aedd1d6b69972ae5;p=emacs-init.git diff --git a/python/init_python.el b/python/init_python.el index 38131c7..4c71a2d 100644 --- a/python/init_python.el +++ b/python/init_python.el @@ -1,17 +1,14 @@ -(autoload 'python-mode "python-mode" "Python Mode." t) -(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) -(add-to-list 'interpreter-mode-alist '("python" . python-mode)) -(require 'python-mode) -(add-hook 'python-mode-hook - (lambda () - (set-variable 'py-indent-offset 4) - ;(set-variable 'py-smart-indentation nil) - (set-variable 'indent-tabs-mode nil) - (define-key py-mode-map (kbd "RET") 'newline-and-indent) - ;(define-key py-mode-map [tab] 'yas/expand) - ;(setq yas/after-exit-snippet-hook 'indent-according-to-mode) - (smart-operator-mode-on) - )) +;(autoload 'python-mode "python-mode" "Python Mode." t) +;(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) +;(add-to-list 'interpreter-mode-alist '("python" . python-mode)) +;(require 'python-mode) +;(provide 'python) +;(provide 'python21) + +(global-unset-key "\C-xpn") + +(require 'python) + ;; pymacs (autoload 'pymacs-apply "pymacs") (autoload 'pymacs-call "pymacs") @@ -22,6 +19,211 @@ ;; '(add-to-list 'pymacs-load-path YOUR-PYMACS-DIRECTORY")) (pymacs-load "ropemacs" "rope-") (setq ropemacs-enable-autoimport t) + +;; M-/ rope-code-assist +;; C-c g rope-goto-definition +;; C-c d rope-show-doc +;; C-c f rope-find-occurrences +;; M-? rope-lucky-assist + +(define-key ropemacs-local-keymap "\M-/" 'hippie-expand) + +(defun write-file-py-cleanup-imports () + (save-excursion + (condition-case nil + (py-cleanup-imports t) + (error . nil))) + nil) + +(defun python-init-auto-cleanup-imports-on-save () + (add-hook 'write-contents-functions 'write-file-py-cleanup-imports nil t)) + +(defun my-flymake-error-at-point () + (condition-case nil + (flymake-ler-text (car (nth 0 (flymake-find-err-info flymake-err-info + (locate-current-line-number))))) + (error (error "no flymake error at point")))) + +(defun my-flymake-show-error () + (interactive) + (message (my-flymake-error-at-point))) + +(defun my-pyflymake-add-import-from-error () + (interactive) + (let ((err (my-flymake-error-at-point))) + (if (string-match "undefined name '\\(.*\\)'" err) + (py-add-import (match-string 1 err)) + (error "no missing symbol at point")))) + +(defun py-add-import (import) + (interactive "sModule to import: ") + (save-window-excursion + (save-excursion + (goto-char (car (py-imports-region))) + (insert "import " import "\n") + (py-cleanup-imports t) + (sit-for 2)))) + +(defun my-flymake-check-and-wait () + (if (boundp flymake-is-running) + (progn + (while flymake-is-running (sit-for .1)) + (flymake-start-syntax-check) + (while flymake-is-running (sit-for .1))))) + +(defun my-flymake-goto-next-error () + (interactive) + (my-flymake-check-and-wait) + (flymake-goto-next-error) + (my-flymake-show-error)) + +(defun my-flymake-goto-prev-error () + (interactive) + (my-flymake-check-and-wait) + (flymake-goto-prev-error) + (my-flymake-show-error)) + +(defun py-find-file (errormark filename defaultdir) + (let ((fullname (expand-file-name filename defaultdir))) + (or (and (not (file-exists-p fullname)) + (let* ((name (loop for name = fullname then (directory-file-name + (file-name-directory name)) + if (file-exists-p name) return name)) + (fmt (and name (with-temp-buffer + (insert-file-contents name nil 0 1024 t) (archive-find-type)))) + (tail (and fmt (substring fullname (1+ (length name)))))) + (if fmt + (with-current-buffer (find-file-noselect name) + (goto-char (point-min)) + (re-search-forward (concat " " (regexp-quote tail) "$")) + (save-window-excursion + (archive-extract) + (current-buffer)))))) + (compilation-find-file errormark filename defaultdir)))) + +(require 'arc-mode) + +(defun py-eshell-goto-error (&optional back) + (interactive "P") + (display-buffer "*eshell*" t) + (let (here end start dir file line errmk example) + (with-current-buffer "*eshell*" + (save-excursion + ;; Find and validate last traceback + (goto-char (point-max)) + (re-search-backward "^\\(.*\\)Traceback \\|^Failed example:") + (beginning-of-line) + (if (looking-at "Failed example:") + (progn + (forward-line -2) + (setq example t))) + (if (or (not (and (boundp 'py-eshell-last-error) + (boundp 'py-eshell-last-point))) + (null py-eshell-last-error) + (null py-eshell-last-point) + (null py-eshell-last-dir) + (not (= py-eshell-last-error (point)))) + (progn + (set (make-local-variable 'py-eshell-last-error) (point)) + (set (make-local-variable 'py-eshell-prefix) (or (match-string 1) "")) + (if (string-match "Original $" py-eshell-prefix) + (setq py-eshell-prefix (substring py-eshell-prefix 0 (match-beginning 0)))) + (if example + (forward-line 2) + (while (and (< (forward-line 1) 1) (looking-at (concat py-eshell-prefix " "))))) + (set (make-local-variable 'py-eshell-last-point) (point)) + (set (make-local-variable 'py-eshell-last-dir) default-directory) + (while + (and (< (forward-line 1) 1) + (not (if (looking-at ".*Leaving directory ") + (progn + (goto-char (match-end 0)) + (skip-chars-forward "'\"`") + (let ((dir (current-word))) + (and dir (setq py-eshell-last-dir + (file-name-as-directory dir))))))))))) + (goto-char py-eshell-last-point) + + ;; Nove to next / prev frame in traceback + (if back + (progn + (while (and (looking-at (concat py-eshell-prefix " ")) + (< (forward-line 1) 1) + (not (looking-at (concat py-eshell-prefix " File "))))) + (setq start (point)) + (while (and (looking-at (concat py-eshell-prefix " ")) + (< (forward-line 1) 1) + (not (looking-at (concat py-eshell-prefix " File "))))) + (setq end (point))) + (while (and (> (forward-line -1) -1) + (not (looking-at (concat py-eshell-prefix (if example "File " " File ")))) + (> (point) py-eshell-last-error))) + (setq end py-eshell-last-point start (point))) + + ;; Parse information and set overlay + (if (save-excursion (goto-char start) (setq errmk (point-marker)) + (looking-at (concat py-eshell-prefix (if example "File " " File ")))) + (let ((default-directory py-eshell-last-dir)) + (set (make-local-variable 'py-eshell-last-point) start) + (if (and (boundp 'py-eshell-overlay) py-eshell-overlay) + (move-overlay py-eshell-overlay start end) + (set (make-local-variable 'py-eshell-overlay) (make-overlay start end)) + (overlay-put py-eshell-overlay 'face 'highlight)) + (save-excursion + (goto-char start) + (forward-char (+ (length py-eshell-prefix) 7)) + (skip-chars-forward "\"") + (setq file (current-word)) + (search-forward " line ") + (skip-chars-forward " ") + (setq line (string-to-number + (buffer-substring-no-properties + (point) (progn (skip-chars-forward "0-9") (point))))) + (setq dir default-directory)) + (if (null file) + (error "File not found"))) + (py-eshell-error-reset) + (error "No further traceback line")))) + + ;; move to error locus + (if (and file line errmk) + (with-current-buffer (py-find-file errmk file dir) + (compilation-goto-locus errmk (save-excursion (goto-line line) (point-marker)) nil))))) + +(defun py-eshell-error-reset () + (interactive) + (save-excursion + (set-buffer "*eshell*") + (if (and (boundp 'py-eshell-overlay) py-eshell-overlay) + (delete-overlay py-eshell-overlay)) + (set (make-local-variable 'py-eshell-last-error) nil) + (set (make-local-variable 'py-eshell-last-point) nil) + (set (make-local-variable 'py-eshell-last-dir) nil) + (set (make-local-variable 'py-eshell-prefix) nil) + (set (make-local-variable 'py-eshell-overlay) nil))) + +(global-set-key "\C-xP" 'py-eshell-goto-error) +(global-set-key "\C-x\C-p" 'python-shell) + +(add-hook 'python-mode-hook 'python-init-auto-cleanup-imports-on-save) + +(defun py-setup-hook () + ;(set-variable 'py-indent-offset 4) + ;(set-variable 'py-smart-indentation nil) + (set-variable 'indent-tabs-mode nil) + ;(define-key py-mode-map (kbd "RET") 'newline-and-indent) + ;(define-key py-mode-map [tab] 'yas/expand) + ;(setq yas/after-exit-snippet-hook 'indent-according-to-mode) + ;(smart-operator-mode-on) + (define-key python-mode-map "\C-ci" 'my-pyflymake-add-import-from-error) + (define-key python-mode-map "\C-ce" 'my-flymake-show-error) + (define-key python-mode-map "\C-cn" 'my-flymake-goto-next-error) + (define-key python-mode-map "\C-cp" 'my-flymake-goto-prev-error) + (define-key python-mode-map "\C-cI" 'py-cleanup-imports) +) + +(add-hook 'python-mode-hook 'py-setup-hook) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Auto-completion ;;; Integrates: @@ -29,67 +231,69 @@ ;;; 2) Yasnippet ;;; all with AutoComplete.el ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defun prefix-list-elements (list prefix) - (let (value) - (nreverse - (dolist (element list value) - (setq value (cons (format "%s%s" prefix element) value)))))) -(defvar ac-source-rope - '((candidates - . (lambda () - (prefix-list-elements (rope-completions) ac-target)))) - "Source for Rope") -(defun ac-python-find () - "Python `ac-find-function'." - (require 'thingatpt) - (let ((symbol (car-safe (bounds-of-thing-at-point 'symbol)))) - (if (null symbol) +(if nil + (defun prefix-list-elements (list prefix) + (let (value) + (nreverse + (dolist (element list value) + (setq value (cons (format "%s%s" prefix element) value)))))) + (defvar ac-source-rope + '((candidates + . (lambda () + (prefix-list-elements (rope-completions) ac-target)))) + "Source for Rope") + (defun ac-python-find () + "Python `ac-find-function'." + (require 'thingatpt) + (let ((symbol (car-safe (bounds-of-thing-at-point 'symbol)))) + (if (null symbol) (if (string= "." (buffer-substring (- (point) 1) (point))) - (point) + (point) nil) - symbol))) -(defun ac-python-candidate () - "Python `ac-candidates-function'" - (let (candidates) - (dolist (source ac-sources) - (if (symbolp source) + symbol))) + (defun ac-python-candidate () + "Python `ac-candidates-function'" + (let (candidates) + (dolist (source ac-sources) + (if (symbolp source) (setq source (symbol-value source))) - (let* ((ac-limit (or (cdr-safe (assq 'limit source)) ac-limit)) - (requires (cdr-safe (assq 'requires source))) - cand) - (if (or (null requires) - (>= (length ac-target) requires)) + (let* ((ac-limit (or (cdr-safe (assq 'limit source)) ac-limit)) + (requires (cdr-safe (assq 'requires source))) + cand) + (if (or (null requires) + (>= (length ac-target) requires)) (setq cand (delq nil (mapcar (lambda (candidate) (propertize candidate 'source source)) (funcall (cdr (assq 'candidates source))))))) - (if (and (> ac-limit 1) - (> (length cand) ac-limit)) + (if (and (> ac-limit 1) + (> (length cand) ac-limit)) (setcdr (nthcdr (1- ac-limit) cand) nil)) - (setq candidates (append candidates cand)))) - (delete-dups candidates))) -(add-hook 'python-mode-hook - (lambda () - (auto-complete-mode 1) - (set (make-local-variable 'ac-sources) - (append ac-sources '(ac-source-rope) '(ac-source-yasnippet))) - (set (make-local-variable 'ac-find-function) 'ac-python-find) - (set (make-local-variable 'ac-candidate-function) 'ac-python-candidate) - (set (make-local-variable 'ac-auto-start) nil))) -;;Ryan's python specific tab completion -(defun ryan-python-tab () - ; Try the following: - ; 1) Do a yasnippet expansion - ; 2) Do a Rope code completion - ; 3) Do an indent - (interactive) - (if (eql (ac-start) 0) + (setq candidates (append candidates cand)))) + (delete-dups candidates))) + (add-hook 'python-mode-hook + (lambda () + (auto-complete-mode 1) + (set (make-local-variable 'ac-sources) + (append ac-sources '(ac-source-rope) '(ac-source-yasnippet))) + (set (make-local-variable 'ac-find-function) 'ac-python-find) + (set (make-local-variable 'ac-candidate-function) 'ac-python-candidate) + (set (make-local-variable 'ac-auto-start) nil))) + ;;Ryan's python specific tab completion + (defun ryan-python-tab () + ; Try the following: + ; 1) Do a yasnippet expansion + ; 2) Do a Rope code completion + ; 3) Do an indent + (interactive) + (if (eql (ac-start) 0) (indent-for-tab-command))) -(defadvice ac-start (before advice-turn-on-auto-start activate) - (set (make-local-variable 'ac-auto-start) t)) -(defadvice ac-cleanup (after advice-turn-off-auto-start activate) - (set (make-local-variable 'ac-auto-start) nil)) + (defadvice ac-start (before advice-turn-on-auto-start activate) + (set (make-local-variable 'ac-auto-start) t)) + (defadvice ac-cleanup (after advice-turn-off-auto-start activate) + (set (make-local-variable 'ac-auto-start) nil)) + ) ;(define-key py-mode-map "\t" 'ryan-python-tab) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; End Auto Completion @@ -102,28 +306,57 @@ (local-file (file-relative-name temp-file (file-name-directory buffer-file-name)))) + (message "flymake init pyflakes %s" local-file) (list "pyflakes" (list local-file)))) (add-to-list 'flymake-allowed-file-name-masks '("\\.py\\'" flymake-pyflakes-init))) -(add-hook 'find-file-hook 'flymake-find-file-hook) -(defun py-cleanup-imports () +(defun safer-flymake-find-file-hook () + "Don't barf if we can't open this flymake file" + (let ((flymake-filename + (flymake-create-temp-inplace (buffer-file-name) "flymake"))) + (if (file-writable-p flymake-filename) + (flymake-find-file-hook) + (message + (format + "Couldn't enable flymake; permission denied on %s" flymake-filename))))) +(add-hook 'find-file-hook 'safer-flymake-find-file-hook) + +(defun py-skip-few-lines (&optional count) + (if (null count) (setq count 3)) + (let ((blanks 0)) + (while + (and (or (when (eolp) (setq count 0) (incf blanks) t) + (when (> count 0) (decf count) t)) + (< (forward-line 1) 1))) + (> blanks 0))) + +(defun py-imports-region () + (save-excursion + (goto-char (point-min)) + (while (and (re-search-forward "^\\(import\\s-+\\|from\\s-+\\)" nil t) + (looking-at "__future__"))) + (beginning-of-line) + (setq beg (point)) + (while (and (py-skip-few-lines) + (looking-at "import\\s-+\\|from\\s-+")) + (setq beg (point))) + (if (not (looking-at "\\(import\\s-+\\|from\\s-+\\)")) + (cons beg beg) + (while (looking-at "\\(import\\s-+\\|from\\s-+\\)") + (forward-line 1)) + (cons beg (point))))) + +(defun py-cleanup-imports (&optional nowait) (interactive) (let (beg end) (if (region-active-p) (setq beg (region-beginning) end (region-end)) - (save-excursion - (goto-char (point-min)) - (while (and (re-search-forward "^\\(import\\s-+\\|from\\s-+\\)" nil t) - (looking-at "__future__"))) - (beginning-of-line) - (if (not (looking-at "\\(import\\s-+\\|from\\s-+\\)")) - (error "No imports found")) - (setq beg (point)) - (while (looking-at "\\(import\\s-+\\|from\\s-+\\)") - (forward-line 1)) - (setq end (point)))) + (setq reg (py-imports-region)) + (if (= (car reg) (cdr reg)) + (error "No imports found")) + (setq beg (car reg) end (cdr reg))) (sort-lines t beg end) (goto-char beg) (let ((end-marker (make-marker)) @@ -150,11 +383,9 @@ (insert "\n" prefix)) (forward-line 1))) (sort-lines nil b (point)) - (if (boundp flymake-is-running) + (if (and (not nowait) (boundp flymake-is-running)) (progn - (while flymake-is-running (sit-for .1)) - (flymake-start-syntax-check) - (while flymake-is-running (sit-for .1)) + (my-flymake-check-and-wait) (goto-char beg) (while (< (point) end-marker) (if (and (loop for ov in (overlays-at (point)) @@ -192,5 +423,3 @@ is ignored (Those are the file local variables and local words)." (flyspell-mode t)) (provide 'init_python) - -