4

I'm a recent convert from vim to emacs (spacemacs). Spacemacs comes with yapf as the standard code reformatter tool for python. I find autopep8 to work better on python code when the code is broken. I can't figure out how to make autopep8 reformat a selected region, rather than an entire buffer. In vim this is equivalent to running gq function on a selection or an object. How do we do that in emacs/spacemacs?

Meitham
  • 9,178
  • 5
  • 34
  • 45

1 Answers1

1

I don't know how you're invoking autopep8, but this particular wrapper already works with the region or marks the current function: https://gist.github.com/whirm/6122031

Save the gist anywhere you keep personal elisp code, such as ~/elisp/autopep8.el.

In .emacs ensure your lisp directory is on the load path, load the file, and override the key binding:

(add-to-list 'load-path "~/elisp") ; or wherever you saved the elisp file
(require 'autopep8)
(define-key evil-normal-state-map "gq" 'autopep8)

The version in the gist defaults to formatting the current function if no region is active. To default to the whole buffer, rewrite the autopep8 function in the file like this:

(defun autopep8 (begin end)
  "Beautify a region of python using autopep8"
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (list (point-min) (point-max))))
  (save-excursion
    (shell-command-on-region begin end
                             (concat "python "
                                     autopep8-path
                                     autopep8-args)
                             nil t))))

The above setup assumes you are starting from scratch with autopep8 in Emacs. If you already have autopep8 in Emacs from some other package that almost does what you want, the ultimate answer to how to customize that will depend on where the code is coming from and what arguments and variables it supports. Type C-h f autopep8 to view the help for an existing function.

For example, if an existing autopep8 function takes arguments for the region to format, then you could use the interactive region and point logic from the code above and define a new function that wraps the existing function on your system.

(define-key evil-normal-state-map "gq" 'autopep8-x)
(defun autopep8-x (begin end)
  "Wraps autopep8 from ??? to format the region or the whole buffer."
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (list (point-min) (point-max))))
  (autopep8 begin end)) ; assuming an existing autopep8 function taking
                        ; region arguments but not defaulting to the
                        ; whole buffer itself

That snippet could all go in .emacs or wherever you keep your customizations.

Shawn Hoover
  • 726
  • 8
  • 9
  • Could you please expand your answer to include where this function should go under .emacs.d/ and how it should replace existing keybinding evil ``gq`` for format-region. – Meitham Dec 10 '15 at 10:31
  • The easiest thing is to put it in your ~/.emacs.d/init.el (or ~/.emacs if you use that). If you want to put it in a separate file, it's recommended to put it in ~/.emacs.d/lisp/ or some other subdirectory rather than in ~/.emacs.d/ directly (don't forget to add it to load-path). As far as rebinding, I don't know evil-mode, but this looks promising: http://stackoverflow.com/questions/19483278/bind-emacs-evil-window-commands-to-g-prefix. – jpkotta Dec 10 '15 at 19:33