Emacs bulk indent for Python
Solution 1
If you are programming Python using Emacs, then you should probably be using python-mode. With python-mode, after marking the block of code,
C-c >
or C-c C-l
shifts the region 4 spaces to the right
C-c <
or C-c C-r
shifts the region 4 spaces to the left
If you need to shift code by two levels of indention, or some arbitary amount you can prefix the command with an argument:
C-u 8 C-c >
shifts the region 8 spaces to the right
C-u 8 C-c <
shifts the region 8 spaces to the left
Another alternative is to use M-x indent-rigidly
which is bound to C-x TAB
:
C-u 8 C-x TAB
shifts the region 8 spaces to the right
C-u -8 C-x TAB
shifts the region 8 spaces to the left
Also useful are the rectangle commands that operate on rectangles of text instead of lines of text.
For example, after marking a rectangular region,
C-x r o
inserts blank space to fill the rectangular region (effectively shifting code to the right)
C-x r k
kills the rectangular region (effectively shifting code to the left)
C-x r t
prompts for a string to replace the rectangle with. Entering C-u 8 <space>
will then enter 8 spaces.
PS. With Ubuntu, to make python-mode the default mode for all .py files, simply install the python-mode
package.
Solution 2
In addition to indent-region
, which is mapped to C-M-\
by default, the rectangle edit commands are very useful for Python. Mark a region as normal, then:
-
C-x r t
(string-rectangle
): will prompt you for characters you'd like to insert into each line; great for inserting a certain number of spaces -
C-x r k
(kill-rectangle
): remove a rectangle region; great for removing indentation
You can also C-x r y
(yank-rectangle
), but that's only rarely useful.
Solution 3
indent-region
mapped to C-M-\
should do the trick.
Solution 4
I'm an Emacs newb, so this answer it probably bordering on useless.
None of the answers mentioned so far cover re-indentation of literals like dict
or list
. E.g. M-x indent-region
or M-x python-indent-shift-right
and company aren't going to help if you've cut-and-pasted the following literal and need it to be re-indented sensibly:
foo = {
'bar' : [
1,
2,
3 ],
'baz' : {
'asdf' : {
'banana' : 1,
'apple' : 2 } } }
It feels like M-x indent-region
should do something sensibly in python-mode
, but that's not (yet) the case.
For the specific case where your literals are bracketed, using TAB on the lines in question gets what you want (because whitespace doesn't play a role).
So what I've been doing in such cases is quickly recording a keyboard macro like <f3> C-n TAB <f4>
as in F3, Ctrl-n (or down arrow), TAB, F4, and then using F4 repeatedly to apply the macro can save a couple of keystrokes. Or you can do C-u 10 C-x e
to apply it 10 times.
(I know it doesn't sound like much, but try re-indenting 100 lines of garbage literal without missing down-arrow, and then having to go up 5 lines and repeat things ;) ).
Solution 5
I use the following snippet. On tab when the selection is inactive, it indents the current line (as it normally does); when the selection is inactive, it indents the whole region to the right.
(defun my-python-tab-command (&optional _)
"If the region is active, shift to the right; otherwise, indent current line."
(interactive)
(if (not (region-active-p))
(indent-for-tab-command)
(let ((lo (min (region-beginning) (region-end)))
(hi (max (region-beginning) (region-end))))
(goto-char lo)
(beginning-of-line)
(set-mark (point))
(goto-char hi)
(end-of-line)
(python-indent-shift-right (mark) (point)))))
(define-key python-mode-map [remap indent-for-tab-command] 'my-python-tab-command)
Vernon
Updated on September 01, 2020Comments
-
Vernon over 3 years
Working with Python in Emacs if I want to add a try/except to a block of code, I often find that I am having to indent the whole block, line by line. In Emacs, how do you indent the whole block at once.
I am not an experienced Emacs user, but just find it is the best tool for working through ssh. I am using Emacs on the command line(Ubuntu), not as a gui, if that makes any difference.
-
Vernon about 14 yearsThanks that works perfectly. with Emacs22 isn't python-mode automatically enabled with all .py files? Anyway, the C-c > works just fine.
-
unutbu about 14 years@Vernon:
C-c >
is defined in python-mode.el, so I think you must have installed thepython-mode
package somewhere along the way. Glad it works for you. -
Daniel Stutzbach about 14 yearsSince whitespace is part of the syntax in Python, indent-region on the whole file is a bad idea.
-
codeasone over 13 yearsC-c > works fine in Emacs 23.2 without installing python-mode as it works with the provided python.el
-
unutbu over 13 years@landstatic: Thanks for the information. That makes me think perhaps all the commands listed above work the same for python-mode.el or python.el?
-
rkachach over 8 yearsJust to add that the C-c > and C-c > are also bind to C-c C-l and C-C-c C-r (left and right). IMHO these are much easier to type. Please, could you update the answer the reflect this? (thanks)
-
unutbu over 8 years@redobot:
C-c C-l
andC-c C-r
must be custom bindings you've set up yourself. If you runemacs -q
(to run emacs without loading an init file) you'll see there is no binding forC-c C-l
orC-c C-r
in Python mode. -
rkachach over 8 yearsNo, probably hey are only available in the latest version of the mode. If you take a look to the file github.com/emacsmirror/python-mode/blob/master/python-mode.el you can find them (just look for py-shift-left and py-shift-right)
-
Sam Clearman over 8 yearsThis is terrible advice. Python indentation cannot be inferred (since it is syntax!) so ident-region is useless.
-
stanri over 7 yearsAs an aside, emacs is my editor of choice for python code purely because of python-mode. I've never encountered a indent syntax error using it.
-
alper over 3 yearsCan I do
C-c <
and<
followed by<
to continue indention? @unutbu