Skip to content

Commit

Permalink
211 Using autopep8 with emacs
Browse files Browse the repository at this point in the history
  • Loading branch information
id774 committed Jul 13, 2015
1 parent 4da6cb5 commit 1bfc196
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 2 deletions.
144 changes: 144 additions & 0 deletions 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 <paetzke@fastmail.fm>

;; Author: Friedrich Paetzke <paetzke@fastmail.fm>
;; 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
15 changes: 13 additions & 2 deletions emacs.d/elisp/python-mode-settings.el
Expand Up @@ -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 ()
Expand All @@ -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)
))))
))

0 comments on commit 1bfc196

Please sign in to comment.