I'm editing a file that was initially written in emacs and that I am now working on in vim. I've been running into an odd problem when switching from one to the other:
At some places in the code, seemingly randomly, there are tabs in the emacs code that are equivalent to two tabs (both visually in emacs and in python). However, in vim these tab characters show up as only a single tab.
When I :set list, an example few lines will show up as:
for i in range(total_pairs):$
^Iwhile 1:$
^I rint = random.randint(0,total_pairs-1)$
^I if(trialData[rint].cueDir == FORWARD)$
^I^ItrialData[rint].cueDir=BACKWARD$
^I^Ibreak$
While it should appear as:
for i in range(total_pairs):$
while 1:$
rint = random.randint(0,total_pairs-1)$
if(trialData[rint].cueDir == FORWARD):$
trialData[rint].cueDir = BACKWARD$
break$
The code still runs either way, but it's fairly annoying to read.
When I run :retab, it replaces each ^I with one tab, instead of the two tabs that it should. What can I do to replace each ^I character with two tabs instead of one. Also, why is this happening?
Thanks.
The easy, (and recommended), answer is replace each tab with 4 spaces and set both emacs and vim to use 4 spaces when tab is pressed.
When I run :retab, it replaces each ^I with one tab, instead of the two tabs that it should.
:retab replaces each tab character (i.e. ^I) with tabstop spaces. In your case, tabstop is evidently set to 4, so Vim replaces each ^I in the file with 4 spaces. If you expect :retab to replace each ^I with 8 spaces, use set tabstop=8 before :retab.
To address the actual problem, do not use mixed indentation in Python; set up both Emacs and Vim to use spaces for tabs.
See :h expandtab, :h tabstop, :h softtabstop, and :h shiftwidth for more information.
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 new to atom, so I opened my existing code using atom and modified few lines, then when I tried running the code with python, I get the following error:
IndentationError: unindent does not match any outer indentation level
I realized that Atom editor does indent my code differently to what I had. refer to the attached picture below showing the different indentation styles. line 1300 is the old indentation and 1301 is the one created by Atom
How can I fix this without modifying my 1000+ line code and so that atom uses the same style of indentation.
You have mixed tabs and spaces in your code. You should use spaces, always.
You can use this plugin to quickly fix your code, and please, use only spaces and 4 spaces for each level of indentation.
I had a similar error while using Atom,I fixed it using below steps.
Install notepad++
Open the file which has issue(one you have mentioned in question) in notepad++.
Go to View > Show Symbol > Show All Characters,this will show up where the tabs and where spaces are available.
Go to Edit->Blank Operations->TAB to Space to replace all tabs with spaces.
Go to View > Show Symbol > Show All Characters,confirm all tabs are replaced with spaces.
Save file and reload page,this will fix this issue.
In the newer versions of Atom, just go to settings > Editor; then scroll down to tab length and change it to 4; then change tab type to soft. This will make the tab key insert 4 spaces instead of a tab character moving forward. You still have to update your previous code using one of the above methods.
In the Atom Text Editor's top menu bar :
click the Packages tab
click Whitespace in the dropdown menu
Choose your preferred option (ie: Convert Spaces to Tabs)
And that will fix this pesky problem.
I'm trying to figure out what the options -t and -tt do.
From the doc:
Issue a warning when a source file mixes tabs and spaces for indentation in a way that makes it depend on the worth of a tab expressed in spaces. Issue an error when the option is given twice (-tt).
I'm not getting it, in particular the bolded sentence, what does it mean? A tab is a tab ('\t') a space is a space (' ') and in ascii table they also have 2 different codes.
I'll ty to make an example to explain better myself. I code:
if True:
print('hello') # here a tab that my editor represents with 4 spaces
print('world') # here just used 4 spaces
Now this code, I tried, doesn't work neither in Python3 nor in Python2, so what does -t do?
Could you give me a clarification?
When used as indentation, tabs must be interpreted as equivalent to a number of spaces. How many spaces depends on how you configured your editor, and how many spaces preceded the tab on the same line. That's because tabs represent a jump to the next tabstop. If you used 2 spaces plus a tab, you have signalled a jump to column 8, as if you inserted 6 spaces.
In addition, some people set their tabstops to be the equivalent of 4 spaces, others set it to be the same as 8 spaces. These people then use tabs in indentation in different ways too. You could use 4 spaces for one indentation level, then use tabs at 8 spaces for the next, then use a tab plus 4 spaces, etc. Or you could use tabs for all indentation levels, having set the tab size to represent 4 spaces.
Python needs to handle mixing of tabs and spaces, and then hope that you used it consistently; e.g. you didn't use 4 spaces first, then a tab to indent to what you thought was an indentation equivalent to 12 spaces. Python can easily get this wrong when you are inconsistent.
The -t and -tt options point out where you may have gotten this wrong by doing more rigorous and thorough testing of all lines.
The ease by which you can produce confusing results, between various tab sizes and mixing tabs and spaces, is the reason why the Python Style Guide (PEP 8) strongly recommends that you use spaces only:
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is already indented with tabs.
In Python 3, mixing tabs and spaces for indentation is now an error.
To be precise: Python starts out assuming you used 8 spaces for a tab. See the Indentation documentation, part of the Lexical Analysis specification:
First, tabs are replaced (from left to right) by one to eight spaces such that the total number of characters up to and including the replacement is a multiple of eight (this is intended to be the same rule as used by Unix). The total number of spaces preceding the first non-blank character then determines the line’s indentation. Indentation cannot be split over multiple physical lines using backslashes; the whitespace up to the first backslash determines the indentation.
Python 2 also looks for Emacs and VI-style configuration comments; if the tokenizer finds a comment with tab-width:, :tabstop=, :ts= or set tabsize= in it, followed by digits, like:
# -*- tab-width: 4 -*- (emacs)
# :tabstop=4 (vi)
or similar variants, then Python sets the tabsize from that. This support was removed from Python 3.
If you then mix tabs and spaces that may be inconsistent, and use -t, the text <filename>: inconsistent use of tabs and spaces in indentation is written to sys.stderr once for that file. If you used -tt, a TabError exception is raised instead.
The error will be thrown when a source file depends on tabs expanding to a certain number of spaces.
For example, a file like this would be problematic:
def function():
print 'hello'
\tprint 'goodbye'
The above code would work if a tab was 4 spaces, but would fail if it was anything else (except 0, which is nonsensical).
The -t option attempts to highlight such issues.
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.
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.