diff --git a/emacs.d/elisp/3rd-party/py-autopep8.el b/emacs.d/elisp/3rd-party/py-autopep8.el new file mode 100644 index 0000000..04300ed --- /dev/null +++ b/emacs.d/elisp/3rd-party/py-autopep8.el @@ -0,0 +1,144 @@ +;;; py-autopep8.el --- Use autopep8 to beautify a Python buffer + +;; Copyright (C) 2013-2015, Friedrich Paetzke + +;; Author: Friedrich Paetzke +;; URL: http://paetzke.me/project/py-autopep8.el +;; Version: 0.6 + +;;; Commentary: + +;; Provides the `py-autopep8' command, which uses the external "autopep8" +;; tool to tidy up the current buffer according to Python's PEP8. + +;; To automatically apply when saving a python file, use the +;; following code: + +;; (add-hook 'before-save-hook 'py-autopep8-before-save) + +;; To customize the behaviour of "autopep8" you can set the +;; py-autopep8-options e.g. + +;; (setq py-autopep8-options '("--max-line-length=100")) + +;;; Code: + +(defgroup py-autopep8 nil + "Use autopep8 to beautify a Python buffer." + :group 'convenience + :prefix "py-autopep8-") + + +(defcustom py-autopep8-options nil + "Options used for autopep8. + +Note that `--in-place' is used by default." + :group 'py-autopep8 + :type '(repeat (string :tag "option"))) + + +(defun py-autopep8-apply-rcs-patch (patch-buffer) + "Apply an RCS-formatted diff from PATCH-BUFFER to the current buffer." + (let ((target-buffer (current-buffer)) + ;; Relative offset between buffer line numbers and line numbers + ;; in patch. + ;; + ;; Line numbers in the patch are based on the source file, so + ;; we have to keep an offset when making changes to the + ;; buffer. + ;; + ;; Appending lines decrements the offset (possibly making it + ;; negative), deleting lines increments it. This order + ;; simplifies the forward-line invocations. + (line-offset 0)) + (save-excursion + (with-current-buffer patch-buffer + (goto-char (point-min)) + (while (not (eobp)) + (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)") + (error "Invalid rcs patch or internal error in py-autopep8-apply-rcs-patch")) + (forward-line) + (let ((action (match-string 1)) + (from (string-to-number (match-string 2))) + (len (string-to-number (match-string 3)))) + (cond + ((equal action "a") + (let ((start (point))) + (forward-line len) + (let ((text (buffer-substring start (point)))) + (with-current-buffer target-buffer + (setq line-offset (- line-offset len)) + (goto-char (point-min)) + (forward-line (- from len line-offset)) + (insert text))))) + ((equal action "d") + (with-current-buffer target-buffer + (goto-char (point-min)) + (forward-line (- from line-offset 1)) + (setq line-offset (+ line-offset len)) + (kill-whole-line len))) + (t + (error "Invalid rcs patch or internal error in py-autopep8-apply-rcs-patch"))))))))) + + +(defun py-autopep8-execute () + (when (not (executable-find "autopep8")) + (error "\"autopep8\" command not found. Install autopep8 with \"pip install autopep8\"")) + (let ((tmpfile (make-temp-file "autopep8" nil ".py")) + (patchbuf (get-buffer-create "*autopep8 patch*")) + (errbuf (get-buffer-create "*autopep8 Errors*")) + (coding-system-for-read 'utf-8) + (coding-system-for-write 'utf-8)) + (with-current-buffer errbuf + (setq buffer-read-only nil) + (erase-buffer)) + (with-current-buffer patchbuf + (erase-buffer)) + (write-region nil nil tmpfile) + (if (zerop (apply 'call-process "autopep8" nil errbuf nil + (append py-autopep8-options `("--in-place" ,tmpfile)))) + (if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile)) + (progn + (kill-buffer errbuf) + (message "Buffer is already autopep8ed")) + (py-autopep8-apply-rcs-patch patchbuf) + (kill-buffer errbuf) + (message "Applied autopep8")) + (error "Could not apply autopep8. Check *autopep8 Errors* for details")) + (kill-buffer patchbuf) + (delete-file tmpfile))) + + +;;;###autoload +(defun py-autopep8 () + "Formats the current buffer according to the autopep8 tool." + (interactive) + (py-autopep8-execute)) + + +;;;###autoload +(defun py-autopep8-region (start end) + "Formats the code in region between START and END according to the autopep8 tool" + (interactive + (if (use-region-p) + (list (region-beginning) (region-end)) + (list (point) (point)))) + (let ((start-line (number-to-string (count-lines (point-min) start))) + (end-line (number-to-string (count-lines (point-min) end)))) + (setq py-autopep8-options (append py-autopep8-options (list "--range" start-line end-line))) + (py-autopep8-execute))) + + +;;;###autoload +(defun py-autopep8-before-save () + "Pre-save hooked to bse used before running py-autopep8." + (interactive) + (when (eq major-mode 'python-mode) + (condition-case err (py-autopep8) + (error (message "%s" (error-message-string err)))))) + + +(provide 'py-autopep8) + + +;;; py-autopep8.el ends here diff --git a/emacs.d/elisp/python-mode-settings.el b/emacs.d/elisp/python-mode-settings.el index 19322a9..b7996b8 100644 --- a/emacs.d/elisp/python-mode-settings.el +++ b/emacs.d/elisp/python-mode-settings.el @@ -4,13 +4,20 @@ ;; Python Path (setq python-shell-interpreter "/opt/python/current/bin/python") +;; for executable-find +(setq exec-path (cons (expand-file-name "/opt/python/current/bin") exec-path)) + ;; python-mode (cond ((< emacs-major-version '24) (progn (setq python-mode-hook (function (lambda () - (local-set-key "\C-c\ p" 'python-pep8)))) + (local-set-key "\C-c\ p" 'python-pep8) + (require 'py-autopep8) + (define-key python-mode-map (kbd "C-c F") 'py-autopep8) ; バッファ全体のコード整形 + (define-key python-mode-map (kbd "C-c f") 'py-autopep8-region) ; 選択リジョン内のコード整形 + ))) (add-hook 'python-mode-hook 'flymake-find-file-hook) (when (load "flymake" t) (defun flymake-pyflakes-init () @@ -27,5 +34,9 @@ (progn (setq python-mode-hook (function (lambda () - (local-set-key "\C-c\ p" 'python-pep8))))) + (local-set-key "\C-c\ p" 'python-pep8) + (require 'py-autopep8) + (define-key python-mode-map (kbd "C-c F") 'py-autopep8) + (define-key python-mode-map (kbd "C-c f") 'py-autopep8-region) + )))) ))