How to make Tab insert a set number of Spaces in Emacs - python

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.

Related

how to indent block of python code without using tabs

I am just learning python and need to know how to indent a block of code without using the tab button (because, as I have read, tab should not be used).
Example:
in a simple print function
def test(string):
print(string)
print("'" + string + "'")
test('test')
IF now, I want to put the print functions in an if statement
def test(string):
if len(string) > 2:
print(string)
print("'" + string + "'")
test('test')
How can I indent the two print statements without using the 'tab', or having to click on every line and insert 4 spaces? I am very used to selecting all the lines I need to move to the right and pressing tab regardless of program (geany, ipython, notepad++).
I would like to set off following the PEP8 style guide from the introduction into Python.
My concern is not this particular example, but if I have a code block I want to move left or right that is many more lines.
Thanks,
Ivan
It depends on what text editor you're using. I use Notepad++, which is one of the ones you mention, and it has an option to use spaces in place of tabs. So I just enable that for .py files, then I can indent a block by hitting tab exactly as you're used to (and unindent with shift-tab).
Go to settings > preferences > tab settings, select "python" from the list on the right and check the "replace by space" checkbox. Other text editors that offer the same feature will presumably each have their own way of enabling it, and their own way of making it language-specific.
Be aware that pressing tab to change the indentation of a selection is just a UI convention, albeit a common one. It doesn't work for example in Notepad, where hitting tab while text is highlighted behaves the same as typing anything else: replaces the selection with a tab. If you were using Notepad then I'm pretty sure the answer would be "it's not possible". If you use lots of different editors then I think unfortunately you're going to have to investigate each one in turn.
As you have mentioned, PEP8 recommends four spaces for each level of indentation. Many text editors allow you to set tabs to be replaced by a certain number of spaces. So in many cases it is still ok to use tab to program in python, just make sure that it is replaced by four spaces.
I personally use Sublime Text and there seems to be an option to customize Tabs:
{
"tab_size": 4,
"translate_tabs_to_spaces": true
}
In the Packages/User/Preferences.sublime-settings. Maybe worth trying that.

Python indentation borked

I saw that there are similar titles to this. But my case seems a little weirder. I somehow used a mixture of PyCharm and Vim (and within Vim I have tabstop=4 and shiftwidth=2), and my Python code seems un-fixabl-y borked, indentation-wise. I first saw that in Vim everything was mis-aligned, so I re-aligned everything; but then when I run it I get an error that there's an unexpected indentation, even though in Vim everything seems perfectly aligned. Here's an example (this is how it looks like in Vim):
for f in files:
for line in f:
items = line.strip().split()
items = items[2:]
items = ' '.join(items).split(', ')
When I run it, I get:
File "getEsSynonymLSAVectors.py", line 136
items = items[2:]
^
IndentationError: unexpected indent
I used PythonTidy, I used reindent, I tried :retab, I tried manual re-aligning - nothing seems to fix this. Any experiences/ advice will be appreciated.
Python treated a tab as 8 spaces by default, if you get indentation borked, you'll generally want to switch the tabs to spaces (or vice versa, but I generally find that spaces are easier to deal with). So make sure to set vim to show tab as 8 spaces wide (:set ts=8), to see what python sees.
To fix tab errors in vim, I usually do the following, first I need to be able to see the tabs, so I enabled highlight search (:set hlsearch) and search for tabs (/\t). Then I eyeball the areas that needs to be retabbed. Next, I try to find the right vim tab width setting for the file (:set ts=n and vary n until everything looks good), enable expand tab (:set et), then run the automatic tab fixing (:retab). When all else fail, retab manually.
If you're using version control, make sure to diff with the files before the changes and manually check that you didn't introduce a bug because of unintentional changes in the indentation level. If you don't use version control, keep a backup and run diff on the files.
Try something like this.
First set appropriate settings.
Always use 4 spaces. So change it to tabs = 4 spaces.
First convert all spaces to tabs.
And then convert all tabs to spaces.
(I use Geany)
It has worked for me before many times.

Reformat a Python file to have 4 space indentations

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.

Emacs 23 built-in python.el indentation broken using tabs with width 4

I've been using the version of python.el found here for a couple of years in Emacs 23 without incident. I decided to try the stock python.el, and ran into a strange issue:
When using tabs for indentation and a tab width of 4, the stock python.el will indent two tab characters for every level instead of 1. With a tab width of 5, the indentation will be 1 tab plus 3 spaces. So, when indent-tabs-mode is t, indent-for-tab-command seems to always force a tab size of 8, regardless of what tab-width is set to.
Is there some other tab-related variable I can set to override this behavior?
I think I've figured this out after digging through the source code for the stock Emacs 23 python.el and the newest python.el on the block.
Given these settings in a python-mode buffer, indentation with tabs and a tab-width of 4 works as expected in stock python.el:
(setq indent-tabs-mode t
tab-width 4
python-indent 4)
For the new python.el, you need to change python-indent to python-indent-offset. I'm using both settings for both modes without issue.
If someone has a better solution to this problem, please add it and I'll gladly accept it as the correct answer.
stuck using tabs? check
trying out emacs 23 with python.el? check
I've run into the same wall as you recently... what I've learned is that I truly hate tabs and that I find python's whitespace significance incredibly annoying.
Are you setting tab-width in your init or with customize?
I had to make sure to change tab-width in the "Editing Basics" section via customize to get "4 space" tabs to stick (something to do with global/local scope). But the fun doesn't end there... python.el seems to only want to indent to the first tab-stop (column 4 now) and no further no matter what I set indent-tab-mode or tab-always-indent to. I finally gave up and went back to using python-mode.el, which has it's own set of idiosyncrasies, but at least python code is indenting "correctly".

Emacs Pabbrev and Python

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)))

Categories