How to configure vim to not put comments at the beginning of lines while editing python files
Question:
When I add a # in insert mode on an empty line in Vim while editing python files, vim moves the # to the beginning of the line, but I would like the # to be inserted at the tab level where I entered it.
For example, when writing this in vim
for i in range(10):
#
the # does not stay there where I entered it.
It is moved like so, by vim.
for i in range(10):
#
Does anyone know of a configuration item in vim that would change this?
If it helps, I am using Ubuntu 8.10.
Answers:
My Vim configuration doesn’t do that. You might try the python.vim script available from this link: http://www.vim.org/scripts/script.php?script_id=790
I found an answer here http://vim.wikia.com/wiki/Restoring_indent_after_typing_hash
It seems that the vim smartindent option is the cause of the problem.
The referenced page above describes work-a-rounds but after reading the help in smartindent in vim itself (:help smartindent), I decided to try cindent instead of smartindent.
I replaced
set smartindent
with
set cindent
in my .vimrc file
and so far it is working perfectly.
This changed also fixed the behavior of ‘<<‘ and ‘>>’ for indenting visual blocks that include python comments.
There are more configuration options for and information on indentation in the vim help for smartindent and cindent (:help smartindent and :help cindent).
It’s caused by the ‘smartindent’ feature. If you have :set smartindent
in your .vimrc you need to remove it.
I have the following lines in my .vimrc, seems to be installed by default with my Ubuntu 8.10
set smartindent
inoremap # X^H#
set autoindent
And I don’t observe the problem. Maybe you can try this. (Note that ^H should be entered by Ctrl-V Ctrl-H)
@PolyThinker Though I see that response a lot to this question, in my opinion it’s not a good solution. The editor still thinks it should be indented all the way to left – check this by pushing == on a line that starts with a hash, or pushing = while a block of code with comments in it is highlighted to reindent.
I would strongly recommend filetype indent on
, and remove the set smartindent
and set autoindent
(or set cindent
) lines from your vimrc. Someone else (appparently David Bustos) was kind enough to write a full indentation parser for us; it’s located at $VIMDIRECTORY/indent/python.vim.
(Paul’s cindent
solution probably works for python, but filetype indent on
is much more generally useful.)
My solution to the unindenting of #:
If you use cindent, recognize that it is designed for C and C++ coding. Here, a # means you are creating a #DEFINE or #MACRO(), so the behavior is correct. But for other languages where # is a comment, it is irritating.
The following worked for me:
" cindent enable specific indenting for C code
" set cin nocin
set cin
" cinkeys The default cinkeys causes leading # to unindent to column 0.
" To prevent this, remove the 0# from the definition.
" set cinkeys=0{,0},0),:,0#,!^F,o,O,e - default
set cinkeys=0{,0},0),:,!^F,o,O,e
I removed set smartindent
from ~/.vimrc
but it still didn’t disable smartindent. When I opened a .py file and ran :set smartindent?
it displayed smartindent
.
Turns out that further down in the ~/.vimrc
was this line:
autocmd BufRead *.py set smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class
^^^^^^^^^^^
Once I deleted “smartindent” from that line, then smartindent was finally disabled and my comments were indented properly again.
Some of the other answers were useful, but none were enough to prevent Vim from reindenting a line when ‘#’ is the first character. PolyThinker’s answer didn’t work for me, but it gave a clue that ‘#’ could be remapped to “insert a character, then #, then delete the extra character and put the cursor where it should be”. This is the mapping that does that:
inoremap # X#<left><backspace><right>
This is needed because vim’s syntax packages seem to treat ‘#’ as a special character, no matter how the options are set. I want a line started with ‘#’ to be the same as a line begun with any other character. The most reliable solution I’ve found is the above mapping, which actually does change the line’s first character.
Note: I’ve found this mapping causes problems after running I#<esc>
then pressing “.” to redo the previous insertion. I haven’t found a solution yet.
When I add a # in insert mode on an empty line in Vim while editing python files, vim moves the # to the beginning of the line, but I would like the # to be inserted at the tab level where I entered it.
For example, when writing this in vim
for i in range(10):
#
the # does not stay there where I entered it.
It is moved like so, by vim.
for i in range(10):
#
Does anyone know of a configuration item in vim that would change this?
If it helps, I am using Ubuntu 8.10.
My Vim configuration doesn’t do that. You might try the python.vim script available from this link: http://www.vim.org/scripts/script.php?script_id=790
I found an answer here http://vim.wikia.com/wiki/Restoring_indent_after_typing_hash
It seems that the vim smartindent option is the cause of the problem.
The referenced page above describes work-a-rounds but after reading the help in smartindent in vim itself (:help smartindent), I decided to try cindent instead of smartindent.
I replaced
set smartindent
with
set cindent
in my .vimrc file
and so far it is working perfectly.
This changed also fixed the behavior of ‘<<‘ and ‘>>’ for indenting visual blocks that include python comments.
There are more configuration options for and information on indentation in the vim help for smartindent and cindent (:help smartindent and :help cindent).
It’s caused by the ‘smartindent’ feature. If you have :set smartindent
in your .vimrc you need to remove it.
I have the following lines in my .vimrc, seems to be installed by default with my Ubuntu 8.10
set smartindent
inoremap # X^H#
set autoindent
And I don’t observe the problem. Maybe you can try this. (Note that ^H should be entered by Ctrl-V Ctrl-H)
@PolyThinker Though I see that response a lot to this question, in my opinion it’s not a good solution. The editor still thinks it should be indented all the way to left – check this by pushing == on a line that starts with a hash, or pushing = while a block of code with comments in it is highlighted to reindent.
I would strongly recommend filetype indent on
, and remove the set smartindent
and set autoindent
(or set cindent
) lines from your vimrc. Someone else (appparently David Bustos) was kind enough to write a full indentation parser for us; it’s located at $VIMDIRECTORY/indent/python.vim.
(Paul’s cindent
solution probably works for python, but filetype indent on
is much more generally useful.)
My solution to the unindenting of #:
If you use cindent, recognize that it is designed for C and C++ coding. Here, a # means you are creating a #DEFINE or #MACRO(), so the behavior is correct. But for other languages where # is a comment, it is irritating.
The following worked for me:
" cindent enable specific indenting for C code
" set cin nocin
set cin
" cinkeys The default cinkeys causes leading # to unindent to column 0.
" To prevent this, remove the 0# from the definition.
" set cinkeys=0{,0},0),:,0#,!^F,o,O,e - default
set cinkeys=0{,0},0),:,!^F,o,O,e
I removed set smartindent
from ~/.vimrc
but it still didn’t disable smartindent. When I opened a .py file and ran :set smartindent?
it displayed smartindent
.
Turns out that further down in the ~/.vimrc
was this line:
autocmd BufRead *.py set smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class
^^^^^^^^^^^
Once I deleted “smartindent” from that line, then smartindent was finally disabled and my comments were indented properly again.
Some of the other answers were useful, but none were enough to prevent Vim from reindenting a line when ‘#’ is the first character. PolyThinker’s answer didn’t work for me, but it gave a clue that ‘#’ could be remapped to “insert a character, then #, then delete the extra character and put the cursor where it should be”. This is the mapping that does that:
inoremap # X#<left><backspace><right>
This is needed because vim’s syntax packages seem to treat ‘#’ as a special character, no matter how the options are set. I want a line started with ‘#’ to be the same as a line begun with any other character. The most reliable solution I’ve found is the above mapping, which actually does change the line’s first character.
Note: I’ve found this mapping causes problems after running I#<esc>
then pressing “.” to redo the previous insertion. I haven’t found a solution yet.