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.
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.
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.
indent-region mapped to C-M-\ should do the trick.
Do indentation interactively.
Select the region to be indented.
C-x TAB.
Use arrows (<- and ->) to indent interactively.
Press Esc three times when you are done with the required indentation.
Copied from my post in: Indent several lines in Emacs
I've been using this function to handle my indenting and unindenting:
(defun unindent-dwim (&optional count-arg)
"Keeps relative spacing in the region. Unindents to the next multiple of the current tab-width"
(interactive)
(let ((deactivate-mark nil)
(beg (or (and mark-active (region-beginning)) (line-beginning-position)))
(end (or (and mark-active (region-end)) (line-end-position)))
(min-indentation)
(count (or count-arg 1)))
(save-excursion
(goto-char beg)
(while (< (point) end)
(add-to-list 'min-indentation (current-indentation))
(forward-line)))
(if (< 0 count)
(if (not (< 0 (apply 'min min-indentation)))
(error "Can't indent any more. Try `indent-rigidly` with a negative arg.")))
(if (> 0 count)
(indent-rigidly beg end (* (- 0 tab-width) count))
(let (
(indent-amount
(apply 'min (mapcar (lambda (x) (- 0 (mod x tab-width))) min-indentation))))
(indent-rigidly beg end (or
(and (< indent-amount 0) indent-amount)
(* (or count 1) (- 0 tab-width))))))))
And then I assign it to a keyboard shortcut:
(global-set-key (kbd "s-[") 'unindent-dwim)
(global-set-key (kbd "s-]") (lambda () (interactive) (unindent-dwim -1)))
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 ;) ).
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)
I do something like this universally
;; intent whole buffer
(defun iwb ()
"indent whole buffer"
(interactive)
;;(delete-trailing-whitespace)
(indent-region (point-min) (point-max) nil)
(untabify (point-min) (point-max)))
Related
I want to not use tabs in emacs, I would like to set it so that pressing the tab key inserts a set number of spaces based on the file type. For example, I would like pressing tab to insert 4 spaces when working on a python file. Here is my current .emacs file
(setq-default indent-tabs-mode nil)
(setq tab-width 4)
(setq tab-stop-list (number-sequence 4 200 4))
Currently, whenever I press tab, it only adds any spaces if it is what emacs deems a proper spot. For example, if i opened a python file and pressed tab, nothing would happen. However, if i typed "if:" and then hit tab on the next line, it would add 4 spaces. However, if i pressed tab again, it takes me back to the beginning of the line. I think I would just like to make it so that it adds a set number of spaces, plain and simple(unless someone can give me a good reason for why it's useful to have tab cycle through the line).
The main reason I want this is because I am working on a project where the commenting following a specific format involving the use of indentation based on sets of 4 spaces.
For example:
r"""
Return the value of the q-gamma function.
.. MATH::
qgamma(z,q) = \Gamma_q (z).
"""
So, for the line with "qgamma", I have to start it with 8 spaces, and I would like to be able to od that by pressing tab twice. However, emacs doesn't think this is a proper place to be able to tab twice, so whenever I press tab twice, it takes me back to the beginning of the line.
Thanks!
Edit: checking the major mode variable says that it is on python-mode.
If you're using the built in python.el, you can set indent-line-function to indent-relative instead of python-indent-line-function in python-mode-hook.
(defun jpk/python-mode-hook ()
(setq indent-line-function #'indent-relative))
(add-hook 'python-mode-hook #'jpk/python-mode-hook)
Each major mode has its own indentation function, pointed to by the indent-line-function variable. indent-relative is a very basic, generic indentation function, and is used for fundamental-mode (the most basic major mode).
Python is a bit weird in Emacs in that it has two widely used major modes, the built in python.el and third-party python-mode.el. Use whichever you want, but be aware of which you're using and which people are referring to in articles and SO answers.
M-x customize, search for py-tab-indent, toggle it off and Apply. I believe that's the behavior that you're looking for. Test it out and if so, Apply and Save the customization.
Noting, as #jpkotta pointed out, that the above is for python-mode.el, not the built-in python.el.
I am attempting to derive a new emacs mode from python.el (the current official gnu one) for Boo and I am having trouble with altering the indentation. Does anyone have any suggestions about how to best handle this? I do not need to change anything drastically, just add some new block forms and stuff.
For example, since this is for Boo, the try/except syntax uses "ensure" instead of "finally". I can change this easily enough in python.el by changing the block-start def of python-rx-constituents. However, I can't seem to be able to override this in a derived mode because python-rx-constituents is being then used by a macro, python-rx, and I guess once those two things are defined when python.el loads (as it has to, since I am deriving from it), I can no longer override it after-load or in a hook? Because I've definitely changed it in memory and in a hook after python.el loads and in an after-load statement and none of them work. While directly altering python.el works fine.
Here is the code in question from python.el:
(eval-when-compile
(defconst python-rx-constituents
`((block-start . ,(rx symbol-start
(or "def" "class" "if" "elif" "else" "try"
"except" "finally" "for" "while" "with"
)
symbol-end))
(decorator . ,(rx line-start (* space) ?# (any letter ?_)
(* (any word ?_))))
(defun . ,(rx symbol-start (or "def" "class") symbol-end))
(if-name-main . ,(rx line-start "if" (+ space) "__name__"
(+ space) "==" (+ space)
(any ?' ?\") "__main__" (any ?' ?\")
(* space) ?:))
(symbol-name . ,(rx (any letter ?_) (* (any word ?_))))
(open-paren . ,(rx (or "{" "[" "(")))
(close-paren . ,(rx (or "}" "]" ")")))
(simple-operator . ,(rx (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%)))
;; FIXME: rx should support (not simple-operator).
(not-simple-operator . ,(rx
(not
(any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))))
;; FIXME: Use regexp-opt.
(operator . ,(rx (or "+" "-" "/" "&" "^" "~" "|" "*" "<" ">"
"=" "%" "**" "//" "<<" ">>" "<=" "!="
"==" ">=" "is" "not")))
;; FIXME: Use regexp-opt.
(assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
">>=" "<<=" "&=" "^=" "|=")))
(string-delimiter . ,(rx (and
;; Match even number of backslashes.
(or (not (any ?\\ ?\' ?\")) point
;; Quotes might be preceded by a escaped quote.
(and (or (not (any ?\\)) point) ?\\
(* ?\\ ?\\) (any ?\' ?\")))
(* ?\\ ?\\)
;; Match single or triple quotes of any kind.
(group (or "\"" "\"\"\"" "'" "'''"))))))
"Additional Python specific sexps for `python-rx'")
(defmacro python-rx (&rest regexps)
"Python mode specialized rx macro.
This variant of `rx' supports common python named REGEXPS."
(let ((rx-constituents (append python-rx-constituents rx-constituents)))
(cond ((null regexps)
(error "No regexp"))
((cdr regexps)
(rx-to-string `(and ,#regexps) t))
(t
(rx-to-string (car regexps) t))))))
I would like to change python-rx-constituents so that block-start includes "ensure" instead of finally.
As commented already, employing derived-mode is not suitable here: you can't back-change a macro. Also re-defining it isn't recommendable: the order of loading/evaluation than will decide which one is in effect - at a larger scale that means running into a mess.
Copy the file, store as boo.el, replace the prefix by "boo-", reload and edit the stuff which needs changing.
Your concern expressed IMO isn't justified, as permitting copying, changing and re-release of the changed code is the core of the GPL.
Copying the file is a bad idea, indeed, since it makes it painful to track the evolution of python.el.
Deriving is not that great an idea either, since Boo isn't really an extension or a variation of Python, so you probably want to reuse some of its indentation machinery and some of its code to understand the significant-indentation, but not much more than that.
You might like to contact python.el's author (with Cc to emacs-devel) to see if python.el could be adjusted to make your life easier. e.g. maybe extract the common code to an auxiliary file that can be shared between the two. Ideally, this file might be usable for cofferscript-mode and maybe Haskell-mode as well.
I can't get the auto-indentations to work properly unless I use the automatic closing of braces, et al (which I don't like), and I see no option allowing one to skip over/out.
Eclipse has a configuration option for this, and Visual Studio doesn't auto-close everything by default, but rather formats the code block after manually entering the closing brace (which I rather prefer).
Surely there's something apart from going all the way over to the "End" key?
Edit / update:
As I consider it bad form to leave a question without a marked answer, would someone with more recent experience with PyCharm (I haven't used it in quite some time) weigh in with a recommendation for the best among the below solutions? Perhaps there's a newer configuration option or simple solution not yet listed?
Press Ctrl-Shift-Enter to close the missing braces on the current line (if any), add the missing colon (if missing) and put the caret into the correctly indented position on the next line.
Shift + Enter will jump past completions and drop you onto the next line.
Ctrl + ] will jump to the end of the current element.
This seems to work in most cases to skip past auto-completions. I find it the most versatile of the options.
Ctrl + [ will jump you to the start of whatever code block you are in.
As previously mentioned Ctrl + Shift + Enter will add any extra auto-completions you might need and drop onto a new line.
A college told me a solution:
First you type this:
def test_foo(
PyCharm inserts self) as soon as you type (
Current state: ^ indicates the cursor position:
def test_foo(self^):
Just type ): and hit ENTER, and you are on the next line.
Since I type with ten fingers Ctrl-Shift-Enter is not a solution for me in such common editing operations.
Why do you dislike the auto-closing brackets? They do not disturb anyone, see:
^ specifies the cursor position
method([a, {b: c^}])
behaves as if no brackets were there if you insert new brackets!
insert a '}':
method([a, {b: c}^])
now insert a ']':
method([a, {b: c}]^)
now insert a ')':
method([a, {b: c}])^
et voila! From a users point of view, if you typed blindly, you can not tell from what you see now if the auto-closing brackets were inserted or not.
Or simply: keep the closing brackets on. IntelliJ did a great work on a lot of small things we want to have intuitively.
I'm editing a Python file that uses two spaces for programmatic indents - I prefer 4 spaces. In my .vimrc I have the following settings related to indentation:
set tabstop=4 "Indentation levels every four columns
set expandtab "Convert all tabs typed to spaces
set shiftwidth=4 "Indent/outdent by four columns
set softtabstop=4
How do I get Vim to convert all the existing 2 space indents to be 4 space indents?
In other words:
if something:
dothis()
becomes
if something:
dothis()
When I tried gg=G
def check():
for a in list:
for b in list2:
check(a, b)
while (len > MAX) :
poll()
while(len(thelist) > 0) :
poll()
return results
became
def check():
for a in list:
for b in list2:
check(a, b)
while (len > MAX) :
poll()
while(len(thelist) > 0) :
poll()
return results
In order to double the number of spaces at the beginning of every line (and only at the beginning):
:%s/^\s*/&&/g
& in replacement pattern is the matched pattern.
Probably it will not have any side-effect for you.
Pressing gg=G is the command to re-indent everything in a file. If you have other elements that can be re-indented, vim will indent these as well, which doesn't always give the desired effects. You'll have to clean these up manually if they're ugly.
Alternately, you can use the > command to indent, with ranges to go through the file somewhat efficiently manually. 99>k, for example, would indent the 99 lines below the cursor by one level.
I've found the reindent script http://pypi.python.org/pypi/Reindent/0.1.0 works well for me. Not pure vim, but really easy!
After its installed you can use it in vim with
:%! reindent
(ie pipe the entire buffer through the reindent program) and it's done.
From the command line it can be used to reindent multiple files (eg all files in a directory, or even recursively down a directory tree).
The best current way to reformat Python, fix many other issues, and also make it PEP8 compliant is to use autopep8. See this related question. So after you've installed autopep8 (e.g. pip install autopep8) in vim you do:
:%! autopep8 -
There's also a vim-autopep8 plugin to make things even simpler.
try the following substitution command:
:%s/ / /g
(To clarify: there are two spaces between the first and second '/' and four the second and third '/'.)
One helpful command when working with whitespace issues is also the
set list
command which will visually show all whitespace. Use
set nolist to unset.
The vim plugin vim-autoformat integrates the formatter autopep8 into vim automatically, if it is installed. You can format the whole file, or the visually selected part using a single keystroke.
More importantly, vim-autoformat takes the relevant settings of your .vimrc into account, e.g. if you have
set shiftwidth=4
in your .vimrc, it will pass this information on to autopep8.
Have you tried?
:retab
I'm not in front of a machine with Vim at the moment so I can't verify this.
Normally when you hit tab on an empty line in emacs python mode it will cycle through the available tab indentations. When I hit tab when the point is at the deepest indent level I get the pabbrev buffer containing the last best match options. Does anyone else have this problem, is there an easy way around it without writing any elisp?
EDIT:
Trey, I want to keep pabbrev working in python mode not turn it off.
So lets say there are 2 indent levels, either none, or 1 level normally if it hit tab 3 times the first would put the point at 4 spaces in (or whatever indent is set to), the second back to 0 spaces, and the third back to 4 spaces.
With pabbrev mode on one indent puts the mark 4 spaces, the second brings up a buffer for autocomplete. This should not happen if there is no letters to the left of my point.
Does that make any more sense?
In light of the clarified requirements, you need something along the lines of this. I'm pretty sure you can't get away w/out writing some elisp. What's nice (IMO) is that this should work for all modes, not just python mode.
(defadvice pabbrev-expand-maybe (around pabbrev-expand-maybe-when-not-after-whitespace activate)
"prevent expansion when only whitespace between point and beginning of line"
(if (save-match-data
(save-excursion
(let ((p (point)))
(string-match "^\\s-*$" (buffer-substring-no-properties (progn (beginning-of-line) (point)) p)))))
(let ((last-command (if (eq last-command this-command) (pabbrev-get-previous-binding) last-command))
(this-command (pabbrev-get-previous-binding)))
(pabbrev-call-previous-tab-binding))
ad-do-it))
How is this for a late response?
This should work out of the box now, thanks to a patch from Trey. Binding tab in the way that pabbrev.el is somewhat naughty, but what are you to do if you want rapid expansion.
No elisp? Sure:
M-x pabbrev-mode
should toggle it off. But, if you don't mind cutting/pasting elisp, you can turn off pabbrev mode in python buffers:
(add-hook 'python-mode (lambda () (pabbrev-mode -1)))